diff --git a/.hgtags b/.hgtags
index 0f990fc3b913e3a6a3630033ed24e0328217b292..b972d376f7d3e57ece33d4c577cb598723076693 100755
--- a/.hgtags
+++ b/.hgtags
@@ -481,3 +481,4 @@ fc066b82343fca51f9c1b8eda0abc6bee9bb4503 3.7.5-release
 d029faf69f20a23007f32420a1ac6a3b89a6d441 3.7.6-release
 83959480cb986522d07b151a0c778ab7f920d41b 3.7.7-release
 bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
+a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
diff --git a/autobuild.xml b/autobuild.xml
index 1d827cb6c44be82e45d81e4f0ee8ec1f8d7d5414..dd4c63f4749b1de096459930309fdb6e98ce1ee4 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -764,7 +764,7 @@
               <key>hash</key>
               <string>aff5566e04003de0383941981198e04e</string>
               <key>url</key>
-          <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -776,7 +776,7 @@
               <key>hash</key>
               <string>52257e5eb166a0b69c9c0c38f6e1920e</string>
               <key>url</key>
-	         <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -834,9 +834,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d2542614df9dd99cbb5ff67e76d4a6c1</string>
+              <string>98994d5b0b4b3d43be22aa6a5c36e6fa</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-mock/rev/274899/arch/CYGWIN/installer/gmock-1.6.0-windows-20130426.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-mock-graham/rev/272961/arch/CYGWIN/installer/gmock-1.6.0-windows-20130327.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b6d29de20de5c8f31925697b30e8f727</string>
+              <string>54e46715e72b7805d9d3f84d45b6b1b7</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/283723/arch/Linux/installer/llappearanceutility_source-0.1-linux-20131109.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/290120/arch/Linux/installer/llappearanceutility_source-0.1-linux-20140519.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index e4b63dc7cb8d8c4bdc954c954299106565a02fdb..e618a988b831e3cdf818bdcc43964a74f4b5acba 100755
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -42,6 +42,11 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
         message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'") 
     endif ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
 
+    if ("${VIEWER_VERSION_REVISION}" STREQUAL "")
+      message("Ultimate fallback, revision was blank or not set: will use 0")
+      set(VIEWER_VERSION_REVISION 0)
+    endif ("${VIEWER_VERSION_REVISION}" STREQUAL "")
+
     set(VIEWER_CHANNEL_VERSION_DEFINES
         "LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\""
         "LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}"
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index beeb570496e335e9607edee65d5b4c0be022630e..c63ad74682b6ce81f684bcf591a71f7b6526aa06 100755
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1,7 +1 @@
-Wed Nov  7 00:25:19 UTC 2012
-
-
-
-
-
-
+2014-02-25 10:34
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
old mode 100644
new mode 100755
index 41fcb6ce4baab9a8e30c55df493372354e7553e0..6fdf9e2e072cb31c1d76e4164d7a73b368003043
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -498,29 +498,9 @@ void LLAvatarAppearance::computeBodySize()
 	mAvatarOffset.mV[VX] = 0.0f;
 	mAvatarOffset.mV[VY] = 0.0f;
 
-	// Certain configurations of avatars can force the overall height (with offset) to go negative.
-	// Enforce a constraint to make sure we don't go below 0.1 meters.
-	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f) 
-	{
-		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail.
-
-		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f);
-
-		if (mWearableData && isSelf()) 
-		{
-			LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
-			if (shape) 
-			{
-				shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false);
-			}
-		}
-	}
-
 	if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
 	{
 		mBodySize = new_body_size;
-		bodySizeChanged();
 	}
 }
 
@@ -1390,14 +1370,14 @@ BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name )
 	return TRUE;
 }
 
-void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
+void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color)
 {
 	U32 param_name[3];
 	if( teToColorParams( te, param_name ) )
 	{
-		setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
-		setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
-		setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
+		setVisualParamWeight( param_name[0], new_color.mV[VX]);
+		setVisualParamWeight( param_name[1], new_color.mV[VY]);
+		setVisualParamWeight( param_name[2], new_color.mV[VZ]);
 	}
 }
 
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
old mode 100644
new mode 100755
index bce25402581032514c6cce838ddc26e69c0d951a..1e898026c037bd39d41b7616a78ccc14ef5b6ce7
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -107,7 +107,6 @@ class LLAvatarAppearance : public LLCharacter
 public:
 	virtual bool 	isSelf() const { return false; } // True if this avatar is for this viewer's agent
 	virtual BOOL	isValid() const;
-	virtual BOOL	isUsingServerBakes() const = 0;
 	virtual BOOL	isUsingLocalAppearance() const = 0;
 	virtual BOOL	isEditingAppearance() const = 0;
 
@@ -137,14 +136,13 @@ class LLAvatarAppearance : public LLCharacter
 	typedef std::map<std::string, LLJoint*> joint_map_t;
 	joint_map_t			mJointMap;
 	
-	void				computeBodySize();
+	void		computeBodySize();
 
 
 protected:
 	static BOOL			parseSkeletonFile(const std::string& filename);
 	virtual void		buildCharacter();
 	virtual BOOL		loadAvatar();
-	virtual void		bodySizeChanged() = 0;
 
 	BOOL				setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
 	BOOL				allocateCharacterJoints(U32 num);
@@ -225,7 +223,7 @@ class LLAvatarAppearance : public LLCharacter
 	// Composites
 	//--------------------------------------------------------------------
 public:
-	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0;
+	virtual void	invalidateComposite(LLTexLayerSet* layerset) = 0;
 
 /********************************************************************************
  **                                                                            **
@@ -256,7 +254,7 @@ class LLAvatarAppearance : public LLCharacter
 	// Clothing colors (convenience functions to access visual parameters)
 	//--------------------------------------------------------------------
 public:
-	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
+	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color);
 	LLColor4		getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
 	static BOOL		teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
 
@@ -265,7 +263,7 @@ class LLAvatarAppearance : public LLCharacter
 	//--------------------------------------------------------------------
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
-	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0;
+	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
 	LLTexGlobalColor* mTexHairColor;
diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
old mode 100644
new mode 100755
index c66a4283740058ee555d0fe0f8e2708aa64a909e..e630c1118bc859c71c8c0911e3ceb6ec0d0a144b
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -152,19 +152,31 @@ void LLDriverParamInfo::toStream(std::ostream &out)
 // LLDriverParam
 //-----------------------------------------------------------------------------
 
-LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) :
+LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */)
+	: LLViewerVisualParam(),
+	mDefaultVec(),
+	mDriven(),
 	mCurrentDistortionParam( NULL ), 
 	mAvatarAppearance(appearance), 
 	mWearablep(wearable)
 {
 	llassert(mAvatarAppearance);
-	if (mWearablep)
-	{
-		llassert(mAvatarAppearance->isSelf());
-	}
+	llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
 	mDefaultVec.clear();
 }
 
+LLDriverParam::LLDriverParam(const LLDriverParam& pOther)
+	: LLViewerVisualParam(pOther),
+	mDefaultVec(pOther.mDefaultVec),
+	mDriven(pOther.mDriven),
+	mCurrentDistortionParam(pOther.mCurrentDistortionParam),
+	mAvatarAppearance(pOther.mAvatarAppearance),
+	mWearablep(pOther.mWearablep)
+{
+	llassert(mAvatarAppearance);
+	llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
+}
+
 LLDriverParam::~LLDriverParam()
 {
 }
@@ -178,7 +190,7 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
 	mID = info->mID;
 	info->mDriverParam = this;
 
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 
 	return TRUE;
 }
@@ -186,16 +198,10 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
 /*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const
 {
 	llassert(wearable);
-	LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable);
-	// FIXME DRANO this clobbers mWearablep, which means any code
-	// currently using mWearablep is wrong, or at least untested.
-	*new_param = *this;
-	//new_param->mWearablep = wearable;
-//	new_param->mDriven.clear(); // clear driven list to avoid overwriting avatar driven params from wearables. 
-	return new_param;
+	return new LLDriverParam(*this);
 }
 
-void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
+void LLDriverParam::setWeight(F32 weight)
 {
 	F32 min_weight = getMinWeight();
 	F32 max_weight = getMaxWeight();
@@ -254,7 +260,7 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
 					driven_weight = driven_min;
 				}
 				
-				setDrivenWeight(driven,driven_weight,upload_bake);
+				setDrivenWeight(driven,driven_weight);
 				continue;
 			}
 			else 
@@ -278,13 +284,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
 					driven_weight = driven_min;
 				}
 
-				setDrivenWeight(driven,driven_weight,upload_bake);
+				setDrivenWeight(driven,driven_weight);
 				continue;
 			}
 		}
 
 		driven_weight = getDrivenWeight(driven, mCurWeight);
-		setDrivenWeight(driven,driven_weight,upload_bake);
+		setDrivenWeight(driven,driven_weight);
 	}
 }
 
@@ -430,9 +436,9 @@ const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const
 //-----------------------------------------------------------------------------
 // setAnimationTarget()
 //-----------------------------------------------------------------------------
-void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
+void LLDriverParam::setAnimationTarget( F32 target_value)
 {
-	LLVisualParam::setAnimationTarget(target_value, upload_bake);
+	LLVisualParam::setAnimationTarget(target_value);
 
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
@@ -441,16 +447,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
 
 		// this isn't normally necessary, as driver params handle interpolation of their driven params
 		// but texture params need to know to assume their final value at beginning of interpolation
-		driven->mParam->setAnimationTarget(driven_weight, upload_bake);
+		driven->mParam->setAnimationTarget(driven_weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // stopAnimating()
 //-----------------------------------------------------------------------------
-void LLDriverParam::stopAnimating(BOOL upload_bake)
+void LLDriverParam::stopAnimating()
 {
-	LLVisualParam::stopAnimating(upload_bake);
+	LLVisualParam::stopAnimating();
 
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
@@ -530,7 +536,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type)
 		LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type);
 		if (wearable)
 		{
-			wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false);
+			wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID));
 		}
 	}
 }
@@ -593,7 +599,7 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
 	return driven_weight;
 }
 
-void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake)
+void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight)
 {
 	bool use_self = false;
 	if(mWearablep &&
@@ -610,10 +616,10 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bo
 	if (use_self)
 	{
 		// call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
-		mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
+		mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight);
 	}
 	else
 	{
-		driven->mParam->setWeight( driven_weight, upload_bake );
+		driven->mParam->setWeight( driven_weight);
 	}
 }
diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h
old mode 100644
new mode 100755
index 2420db76e7fdc59cc153ccffff0574f4e37c2082..f71c930e5e3716fbf67683690f9f372fd5f02142
--- a/indra/llappearance/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -111,9 +111,9 @@ class LLDriverParam : public LLViewerVisualParam
 
 	// LLVisualParam Virtual functions
 	/*virtual*/ void				apply( ESex sex ) {} // apply is called separately for each driven param.
-	/*virtual*/ void				setWeight(F32 weight, BOOL upload_bake);
-	/*virtual*/ void				setAnimationTarget( F32 target_value, BOOL upload_bake );
-	/*virtual*/ void				stopAnimating(BOOL upload_bake);
+	/*virtual*/ void				setWeight(F32 weight);
+	/*virtual*/ void				setAnimationTarget( F32 target_value);
+	/*virtual*/ void				stopAnimating();
 	/*virtual*/ BOOL				linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
 	/*virtual*/ void				resetDrivenParams();
 	
@@ -129,8 +129,9 @@ class LLDriverParam : public LLViewerVisualParam
 	const LLViewerVisualParam*		getDrivenParam(S32 index) const;
 
 protected:
+	LLDriverParam(const LLDriverParam& pOther);
 	F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
-	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
+	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight);
 
 
 	LL_ALIGN_16(LLVector4a	mDefaultVec); // temp holder
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index ce8a0b0b764692884e8e49e7dde9254ae4831fb7..e3992a080e4b02d93c0be859e9a69100ccb4ed01 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -315,10 +315,27 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
 // LLPolyMorphTarget()
 //-----------------------------------------------------------------------------
 LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
-	: mMorphData(NULL), mMesh(poly_mesh),
-	  mVertMask(NULL),
-	  mLastSex(SEX_FEMALE),
-	  mNumMorphMasksPending(0)
+	: LLViewerVisualParam(),
+	mMorphData(NULL),
+	mMesh(poly_mesh),
+	mVertMask(NULL),
+	mLastSex(SEX_FEMALE),
+	mNumMorphMasksPending(0),
+	mVolumeMorphs()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget()
+//-----------------------------------------------------------------------------
+LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther)
+	: LLViewerVisualParam(pOther),
+	mMorphData(pOther.mMorphData),
+	mMesh(pOther.mMesh),
+	mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)),
+	mLastSex(pOther.mLastSex),
+	mNumMorphMasksPending(pOther.mNumMorphMasksPending),
+	mVolumeMorphs(pOther.mVolumeMorphs)
 {
 }
 
@@ -327,10 +344,8 @@ LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
 //-----------------------------------------------------------------------------
 LLPolyMorphTarget::~LLPolyMorphTarget()
 {
-	if (mVertMask)
-	{
-		delete mVertMask;
-	}
+	delete mVertMask;
+	mVertMask = NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -343,7 +358,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
 		return FALSE;
 	mInfo = info;
 	mID = info->mID;
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 
 	LLAvatarAppearance* avatarp = mMesh->getAvatar();
 	LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
@@ -385,9 +400,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
 
 /*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
 {
-	LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
-	*new_param = *this;
-	return new_param;
+	return new LLPolyMorphTarget(*this);
 }
 
 #if 0 // obsolete
@@ -722,10 +735,25 @@ void	LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3
 // LLPolyVertexMask()
 //-----------------------------------------------------------------------------
 LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
+	: mWeights(new F32[morph_data->mNumIndices]),
+	mMorphData(morph_data),
+	mWeightsGenerated(FALSE)
+{
+	llassert(mMorphData != NULL);
+	llassert(mMorphData->mNumIndices > 0);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther)
+	: mWeights(new F32[pOther.mMorphData->mNumIndices]),
+	mMorphData(pOther.mMorphData),
+	mWeightsGenerated(pOther.mWeightsGenerated)
 {
-	mWeights = new F32[morph_data->mNumIndices];
-	mMorphData = morph_data;
-	mWeightsGenerated = FALSE;
+	llassert(mMorphData != NULL);
+	llassert(mMorphData->mNumIndices > 0);
+	memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices);
 }
 
 //-----------------------------------------------------------------------------
@@ -733,7 +761,8 @@ LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
 //-----------------------------------------------------------------------------
 LLPolyVertexMask::~LLPolyVertexMask()
 {
-	delete[] mWeights;
+	delete [] mWeights;
+	mWeights = NULL;
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
index ee380ae7c3792bf2b85217deadd8b19d282ddd27..7e712f9e9478d6f250d1e61166b191417060837f 100644
--- a/indra/llappearance/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -91,6 +91,7 @@ class LLPolyVertexMask
 {
 public:
 	LLPolyVertexMask(LLPolyMorphData* morph_data);
+	LLPolyVertexMask(const LLPolyVertexMask& pOther);
 	~LLPolyVertexMask();
 
 	void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
@@ -182,6 +183,8 @@ class LLPolyMorphTarget : public LLViewerVisualParam
 	void	addPendingMorphMask() { mNumMorphMasksPending++; }
 
 protected:
+	LLPolyMorphTarget(const LLPolyMorphTarget& pOther);
+
 	LLPolyMorphData*				mMorphData;
 	LLPolyMesh*						mMesh;
 	LLPolyVertexMask *				mVertMask;
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index a72b446ace9fa148e23e5f09d8c325f02557a25c..ea29cbd4519c7fae24617a3d20d9733d67426a0f 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -104,9 +104,25 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
 // LLPolySkeletalDistortion()
 //-----------------------------------------------------------------------------
 LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp)
+	: LLViewerVisualParam(),
+	mDefaultVec(),
+	mJointScales(),
+	mJointOffsets(),
+	mAvatar(avatarp)
+{
+	mDefaultVec.splat(0.001f);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::LLPolySkeletalDistortion(const LLPolySkeletalDistortion &pOther)
+	: LLViewerVisualParam(pOther),
+	mDefaultVec(pOther.mDefaultVec),
+	mJointScales(pOther.mJointScales),
+	mJointOffsets(pOther.mJointOffsets),
+	mAvatar(pOther.mAvatar)
 {
-        mAvatar = avatarp;
-        mDefaultVec.splat(0.001f);
 }
 
 //-----------------------------------------------------------------------------
@@ -123,7 +139,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
                 return FALSE;
         mInfo = info;
         mID = info->mID;
-        setWeight(getDefaultWeight(), FALSE );
+        setWeight(getDefaultWeight());
 
         LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
         for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
@@ -171,9 +187,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
 
 /*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
 {
-        LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
-        *new_param = *this;
-        return new_param;
+	return new LLPolySkeletalDistortion(*this);
 }
 
 //-----------------------------------------------------------------------------
@@ -185,7 +199,7 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
 {
 	LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY);
 
-        F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+	F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
 
         LLJoint* joint;
         joint_vec_map_t::iterator iter;
@@ -197,8 +211,10 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
                 joint = iter->first;
                 LLVector3 newScale = joint->getScale();
                 LLVector3 scaleDelta = iter->second;
-                newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
-                joint->setScale(newScale);
+                newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);				                
+				//An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached
+				joint->storeScaleForReset( newScale );				
+				joint->setScale(newScale);
         }
 
         for (iter = mJointOffsets.begin();
@@ -207,8 +223,8 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
         {
                 joint = iter->first;
                 LLVector3 newPosition = joint->getPosition();
-                LLVector3 positionDelta = iter->second;
-                newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+                LLVector3 positionDelta = iter->second;				
+                newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);		
                 joint->setPosition(newPosition);
         }
 
diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h
index 24c9e9ae48aa5b06e4b50bf218a9094f29a1c773..ea2adb8a87c3e1033cc1b624db6cd4cf27190b5c 100644
--- a/indra/llappearance/llpolyskeletaldistortion.h
+++ b/indra/llappearance/llpolyskeletaldistortion.h
@@ -118,6 +118,8 @@ class LLPolySkeletalDistortion : public LLViewerVisualParam
 	/*virtual*/ const LLVector4a*	getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
 
 protected:
+	LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther);
+
 	LL_ALIGN_16(LLVector4a mDefaultVec);
 	typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
 	joint_vec_map_t mJointScales;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
old mode 100644
new mode 100755
index 186c53765979bc8453a1c4b81bab8586c00b602e..3df2254b1423ec8477b270050b38dfe320b6e12a
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -90,22 +90,36 @@ const std::string& LLTexGlobalColor::getName() const
 //-----------------------------------------------------------------------------
 // LLTexParamGlobalColor
 //-----------------------------------------------------------------------------
-LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
-	LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
+LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
+	: LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
 	mTexGlobalColor(tex_global_color)
 {
 }
 
+//-----------------------------------------------------------------------------
+// LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther)
+	: LLTexLayerParamColor(pOther),
+	mTexGlobalColor(pOther.mTexGlobalColor)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::~LLTexParamGlobalColor()
+{
+}
+
 /*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
 {
-	LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
-	*new_param = *this;
-	return new_param;
+	return new LLTexParamGlobalColor(*this);
 }
 
-void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
+void LLTexParamGlobalColor::onGlobalColorChanged()
 {
-	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake);
+	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
old mode 100644
new mode 100755
index 2867479876d72f9c434132bca2821bd1a3b3429a..3b426053dee2556bb06ef9ee24ba85624b9349fe
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -73,9 +73,11 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
 {
 public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
+	virtual ~LLTexParamGlobalColor();
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
 protected:
-	/*virtual*/ void onGlobalColorChanged(bool upload_bake);
+	LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther);
+	/*virtual*/ void onGlobalColorChanged();
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
 };
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index f6abaa5eb32f50299e198e6e03fdb40a44ffec8a..2cf86bb4feca68eded411656a0e8870c53902c7a 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1560,10 +1560,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
 		}
 
 		U32 cache_index = alpha_mask_crc.getCRC();
-		U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL);
-		if (!alpha_data)
+		U8* alpha_data = NULL; 
+                // We believe we need to generate morph masks, do not assume that the cached version is accurate.
+                // We can get bad morph masks during login, on minimize, and occasional gl errors.
+                // We should only be doing this when we believe something has changed with respect to the user's appearance.
 		{
-			// clear out a slot if we have filled our cache
+                       LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
+                        // clear out a slot if we have filled our cache
 			S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
 			while ((S32)mAlphaCache.size() >= max_cache_entries)
 			{
@@ -1783,13 +1786,11 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
 /*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
 {
 	U32 num_wearables = updateWearableCache();
-	for (U32 i = 0; i < num_wearables; i++)
+	U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
+	LLTexLayer *layer = getLayer(i);
+	if (layer)
 	{
-		LLTexLayer *layer = getLayer(i);
-		if (layer)
-		{
-			layer->addAlphaMask(data, originX, originY, width, height);
-		}
+		layer->addAlphaMask(data, originX, originY, width, height);
 	}
 }
 
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
old mode 100644
new mode 100755
index f1f7d07fa9c98cf82f458edb0d16e3c048f0a2c3..ff682d69069ad15696e65852734dd488e227c39c
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -40,7 +40,8 @@
 //-----------------------------------------------------------------------------
 // LLTexLayerParam
 //-----------------------------------------------------------------------------
-LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
+LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer)
+	: LLViewerVisualParam(),
 	mTexLayer(layer),
 	mAvatarAppearance(NULL)
 {
@@ -54,12 +55,19 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
 	}
 }
 
-LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) :
+LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance)
+	: LLViewerVisualParam(),
 	mTexLayer(NULL),
 	mAvatarAppearance(appearance)
 {
 }
 
+LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther)
+	: LLViewerVisualParam(pOther),
+	mTexLayer(pOther.mTexLayer),
+	mAvatarAppearance(pOther.mAvatarAppearance)
+{
+}
 
 BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance)
 {
@@ -112,9 +120,11 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
 	}
 }
 
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
-	LLTexLayerParam(layer),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer)
+	: LLTexLayerParam(layer),
 	mCachedProcessedTexture(NULL),
+	mStaticImageTGA(),
+	mStaticImageRaw(),
 	mNeedsCreateTexture(FALSE),
 	mStaticImageInvalid(FALSE),
 	mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -123,9 +133,11 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
 	sInstances.push_front(this);
 }
 
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
-	LLTexLayerParam(appearance),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance)
+	: LLTexLayerParam(appearance),
 	mCachedProcessedTexture(NULL),
+	mStaticImageTGA(),
+	mStaticImageRaw(),
 	mNeedsCreateTexture(FALSE),
 	mStaticImageInvalid(FALSE),
 	mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -134,6 +146,18 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
 	sInstances.push_front(this);
 }
 
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)
+	: LLTexLayerParam(pOther),
+	mCachedProcessedTexture(pOther.mCachedProcessedTexture),
+	mStaticImageTGA(pOther.mStaticImageTGA),
+	mStaticImageRaw(pOther.mStaticImageRaw),
+	mNeedsCreateTexture(pOther.mNeedsCreateTexture),
+	mStaticImageInvalid(pOther.mStaticImageInvalid),
+	mAvgDistortionVec(pOther.mAvgDistortionVec),
+	mCachedEffectiveWeight(pOther.mCachedEffectiveWeight)
+{
+	sInstances.push_front(this);
+}
 
 LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
 {
@@ -143,9 +167,7 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
 
 /*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
 {
-	LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
-	*new_param = *this;
-	return new_param;
+	return new LLTexLayerParamAlpha(*this);
 }
 
 void LLTexLayerParamAlpha::deleteCaches()
@@ -161,7 +183,7 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
 	return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; 	
 }
 
-void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
+void LLTexLayerParamAlpha::setWeight(F32 weight)
 {
 	if (mIsAnimating || mTexLayer == NULL)
 	{
@@ -179,35 +201,35 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
 		if ((mAvatarAppearance->getSex() & getSex()) &&
 			(mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
-			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			mTexLayer->invalidateMorphMasks();
 		}
 	}
 }
 
-void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value)
 { 
 	// do not animate dummy parameters
 	if (mIsDummy)
 	{
-		setWeight(target_value, upload_bake);
+		setWeight(target_value);
 		return;
 	}
 
 	mTargetWeight = target_value; 
-	setWeight(target_value, upload_bake); 
+	setWeight(target_value); 
 	mIsAnimating = TRUE;
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
-void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamAlpha::animate(F32 delta)
 {
 	if (mNext)
 	{
-		mNext->animate(delta, upload_bake);
+		mNext->animate(delta);
 	}
 }
 
@@ -399,27 +421,31 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
 
 
 
-LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
-	LLTexLayerParam(layer),
+LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer)
+	: LLTexLayerParam(layer),
 	mAvgDistortionVec(1.f, 1.f, 1.f)
 {
 }
 
-LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) :
-	LLTexLayerParam(appearance),
+LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance)
+	: LLTexLayerParam(appearance),
 	mAvgDistortionVec(1.f, 1.f, 1.f)
 {
 }
 
+LLTexLayerParamColor::LLTexLayerParamColor(const LLTexLayerParamColor& pOther)
+	: LLTexLayerParam(pOther),
+	mAvgDistortionVec(pOther.mAvgDistortionVec)
+{
+}
+
 LLTexLayerParamColor::~LLTexLayerParamColor()
 {
 }
 
 /*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
 {
-	LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
-	*new_param = *this;
-	return new_param;
+	return new LLTexLayerParamColor(*this);
 }
 
 LLColor4 LLTexLayerParamColor::getNetColor() const
@@ -450,14 +476,14 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
 	}
 }
 
-void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
+
+void LLTexLayerParamColor::setWeight(F32 weight)
 {
 	if (mIsAnimating)
 	{
 		return;
 	}
 
-	const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
 	F32 min_weight = getMinWeight();
 	F32 max_weight = getMaxWeight();
 	F32 new_weight = llclamp(weight, min_weight, max_weight);
@@ -467,6 +493,8 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 	{
 		mCurWeight = new_weight;
 
+                const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
+
 		if (info->mNumColors <= 0)
 		{
 			// This will happen when we set the default weight the first time.
@@ -475,10 +503,10 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 
 		if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
-			onGlobalColorChanged(upload_bake);
+			onGlobalColorChanged();
 			if (mTexLayer)
 			{
-				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			}
 		}
 
@@ -486,23 +514,23 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 	}
 }
 
-void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamColor::setAnimationTarget(F32 target_value)
 { 
 	// set value first then set interpolating flag to ignore further updates
 	mTargetWeight = target_value; 
-	setWeight(target_value, upload_bake);
+	setWeight(target_value);
 	mIsAnimating = TRUE;
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
-void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamColor::animate(F32 delta)
 {
 	if (mNext)
 	{
-		mNext->animate(delta, upload_bake);
+		mNext->animate(delta);
 	}
 }
 
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
old mode 100644
new mode 100755
index b38d28d3ebb4d666265747e5696c263fc6c7f715..0cb2dedbff869d21e70f45f16ecf166c173a799a
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -52,6 +52,8 @@ class LLTexLayerParam : public LLViewerVisualParam
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
 
 protected:
+	LLTexLayerParam(const LLTexLayerParam& pOther);
+
 	LLTexLayerInterface*	mTexLayer;
 	LLAvatarAppearance*		mAvatarAppearance;
 };
@@ -83,9 +85,9 @@ class LLTexLayerParamAlpha : public LLTexLayerParam
 	// LLVisualParam Virtual functions
 	///*virtual*/ BOOL		parseData(LLXmlTreeNode* node);
 	/*virtual*/ void		apply( ESex avatar_sex ) {}
-	/*virtual*/ void		setWeight(F32 weight, BOOL upload_bake);
-	/*virtual*/ void		setAnimationTarget(F32 target_value, BOOL upload_bake); 
-	/*virtual*/ void		animate(F32 delta, BOOL upload_bake);
+	/*virtual*/ void		setWeight(F32 weight);
+	/*virtual*/ void		setAnimationTarget(F32 target_value); 
+	/*virtual*/ void		animate(F32 delta);
 
 	// LLViewerVisualParam Virtual functions
 	/*virtual*/ F32					getTotalDistortion()									{ return 1.f; }
@@ -102,6 +104,8 @@ class LLTexLayerParamAlpha : public LLTexLayerParam
 	BOOL					getMultiplyBlend() const;
 
 private:
+	LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther);
+
 	LLPointer<LLGLTexture>	mCachedProcessedTexture;
 	LLPointer<LLImageTGA>	mStaticImageTGA;
 	LLPointer<LLImageRaw>	mStaticImageRaw;
@@ -174,9 +178,9 @@ class LLTexLayerParamColor : public LLTexLayerParam
 	// LLVisualParam Virtual functions
 	///*virtual*/ BOOL			parseData(LLXmlTreeNode* node);
 	/*virtual*/ void			apply( ESex avatar_sex ) {}
-	/*virtual*/ void			setWeight(F32 weight, BOOL upload_bake);
-	/*virtual*/ void			setAnimationTarget(F32 target_value, BOOL upload_bake);
-	/*virtual*/ void			animate(F32 delta, BOOL upload_bake);
+	/*virtual*/ void			setWeight(F32 weight);
+	/*virtual*/ void			setAnimationTarget(F32 target_value);
+	/*virtual*/ void			animate(F32 delta);
 
 
 	// LLViewerVisualParam Virtual functions
@@ -190,7 +194,9 @@ class LLTexLayerParamColor : public LLTexLayerParam
 	// New functions
 	LLColor4				getNetColor() const;
 protected:
-	virtual void onGlobalColorChanged(bool upload_bake) {}
+	LLTexLayerParamColor(const LLTexLayerParamColor& pOther);
+
+	virtual void onGlobalColorChanged() {}
 private:
 	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);
 } LL_ALIGN_POSTFIX(16);
diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
index cc81bcf118a2a964d9a40feb556c400eed2cdf99..af8394b60ce9209fe92bde53ec38a2e55c18fbe7 100644
--- a/indra/llappearance/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -123,6 +123,22 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
 // LLViewerVisualParam()
 //-----------------------------------------------------------------------------
 LLViewerVisualParam::LLViewerVisualParam()
+	: LLVisualParam()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::LLViewerVisualParam(const LLViewerVisualParam& pOther)
+	: LLVisualParam(pOther)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::~LLViewerVisualParam()
 {
 }
 
@@ -137,7 +153,7 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info)
 		return FALSE;
 	mInfo = info;
 	mID = info->mID;
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 	return TRUE;
 }
 
diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h
index 2826e6c31661b8877b57cbcb214bbbf4c8083385..1a710c0ca691b21a6e5b9ac449bce76e4904d756 100644
--- a/indra/llappearance/llviewervisualparam.h
+++ b/indra/llappearance/llviewervisualparam.h
@@ -70,7 +70,7 @@ class LLViewerVisualParam : public LLVisualParam
 {
 public:
 	LLViewerVisualParam();
-	/*virtual*/ ~LLViewerVisualParam(){};
+	virtual ~LLViewerVisualParam();
 
 	// Special: These functions are overridden by child classes
 	LLViewerVisualParamInfo 	*getInfo() const { return (LLViewerVisualParamInfo*)mInfo; };
@@ -105,6 +105,8 @@ class LLViewerVisualParam : public LLVisualParam
 
 	BOOL				getCrossWearable() const 	{ return getInfo()->mCrossWearable; }
 
+protected:
+	LLViewerVisualParam(const LLViewerVisualParam& pOther);
 } LL_ALIGN_POSTFIX(16);
 
 #endif // LL_LLViewerVisualParam_H
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
old mode 100644
new mode 100755
index 389505fa3449e035057ed662d5ab45021d8d76bc..4bce3f99ed8fd4719c2becf083aa661b2bc8f9a4
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -43,9 +43,32 @@ S32 LLWearable::sCurrentDefinitionVersion = 1;
 // Private local functions
 static std::string terse_F32_to_string(F32 f);
 
+LLWearable::LLWearable()
+	: mDefinitionVersion(-1),
+	mName(),
+	mDescription(),
+	mPermissions(),
+	mSaleInfo(),
+	mType(LLWearableType::WT_NONE),
+	mSavedVisualParamMap(),
+	mVisualParamIndexMap(),
+	mTEMap(),
+	mSavedTEMap()
+{
+}
+
 // virtual
 LLWearable::~LLWearable()
 {
+	for (visual_param_index_map_t::iterator vpIter = mVisualParamIndexMap.begin(); vpIter != mVisualParamIndexMap.end(); ++vpIter)
+	{
+		LLVisualParam* vp = vpIter->second;
+		vp->clearNextParam();
+		delete vp;
+		vpIter->second = NULL;
+	}
+
+	destroyTextures();
 }
 
 const std::string& LLWearable::getTypeLabel() const
@@ -525,7 +548,7 @@ void LLWearable::revertValues()
 		LLVisualParam *param = getVisualParam(id);
 		if(param &&  !dynamic_cast<LLDriverParam*>(param) )
 		{
-			setVisualParamWeight(id, value, TRUE);
+			setVisualParamWeight(id, value);
 		}
 	}
 
@@ -537,7 +560,7 @@ void LLWearable::revertValues()
 		LLVisualParam *param = getVisualParam(id);
 		if(param &&  dynamic_cast<LLDriverParam*>(param) )
 		{
-			setVisualParamWeight(id, value, TRUE);
+			setVisualParamWeight(id, value);
 		}
 	}
 
@@ -620,17 +643,10 @@ void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
 
 void LLWearable::destroyTextures()
 {
-	for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
+	std::for_each(mTEMap.begin(), mTEMap.end(), DeletePairedPointer());
 	mTEMap.clear();
-	for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
+
+	std::for_each(mSavedTEMap.begin(), mSavedTEMap.end(), DeletePairedPointer());
 	mSavedTEMap.clear();
 }
 
@@ -647,12 +663,12 @@ void LLWearable::addVisualParam(LLVisualParam *param)
 }
 
 
-void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake)
+void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
 {
 	if( is_in_map(mVisualParamIndexMap, param_index ) )
 	{
 		LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
-		wearable_param->setWeight(value, upload_bake);
+		wearable_param->setWeight(value);
 	}
 	else
 	{
@@ -693,14 +709,14 @@ void LLWearable::getVisualParams(visual_param_vec_t &list)
 	}
 }
 
-void LLWearable::animateParams(F32 delta, BOOL upload_bake)
+void LLWearable::animateParams(F32 delta)
 {
 	for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
 		 iter != mVisualParamIndexMap.end();
 		 ++iter)
 	{
 		LLVisualParam *param = (LLVisualParam*) iter->second;
-		param->animate(delta, upload_bake);
+		param->animate(delta);
 	}
 }
 
@@ -718,14 +734,14 @@ LLColor4 LLWearable::getClothesColor(S32 te) const
 	return color;
 }
 
-void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake )
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color)
 {
 	U32 param_name[3];
 	if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) )
 	{
 		for( U8 index = 0; index < 3; index++ )
 		{
-			setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake);
+			setVisualParamWeight(param_name[index], new_color.mV[index]);
 		}
 	}
 }
@@ -744,7 +760,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
 			S32 param_id = param->getID();
 			F32 weight = getVisualParamWeight(param_id);
 
-			avatarp->setVisualParamWeight( param_id, weight, FALSE );
+			avatarp->setVisualParamWeight( param_id, weight);
 		}
 	}
 }
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
old mode 100644
new mode 100755
index 132c153bcdb5c1515648391d9476b4b17b26043c..406fc7e88349c386a13781dedb3dbd84f7eae87f
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -46,6 +46,7 @@ class LLWearable
 	// Constructors and destructors
 	//--------------------------------------------------------------------
 public:
+	LLWearable();
 	virtual ~LLWearable();
 
 	//--------------------------------------------------------------------
@@ -94,14 +95,14 @@ class LLWearable
 
 	void				setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
 	void				addVisualParam(LLVisualParam *param);
-	void 				setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
+	void 				setVisualParamWeight(S32 index, F32 value);
 	F32					getVisualParamWeight(S32 index) const;
 	LLVisualParam*		getVisualParam(S32 index) const;
 	void				getVisualParams(visual_param_vec_t &list);
-	void				animateParams(F32 delta, BOOL upload_bake);
+	void				animateParams(F32 delta);
 
 	LLColor4			getClothesColor(S32 te) const;
-	void 				setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
+	void 				setClothesColor( S32 te, const LLColor4& new_color);
 
 	virtual void		revertValues();
 	virtual void		saveValues();
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
old mode 100644
new mode 100755
index 089370dbc45995896459d6f904bf80c02a36c93a..cf1ee435a890f22db7adaaf822be92bf1594f6a0
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -119,13 +119,6 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
 void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
 {
 	wearable->setUpdated();
-	// FIXME DRANO avoid updating params via wearables when rendering server-baked appearance.
-#if 0
-	if (mAvatarAppearance->isUsingServerBakes() && !mAvatarAppearance->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
 	if (!removed)
 	{
 		pullCrossWearableValues(wearable->getType());
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 82ddfa01ecf92222a7f8d9377f62355dc207d4f5..4df975ecc5d425ec4e0af8387b9efd2b9290a121 100755
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -287,13 +287,13 @@ void LLCharacter::removeAnimationData(std::string name)
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight)
 {
 	S32 index = which_param->getID();
 	visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
 	if (index_iter != mVisualParamIndexMap.end())
 	{
-		index_iter->second->setWeight(weight, upload_bake);
+		index_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	return FALSE;
@@ -302,7 +302,7 @@ BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 wei
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight)
 {
 	std::string tname(param_name);
 	LLStringUtil::toLower(tname);
@@ -310,7 +310,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
 	visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
 	if (name_iter != mVisualParamNameMap.end())
 	{
-		name_iter->second->setWeight(weight, upload_bake);
+		name_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	LL_WARNS() << "LLCharacter::setVisualParamWeight() Invalid visual parameter: " << param_name << LL_ENDL;
@@ -320,12 +320,12 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight)
 {
 	visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
 	if (index_iter != mVisualParamIndexMap.end())
 	{
-		index_iter->second->setWeight(weight, upload_bake);
+		index_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	LL_WARNS() << "LLCharacter::setVisualParamWeight() Invalid visual parameter index: " << index << LL_ENDL;
@@ -395,7 +395,7 @@ void LLCharacter::clearVisualParamWeights()
 	{
 		if (param->isTweakable())
 		{
-			param->setWeight( param->getDefaultWeight(), FALSE );
+			param->setWeight( param->getDefaultWeight());
 		}
 	}
 }
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index b10a8a5f34a99bf4a35631aa1bbb6eba8327d9e1..d4e3b763865d211f036e38fa166237ab794e2ca6 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -190,9 +190,9 @@ class LLCharacter
 	void addVisualParam(LLVisualParam *param);
 	void addSharedVisualParam(LLVisualParam *param);
 
-	virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
-	virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
-	virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+	virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
+	virtual BOOL setVisualParamWeight(const char* param_name, F32 weight);
+	virtual BOOL setVisualParamWeight(S32 index, F32 weight);
 
 	// get visual param weight by param or name
 	F32 getVisualParamWeight(LLVisualParam *distortion);
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 1492cc172cf97e959917d6d87d221bbae23b413c..dbd6d48a95fbf22ac1ba0be98a7e0374b8a86e4e 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -48,8 +48,11 @@ void LLJoint::init()
 	mParent = NULL;
 	mXform.setScaleChildOffset(TRUE);
 	mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
+	mOldXform.setScaleChildOffset(TRUE);
+	mOldXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
 	mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
 	mUpdateXform = TRUE;
+	mResetAfterRestoreOldXform = false;	
 }
 
 LLJoint::LLJoint() :
@@ -57,7 +60,6 @@ LLJoint::LLJoint() :
 {
 	init();
 	touch();
-	mResetAfterRestoreOldXform = false;
 }
 
 LLJoint::LLJoint(S32 joint_num) :
@@ -65,7 +67,6 @@ LLJoint::LLJoint(S32 joint_num) :
 {
 	init();
 	touch();
-	mResetAfterRestoreOldXform = false;
 }
 
 
@@ -78,7 +79,6 @@ LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
 {
 	init();
 	mUpdateXform = FALSE;
-	// *TODO: mResetAfterRestoreOldXform is not initialized!!!
 
 	setName(name);
 	if (parent)
@@ -239,11 +239,8 @@ const LLVector3& LLJoint::getPosition()
 //--------------------------------------------------------------------
 void LLJoint::setPosition( const LLVector3& pos )
 {
-//	if (mXform.getPosition() != pos)
-	{
-		mXform.setPosition(pos);
-		touch(MATRIX_DIRTY | POSITION_DIRTY);
-	}
+	mXform.setPosition(pos);
+	touch(MATRIX_DIRTY | POSITION_DIRTY);
 }
 
 
@@ -251,38 +248,37 @@ void LLJoint::setPosition( const LLVector3& pos )
 // setPosition()
 //--------------------------------------------------------------------
 void LLJoint::setDefaultFromCurrentXform( void )
-{
+{		
 	mDefaultXform = mXform;
-	touch(MATRIX_DIRTY | POSITION_DIRTY);
-	
 }
 
 //--------------------------------------------------------------------
 // storeCurrentXform()
 //--------------------------------------------------------------------
 void LLJoint::storeCurrentXform( const LLVector3& pos )
-{
+{	
 	mOldXform = mXform;
-	mResetAfterRestoreOldXform = true;
+	mResetAfterRestoreOldXform = true;	
 	setPosition( pos );
+	touch(ALL_DIRTY);	
 }
+
 //--------------------------------------------------------------------
-// restoreOldXform()
+// storeScaleForReset()
 //--------------------------------------------------------------------
-void LLJoint::restoreOldXform( void )
+void LLJoint::storeScaleForReset( const LLVector3& scale )
 {
-	mResetAfterRestoreOldXform = false;
-	mXform = mOldXform;
+	mOldXform.setScale( scale );
 }
 //--------------------------------------------------------------------
 // restoreOldXform()
 //--------------------------------------------------------------------
-void LLJoint::restoreToDefaultXform( void )
+void LLJoint::restoreOldXform( void )
 {	
 	mXform = mDefaultXform;
-	setPosition( mXform.getPosition() );	
+	mResetAfterRestoreOldXform = false;
+	mDirtyFlags = ALL_DIRTY;	
 }
-
 //--------------------------------------------------------------------
 // getWorldPosition()
 //--------------------------------------------------------------------
@@ -299,8 +295,6 @@ LLVector3 LLJoint::getLastWorldPosition()
 {
 	return mXform.getWorldPosition();
 }
-
-
 //--------------------------------------------------------------------
 // setWorldPosition()
 //--------------------------------------------------------------------
@@ -404,7 +398,7 @@ void LLJoint::setWorldRotation( const LLQuaternion& rot )
 //--------------------------------------------------------------------
 const LLVector3& LLJoint::getScale()
 {
-	return mXform.getScale();
+	return mXform.getScale();	
 }
 
 //--------------------------------------------------------------------
@@ -413,7 +407,7 @@ const LLVector3& LLJoint::getScale()
 void LLJoint::setScale( const LLVector3& scale )
 {
 //	if (mXform.getScale() != scale)
-	{
+	{	
 		mXform.setScale(scale);
 		touch();
 	}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 6efa13aeb55592e6986332355514c259a7e2fed5..b65d6979d4ab72f8d5abafe45d80c0690ee8faf1 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -83,6 +83,7 @@ class LLJoint
 	LLXformMatrix		mDefaultXform;
 
 	LLUUID				mId;
+
 public:
 	U32				mDirtyFlags;
 	BOOL			mUpdateXform;
@@ -159,7 +160,7 @@ class LLJoint
 	// get/set local scale
 	const LLVector3& getScale();
 	void setScale( const LLVector3& scale );
-
+	void storeScaleForReset( const LLVector3& scale );
 	// get/set world matrix
 	const LLMatrix4 &getWorldMatrix();
 	void setWorldMatrix( const LLMatrix4& mat );
@@ -184,7 +185,6 @@ class LLJoint
 	S32 getJointNum() const { return mJointNum; }
 	
 	void restoreOldXform( void );
-	void restoreToDefaultXform( void );
 	void setDefaultFromCurrentXform( void );
 	void storeCurrentXform( const LLVector3& pos );
 
@@ -195,8 +195,8 @@ class LLJoint
 
 	//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
 	const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
-	//Setter for joint reset flag
-	void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
+	void setJointResetFlag( bool val ) { mResetAfterRestoreOldXform = val; }
+	
 };
 #endif // LL_LLJOINT_H
 
diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 50ccfd75fbc9bad63285ea44f34cb3c28b8a4d41..e02b139608fc6cb2abd04b86dff83b645591cce8 100755
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -172,6 +172,13 @@ void LLMotionController::deleteAllMotions()
 
 	for_each(mAllMotions.begin(), mAllMotions.end(), DeletePairedPointer());
 	mAllMotions.clear();
+
+	// stinson 05/12/20014 : Ownership of the LLMotion pointers is transferred from
+	// mAllMotions to mDeprecatedMotions in method
+	// LLMotionController::deprecateMotionInstance().  Thus, we should also clean
+	// up the mDeprecatedMotions list as well.
+	for_each(mDeprecatedMotions.begin(), mDeprecatedMotions.end(), DeletePointer());
+	mDeprecatedMotions.clear();
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 0df7fb2bc3c73b9784e452bc2b037bc601064363..2235496ac5f411882df6cf387887ea9755447eb2 100755
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -159,26 +159,42 @@ void LLVisualParamInfo::toStream(std::ostream &out)
 //-----------------------------------------------------------------------------
 // LLVisualParam()
 //-----------------------------------------------------------------------------
-LLVisualParam::LLVisualParam()	
-	:
-	mCurWeight( 0.f ),
+LLVisualParam::LLVisualParam()
+	: mCurWeight( 0.f ),
 	mLastWeight( 0.f ),
 	mNext( NULL ),
 	mTargetWeight( 0.f ),
 	mIsAnimating( FALSE ),
+	mIsDummy(FALSE),
 	mID( -1 ),
 	mInfo( 0 ),
-	mIsDummy(FALSE),
 	mParamLocation(LOC_UNKNOWN)
 {
 }
 
+//-----------------------------------------------------------------------------
+// LLVisualParam()
+//-----------------------------------------------------------------------------
+LLVisualParam::LLVisualParam(const LLVisualParam& pOther)
+	: mCurWeight(pOther.mCurWeight),
+	mLastWeight(pOther.mLastWeight),
+	mNext(pOther.mNext),
+	mTargetWeight(pOther.mTargetWeight),
+	mIsAnimating(pOther.mIsAnimating),
+	mIsDummy(pOther.mIsDummy),
+	mID(pOther.mID),
+	mInfo(pOther.mInfo),
+	mParamLocation(pOther.mParamLocation)
+{
+}
+
 //-----------------------------------------------------------------------------
 // ~LLVisualParam()
 //-----------------------------------------------------------------------------
 LLVisualParam::~LLVisualParam()
 {
 	delete mNext;
+	mNext = NULL;
 }
 
 /*
@@ -220,7 +236,7 @@ BOOL LLVisualParam::parseData(LLXmlTreeNode *node)
 //-----------------------------------------------------------------------------
 // setWeight()
 //-----------------------------------------------------------------------------
-void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
+void LLVisualParam::setWeight(F32 weight)
 {
 	if (mIsAnimating)
 	{
@@ -238,19 +254,19 @@ void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
 	
 	if (mNext)
 	{
-		mNext->setWeight(weight, upload_bake);
+		mNext->setWeight(weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // setAnimationTarget()
 //-----------------------------------------------------------------------------
-void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLVisualParam::setAnimationTarget(F32 target_value)
 {
 	// don't animate dummy parameters
 	if (mIsDummy)
 	{
-		setWeight(target_value, upload_bake);
+		setWeight(target_value);
 		mTargetWeight = mCurWeight;
 		return;
 	}
@@ -270,7 +286,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
 
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
@@ -284,27 +300,35 @@ void LLVisualParam::setNextParam( LLVisualParam *next )
 	mNext = next;
 }
 
+//-----------------------------------------------------------------------------
+// clearNextParam()
+//-----------------------------------------------------------------------------
+void LLVisualParam::clearNextParam()
+{
+	mNext = NULL;
+}
+
 //-----------------------------------------------------------------------------
 // animate()
 //-----------------------------------------------------------------------------
-void LLVisualParam::animate( F32 delta, BOOL upload_bake )
+void LLVisualParam::animate( F32 delta)
 {
 	if (mIsAnimating)
 	{
 		F32 new_weight = ((mTargetWeight - mCurWeight) * delta) + mCurWeight;
-		setWeight(new_weight, upload_bake);
+		setWeight(new_weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // stopAnimating()
 //-----------------------------------------------------------------------------
-void LLVisualParam::stopAnimating(BOOL upload_bake)
+void LLVisualParam::stopAnimating()
 { 
 	if (mIsAnimating && isTweakable())
 	{
 		mIsAnimating = FALSE; 
-		setWeight(mTargetWeight, upload_bake);
+		setWeight(mTargetWeight);
 	}
 }
 
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index a4d9f93e56f78b5fb3f8f6f970e6a62fa6ca64a7..c6b97d7e8b4f18f0a0fddc2eb80ef09c6bf59c56 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -120,10 +120,10 @@ class LLVisualParam
 	//virtual BOOL			parseData( LLXmlTreeNode *node ) = 0;
 	virtual void			apply( ESex avatar_sex ) = 0;
 	//  Default functions
-	virtual void			setWeight(F32 weight, BOOL upload_bake);
-	virtual void			setAnimationTarget( F32 target_value, BOOL upload_bake );
-	virtual void			animate(F32 delta, BOOL upload_bake);
-	virtual void			stopAnimating(BOOL upload_bake);
+	virtual void			setWeight(F32 weight);
+	virtual void			setAnimationTarget( F32 target_value);
+	virtual void			animate(F32 delta);
+	virtual void			stopAnimating();
 
 	virtual BOOL			linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
 	virtual void			resetDrivenParams();
@@ -155,6 +155,7 @@ class LLVisualParam
 
 	LLVisualParam*			getNextParam()		{ return mNext; }
 	void					setNextParam( LLVisualParam *next );
+	void					clearNextParam();
 	
 	virtual void			setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
 	BOOL					getAnimating() const { return mIsAnimating; }
@@ -165,6 +166,8 @@ class LLVisualParam
 	EParamLocation			getParamLocation() const { return mParamLocation; }
 
 protected:
+	LLVisualParam(const LLVisualParam& pOther);
+
 	F32					mCurWeight;			// current weight
 	F32					mLastWeight;		// last weight
 	LLVisualParam*		mNext;				// next param in a shared chain
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5856e06b67510e9686a0eeaefa07ece22a094cf4..8eeb1869361dc06977aaef841097b226c9886589 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -158,7 +158,6 @@ set(llcommon_HEADER_FILES
     llhandle.h
     llhash.h
     llheartbeat.h
-    llhttpstatuscodes.h
     llindexedvector.h
     llinitparam.h
     llinstancetracker.h
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index a7963174adde80b2e2541b5103998b8ca130734c..22cd861c72ff11f382865e92f86e163e53ad2949 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -47,6 +47,7 @@
 #include "lllivefile.h"
 #include "llsd.h"
 #include "llsdserialize.h"
+#include "llsingleton.h"
 #include "llstl.h"
 #include "lltimer.h"
 
@@ -356,30 +357,31 @@ namespace
 
 
 	typedef std::map<std::string, LLError::ELevel> LevelMap;
-	typedef std::vector<LLError::Recorder*> Recorders;
+	typedef std::vector<LLError::RecorderPtr> Recorders;
 	typedef std::vector<LLError::CallSite*> CallSiteVector;
 
-	class Globals
+	class Globals : public LLSingleton<Globals>
 	{
 	public:
+		Globals();
+
 		std::ostringstream messageStream;
 		bool messageStreamInUse;
 
 		void addCallSite(LLError::CallSite&);
 		void invalidateCallSites();
-		
-		static Globals& get();
-			// return the one instance of the globals
 
 	private:
 		CallSiteVector callSites;
-
-		Globals()
-			:	messageStreamInUse(false)
-			{ }
-		
 	};
 
+	Globals::Globals()
+		: messageStream(),
+		messageStreamInUse(false),
+		callSites()
+	{
+	}
+
 	void Globals::addCallSite(LLError::CallSite& site)
 	{
 		callSites.push_back(&site);
@@ -396,25 +398,17 @@ namespace
 		
 		callSites.clear();
 	}
-
-	Globals& Globals::get()
-	{
-		/* This pattern, of returning a reference to a static function
-		   variable, is to ensure that this global is constructed before
-		   it is used, no matter what the global initialization sequence
-		   is.
-		   See C++ FAQ Lite, sections 10.12 through 10.14
-		*/
-		static Globals* globals = new Globals;		
-		return *globals;
-	}
 }
 
 namespace LLError
 {
-	class Settings
+	class SettingsConfig : public LLRefCount
 	{
+		friend class Settings;
+
 	public:
+		virtual ~SettingsConfig();
+
 		bool                                mPrintLocation;
 
 		LLError::ELevel                     mDefaultLevel;
@@ -429,81 +423,86 @@ namespace LLError
 		LLError::TimeFunction               mTimeFunction;
 		
 		Recorders                           mRecorders;
-		Recorder*                           mFileRecorder;
-		Recorder*                           mFixedBufferRecorder;
+		RecorderPtr                         mFileRecorder;
+		RecorderPtr                         mFixedBufferRecorder;
 		std::string                         mFileRecorderFileName;
 		
 		int									mShouldLogCallCounter;
 		
-		static Settings& get();
+	private:
+		SettingsConfig();
+	};
+
+	typedef LLPointer<SettingsConfig> SettingsConfigPtr;
+
+	class Settings : public LLSingleton<Settings>
+	{
+	public:
+		Settings();
+
+		SettingsConfigPtr getSettingsConfig();
 	
-		static void reset();
-		static Settings* saveAndReset();
-		static void restore(Settings*);
+		void reset();
+		SettingsStoragePtr saveAndReset();
+		void restore(SettingsStoragePtr pSettingsStorage);
 		
 	private:
-		Settings()
-		:	mPrintLocation(false),
-			mDefaultLevel(LLError::LEVEL_DEBUG),
-			mCrashFunction(),
-			mTimeFunction(NULL),
-			mFileRecorder(NULL),
-			mFixedBufferRecorder(NULL),
-			mShouldLogCallCounter(0)
-			{ }
-		
-		~Settings()
-		{
-			for_each(mRecorders.begin(), mRecorders.end(), DeletePointer());
-			mRecorders.clear();
-		}
-		
-		static Settings*& getPtr();
+		SettingsConfigPtr mSettingsConfig;
 	};
 	
-	Settings& Settings::get()
+	SettingsConfig::SettingsConfig()
+		: LLRefCount(),
+		mPrintLocation(false),
+		mDefaultLevel(LLError::LEVEL_DEBUG),
+		mFunctionLevelMap(),
+		mClassLevelMap(),
+		mFileLevelMap(),
+		mTagLevelMap(),
+		mUniqueLogMessages(),
+		mCrashFunction(NULL),
+		mTimeFunction(NULL),
+		mRecorders(),
+		mFileRecorder(),
+		mFixedBufferRecorder(),
+		mFileRecorderFileName(),
+		mShouldLogCallCounter(0)
 	{
-		Settings* p = getPtr();
-		if (!p)
-		{
-			reset();
-			p = getPtr();
-		}
-		return *p;
 	}
-	
-	void Settings::reset()
+
+	SettingsConfig::~SettingsConfig()
 	{
-		Globals::get().invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		delete p;
-		p = new Settings();
+		mRecorders.clear();
+	}
+
+	Settings::Settings()
+		: LLSingleton<Settings>(),
+		mSettingsConfig(new SettingsConfig())
+	{
+	}
+
+	SettingsConfigPtr Settings::getSettingsConfig()
+	{
+		return mSettingsConfig;
 	}
 	
-	Settings* Settings::saveAndReset()
+	void Settings::reset()
 	{
-		Globals::get().invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		Settings* originalSettings = p;
-		p = new Settings();
-		return originalSettings;
+		Globals::getInstance()->invalidateCallSites();
+		mSettingsConfig = new SettingsConfig();
 	}
 	
-	void Settings::restore(Settings* originalSettings)
+	SettingsStoragePtr Settings::saveAndReset()
 	{
-		Globals::get().invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		delete p;
-		p = originalSettings;
+		SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
+		reset();
+		return oldSettingsConfig;
 	}
 	
-	Settings*& Settings::getPtr()
+	void Settings::restore(SettingsStoragePtr pSettingsStorage)
 	{
-		static Settings* currentSettings = NULL;
-		return currentSettings;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
+		mSettingsConfig = newSettingsConfig;
 	}
 }
 
@@ -604,7 +603,7 @@ namespace
 	
 	void commonInit(const std::string& dir, bool log_to_stderr = true)
 	{
-		LLError::Settings::reset();
+		LLError::Settings::getInstance()->reset();
 		
 		LLError::setDefaultLevel(LLError::LEVEL_INFO);
 		LLError::setFatalFunction(LLError::crashAndLoop);
@@ -613,11 +612,13 @@ namespace
 		// log_to_stderr is only false in the unit and integration tests to keep builds quieter
 		if (log_to_stderr && shouldLogToStderr())
 		{
-			LLError::addRecorder(new RecordToStderr(stderrLogWantsTime()));
+			LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime()));
+			LLError::addRecorder(recordToStdErr);
 		}
 		
 #if LL_WINDOWS
-		LLError::addRecorder(new RecordToWinDebug);
+		LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
+		LLError::addRecorder(recordToWinDebug);
 #endif
 
 		LogControlFile& e = LogControlFile::fromDirectory(dir);
@@ -645,7 +646,8 @@ namespace LLError
 		}
 		commonInit(dir);
 #if !LL_WINDOWS
-		addRecorder(new RecordToSyslog(identity));
+		LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity));
+		addRecorder(recordToSyslog);
 #endif
 	}
 
@@ -656,72 +658,67 @@ namespace LLError
 
 	void setPrintLocation(bool print)
 	{
-		Settings& s = Settings::get();
-		s.mPrintLocation = print;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mPrintLocation = print;
 	}
 
 	void setFatalFunction(const FatalFunction& f)
 	{
-		Settings& s = Settings::get();
-		s.mCrashFunction = f;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mCrashFunction = f;
 	}
 
     FatalFunction getFatalFunction()
     {
-        Settings& s = Settings::get();
-        return s.mCrashFunction;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+        return s->mCrashFunction;
     }
 
 	void setTimeFunction(TimeFunction f)
 	{
-		Settings& s = Settings::get();
-		s.mTimeFunction = f;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mTimeFunction = f;
 	}
 
 	void setDefaultLevel(ELevel level)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
-		g.invalidateCallSites();
-		s.mDefaultLevel = level;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mDefaultLevel = level;
 	}
 
 	ELevel getDefaultLevel()
 	{
-		Settings& s = Settings::get();
-		return s.mDefaultLevel;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mDefaultLevel;
 	}
 
 	void setFunctionLevel(const std::string& function_name, ELevel level)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
-		g.invalidateCallSites();
-		s.mFunctionLevelMap[function_name] = level;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mFunctionLevelMap[function_name] = level;
 	}
 
 	void setClassLevel(const std::string& class_name, ELevel level)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
-		g.invalidateCallSites();
-		s.mClassLevelMap[class_name] = level;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mClassLevelMap[class_name] = level;
 	}
 
 	void setFileLevel(const std::string& file_name, ELevel level)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
-		g.invalidateCallSites();
-		s.mFileLevelMap[file_name] = level;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mFileLevelMap[file_name] = level;
 	}
 
 	void setTagLevel(const std::string& tag_name, ELevel level)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
-		g.invalidateCallSites();
-		s.mTagLevelMap[tag_name] = level;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mTagLevelMap[tag_name] = level;
 	}
 
 	LLError::ELevel decodeLevel(std::string name)
@@ -765,15 +762,14 @@ namespace LLError
 {
 	void configure(const LLSD& config)
 	{
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		
-		g.invalidateCallSites();
-		s.mFunctionLevelMap.clear();
-		s.mClassLevelMap.clear();
-		s.mFileLevelMap.clear();
-		s.mTagLevelMap.clear();
-		s.mUniqueLogMessages.clear();
+		s->mFunctionLevelMap.clear();
+		s->mClassLevelMap.clear();
+		s->mFileLevelMap.clear();
+		s->mTagLevelMap.clear();
+		s->mUniqueLogMessages.clear();
 		
 		setPrintLocation(config["print-location"]);
 		setDefaultLevel(decodeLevel(config["default-level"]));
@@ -786,10 +782,10 @@ namespace LLError
 			
 			ELevel level = decodeLevel(entry["level"]);
 			
-			setLevels(s.mFunctionLevelMap,	entry["functions"],	level);
-			setLevels(s.mClassLevelMap,		entry["classes"],	level);
-			setLevels(s.mFileLevelMap,		entry["files"],		level);
-			setLevels(s.mTagLevelMap,		entry["tags"],		level);
+			setLevels(s->mFunctionLevelMap,	entry["functions"],	level);
+			setLevels(s->mClassLevelMap,	entry["classes"],	level);
+			setLevels(s->mFileLevelMap,		entry["files"],		level);
+			setLevels(s->mTagLevelMap,		entry["tags"],		level);
 		}
 	}
 }
@@ -803,10 +799,12 @@ namespace LLError
 		mWantsLevel(true),
 		mWantsLocation(false),
 		mWantsFunctionName(true)
-	{}
+	{
+	}
 
 	Recorder::~Recorder()
-		{ }
+	{
+	}
 
 	bool Recorder::wantsTime()
 	{ 
@@ -837,25 +835,25 @@ namespace LLError
 		return mWantsFunctionName;
 	}
 
-	void addRecorder(Recorder* recorder)
+	void addRecorder(RecorderPtr recorder)
 	{
-		if (recorder == NULL)
+		if (!recorder)
 		{
 			return;
 		}
-		Settings& s = Settings::get();
-		s.mRecorders.push_back(recorder);
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mRecorders.push_back(recorder);
 	}
 
-	void removeRecorder(Recorder* recorder)
+	void removeRecorder(RecorderPtr recorder)
 	{
-		if (recorder == NULL)
+		if (!recorder)
 		{
 			return;
 		}
-		Settings& s = Settings::get();
-		s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
-							s.mRecorders.end());
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
+							s->mRecorders.end());
 	}
 }
 
@@ -863,51 +861,47 @@ namespace LLError
 {
 	void logToFile(const std::string& file_name)
 	{
-		LLError::Settings& s = LLError::Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
-		removeRecorder(s.mFileRecorder);
-		delete s.mFileRecorder;
-		s.mFileRecorder = NULL;
-		s.mFileRecorderFileName.clear();
+		removeRecorder(s->mFileRecorder);
+		s->mFileRecorder.reset();
+		s->mFileRecorderFileName.clear();
 		
 		if (file_name.empty())
 		{
 			return;
 		}
 		
-		RecordToFile* f = new RecordToFile(file_name);
-		if (!f->okay())
+		RecorderPtr recordToFile(new RecordToFile(file_name));
+		if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())
 		{
-			delete f;
-			return;
+			s->mFileRecorderFileName = file_name;
+			s->mFileRecorder = recordToFile;
+			addRecorder(recordToFile);
 		}
-
-		s.mFileRecorderFileName = file_name;
-		s.mFileRecorder = f;
-		addRecorder(f);
 	}
 	
 	void logToFixedBuffer(LLLineBuffer* fixedBuffer)
 	{
-		LLError::Settings& s = LLError::Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
-		removeRecorder(s.mFixedBufferRecorder);
-		delete s.mFixedBufferRecorder;
-		s.mFixedBufferRecorder = NULL;
+		removeRecorder(s->mFixedBufferRecorder);
+		s->mFixedBufferRecorder.reset();
 		
 		if (!fixedBuffer)
 		{
 			return;
 		}
 		
-		s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
-		addRecorder(s.mFixedBufferRecorder);
+		RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
+		s->mFixedBufferRecorder = recordToFixedBuffer;
+		addRecorder(recordToFixedBuffer);
 	}
 
 	std::string logFileName()
 	{
-		LLError::Settings& s = LLError::Settings::get();
-		return s.mFileRecorderFileName;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mFileRecorderFileName;
 	}
 }
 
@@ -916,24 +910,24 @@ namespace
 	void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
 	{
 		LLError::ELevel level = site.mLevel;
-		LLError::Settings& s = LLError::Settings::get();
+		LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
 	
-		for (Recorders::const_iterator i = s.mRecorders.begin();
-			i != s.mRecorders.end();
+		for (Recorders::const_iterator i = s->mRecorders.begin();
+			i != s->mRecorders.end();
 			++i)
 		{
-			LLError::Recorder* r = *i;
+			LLError::RecorderPtr r = *i;
 			
 			std::ostringstream message_stream;
 
-			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
+			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
 			{
 				message_stream << site.mLocationString << " ";
 			}
 
-			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
+			if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
 			{
-				message_stream << s.mTimeFunction() << " ";
+				message_stream << s->mTimeFunction() << " ";
 			}
 
 			if (show_level && r->wantsLevel())
@@ -1060,10 +1054,9 @@ namespace LLError
 			return false;
 		}
 		
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		
-		s.mShouldLogCallCounter++;
+		s->mShouldLogCallCounter++;
 		
 		const std::string& class_name = className(site.mClassInfo);
 		std::string function_name = functionName(site.mFunction);
@@ -1077,21 +1070,21 @@ namespace LLError
 			function_name = class_name + "::" + function_name;
 		}
 
-		ELevel compareLevel = s.mDefaultLevel;
+		ELevel compareLevel = s->mDefaultLevel;
 
 		// The most specific match found will be used as the log level,
 		// since the computation short circuits.
 		// So, in increasing order of importance:
 		// Default < Tags < File < Class < Function
-		checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
-		|| checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
-		|| checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+		checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel)
+		|| checkLevelMap(s->mClassLevelMap, class_name, compareLevel)
+		|| checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
 		|| (site.mTagCount > 0
-			? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
+			? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
 			: false);
 
 		site.mCached = true;
-		g.addCallSite(site);
+		Globals::getInstance()->addCallSite(site);
 		return site.mShouldLog = site.mLevel >= compareLevel;
 	}
 
@@ -1101,12 +1094,12 @@ namespace LLError
 		LogLock lock;
 		if (lock.ok())
 		{
-			Globals& g = Globals::get();
+			Globals* g = Globals::getInstance();
 
-			if (!g.messageStreamInUse)
+			if (!g->messageStreamInUse)
 			{
-				g.messageStreamInUse = true;
-				return &g.messageStream;
+				g->messageStreamInUse = true;
+				return &g->messageStream;
 			}
 		}
 		
@@ -1131,13 +1124,12 @@ namespace LLError
 		   message[127] = '\0' ;
 	   }
 	   
-	   Globals& g = Globals::get();
-
-       if (out == &g.messageStream)
+	   Globals* g = Globals::getInstance();
+       if (out == &g->messageStream)
        {
-           g.messageStream.clear();
-           g.messageStream.str("");
-           g.messageStreamInUse = false;
+           g->messageStream.clear();
+           g->messageStream.str("");
+           g->messageStreamInUse = false;
        }
        else
        {
@@ -1154,15 +1146,15 @@ namespace LLError
 			return;
 		}
 		
-		Globals& g = Globals::get();
-		Settings& s = Settings::get();
+		Globals* g = Globals::getInstance();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
 		std::string message = out->str();
-		if (out == &g.messageStream)
+		if (out == &g->messageStream)
 		{
-			g.messageStream.clear();
-			g.messageStream.str("");
-			g.messageStreamInUse = false;
+			g->messageStream.clear();
+			g->messageStream.str("");
+			g->messageStreamInUse = false;
 		}
 		else
 		{
@@ -1178,8 +1170,8 @@ namespace LLError
 
 		if (site.mPrintOnce)
 		{
-			std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
-			if (messageIter != s.mUniqueLogMessages.end())
+			std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
+			if (messageIter != s->mUniqueLogMessages.end())
 			{
 				messageIter->second++;
 				unsigned int num_messages = messageIter->second;
@@ -1195,7 +1187,7 @@ namespace LLError
 			else 
 			{
 				message_stream << "ONCE: ";
-				s.mUniqueLogMessages[message] = 1;
+				s->mUniqueLogMessages[message] = 1;
 			}
 		}
 		
@@ -1203,23 +1195,23 @@ namespace LLError
 		
 		writeToRecorders(site, message_stream.str());
 		
-		if (site.mLevel == LEVEL_ERROR  &&  s.mCrashFunction)
+		if (site.mLevel == LEVEL_ERROR  &&  s->mCrashFunction)
 		{
-			s.mCrashFunction(message_stream.str());
+			s->mCrashFunction(message_stream.str());
 		}
 	}
 }
 
 namespace LLError
 {
-	Settings* saveAndResetSettings()
+	SettingsStoragePtr saveAndResetSettings()
 	{
-		return Settings::saveAndReset();
+		return Settings::getInstance()->saveAndReset();
 	}
 	
-	void restoreSettings(Settings* s)
+	void restoreSettings(SettingsStoragePtr pSettingsStorage)
 	{
-		return Settings::restore(s);
+		return Settings::getInstance()->restore(pSettingsStorage);
 	}
 
 	std::string removePrefix(std::string& s, const std::string& p)
@@ -1265,8 +1257,8 @@ namespace LLError
 
 	int shouldLogCallCount()
 	{
-		Settings& s = Settings::get();
-		return s.mShouldLogCallCounter;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mShouldLogCallCounter;
 	}
 
 #if LL_WINDOWS
@@ -1375,15 +1367,9 @@ namespace LLError
 #endif
 
 	//static
-   void LLCallStacks::push(const char* function, const int line)
+   void LLCallStacks::allocateStackBuffer()
    {
-	   CallStacksLogLock lock;
-       if (!lock.ok())
-       {
-           return;
-       }
-
-	   if(!sBuffer)
+	   if(sBuffer == NULL)
 	   {
 		   sBuffer = new char*[512] ;
 		   sBuffer[0] = new char[512 * 128] ;
@@ -1393,6 +1379,31 @@ namespace LLError
 		   }
 		   sIndex = 0 ;
 	   }
+   }
+
+   void LLCallStacks::freeStackBuffer()
+   {
+	   if(sBuffer != NULL)
+	   {
+		   delete [] sBuffer[0] ;
+		   delete [] sBuffer ;
+		   sBuffer = NULL ;
+	   }
+   }
+
+   //static
+   void LLCallStacks::push(const char* function, const int line)
+   {
+	   CallStacksLogLock lock;
+       if (!lock.ok())
+       {
+           return;
+       }
+
+	   if(sBuffer == NULL)
+	   {
+		   allocateStackBuffer();
+	   }
 
 	   if(sIndex > 511)
 	   {
@@ -1424,15 +1435,9 @@ namespace LLError
            return;
        }
 
-	   if(!sBuffer)
+	   if(sBuffer == NULL)
 	   {
-		   sBuffer = new char*[512] ;
-		   sBuffer[0] = new char[512 * 128] ;
-		   for(S32 i = 1 ; i < 512 ; i++)
-		   {
-			   sBuffer[i] = sBuffer[i-1] + 128 ;
-		   }
-		   sIndex = 0 ;
+		   allocateStackBuffer();
 	   }
 
 	   if(sIndex > 511)
@@ -1463,11 +1468,9 @@ namespace LLError
            LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
        }
 
-	   if(sBuffer)
+	   if(sBuffer != NULL)
 	   {
-		   delete[] sBuffer[0] ;
-		   delete[] sBuffer ;
-		   sBuffer = NULL ;
+		   freeStackBuffer();
 	   }
    }
 
@@ -1477,5 +1480,10 @@ namespace LLError
        sIndex = 0 ;
    }
 
+   //static
+   void LLCallStacks::cleanup()
+   {
+	   freeStackBuffer();
+   }
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index bc80e64423ba9ba5ab852ee6ff643c5a211de4b3..63040e1772a15b4a9239127df183e1b15a3a0df8 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -261,6 +261,9 @@ namespace LLError
    private:
        static char**  sBuffer ;
 	   static S32     sIndex ;
+
+	   static void allocateStackBuffer();
+	   static void freeStackBuffer();
           
    public:   
 	   static void push(const char* function, const int line) ;
@@ -268,6 +271,7 @@ namespace LLError
        static void print() ;
        static void clear() ;
 	   static void end(std::ostringstream* _out) ;
+	   static void cleanup();
    }; 
 }
 
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index aab695094c7d50ce9ad23fd318f4c19c10ce0a3b..56ac52e5de4edfbb8b5a17c8c34abf4bef779823 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -29,7 +29,10 @@
 #define LL_LLERRORCONTROL_H
 
 #include "llerror.h"
+#include "llpointer.h"
+#include "llrefcount.h"
 #include "boost/function.hpp"
+#include "boost/shared_ptr.hpp"
 #include <string>
 
 class LLSD;
@@ -156,16 +159,14 @@ namespace LLError
 				mWantsFunctionName;
 	};
 
+	typedef boost::shared_ptr<Recorder> RecorderPtr;
+
 	/**
-	 * @NOTE: addRecorder() conveys ownership to the underlying Settings
-	 * object -- when destroyed, it will @em delete the passed Recorder*!
-	 */
-	LL_COMMON_API void addRecorder(Recorder*);
-	/**
-	 * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its
-	 * lifespan becomes the caller's problem.
+	 * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
+	 * while still ensuring that the allocated memory is eventually freed
 	 */
-	LL_COMMON_API void removeRecorder(Recorder*);
+	LL_COMMON_API void addRecorder(RecorderPtr);
+	LL_COMMON_API void removeRecorder(RecorderPtr);
 		// each error message is passed to each recorder via recordMessage()
 
 	LL_COMMON_API void logToFile(const std::string& filename);
@@ -182,9 +183,9 @@ namespace LLError
 		Utilities for use by the unit tests of LLError itself.
 	*/
 
-	class Settings;
-	LL_COMMON_API Settings* saveAndResetSettings();
-	LL_COMMON_API void restoreSettings(Settings *);
+	typedef LLPointer<LLRefCount> SettingsStoragePtr;
+	LL_COMMON_API SettingsStoragePtr saveAndResetSettings();
+	LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);
 
 	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
 	LL_COMMON_API int shouldLogCallCount();
diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h
deleted file mode 100755
index 0173461dad3966ffc81b94225b7ef5d254f1617b..0000000000000000000000000000000000000000
--- a/indra/llcommon/llhttpstatuscodes.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/** 
- * @file llhttpstatuscodes.h
- * @brief Constants for HTTP status codes
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTP_STATUS_CODES_H
-#define LL_HTTP_STATUS_CODES_H
-
-#include "stdtypes.h"
-
-// Standard errors from HTTP spec:
-// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
-const S32 HTTP_CONTINUE = 100;
-const S32 HTTP_SWITCHING_PROTOCOLS = 101;
-
-// Success
-const S32 HTTP_OK = 200;
-const S32 HTTP_CREATED = 201;
-const S32 HTTP_ACCEPTED = 202;
-const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_RESET_CONTENT = 205;
-const S32 HTTP_PARTIAL_CONTENT = 206;
-
-// Redirection
-const S32 HTTP_MULTIPLE_CHOICES = 300;
-const S32 HTTP_MOVED_PERMANENTLY = 301;
-const S32 HTTP_FOUND = 302;
-const S32 HTTP_SEE_OTHER = 303;
-const S32 HTTP_NOT_MODIFIED = 304;
-const S32 HTTP_USE_PROXY = 305;
-const S32 HTTP_TEMPORARY_REDIRECT = 307;
-
-// Client Error
-const S32 HTTP_BAD_REQUEST = 400;
-const S32 HTTP_UNAUTHORIZED = 401;
-const S32 HTTP_PAYMENT_REQUIRED = 402;
-const S32 HTTP_FORBIDDEN = 403;
-const S32 HTTP_NOT_FOUND = 404;
-const S32 HTTP_METHOD_NOT_ALLOWED = 405;
-const S32 HTTP_NOT_ACCEPTABLE = 406;
-const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
-const S32 HTTP_REQUEST_TIME_OUT = 408;
-const S32 HTTP_CONFLICT = 409;
-const S32 HTTP_GONE = 410;
-const S32 HTTP_LENGTH_REQUIRED = 411;
-const S32 HTTP_PRECONDITION_FAILED = 412;
-const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
-const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
-const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
-const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
-const S32 HTTP_EXPECTATION_FAILED = 417;
-
-// Server Error
-const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
-const S32 HTTP_NOT_IMPLEMENTED = 501;
-const S32 HTTP_BAD_GATEWAY = 502;
-const S32 HTTP_SERVICE_UNAVAILABLE = 503;
-const S32 HTTP_GATEWAY_TIME_OUT = 504;
-const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
-
-// We combine internal process errors with status codes
-// These status codes should not be sent over the wire
-//   and indicate something went wrong internally.
-// If you get these they are not normal.
-const S32 HTTP_INTERNAL_ERROR = 499;
-
-#endif
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 25325663191cac0094207b80328fc7dec86ae31a..7aa87fcd0e70dc6442bcbd85f6dfefc866c5f88f 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -31,6 +31,7 @@
 #include <vector>
 #include <list>
 #include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/is_enum.hpp>
 #include <boost/unordered_map.hpp>
@@ -629,7 +630,7 @@ namespace LLInitParam
 		UserData*			mUserData;
 	};
 
-	typedef ParamDescriptor* ParamDescriptorPtr;
+	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
 
 	// each derived Block class keeps a static data structure maintaining offsets to various params
 	class LL_COMMON_API BlockDescriptor
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index c9ebc70d193f68831c145241b4dd5b0641b27221..9a6453ea482e9ecc97fd8fa027551e65b4be1443 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,6 +166,132 @@ template <class Type> class LLPointer
 	Type*	mPointer;
 };
 
+template <class Type> class LLConstPointer
+{
+public:
+	LLConstPointer() : 
+		mPointer(NULL)
+	{
+	}
+
+	LLConstPointer(const Type* ptr) : 
+		mPointer(ptr)
+	{
+		ref();
+	}
+
+	LLConstPointer(const LLConstPointer<Type>& ptr) : 
+		mPointer(ptr.mPointer)
+	{
+		ref();
+	}
+
+	// support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer(const LLConstPointer<Subclass>& ptr) : 
+		mPointer(ptr.get())
+	{
+		ref();
+	}
+
+	~LLConstPointer()
+	{
+		unref();
+	}
+
+	const Type*	get() const						{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }
+	const Type&	operator*() const				{ return *mPointer; }
+
+	operator BOOL()  const						{ return (mPointer != NULL); }
+	operator bool()  const						{ return (mPointer != NULL); }
+	bool operator!() const						{ return (mPointer == NULL); }
+	bool isNull() const							{ return (mPointer == NULL); }
+	bool notNull() const						{ return (mPointer != NULL); }
+
+	operator const Type*()       const			{ return mPointer; }
+	bool operator !=(const Type* ptr) const     { return (mPointer != ptr); 	}
+	bool operator ==(const Type* ptr) const     { return (mPointer == ptr); 	}
+	bool operator ==(const LLConstPointer<Type>& ptr) const           { return (mPointer == ptr.mPointer); 	}
+	bool operator < (const LLConstPointer<Type>& ptr) const           { return (mPointer < ptr.mPointer); 	}
+	bool operator > (const LLConstPointer<Type>& ptr) const           { return (mPointer > ptr.mPointer); 	}
+
+	LLConstPointer<Type>& operator =(const Type* ptr)                   
+	{
+		if( mPointer != ptr )
+		{
+			unref(); 
+			mPointer = ptr; 
+			ref();
+		}
+
+		return *this; 
+	}
+
+	LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)  
+	{ 
+		if( mPointer != ptr.mPointer )
+		{
+			unref(); 
+			mPointer = ptr.mPointer;
+			ref();
+		}
+		return *this; 
+	}
+
+	// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)  
+	{ 
+		if( mPointer != ptr.get() )
+		{
+			unref(); 
+			mPointer = ptr.get();
+			ref();
+		}
+		return *this; 
+	}
+	
+	// Just exchange the pointers, which will not change the reference counts.
+	static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
+	{
+		const Type* temp = a.mPointer;
+		a.mPointer = b.mPointer;
+		b.mPointer = temp;
+	}
+
+protected:
+#ifdef LL_LIBRARY_INCLUDE
+	void ref();                             
+	void unref();
+#else
+	void ref()                             
+	{ 
+		if (mPointer)
+		{
+			mPointer->ref();
+		}
+	}
+
+	void unref()
+	{
+		if (mPointer)
+		{
+			const Type *tempp = mPointer;
+			mPointer = NULL;
+			tempp->unref();
+			if (mPointer != NULL)
+			{
+				LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+				unref();
+			}
+		}
+	}
+#endif
+protected:
+	const Type*	mPointer;
+};
+
 template<typename Type>
 class LLCopyOnWritePointer : public LLPointer<Type>
 {
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index f9624852843c6a41cd6b35ede7cd4d03a69ff88b..d8bbb3a74fef0e47974b6e6825ed76f9b3c29bad 100755
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -126,7 +126,9 @@ class LLSD::Impl
 	virtual UUID	asUUID() const				{ return LLUUID(); }
 	virtual Date	asDate() const				{ return LLDate(); }
 	virtual URI		asURI() const				{ return LLURI(); }
-	virtual Binary	asBinary() const			{ return std::vector<U8>(); }
+	virtual const Binary&	asBinary() const	{ static const std::vector<U8> empty; return empty; }
+
+	virtual const String& asStringRef() const { static const std::string empty; return empty; } 
 	
 	virtual bool has(const String&) const		{ return false; }
 	virtual LLSD get(const String&) const		{ return LLSD(); }
@@ -270,6 +272,7 @@ namespace
 		virtual LLSD::Date		asDate() const	{ return LLDate(mValue); }
 		virtual LLSD::URI		asURI() const	{ return LLURI(mValue); }
 		virtual int				size() const	{ return mValue.size(); }
+		virtual const LLSD::String&	asStringRef() const { return mValue; }
 	};
 	
 	LLSD::Integer	ImplString::asInteger() const
@@ -348,7 +351,7 @@ namespace
 	public:
 		ImplBinary(const LLSD::Binary& v) : Base(v) { }
 				
-		virtual LLSD::Binary	asBinary() const{ return mValue; }
+		virtual const LLSD::Binary&	asBinary() const{ return mValue; }
 	};
 
 
@@ -840,7 +843,9 @@ LLSD::String	LLSD::asString() const	{ return safe(impl).asString(); }
 LLSD::UUID		LLSD::asUUID() const	{ return safe(impl).asUUID(); }
 LLSD::Date		LLSD::asDate() const	{ return safe(impl).asDate(); }
 LLSD::URI		LLSD::asURI() const		{ return safe(impl).asURI(); }
-LLSD::Binary	LLSD::asBinary() const	{ return safe(impl).asBinary(); }
+const LLSD::Binary&	LLSD::asBinary() const	{ return safe(impl).asBinary(); }
+
+const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
 
 // const char * helpers
 LLSD::LLSD(const char* v) : impl(0)		{ ALLOC_LLSD_OBJECT;	assign(v); }
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index deb87d74976fac998503de8c3365e2d5dd3f1cae..7b9b1285f59c1a3bda4c85de7c25585c84c67547 100755
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -249,7 +249,10 @@ class LL_COMMON_API LLSD
 		UUID	asUUID() const;
 		Date	asDate() const;
 		URI		asURI() const;
-		Binary	asBinary() const;
+		const Binary&	asBinary() const;
+
+		// asStringRef on any non-string type will return a ref to an empty string.
+		const String&	asStringRef() const;
 
 		operator Boolean() const	{ return asBoolean(); }
 		operator Integer() const	{ return asInteger(); }
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 04d7a6ed5674eb89cb648eac53838b2111f58e8d..b2add301f986e7187ec68927064be36b62d4796d 100755
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -873,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 {
 /**
  * Undefined: '!'<br>
- * Boolean: 't' for true 'f' for false<br>
+ * Boolean: '1' for true '0' for false<br>
  * Integer: 'i' + 4 bytes network byte order<br>
  * Real: 'r' + 8 bytes IEEE double<br>
  * UUID: 'u' + 16 byte unsigned integer<br>
@@ -1260,13 +1260,38 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in)
 
 // virtual
 S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
+{
+	S32 rv = format_impl(data, ostr, options, 0);
+	return rv;
+}
+
+S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const
 {
 	S32 format_count = 1;
+	std::string pre;
+	std::string post;
+
+	if (options & LLSDFormatter::OPTIONS_PRETTY)
+	{
+		for (U32 i = 0; i < level; i++)
+		{
+			pre += "    ";
+		}
+		post = "\n";
+	}
+
 	switch(data.type())
 	{
 	case LLSD::TypeMap:
 	{
+		if (0 != level) ostr << post << pre;
 		ostr << "{";
+		std::string inner_pre;
+		if (options & LLSDFormatter::OPTIONS_PRETTY)
+		{
+			inner_pre = pre + "    ";
+		}
+
 		bool need_comma = false;
 		LLSD::map_const_iterator iter = data.beginMap();
 		LLSD::map_const_iterator end = data.endMap();
@@ -1274,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 		{
 			if(need_comma) ostr << ",";
 			need_comma = true;
-			ostr << '\'';
+			ostr << post << inner_pre << '\'';
 			serialize_string((*iter).first, ostr);
 			ostr << "':";
-			format_count += format((*iter).second, ostr);
+			format_count += format_impl((*iter).second, ostr, options, level + 2);
 		}
-		ostr << "}";
+		ostr << post << pre << "}";
 		break;
 	}
 
 	case LLSD::TypeArray:
 	{
-		ostr << "[";
+		ostr << post << pre << "[";
 		bool need_comma = false;
 		LLSD::array_const_iterator iter = data.beginArray();
 		LLSD::array_const_iterator end = data.endArray();
@@ -1293,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 		{
 			if(need_comma) ostr << ",";
 			need_comma = true;
-			format_count += format(*iter, ostr);
+			format_count += format_impl(*iter, ostr, options, level + 1);
 		}
 		ostr << "]";
 		break;
@@ -1343,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 
 	case LLSD::TypeString:
 		ostr << '\'';
-		serialize_string(data.asString(), ostr);
+		serialize_string(data.asStringRef(), ostr);
 		ostr << '\'';
 		break;
 
@@ -1360,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 	case LLSD::TypeBinary:
 	{
 		// *FIX: memory inefficient.
-		std::vector<U8> buffer = data.asBinary();
+		const std::vector<U8>& buffer = data.asBinary();
 		ostr << "b(" << buffer.size() << ")\"";
-		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+		if(buffer.size())
+		{
+			if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY)
+			{
+				std::ios_base::fmtflags old_flags = ostr.flags();
+				ostr.setf( std::ios::hex, std::ios::basefield );
+				ostr << "0x";
+				for (int i = 0; i < buffer.size(); i++)
+				{
+					ostr << (int) buffer[i];
+				}
+				ostr.flags(old_flags);
+			}
+			else
+			{
+				ostr.write((const char*)&buffer[0], buffer.size());
+			}
+		}
 		ostr << "\"";
 		break;
 	}
@@ -1460,7 +1502,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
 
 	case LLSD::TypeString:
 		ostr.put('s');
-		formatString(data.asString(), ostr);
+		formatString(data.asStringRef(), ostr);
 		break;
 
 	case LLSD::TypeDate:
@@ -1478,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
 
 	case LLSD::TypeBinary:
 	{
-		// *FIX: memory inefficient.
 		ostr.put('b');
-		std::vector<U8> buffer = data.asBinary();
+		const std::vector<U8>& buffer = data.asBinary();
 		U32 size_nbo = htonl(buffer.size());
 		ostr.write((const char*)(&size_nbo), sizeof(U32));
 		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index e7a5507385c07bd0c05b42d2477336e04d6d3c1d..23a0c8cfb1e332ea0346517c1cec74d2e33514b9 100755
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -416,7 +416,8 @@ class LL_COMMON_API LLSDFormatter : public LLRefCount
 	typedef enum e_formatter_options_type
 	{
 		OPTIONS_NONE = 0,
-		OPTIONS_PRETTY = 1
+		OPTIONS_PRETTY = 1,
+		OPTIONS_PRETTY_BINARY = 2
 	} EFormatterOptions;
 
 	/** 
@@ -507,6 +508,17 @@ class LL_COMMON_API LLSDNotationFormatter : public LLSDFormatter
 	 * @return Returns The number of LLSD objects fomatted out
 	 */
 	virtual S32 format(const LLSD& data, std::ostream& ostr, U32 options = LLSDFormatter::OPTIONS_NONE) const;
+
+protected:
+
+	/** 
+	 * @brief Implementation to format the data. This is called recursively.
+	 *
+	 * @param data The data to write.
+	 * @param ostr The destination stream for the data.
+	 * @return Returns The number of LLSD objects fomatted out
+	 */
+	S32 format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const;
 };
 
 
@@ -634,7 +646,7 @@ class LL_COMMON_API LLSDBinaryFormatter : public LLSDFormatter
  *  </code>
  *
  * *NOTE - formerly this class inherited from its template parameter Formatter,
- * but all insnatiations passed in LLRefCount subclasses.  This conflicted with
+ * but all instantiations passed in LLRefCount subclasses.  This conflicted with
  * the auto allocation intended for this class template (demonstrated in the
  * example above).  -brad
  */
@@ -720,6 +732,18 @@ class LL_COMMON_API LLSDSerialize
 		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
 		return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
 	}
+	static S32 toPrettyNotation(const LLSD& sd, std::ostream& str)
+	{
+		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+		return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
+	}
+	static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str)
+	{
+		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+		return f->format(sd, str, 
+				LLSDFormatter::OPTIONS_PRETTY | 
+				LLSDFormatter::OPTIONS_PRETTY_BINARY);
+	}
 	static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes)
 	{
 		LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 4e2af0e5890ec181a167018ae24098800fa3f49e..e1a91f13675d23044ef2e1c6b7dc75220b36e4bd 100755
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -168,8 +168,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
 		break;
 
 	case LLSD::TypeString:
-		if(data.asString().empty()) ostr << pre << "<string />" << post;
-		else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post;
+		if(data.asStringRef().empty()) ostr << pre << "<string />" << post;
+		else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post;
 		break;
 
 	case LLSD::TypeDate:
@@ -182,7 +182,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
 
 	case LLSD::TypeBinary:
 	{
-		LLSD::Binary buffer = data.asBinary();
+		const LLSD::Binary& buffer = data.asBinary();
 		if(buffer.empty())
 		{
 			ostr << pre << "<binary />" << post;
@@ -375,13 +375,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
 		{
 			break;
 		}
+		count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
+		if (!count)
 		{
-		
-			count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
-			if (!count)
-			{
-				break;
-			}
+			break;
 		}
 		status = XML_ParseBuffer(mParser, count, false);
 
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 803417d368b899d81a9cc8c8aca09e925103a097..562fd26658e6e30346ef026e8c916222a8c8acd4 100755
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -182,7 +182,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd)
 
 char* ll_pretty_print_sd(const LLSD& sd)
 {
-	const U32 bufferSize = 10 * 1024;
+	const U32 bufferSize = 100 * 1024;
 	static char buffer[bufferSize];
 	std::ostringstream stream;
 	//stream.rdbuf()->pubsetbuf(buffer, bufferSize);
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 0699dcda83b8d66851278b3436bf6fc287d45506..dd8660a3c8dbc1275a5ae04724124b3becf7e593 100755
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -132,10 +132,14 @@ class LL_COMMON_API LLUUID
 };
 
 typedef std::vector<LLUUID> uuid_vec_t;
-
-
-// Helper structure for ordering lluuids in stl containers.
-// eg: 	std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+typedef std::set<LLUUID> uuid_set_t;
+
+// Helper structure for ordering lluuids in stl containers.  eg:
+// std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+//
+// (isn't this the default behavior anyway? I think we could
+// everywhere replace these with uuid_set_t, but someone should
+// verify.)
 struct lluuid_less
 {
 	bool operator()(const LLUUID& lhs, const LLUUID& rhs) const
@@ -145,7 +149,6 @@ struct lluuid_less
 };
 
 typedef std::set<LLUUID, lluuid_less> uuid_list_t;
-
 /*
  * Sub-classes for keeping transaction IDs and asset IDs
  * straight.
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index b28c5ba4b316cf7df77f2e36a2a8be78fd515e28..a5aaff10c55a70bf71e74de0126980271488ead0 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -56,9 +56,9 @@ namespace tut
 	{
 	public:
 		TestRecorder() { mWantsTime = false; }
-		~TestRecorder() { LLError::removeRecorder(this); }
+		virtual ~TestRecorder() {  }
 
-		void recordMessage(LLError::ELevel level,
+		virtual void recordMessage(LLError::ELevel level,
 						   const std::string& message)
 		{
 			mMessages.push_back(message);
@@ -85,15 +85,11 @@ namespace tut
 
 	struct ErrorTestData
 	{
-		// addRecorder() expects to be able to later delete the passed
-		// Recorder*. Even though removeRecorder() reclaims ownership, passing
-		// a pointer to a data member rather than a heap Recorder subclass
-		// instance would just be Wrong.
-		TestRecorder* mRecorder;
-		LLError::Settings* mPriorErrorSettings;
+		LLError::RecorderPtr mRecorder;
+		LLError::SettingsStoragePtr mPriorErrorSettings;
 
 		ErrorTestData():
-			mRecorder(new TestRecorder)
+			mRecorder(new TestRecorder())
 		{
 			fatalWasCalled = false;
 
@@ -106,13 +102,32 @@ namespace tut
 		~ErrorTestData()
 		{
 			LLError::removeRecorder(mRecorder);
-			delete mRecorder;
 			LLError::restoreSettings(mPriorErrorSettings);
 		}
 
+		int countMessages()
+		{
+			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages();
+		}
+
+		void clearMessages()
+		{
+			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages();
+		}
+
+		void setWantsTime(bool t)
+		{
+			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->setWantsTime(t);
+		}
+
+		std::string message(int n)
+		{
+			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n);
+		}
+
 		void ensure_message_count(int expectedCount)
 		{
-			ensure_equals("message count", mRecorder->countMessages(), expectedCount);
+			ensure_equals("message count", countMessages(), expectedCount);
 		}
 
 		void ensure_message_contains(int n, const std::string& expectedText)
@@ -120,7 +135,7 @@ namespace tut
 			std::ostringstream test_name;
 			test_name << "testing message " << n;
 
-			ensure_contains(test_name.str(), mRecorder->message(n), expectedText);
+			ensure_contains(test_name.str(), message(n), expectedText);
 		}
 
 		void ensure_message_does_not_contain(int n, const std::string& expectedText)
@@ -128,7 +143,7 @@ namespace tut
 			std::ostringstream test_name;
 			test_name << "testing message " << n;
 
-			ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText);
+			ensure_does_not_contain(test_name.str(), message(n), expectedText);
 		}
 	};
 
@@ -385,15 +400,15 @@ namespace
 	}
 
 	typedef std::string (*LogFromFunction)(bool);
-	void testLogName(tut::TestRecorder* recorder, LogFromFunction f,
+	void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,
 		const std::string& class_name = "")
 	{
-		recorder->clearMessages();
+		boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();
 		std::string name = f(false);
 		f(true);
 
-		std::string messageWithoutName = recorder->message(0);
-		std::string messageWithName = recorder->message(1);
+		std::string messageWithoutName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0);
+		std::string messageWithName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);
 
 		ensure_has(name + " logged without name",
 			messageWithoutName, name);
@@ -528,12 +543,12 @@ namespace tut
 	{
 		LLError::setTimeFunction(roswell);
 
-		mRecorder->setWantsTime(false);
+		setWantsTime(false);
 		ufoSighting();
 		ensure_message_contains(0, "ufo");
 		ensure_message_does_not_contain(0, roswell());
 
-		mRecorder->setWantsTime(true);
+		setWantsTime(true);
 		ufoSighting();
 		ensure_message_contains(1, "ufo");
 		ensure_message_contains(1, roswell());
@@ -545,13 +560,13 @@ namespace tut
 	{
 		LLError::setPrintLocation(true);
 		LLError::setTimeFunction(roswell);
-		mRecorder->setWantsTime(true);
+		setWantsTime(true);
 		std::string location,
 					function;
 		writeReturningLocationAndFunction(location, function);
 
 		ensure_equals("order is location time type function message",
-			mRecorder->message(0),
+			message(0),
 			location + roswell() + " INFO: " + function + ": apple");
 	}
 
@@ -559,19 +574,19 @@ namespace tut
 		// multiple recorders
 	void ErrorTestObject::test<11>()
 	{
-		TestRecorder* altRecorder(new TestRecorder);
+		LLError::RecorderPtr altRecorder(new TestRecorder());
 		LLError::addRecorder(altRecorder);
 
 		LL_INFOS() << "boo" << LL_ENDL;
 
 		ensure_message_contains(0, "boo");
-		ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
-		ensure_contains("alt recorder message 0", altRecorder->message(0), "boo");
+		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
+		ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
 
 		LLError::setTimeFunction(roswell);
 
-		TestRecorder* anotherRecorder(new TestRecorder);
-		anotherRecorder->setWantsTime(true);
+		LLError::RecorderPtr anotherRecorder(new TestRecorder());
+		boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->setWantsTime(true);
 		LLError::addRecorder(anotherRecorder);
 
 		LL_INFOS() << "baz" << LL_ENDL;
@@ -579,10 +594,13 @@ namespace tut
 		std::string when = roswell();
 
 		ensure_message_does_not_contain(1, when);
-		ensure_equals("alt recorder count", altRecorder->countMessages(), 2);
-		ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when);
-		ensure_equals("another recorder count", anotherRecorder->countMessages(), 1);
-		ensure_contains("another recorder message 0", anotherRecorder->message(0), when);
+		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2);
+		ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when);
+		ensure_equals("another recorder count", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1);
+		ensure_contains("another recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when);
+
+		LLError::removeRecorder(altRecorder);
+		LLError::removeRecorder(anotherRecorder);
 	}
 }
 
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 3e4ca548e55453284bf8b5ea5c6e80a5988ef156..2a4ed44a67505d88caeebcea0304e263bb629891 100755
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -95,7 +95,7 @@ namespace tut
         ensure_equals(stringize(f),    "3.14159");
         ensure_equals(stringize(d),    "3.14159");
         ensure_equals(stringize(abc),  "abc def");
-        ensure_equals(stringize(def),  "def ghi"); //Will generate llwarns due to narrowing.
+        ensure_equals(stringize(def),  "def ghi"); //Will generate LL_WARNS() due to narrowing.
         ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
     }
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 3137bd8fea9199445c9c51ce19cdd94fab655adc..785197ba111fda1139b6cfbda6494faee726ffd6 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -38,6 +38,7 @@
 #include "stringize.h"
 #include <boost/bind.hpp>
 #include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
 #include <list>
 #include <string>
 #include <stdexcept>
@@ -81,72 +82,29 @@ struct WrapLLErrs
     }
 
     std::string error;
-    LLError::Settings* mPriorErrorSettings;
+    LLError::SettingsStoragePtr mPriorErrorSettings;
     LLError::FatalFunction mPriorFatal;
 };
 
-/**
- * LLError::addRecorder() accepts ownership of the passed Recorder* -- it
- * expects to be able to delete it later. CaptureLog isa Recorder whose
- * pointer we want to be able to pass without any ownership implications.
- * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass
- * that. Your heap RecorderProxy might later be deleted, but not yourRecorder.
- */
-class RecorderProxy: public LLError::Recorder
-{
-public:
-    RecorderProxy(LLError::Recorder* recorder):
-        mRecorder(recorder)
-    {}
-
-    virtual void recordMessage(LLError::ELevel level, const std::string& message)
-    {
-        mRecorder->recordMessage(level, message);
-    }
-
-    virtual bool wantsTime()
-    {
-        return mRecorder->wantsTime();
-    }
-
-private:
-    LLError::Recorder* mRecorder;
-};
-
 /**
  * Capture log messages. This is adapted (simplified) from the one in
  * llerror_test.cpp.
  */
-class CaptureLog : public LLError::Recorder, public boost::noncopyable
+class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable
 {
 public:
-    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG):
-        // Mostly what we're trying to accomplish by saving and resetting
-        // LLError::Settings is to bypass the default RecordToStderr and
-        // RecordToWinDebug Recorders. As these are visible only inside
-        // llerror.cpp, we can't just call LLError::removeRecorder() with
-        // each. For certain tests we need to produce, capture and examine
-        // DEBUG log messages -- but we don't want to spam the user's console
-        // with that output. If it turns out that saveAndResetSettings() has
-        // some bad effect, give up and just let the DEBUG level log messages
-        // display.
-        mOldSettings(LLError::saveAndResetSettings()),
-        mProxy(new RecorderProxy(this))
+    CaptureLogRecorder()
+		: LLError::Recorder(),
+		boost::noncopyable(),
+		mMessages()
     {
-        LLError::setFatalFunction(wouldHaveCrashed);
-        LLError::setDefaultLevel(level);
-        LLError::addRecorder(mProxy);
     }
 
-    ~CaptureLog()
+    virtual ~CaptureLogRecorder()
     {
-        LLError::removeRecorder(mProxy);
-        delete mProxy;
-        LLError::restoreSettings(mOldSettings);
     }
 
-    void recordMessage(LLError::ELevel level,
-                       const std::string& message)
+    virtual void recordMessage(LLError::ELevel level, const std::string& message)
     {
         mMessages.push_back(message);
     }
@@ -154,7 +112,7 @@ class CaptureLog : public LLError::Recorder, public boost::noncopyable
     /// Don't assume the message we want is necessarily the LAST log message
     /// emitted by the underlying code; search backwards through all messages
     /// for the sought string.
-    std::string messageWith(const std::string& search, bool required=true)
+    std::string messageWith(const std::string& search, bool required)
     {
         for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend());
              rmi != rmend; ++rmi)
@@ -187,14 +145,63 @@ class CaptureLog : public LLError::Recorder, public boost::noncopyable
         return out;
     }
 
+private:
     typedef std::list<std::string> MessageList;
     MessageList mMessages;
-    LLError::Settings* mOldSettings;
-    LLError::Recorder* mProxy;
+};
+
+/**
+ * Capture log messages. This is adapted (simplified) from the one in
+ * llerror_test.cpp.
+ */
+class CaptureLog : public boost::noncopyable
+{
+public:
+    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG)
+        // Mostly what we're trying to accomplish by saving and resetting
+        // LLError::Settings is to bypass the default RecordToStderr and
+        // RecordToWinDebug Recorders. As these are visible only inside
+        // llerror.cpp, we can't just call LLError::removeRecorder() with
+        // each. For certain tests we need to produce, capture and examine
+        // DEBUG log messages -- but we don't want to spam the user's console
+        // with that output. If it turns out that saveAndResetSettings() has
+        // some bad effect, give up and just let the DEBUG level log messages
+        // display.
+		: boost::noncopyable(),
+        mOldSettings(LLError::saveAndResetSettings()),
+		mRecorder(new CaptureLogRecorder())
+    {
+        LLError::setFatalFunction(wouldHaveCrashed);
+        LLError::setDefaultLevel(level);
+        LLError::addRecorder(mRecorder);
+    }
+
+    ~CaptureLog()
+    {
+        LLError::removeRecorder(mRecorder);
+        LLError::restoreSettings(mOldSettings);
+    }
+
+    /// Don't assume the message we want is necessarily the LAST log message
+    /// emitted by the underlying code; search backwards through all messages
+    /// for the sought string.
+    std::string messageWith(const std::string& search, bool required=true)
+    {
+		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);
+    }
+
+    std::ostream& streamto(std::ostream& out) const
+    {
+		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);
+    }
+
+private:
+    LLError::SettingsStoragePtr mOldSettings;
+	LLError::RecorderPtr mRecorder;
 };
 
 inline
-std::ostream& operator<<(std::ostream& out, const CaptureLog& log)
+std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log)
 {
     return log.streamto(out);
 }
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index fc257fb0c1bb35b14ac58de9521ce7342577ed50..e56bc8417447fdba9b9491ed60e6bad66208fe7a 100755
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -31,7 +31,7 @@
 #include "_httpoprequest.h"
 #include "_httppolicy.h"
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 
 
 namespace LLCore
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 926031501e6a029ff145674a7b3fb6cb8984ceee..43dd069bc6784d4028105b0fde051be677ddfdfa 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -44,7 +44,7 @@
 #include "_httplibcurl.h"
 #include "_httpinternal.h"
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llproxy.h"
 
 namespace
@@ -531,6 +531,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
 			check_curl_easy_code(code, CURLOPT_POSTFIELDS);
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
+			// *TODO: Should this be 'Keep-Alive' ?
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
 		}
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index c40deb2b72137b6aa5aea22bb02dc2aa49369392..7a97c16ea7048c6a0b1c86ccc64352795f2b8c7b 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -52,17 +52,20 @@ BOOL gSent = false;
 
 class LLCrashLoggerResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLCrashLoggerResponder);
 public:
 	LLCrashLoggerResponder() 
 	{
 	}
 
-	virtual void error(U32 status, const std::string& reason)
+protected:
+	virtual void httpFailure()
 	{
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 		gBreak = true;
 	}
 
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
 		gBreak = true;
 		gSent = true;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 7fb2a801b27566d282173bfcb9ae054088ec04ba..11647c5518587d0fd841c0e32bc3284a7bc5bb39 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -51,6 +51,7 @@ static const std::string INV_DESC_LABEL("desc");
 static const std::string INV_PERMISSIONS_LABEL("permissions");
 static const std::string INV_SHADOW_ID_LABEL("shadow_id");
 static const std::string INV_ASSET_ID_LABEL("asset_id");
+static const std::string INV_LINKED_ID_LABEL("linked_id");
 static const std::string INV_SALE_INFO_LABEL("sale_info");
 static const std::string INV_FLAGS_LABEL("flags");
 static const std::string INV_CREATION_DATE_LABEL("created_at");
@@ -257,13 +258,6 @@ BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) co
 	return TRUE;
 }
 
-
-void LLInventoryObject::removeFromServer()
-{
-	// don't do nothin'
-	LL_WARNS() << "LLInventoryObject::removeFromServer() called.  Doesn't do anything." << LL_ENDL;
-}
-
 void LLInventoryObject::updateParentOnServer(BOOL) const
 {
 	// don't do nothin'
@@ -276,7 +270,7 @@ void LLInventoryObject::updateServer(BOOL) const
 	LL_WARNS() << "LLInventoryObject::updateServer() called.  Doesn't do anything." << LL_ENDL;
 }
 
-inline
+// static
 void LLInventoryObject::correctInventoryName(std::string& name)
 {
 	LLStringUtil::replaceNonstandardASCII(name, ' ');
@@ -435,12 +429,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 )
 	{
 		disclaimMem(mDescription);
@@ -1068,11 +1067,16 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
 
 LLTrace::BlockTimerStatHandle FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
 
-bool LLInventoryItem::fromLLSD(const LLSD& sd)
+bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
 {
 	LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SD_DESERIALIZE);
-	mInventoryType = LLInventoryType::IT_NONE;
-	mAssetUUID.setNull();
+	if (is_new)
+	{
+		// If we're adding LLSD to an existing object, need avoid
+		// clobbering these fields.
+		mInventoryType = LLInventoryType::IT_NONE;
+		mAssetUUID.setNull();
+	}
 	std::string w;
 
 	w = INV_ITEM_ID_LABEL;
@@ -1129,6 +1133,11 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
 	{
 		mAssetUUID = sd[w];
 	}
+	w = INV_LINKED_ID_LABEL;
+	if (sd.has(w))
+	{
+		mAssetUUID = sd[w];
+	}
 	w = INV_ASSET_TYPE_LABEL;
 	if (sd.has(w))
 	{
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index aa0b4cc24cbb4fc2ee1ed4285ccb43348edf13ba..70b200e139401504ad00f0539bd89cf23c5c9146 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -48,6 +48,7 @@ class LLInventoryObject : public LLRefCount, public LLTrace::MemTrackable<LLInve
 {
 public:
 	typedef std::list<LLPointer<LLInventoryObject> > object_list_t;
+	typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t;
 
 	//--------------------------------------------------------------------
 	// Initialization
@@ -86,22 +87,19 @@ class LLInventoryObject : public LLRefCount, public LLTrace::MemTrackable<LLInve
 	void setType(LLAssetType::EType type);
 	virtual void setCreationDate(time_t creation_date_utc); // only stored for items
 
-private:
 	// in place correction for inventory name string
-	void correctInventoryName(std::string& name);
+	static void correctInventoryName(std::string& name);
 
 	//--------------------------------------------------------------------
 	// File Support
 	//   Implemented here so that a minimal information set can be transmitted
 	//   between simulator and viewer.
 	//--------------------------------------------------------------------
-public:
 	// virtual BOOL importFile(LLFILE* fp);
 	virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
 	virtual BOOL importLegacyStream(std::istream& input_stream);
 	virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
 
-	virtual void removeFromServer();
 	virtual void updateParentOnServer(BOOL) const;
 	virtual void updateServer(BOOL) const;
 
@@ -174,6 +172,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);
@@ -212,7 +211,7 @@ class LLInventoryItem : public LLInventoryObject
 	void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size);
 	LLSD asLLSD() const;
 	void asLLSD( LLSD& sd ) const;
-	bool fromLLSD(const LLSD& sd);
+	bool fromLLSD(const LLSD& sd, bool is_new = true);
 
 	//--------------------------------------------------------------------
 	// Member Variables
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index ca48e613d27d93dbbc364adfdba79bd5485d02e0..8bd134dc84171ce24a079f5724cf148b9491ebcc 100755
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -44,6 +44,7 @@ set(llmessage_SOURCE_FILES
     llhttpassetstorage.cpp
     llhttpclient.cpp
     llhttpclientadapter.cpp
+    llhttpconstants.cpp
     llhttpnode.cpp
     llhttpsender.cpp
     llinstantmessage.cpp
@@ -59,7 +60,6 @@ set(llmessage_SOURCE_FILES
     llmessagetemplate.cpp
     llmessagetemplateparser.cpp
     llmessagethrottle.cpp
-    llmime.cpp
     llnamevalue.cpp
     llnullcipher.cpp
     llpacketack.cpp
@@ -68,7 +68,6 @@ set(llmessage_SOURCE_FILES
     llpartdata.cpp
     llproxy.cpp
     llpumpio.cpp
-    llregionpresenceverifier.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
     llsdmessage.cpp
@@ -138,6 +137,7 @@ set(llmessage_HEADER_FILES
     llhttpclient.h
     llhttpclientinterface.h
     llhttpclientadapter.h
+    llhttpconstants.h
     llhttpnode.h
     llhttpnodeadapter.h
     llhttpsender.h
@@ -156,7 +156,6 @@ set(llmessage_HEADER_FILES
     llmessagetemplate.h
     llmessagetemplateparser.h
     llmessagethrottle.h
-    llmime.h
     llmsgvariabletype.h
     llnamevalue.h
     llnullcipher.h
@@ -169,7 +168,6 @@ set(llmessage_HEADER_FILES
     llqueryflags.h
     llregionflags.h
     llregionhandle.h
-    llregionpresenceverifier.h
     llsdappservices.h
     llsdhttpserver.h
     llsdmessage.h
@@ -233,17 +231,15 @@ target_link_libraries(
 # tests
 if (LL_TESTS)
   SET(llmessage_TEST_SOURCE_FILES
-    # llhttpclientadapter.cpp
-    llmime.cpp
     llnamevalue.cpp
     lltrustedmessageservice.cpp
     lltemplatemessagedispatcher.cpp
-      llregionpresenceverifier.cpp
     )
   LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
 
   #    set(TEST_DEBUG on)
   set(test_libs
+    ${CURL_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
@@ -270,6 +266,7 @@ if (LL_TESTS)
 
   LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
 endif (LL_TESTS)
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index 81e28121fd906e445b2fee380c25128b9265599b..9f90ae1544782ad11574a1545633d4a619e65187 100755
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -610,6 +610,15 @@ LLAres *ll_init_ares()
 	return gAres;
 }
 
+void ll_cleanup_ares()
+{
+	if (gAres != NULL)
+	{
+		delete gAres;
+		gAres = NULL;
+	}
+}
+
 LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
 						 unsigned ttl)
 	: LLRefCount(),
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index 800781ee884059bd9c9477ee6b754b0777e94646..0b5d49e3227d66ccc03a3d4eef424a3b200ccc10 100755
--- a/indra/llmessage/llares.h
+++ b/indra/llmessage/llares.h
@@ -578,5 +578,6 @@ extern LLAres *gAres;
  * thread safe.
  */
 extern LLAres *ll_init_ares();
+extern void ll_cleanup_ares();
 
 #endif // LL_LLARES_H
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 31dd2640218217ae74551c390a940d0ae4435b56..d02a60b7b205616e762b87defe1975fed42bf1e6 100755
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -121,7 +121,7 @@ namespace LLAvatarNameCache
 	// Erase expired names from cache
 	void eraseUnrefreshed();
 
-	bool expirationFromCacheControl(LLSD headers, F64 *expires);
+	bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
 }
 
 /* Sample response:
@@ -165,33 +165,31 @@ namespace LLAvatarNameCache
 
 class LLAvatarNameResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLAvatarNameResponder);
 private:
 	// need to store agent ids that are part of this request in case of
 	// an error, so we can flag them as unavailable
 	std::vector<LLUUID> mAgentIDs;
 
-	// Need the headers to look up Expires: and Retry-After:
-	LLSD mHeaders;
-	
 public:
 	LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
-	:	mAgentIDs(agent_ids),
-		mHeaders()
+	:	mAgentIDs(agent_ids)
 	{ }
 	
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, 
-		const LLSD& headers)
-	{
-		mHeaders = headers;
-	}
-
-	/*virtual*/ void result(const LLSD& content)
+protected:
+	/*virtual*/ void httpSuccess()
 	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		// Pull expiration out of headers if available
-		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
+		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
 		F64 now = LLFrameTimer::getTotalSeconds();
 
-		LLSD agents = content["agents"];
+		const LLSD& agents = content["agents"];
 		LLSD::array_const_iterator it = agents.beginArray();
 		for ( ; it != agents.endArray(); ++it)
 		{
@@ -212,7 +210,7 @@ class LLAvatarNameResponder : public LLHTTPClient::Responder
 		}
 
 		// Same logic as error response case
-		LLSD unresolved_agents = content["bad_ids"];
+		const LLSD& unresolved_agents = content["bad_ids"];
 		S32  num_unresolved = unresolved_agents.size();
 		if (num_unresolved > 0)
 		{
@@ -236,14 +234,13 @@ class LLAvatarNameResponder : public LLHTTPClient::Responder
                                  << LL_ENDL;
     }
 
-	/*virtual*/ void error(U32 status, const std::string& reason)
+	/*virtual*/ void httpFailure()
 	{
 		// If there's an error, it might be caused by PeopleApi,
 		// or when loading textures on startup and using a very slow 
 		// network, this query may time out.
 		// What we should do depends on whether or not we have a cached name
-		LL_WARNS("AvNameCache") << "LLAvatarNameResponder::error " << status << " " << reason
-								<< LL_ENDL;
+		LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
 
 		// Add dummy records for any agent IDs in this request that we do not have cached already
 		std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
@@ -700,7 +697,7 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
 	sCache[agent_id] = av_name;
 }
 
-F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
+F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
 {
 	F64 expires = 0.0;
 	if (expirationFromCacheControl(headers, &expires))
@@ -716,17 +713,21 @@ F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
 	}
 }
 
-bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
+bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires)
 {
 	bool fromCacheControl = false;
 	F64 now = LLFrameTimer::getTotalSeconds();
 
 	// Allow the header to override the default
-	LLSD cache_control_header = headers["cache-control"];
-	if (cache_control_header.isDefined())
+	std::string cache_control;
+	if (headers.has(HTTP_IN_HEADER_CACHE_CONTROL))
+	{
+		cache_control = headers[HTTP_IN_HEADER_CACHE_CONTROL].asString();
+	}
+
+	if (!cache_control.empty())
 	{
 		S32 max_age = 0;
-		std::string cache_control = cache_control_header.asString();
 		if (max_age_from_cache_control(cache_control, &max_age))
 		{
 			*expires = now + (F64)max_age;
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 3a19cee3ed5e579ffd8571dc518930a9cb198c8b..ea016b31253bfd4343d0035f05ec6da1ad8a0821 100755
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -90,7 +90,7 @@ namespace LLAvatarNameCache
 
 	// Compute name expiration time from HTTP Cache-Control header,
 	// or return default value, in seconds from epoch.
-	F64 nameExpirationFromHeaders(LLSD headers);
+	F64 nameExpirationFromHeaders(const LLSD& headers);
 
 	void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
 }
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 147940c983d313867065a10436fc18e3c8e25e22..73df47b933f91db8f06d44ad450feb59025535f1 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -49,6 +49,7 @@
 #include "llproxy.h"
 #include "llsdserialize.h"
 #include "llstl.h"
+#include "llstring.h"
 #include "llthread.h"
 #include "lltimer.h"
 
@@ -100,7 +101,7 @@ void check_curl_code(CURLcode code)
 	{
 		// linux appears to throw a curl error once per session for a bad initialization
 		// at a pretty random time (when enabling cookies).
-		LL_INFOS() << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
+		LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
 	}
 }
 
@@ -110,7 +111,7 @@ void check_curl_multi_code(CURLMcode code)
 	{
 		// linux appears to throw a curl error once per session for a bad initialization
 		// at a pretty random time (when enabling cookies).
-		LL_INFOS() << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
+		LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
 	}
 }
 
@@ -135,6 +136,7 @@ std::string LLCurl::getVersionString()
 //////////////////////////////////////////////////////////////////////////////
 
 LLCurl::Responder::Responder()
+	: mHTTPMethod(HTTP_INVALID), mStatus(HTTP_INTERNAL_ERROR)
 {
 }
 
@@ -144,22 +146,30 @@ LLCurl::Responder::~Responder()
 }
 
 // virtual
-void LLCurl::Responder::errorWithContent(
-	U32 status,
-	const std::string& reason,
-	const LLSD&)
+void LLCurl::Responder::httpFailure()
 {
-	error(status, reason);
+	LL_WARNS("curl") << dumpResponse() << LL_ENDL;
 }
 
-// virtual
-void LLCurl::Responder::error(U32 status, const std::string& reason)
+std::string LLCurl::Responder::dumpResponse() const 
 {
-	LL_INFOS() << mURL << " [" << status << "]: " << reason << LL_ENDL;
+	std::ostringstream s;
+	s << "[" << httpMethodAsVerb(mHTTPMethod) << ":" << mURL << "] "
+	  << "[status:" << mStatus << "] "
+	  << "[reason:" << mReason << "] ";
+
+	if (mResponseHeaders.has(HTTP_IN_HEADER_CONTENT_TYPE))
+	{
+		s << "[content-type:" << mResponseHeaders[HTTP_IN_HEADER_CONTENT_TYPE] << "] ";
+	}
+
+	s << "[content:" << mContent << "]";
+
+	return s.str();
 }
 
 // virtual
-void LLCurl::Responder::result(const LLSD& content)
+void LLCurl::Responder::httpSuccess()
 {
 }
 
@@ -168,44 +178,109 @@ void LLCurl::Responder::setURL(const std::string& url)
 	mURL = url;
 }
 
+void LLCurl::Responder::successResult(const LLSD& content)
+{
+	setResult(HTTP_OK, "", content);
+	httpSuccess();
+}
+
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	setResult(status, reason, content);
+	httpFailure();
+}
+
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	setResult(status, reason, content);
+	httpCompleted();
+}
+
+void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	mStatus = status;
+	mReason = reason;
+	mContent = content;
+}
+
+void LLCurl::Responder::setHTTPMethod(EHTTPMethod method)
+{
+	mHTTPMethod = method;
+}
+
+void LLCurl::Responder::setResponseHeader(const std::string& header, const std::string& value)
+{
+	mResponseHeaders[header] = value;
+}
+
+const std::string& LLCurl::Responder::getResponseHeader(const std::string& header) const
+{
+	if (mResponseHeaders.has(header))
+	{
+		return mResponseHeaders[header].asStringRef();
+	}
+	static const std::string empty;
+	return empty;
+}
+
+bool LLCurl::Responder::hasResponseHeader(const std::string& header) const
+{
+	if (mResponseHeaders.has(header)) return true;
+	return false;
+}
+
 // virtual
 void LLCurl::Responder::completedRaw(
-	U32 status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
-	LLSD content;
 	LLBufferStream istr(channels, buffer.get());
-	const bool emit_errors = false;
-	if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors))
+	const bool emit_parse_errors = false;
+
+	std::string debug_body("(empty)");
+	bool parsed=true;
+	if (EOF == istr.peek())
+	{
+		parsed=false;
+	}
+	// Try to parse body as llsd, no matter what 'content-type' says.
+	else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors))
+	{
+		parsed=false;
+		char body[1025]; 
+		body[1024] = '\0';
+		istr.seekg(0, std::ios::beg);
+		istr.get(body,1024);
+		if (strlen(body) > 0)
+		{
+			mContent = body;
+			debug_body = body;
+		}
+	}
+
+	// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
 	{
-		LL_INFOS() << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << LL_ENDL;
-		content["reason"] = reason;
+		LL_WARNS() << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
+			<< "(" << mReason << ") body: " << debug_body << LL_ENDL;
 	}
 
-	completed(status, reason, content);
+	httpCompleted();
 }
 
 // virtual
-void LLCurl::Responder::completed(U32 status, const std::string& reason, const LLSD& content)
+void LLCurl::Responder::httpCompleted()
 {
-	if (isGoodStatus(status))
+	if (isGoodStatus())
 	{
-		result(content);
+		httpSuccess();
 	}
 	else
 	{
-		errorWithContent(status, reason, content);
+		httpFailure();
 	}
 }
 
-//virtual
-void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, const LLSD& content)
-{
-
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 std::set<CURL*> LLCurl::Easy::sFreeHandles;
@@ -274,6 +349,36 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 	}
 }
 
+//static
+void LLCurl::Easy::deleteAllActiveHandles()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+	LL_CHECK_MEMORY
+	for (std::set<CURL*>::iterator activeHandle = sActiveHandles.begin(); activeHandle != sActiveHandles.end(); ++activeHandle)
+	{
+		CURL* curlHandle = *activeHandle;
+		LLCurl::deleteEasyHandle(curlHandle);
+		LL_CHECK_MEMORY
+	}
+
+	sFreeHandles.clear();
+}
+
+//static
+void LLCurl::Easy::deleteAllFreeHandles()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+	LL_CHECK_MEMORY
+	for (std::set<CURL*>::iterator freeHandle = sFreeHandles.begin(); freeHandle != sFreeHandles.end(); ++freeHandle)
+	{
+		CURL* curlHandle = *freeHandle;
+		LLCurl::deleteEasyHandle(curlHandle);
+		LL_CHECK_MEMORY
+	}
+
+	sFreeHandles.clear();
+}
+
 LLCurl::Easy::Easy()
 	: mHeaders(NULL),
 	  mCurlEasyHandle(NULL)
@@ -289,7 +394,8 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
 	if (!easy->mCurlEasyHandle)
 	{
 		// this can happen if we have too many open files (fails in c-ares/ares_init.c)
-		LL_WARNS() << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
+		LL_WARNS("curl") << "allocEasyHandle() returned NULL! Easy handles: " 
+			<< gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
 		delete easy;
 		return NULL;
 	}
@@ -317,10 +423,14 @@ LLCurl::Easy::~Easy()
 	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
 	LL_CHECK_MEMORY
 	if (mResponder && LLCurl::sNotQuitting) //aborted
-	{	
-		std::string reason("Request timeout, aborted.") ;
-		mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort
-			reason, mChannels, mOutput);		
+	{
+		// HTTP_REQUEST_TIME_OUT, timeout, abort
+		// *TODO: This looks like improper use of the 408 status code.
+		// See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9
+		// This status code should be returned by the *server* when:
+		// "The client did not produce a request within the time that the server was prepared to wait."
+		mResponder->setResult(HTTP_REQUEST_TIME_OUT, "Request timeout, aborted.");
+		mResponder->completedRaw(mChannels, mOutput);
 		LL_CHECK_MEMORY
 	}
 	mResponder = NULL;
@@ -384,9 +494,9 @@ void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info)
 	check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload));
 }
 
-U32 LLCurl::Easy::report(CURLcode code)
+S32 LLCurl::Easy::report(CURLcode code)
 {
-	U32 responseCode = 0;	
+	S32 responseCode = 0;
 	std::string responseReason;
 	
 	if (code == CURLE_OK)
@@ -396,14 +506,15 @@ U32 LLCurl::Easy::report(CURLcode code)
 	}
 	else
 	{
-		responseCode = 499;
+		responseCode = HTTP_INTERNAL_ERROR;
 		responseReason = strerror(code) + " : " + mErrorBuffer;
 		setopt(CURLOPT_FRESH_CONNECT, TRUE);
 	}
 
 	if (mResponder)
 	{	
-		mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput);
+		mResponder->setResult(responseCode, responseReason);
+		mResponder->completedRaw(mChannels, mOutput);
 		mResponder = NULL;
 	}
 	
@@ -440,9 +551,31 @@ void LLCurl::Easy::setoptString(CURLoption option, const std::string& value)
 	check_curl_code(result);
 }
 
+void LLCurl::Easy::slist_append(const std::string& header, const std::string& value)
+{
+	std::string pair(header);
+	if (value.empty())
+	{
+		pair += ":";
+	}
+	else
+	{
+		pair += ": ";
+		pair += value;
+	}
+	slist_append(pair.c_str());
+}
+
 void LLCurl::Easy::slist_append(const char* str)
 {
-	mHeaders = curl_slist_append(mHeaders, str);
+	if (str)
+	{
+		mHeaders = curl_slist_append(mHeaders, str);
+		if (!mHeaders)
+		{
+			LL_WARNS() << "curl_slist_append() call returned NULL appending " << str << LL_ENDL;
+		}
+	}
 }
 
 size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)
@@ -530,8 +663,9 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 
 	if (!post)
 	{
-		slist_append("Connection: keep-alive");
-		slist_append("Keep-alive: 300");
+		// *TODO: Should this be set to 'Keep-Alive' ?
+		slist_append(HTTP_OUT_HEADER_CONNECTION, "keep-alive");
+		slist_append(HTTP_OUT_HEADER_KEEP_ALIVE, "300");
 		// Accept and other headers
 		for (std::vector<std::string>::const_iterator iter = headers.begin();
 			 iter != headers.end(); ++iter)
@@ -810,7 +944,7 @@ S32 LLCurl::Multi::process()
 		++processed;
 		if (msg->msg == CURLMSG_DONE)
 		{
-			U32 response = 0;
+			S32 response = 0;
 			Easy* easy = NULL ;
 
 			{
@@ -829,7 +963,7 @@ S32 LLCurl::Multi::process()
 			}
 			else
 			{
-				response = 499;
+				response = HTTP_INTERNAL_ERROR;
 				//*TODO: change to LL_WARNS()
 				LL_ERRS() << "cleaned up curl request completed!" << LL_ENDL;
 			}
@@ -1128,13 +1262,13 @@ bool LLCurlRequest::getByteRange(const std::string& url,
 	easy->setopt(CURLOPT_HTTPGET, 1);
 	if (length > 0)
 	{
-		std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1);
-		easy->slist_append(range.c_str());
+		std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
+		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
 	}
 	else if (offset > 0)
 	{
-		std::string range = llformat("Range: bytes=%d-", offset);
-		easy->slist_append(range.c_str());
+		std::string range = llformat("bytes=%d-", offset);
+		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
 	}
 	easy->setHeaders();
 	bool res = addEasy(easy);
@@ -1161,7 +1295,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append("Content-Type: application/llsd+xml");
+	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	easy->setHeaders();
 
 	LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
@@ -1189,7 +1323,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append("Content-Type: application/octet-stream");
+	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
 	easy->setHeaders();
 
 	LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
@@ -1561,6 +1695,14 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*
 	}
 }
 
+void LLCurlEasyRequest::slist_append(const std::string& header, const std::string& value)
+{
+	if (isValid() && mEasy)
+	{
+		mEasy->slist_append(header, value);
+	}
+}
+
 void LLCurlEasyRequest::slist_append(const char* str)
 {
 	if (isValid() && mEasy)
@@ -1745,17 +1887,14 @@ void LLCurl::cleanupClass()
 #endif
 	
 	LL_CHECK_MEMORY
-
-	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
-	{
-		CURL* curl = *iter;
-		LLCurl::deleteEasyHandle(curl);
-	}
-	
+	Easy::deleteAllFreeHandles();
+	LL_CHECK_MEMORY
+	Easy::deleteAllActiveHandles();
 	LL_CHECK_MEMORY
 
-	Easy::sFreeHandles.clear();
-
+	// Free the template easy handle
+	curl_easy_cleanup(sCurlTemplateStandardHandle);
+	sCurlTemplateStandardHandle = NULL;
 	LL_CHECK_MEMORY
 
 	delete Easy::sHandleMutexp ;
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fc9761ff9f3a84ea0464a6d691f115a928e91dcd..385d9fffa8990beb1f07dad83e994eb2ccd53b7d 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -39,6 +39,7 @@
 #include <curl/curl.h> // TODO: remove dependency
 
 #include "llbuffer.h"
+#include "llhttpconstants.h"
 #include "lliopipe.h"
 #include "llsd.h"
 #include "llqueuedthread.h"
@@ -76,59 +77,92 @@ class LLCurl
 		Responder();
 		virtual ~Responder();
 
-		/**
-		 * @brief return true if the status code indicates success.
-		 */
-		static bool isGoodStatus(U32 status)
+		virtual bool followRedir() 
 		{
-			return((200 <= status) && (status < 300));
+			return false;
 		}
-		
-		virtual void errorWithContent(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
-			//< called by completed() on bad status 
-
-		virtual void error(U32 status, const std::string& reason);
-			//< called by default error(status, reason, content)
-		
-		virtual void result(const LLSD& content);
-			//< called by completed for good status codes.
 
+		/**
+		 * @brief return true if the status code indicates success.
+		 */
+		bool isGoodStatus() const { return isHttpGoodStatus(mStatus); }
+
+		S32 getStatus() const { return mStatus; }
+		const std::string& getReason() const { return mReason; }
+		const LLSD& getContent() const { return mContent; }
+		bool hasResponseHeader(const std::string& header) const;
+		const std::string& getResponseHeader(const std::string& header) const;
+		const LLSD& getResponseHeaders() const { return mResponseHeaders; }
+		const std::string& getURL() const { return mURL; }
+		EHTTPMethod getHTTPMethod() const { return mHTTPMethod; }
+
+		// This formats response information for use in log spam.  Includes content spam.
+		std::string dumpResponse() const;
+
+		// Allows direct triggering of success/error with different results.
+		void completeResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+		void successResult(const LLSD& content);
+		void failureResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+
+		// The default implementation will try to parse body content as an LLSD, however
+		// it should not spam about parsing failures unless the server sent a
+		// Content-Type: application/llsd+xml header.
 		virtual void completedRaw(
-			U32 status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 			/**< Override point for clients that may want to use this
 			   class when the response is some other format besides LLSD
 			*/
+			
+
+		// The http* methods are not public since these should be triggered internally
+		// after status, reason, content, etc have been set.
+		// If you need to trigger a completion method, use the *Result methods, above.
+	protected:
+		// These methods are the preferred way to process final results.
+		// By default, when one of these is called the following information will be resolved:
+		// * HTTP status code - getStatus()
+		// * Reason string - getReason()
+		// * Content - getContent()
+		// * Response Headers - getResponseHeaders()
+
+		// By default, httpSuccess is triggered whenever httpCompleted is called with a 2xx status code.
+		virtual void httpSuccess();
+			//< called by completed for good status codes.
+
+		// By default, httpFailure is triggered whenever httpCompleted is called with a non-2xx status code.
+		virtual void httpFailure();
+			//< called by httpCompleted() on bad status 
 
-		virtual void completed(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
-			/**< The default implemetnation calls
+		// httpCompleted does not generally need to be overridden, unless
+		// you don't care about the status code (which determine httpFailure or httpSuccess)
+		// or if you want to re-interpret what a 'good' vs' bad' status code is.
+		virtual void httpCompleted();
+			/**< The default implementation calls
 				either:
-				* result(), or
-				* error() 
+				* httpSuccess(), or
+				* httpFailure() 
 			*/
-			
-			// Override to handle parsing of the header only.  Note: this is the only place where the contents
-			// of the header can be parsed.  In the ::completed call above only the body is contained in the LLSD.
-			virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
-
-			// Used internally to set the url for debugging later.
-			void setURL(const std::string& url);
 
-			virtual bool followRedir() 
-			{
-				return false;
-			}
+	public:
+		void setHTTPMethod(EHTTPMethod method);
+		void setURL(const std::string& url);
+		void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+		void setResponseHeader(const std::string& header, const std::string& value);
 
 	private:
+		// These can be accessed by the get* methods.  Treated as 'read-only' during completion handlers.
+		EHTTPMethod mHTTPMethod;
 		std::string mURL;
+		LLSD mResponseHeaders;
+
+	protected:
+		// These should also generally be treated as 'read-only' during completion handlers
+		// and should be accessed by the get* methods.  The exception to this rule would
+		// be when overriding the completedRaw method in preparation for calling httpCompleted().
+		S32 mStatus;
+		std::string mReason;
+		LLSD mContent;
 	};
 	typedef LLPointer<Responder>	ResponderPtr;
 
@@ -227,10 +261,11 @@ class LLCurl::Easy
 	// Copies the string so that it is guaranteed to stick around
 	void setoptString(CURLoption option, const std::string& value);
 
+	void slist_append(const std::string& header, const std::string& value);
 	void slist_append(const char* str);
 	void setHeaders();
 
-	U32 report(CURLcode);
+	S32 report(CURLcode);
 	void getTransferInfo(LLCurl::TransferInfo* info);
 
 	void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
@@ -269,6 +304,9 @@ class LLCurl::Easy
 	static std::set<CURL*> sFreeHandles;
 	static std::set<CURL*> sActiveHandles;
 	static LLMutex*        sHandleMutexp ;
+
+	static void deleteAllActiveHandles();
+	static void deleteAllFreeHandles();
 };
 
 class LLCurl::Multi
@@ -486,6 +524,7 @@ class LLCurlEasyRequest
 	void setWriteCallback(curl_write_callback callback, void* userdata);
 	void setReadCallback(curl_read_callback callback, void* userdata);
 	void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
+	void slist_append(const std::string& header, const std::string& value);
 	void slist_append(const char* str);
 	void sendRequest(const std::string& url);
 	void requestComplete();
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 095da6f0f9be7f37da6a59ae7d032f3eb1c1db7c..f168ac4ec67aa1f2639e2647acbe24c038d2e986 100755
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -54,13 +54,6 @@ const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f;
 
 const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096;
 
-const S32 HTTP_OK = 200;
-const S32 HTTP_PUT_OK = 201;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_MISSING = 404;
-const S32 HTTP_SERVER_BAD_GATEWAY = 502;
-const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503;
-
 /////////////////////////////////////////////////////////////////////////////////
 // LLTempAssetData
 // An asset not stored on central asset store, but on a simulator node somewhere.
@@ -955,7 +948,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
 			{
 				if (curl_msg->data.result == CURLE_OK && 
 					(   curl_result == HTTP_OK 
-					 || curl_result == HTTP_PUT_OK 
+					 || curl_result == HTTP_CREATED
 					 || curl_result == HTTP_NO_CONTENT))
 				{
 					LL_INFOS() << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << LL_ENDL;
@@ -966,8 +959,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
 				}
 				else if (curl_msg->data.result == CURLE_COULDNT_CONNECT ||
 						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_SERVER_BAD_GATEWAY ||
-						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)
+						curl_result == HTTP_BAD_GATEWAY ||
+						curl_result == HTTP_SERVICE_UNAVAILABLE)
 				{
 					LL_WARNS() << "Re-requesting upload for " << req->getUUID() << ".  Received upload error to " << req->mURLBuffer <<
 						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
@@ -988,8 +981,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
 
 				if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT ||
 						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_SERVER_BAD_GATEWAY ||
-						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE))
+						curl_result == HTTP_BAD_GATEWAY ||
+						curl_result == HTTP_SERVICE_UNAVAILABLE))
 				{
 					// shared upload finished callback
 					// in the base class, this is called from processUploadComplete
@@ -1021,7 +1014,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
 					LL_WARNS() << "Failure downloading " << req->mURLBuffer << 
 						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
 
-					xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+					xfer_result = (curl_result == HTTP_NOT_FOUND) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
 
 					if (req->mVFile)
 					{
@@ -1243,7 +1236,7 @@ S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asse
 		}
 		else
 		{
-			xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+			xfer_result = curl_result == HTTP_NOT_FOUND ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
 			LL_INFOS() << "Failure downloading " << req.mURLBuffer << 
 				" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
 		}
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 31a499b370c57725c36d502ac7608d7e74436d9e..200116337d928042d172543568d133ad249c0d12 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -54,7 +54,7 @@ namespace
 	{
 	public:
 		LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder)
-			: LLURLRequestComplete(), mResponder(responder), mStatus(499),
+			: LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR),
 			  mReason("LLURLRequest complete w/no status")
 		{
 		}
@@ -63,7 +63,7 @@ namespace
 		{
 		}
 
-		virtual void httpStatus(U32 status, const std::string& reason)
+		virtual void httpStatus(S32 status, const std::string& reason)
 		{
 			LLURLRequestComplete::httpStatus(status,reason);
 
@@ -74,30 +74,33 @@ namespace
 		virtual void complete(const LLChannelDescriptors& channels,
 							  const buffer_ptr_t& buffer)
 		{
+			// *TODO: Re-interpret mRequestStatus codes?
+			//        Would like to detect curl errors, such as
+			//        connection errors, write erros, etc.
 			if (mResponder.get())
 			{
-				// Allow clients to parse headers before we attempt to parse
-				// the body and provide completed/result/error calls.
-				mResponder->completedHeader(mStatus, mReason, mHeaderOutput);
-				mResponder->completedRaw(mStatus, mReason, channels, buffer);
+				mResponder->setResult(mStatus, mReason);
+				mResponder->completedRaw(channels, buffer);
 			}
 		}
 		virtual void header(const std::string& header, const std::string& value)
 		{
-			mHeaderOutput[header] = value;
+			if (mResponder.get())
+			{
+				mResponder->setResponseHeader(header, value);
+			}
 		}
 
 	private:
 		LLCurl::ResponderPtr mResponder;
-		U32 mStatus;
+		S32 mStatus;
 		std::string mReason;
-		LLSD mHeaderOutput;
 	};
 	
 	class Injector : public LLIOPipe
 	{
 	public:
-		virtual const char* contentType() = 0;
+		virtual const std::string& contentType() = 0;
 	};
 
 	class LLSDInjector : public Injector
@@ -106,7 +109,7 @@ namespace
 		LLSDInjector(const LLSD& sd) : mSD(sd) {}
 		virtual ~LLSDInjector() {}
 
-		const char* contentType() { return "application/llsd+xml"; }
+		const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -124,9 +127,9 @@ namespace
 	{
 	public:
 		RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
-		virtual ~RawInjector() {delete mData;}
+		virtual ~RawInjector() {delete [] mData;}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -147,7 +150,7 @@ namespace
 		FileInjector(const std::string& filename) : mFilename(filename) {}
 		virtual ~FileInjector() {}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -180,7 +183,7 @@ namespace
 		VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
 		virtual ~VFileInjector() {}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -213,7 +216,7 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal
 
 static void request(
 	const std::string& url,
-	LLURLRequest::ERequestAction method,
+	EHTTPMethod method,
 	Injector* body_injector,
 	LLCurl::ResponderPtr responder,
 	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
@@ -225,7 +228,7 @@ static void request(
 	{
 		if (responder)
 		{
-		responder->completed(U32_MAX, "No pump", LLSD());
+			responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
 		}
 		delete body_injector;
 		return;
@@ -237,90 +240,82 @@ static void request(
 	{
 		if (responder)
 		{
-			responder->completed(498, "Internal Error - curl failure", LLSD());
+			responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
 		}
-		delete req ;
+		delete req;
 		delete body_injector;
-		return ;
+		return;
 	}
 
 	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
 
-	
-	LL_DEBUGS() << LLURLRequest::actionAsVerb(method) << " " << url << " "
-		<< headers << LL_ENDL;
+	LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
 
 	// Insert custom headers if the caller sent any
 	if (headers.isMap())
 	{
-		if (headers.has("Cookie"))
+		if (headers.has(HTTP_OUT_HEADER_COOKIE))
 		{
 			req->allowCookies();
 		}
 
-        LLSD::map_const_iterator iter = headers.beginMap();
-        LLSD::map_const_iterator end  = headers.endMap();
-
-        for (; iter != end; ++iter)
-        {
-            std::ostringstream header;
-            //if the header is "Pragma" with no value
-            //the caller intends to force libcurl to drop
-            //the Pragma header it so gratuitously inserts
-            //Before inserting the header, force libcurl
-            //to not use the proxy (read: llurlrequest.cpp)
-			static const std::string PRAGMA("Pragma");
-			if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
-            {
-                req->useProxy(false);
-            }
-            header << iter->first << ": " << iter->second.asString() ;
-            LL_DEBUGS() << "header = " << header.str() << LL_ENDL;
-            req->addHeader(header.str().c_str());
-        }
-    }
+		LLSD::map_const_iterator iter = headers.beginMap();
+		LLSD::map_const_iterator end  = headers.endMap();
+
+		for (; iter != end; ++iter)
+		{
+			//if the header is "Pragma" with no value
+			//the caller intends to force libcurl to drop
+			//the Pragma header it so gratuitously inserts
+			//Before inserting the header, force libcurl
+			//to not use the proxy (read: llurlrequest.cpp)
+			if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
+			{
+				req->useProxy(false);
+			}
+			LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
+				<< ": " << iter->second.asString() << LL_ENDL;
+			req->addHeader(iter->first, iter->second.asString());
+		}
+	}
 
 	// Check to see if we have already set Accept or not. If no one
 	// set it, set it to application/llsd+xml since that's what we
 	// almost always want.
-	if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST )
+	if( method != HTTP_PUT && method != HTTP_POST )
 	{
-		static const std::string ACCEPT("Accept");
-		if(!headers.has(ACCEPT))
+		if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
 		{
-			req->addHeader("Accept: application/llsd+xml");
+			req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
 		}
 	}
 
 	if (responder)
 	{
 		responder->setURL(url);
+		responder->setHTTPMethod(method);
 	}
 
 	req->setCallback(new LLHTTPClientURLAdaptor(responder));
 
-	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem)
+	if (method == HTTP_POST  &&  gMessageSystem)
 	{
-		req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
-								gMessageSystem->mPort).c_str());
-   	}
+		req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
+					gMessageSystem->mPort));
+	}
 
-	if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
+	if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
 	{
-		static const std::string CONTENT_TYPE("Content-Type");
-		if(!headers.has(CONTENT_TYPE))
+		if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
 		{
 			// If the Content-Type header was passed in, it has
 			// already been added as a header through req->addHeader
 			// in the loop above. We defer to the caller's wisdom, but
 			// if they did not specify a Content-Type, then ask the
 			// injector.
-			req->addHeader(
-				llformat(
-					"Content-Type: %s",
-					body_injector->contentType()).c_str());
+			req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
 		}
-   		chain.push_back(LLIOPipe::ptr_t(body_injector));
+		chain.push_back(LLIOPipe::ptr_t(body_injector));
 	}
 
 	chain.push_back(LLIOPipe::ptr_t(req));
@@ -342,9 +337,9 @@ void LLHTTPClient::getByteRange(
 	if(offset > 0 || bytes > 0)
 	{
 		std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
-		headers["Range"] = range;
+		headers[HTTP_OUT_HEADER_RANGE] = range;
 	}
-    request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+    request(url,HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
 }
 
 void LLHTTPClient::head(
@@ -354,18 +349,18 @@ void LLHTTPClient::head(
 	const F32 timeout,
 	bool follow_redirects /* = true */)
 {
-	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+	request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
 }
 
 void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout,
 					   bool follow_redirects /* = true */)
 {
-	request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+	request(url, HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
 }
 void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers,
 								 const F32 timeout, bool follow_redirects /* = true */)
 {
-	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+	request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
 }
 void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout,
 								 bool follow_redirects /* = true */)
@@ -408,7 +403,7 @@ class LLHTTPBuffer
 		return content;
 	}
 
-	std::string asString()
+	const std::string& asString()
 	{
 		return mBuffer;
 	}
@@ -437,7 +432,7 @@ class LLHTTPBuffer
   */
 static LLSD blocking_request(
 	const std::string& url,
-	LLURLRequest::ERequestAction method,
+	EHTTPMethod method,
 	const LLSD& body,
 	const LLSD& headers = LLSD(),
 	const F32 timeout = 5
@@ -480,11 +475,11 @@ static LLSD blocking_request(
 	}
 	
 	// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
-	if (method == LLURLRequest::HTTP_GET)
+	if (method == HTTP_GET)
 	{
 		curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
 	}
-	else if (method == LLURLRequest::HTTP_POST)
+	else if (method == HTTP_POST)
 	{
 		curl_easy_setopt(curlp, CURLOPT_POST, 1);
 		//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
@@ -493,18 +488,20 @@ static LLSD blocking_request(
 		body_str = ostr.str();
 		curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
 		//copied from PHP libs, correct?
-		headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
+		headers_list = curl_slist_append(headers_list, 
+				llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 
 		// copied from llurlrequest.cpp
 		// it appears that apache2.2.3 or django in etch is busted. If
 		// we do not clear the expect header, we get a 500. May be
 		// limited to django/mod_wsgi.
-		headers_list = curl_slist_append(headers_list, "Expect:");
+		headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str());
 	}
 	
 	// * Do the action using curl, handle results
 	LL_DEBUGS() << "HTTP body: " << body_str << LL_ENDL;
-	headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
+	headers_list = curl_slist_append(headers_list,
+				llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 	CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
 	if ( curl_result != CURLE_OK )
 	{
@@ -513,11 +510,11 @@ static LLSD blocking_request(
 
 	LLSD response = LLSD::emptyMap();
 	S32 curl_success = curl_easy_perform(curlp);
-	S32 http_status = 499;
+	S32 http_status = HTTP_INTERNAL_ERROR;
 	curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
 	response["status"] = http_status;
 	// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
-	if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
+	if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) )
 	{
 		// We expect 404s, don't spam for them.
 		LL_WARNS() << "CURL REQ URL: " << url << LL_ENDL;
@@ -547,12 +544,12 @@ static LLSD blocking_request(
 
 LLSD LLHTTPClient::blockingGet(const std::string& url)
 {
-	return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
+	return blocking_request(url, HTTP_GET, LLSD());
 }
 
 LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
 {
-	return blocking_request(url, LLURLRequest::HTTP_POST, body);
+	return blocking_request(url, HTTP_POST, body);
 }
 
 void LLHTTPClient::put(
@@ -562,7 +559,17 @@ void LLHTTPClient::put(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+	request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+}
+
+void LLHTTPClient::patch(
+	const std::string& url,
+	const LLSD& body,
+	ResponderPtr responder,
+	const LLSD& headers,
+	const F32 timeout)
+{
+	request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers);
 }
 
 void LLHTTPClient::post(
@@ -572,7 +579,7 @@ void LLHTTPClient::post(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
+	request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
 }
 
 void LLHTTPClient::postRaw(
@@ -583,7 +590,7 @@ void LLHTTPClient::postRaw(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
+	request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
 }
 
 void LLHTTPClient::postFile(
@@ -593,7 +600,7 @@ void LLHTTPClient::postFile(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers);
+	request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers);
 }
 
 void LLHTTPClient::postFile(
@@ -604,7 +611,7 @@ void LLHTTPClient::postFile(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
+	request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
 }
 
 // static
@@ -614,7 +621,7 @@ void LLHTTPClient::del(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers);
+	request(url, HTTP_DELETE, NULL, responder, timeout, headers);
 }
 
 // static
@@ -626,8 +633,21 @@ void LLHTTPClient::move(
 	const F32 timeout)
 {
 	LLSD headers = hdrs;
-	headers["Destination"] = destination;
-	request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers);
+	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+	request(url, HTTP_MOVE, NULL, responder, timeout, headers);
+}
+
+// static
+void LLHTTPClient::copy(
+	const std::string& url,
+	const std::string& destination,
+	ResponderPtr responder,
+	const LLSD& hdrs,
+	const F32 timeout)
+{
+	LLSD headers = hdrs;
+	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+	request(url, HTTP_COPY, NULL, responder, timeout, headers);
 }
 
 
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index 5de257a4f69b70b2405822ae23f3a5ce5a091a52..b18258fd7bc17d84b1a1492df2141bea94948ece 100755
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -79,6 +79,14 @@ class LLHTTPClient
 		ResponderPtr,
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
+	static void patch(
+		const std::string& url,
+		const LLSD& body,
+		ResponderPtr,
+		const LLSD& headers = LLSD(),
+		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
 	static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
 							  bool follow_redirects = true);
 	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers,
@@ -118,7 +126,7 @@ class LLHTTPClient
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 		///< sends a DELETE method, but we can't call it delete in c++
-	
+
 	/**
 	 * @brief Send a MOVE webdav method
 	 *
@@ -135,6 +143,22 @@ class LLHTTPClient
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 
+	/**
+	 * @brief Send a COPY webdav method
+	 *
+	 * @param url The complete serialized (and escaped) url to get.
+	 * @param destination The complete serialized destination url.
+	 * @param responder The responder that will handle the result.
+	 * @param headers A map of key:value headers to pass to the request
+	 * @param timeout The number of seconds to give the server to respond.
+	 */
+	static void copy(
+		const std::string& url,
+		const std::string& destination,
+		ResponderPtr responder,
+		const LLSD& headers = LLSD(),
+		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
 	//@}
 
 	/**
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index dcd2d79d67ef1646552bca319768ab1ce2ab7d2b..b56a804f9422ad5a475d2fbd051a6c801e36dc0d 100755
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -35,18 +35,18 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo
 {
 	LLSD empty_pragma_header;
 	// Pragma is required to stop curl adding "no-cache"
-	// Space is required to stop llurlrequest from turnning off proxying
-	empty_pragma_header["Pragma"] = " "; 
+	// Space is required to stop llurlrequest from turning off proxying
+	empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " "; 
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
 void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
 {
 	LLSD empty_pragma_header = headers;
-	if (!empty_pragma_header.has("Pragma"))
+	if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
 	{
-	// as above
-	empty_pragma_header["Pragma"] = " ";
+		// as above
+		empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
 	}
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
@@ -56,3 +56,18 @@ void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::
 	LLHTTPClient::put(url, body, responder);
 }
 
+void LLHTTPClientAdapter::put(
+		const std::string& url,
+		const LLSD& body,
+		LLCurl::ResponderPtr responder,
+		const LLSD& headers)
+{
+	LLHTTPClient::put(url, body, responder, headers);
+}
+
+void LLHTTPClientAdapter::del(
+	const std::string& url,
+	LLCurl::ResponderPtr responder)
+{
+	LLHTTPClient::del(url, responder);
+}
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index aae6426a5921646cbf2768324c103cd21d39de96..270282c66fb43ed6ee2a516d7572e744e226e6ed 100755
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -37,6 +37,14 @@ class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLH
 	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
 	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
 	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
+	virtual void put(
+		const std::string& url,
+		const LLSD& body,
+		LLCurl::ResponderPtr responder,
+		const LLSD& headers);
+	virtual void del(
+		const std::string& url,
+		LLCurl::ResponderPtr responder);
 };
 
 #endif
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..01f4a080b0e202522bbf9d289bf5acc760da71f3
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -0,0 +1,228 @@
+/** 
+ * @file llhttpconstants.cpp
+ * @brief Implementation of the HTTP request / response constant lookups
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * 
+ * Copyright (c) 2013, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpconstants.h"
+#include "lltimer.h"
+
+// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
+#include <curl/curl.h>
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+const std::string HTTP_OUT_HEADER_ACCEPT("Accept");
+const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET("Accept-Charset");
+const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING("Accept-Encoding");
+const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE("Accept-Language");
+const std::string HTTP_OUT_HEADER_ACCEPT_RANGES("Accept-Ranges");
+const std::string HTTP_OUT_HEADER_AGE("Age");
+const std::string HTTP_OUT_HEADER_ALLOW("Allow");
+const std::string HTTP_OUT_HEADER_AUTHORIZATION("Authorization");
+const std::string HTTP_OUT_HEADER_CACHE_CONTROL("Cache-Control");
+const std::string HTTP_OUT_HEADER_CONNECTION("Connection");
+const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION("Content-Description");
+const std::string HTTP_OUT_HEADER_CONTENT_ENCODING("Content-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_ID("Content-ID");
+const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE("Content-Language");
+const std::string HTTP_OUT_HEADER_CONTENT_LENGTH("Content-Length");
+const std::string HTTP_OUT_HEADER_CONTENT_LOCATION("Content-Location");
+const std::string HTTP_OUT_HEADER_CONTENT_MD5("Content-MD5");
+const std::string HTTP_OUT_HEADER_CONTENT_RANGE("Content-Range");
+const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_TYPE("Content-Type");
+const std::string HTTP_OUT_HEADER_COOKIE("Cookie");
+const std::string HTTP_OUT_HEADER_DATE("Date");
+const std::string HTTP_OUT_HEADER_DESTINATION("Destination");
+const std::string HTTP_OUT_HEADER_ETAG("ETag");
+const std::string HTTP_OUT_HEADER_EXPECT("Expect");
+const std::string HTTP_OUT_HEADER_EXPIRES("Expires");
+const std::string HTTP_OUT_HEADER_FROM("From");
+const std::string HTTP_OUT_HEADER_HOST("Host");
+const std::string HTTP_OUT_HEADER_IF_MATCH("If-Match");
+const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
+const std::string HTTP_OUT_HEADER_IF_NONE_MATCH("If-None-Match");
+const std::string HTTP_OUT_HEADER_IF_RANGE("If-Range");
+const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
+const std::string HTTP_OUT_HEADER_KEEP_ALIVE("Keep-Alive");
+const std::string HTTP_OUT_HEADER_LAST_MODIFIED("Last-Modified");
+const std::string HTTP_OUT_HEADER_LOCATION("Location");
+const std::string HTTP_OUT_HEADER_MAX_FORWARDS("Max-Forwards");
+const std::string HTTP_OUT_HEADER_MIME_VERSION("MIME-Version");
+const std::string HTTP_OUT_HEADER_PRAGMA("Pragma");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
+const std::string HTTP_OUT_HEADER_RANGE("Range");
+const std::string HTTP_OUT_HEADER_REFERER("Referer");
+const std::string HTTP_OUT_HEADER_RETRY_AFTER("Retry-After");
+const std::string HTTP_OUT_HEADER_SERVER("Server");
+const std::string HTTP_OUT_HEADER_SET_COOKIE("Set-Cookie");
+const std::string HTTP_OUT_HEADER_TE("TE");
+const std::string HTTP_OUT_HEADER_TRAILER("Trailer");
+const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_UPGRADE("Upgrade");
+const std::string HTTP_OUT_HEADER_USER_AGENT("User-Agent");
+const std::string HTTP_OUT_HEADER_VARY("Vary");
+const std::string HTTP_OUT_HEADER_VIA("Via");
+const std::string HTTP_OUT_HEADER_WARNING("Warning");
+const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
+
+// Incoming headers are normalized to lower-case.
+const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE("accept-language");
+const std::string HTTP_IN_HEADER_CACHE_CONTROL("cache-control");
+const std::string HTTP_IN_HEADER_CONTENT_LENGTH("content-length");
+const std::string HTTP_IN_HEADER_CONTENT_LOCATION("content-location");
+const std::string HTTP_IN_HEADER_CONTENT_TYPE("content-type");
+const std::string HTTP_IN_HEADER_HOST("host");
+const std::string HTTP_IN_HEADER_LOCATION("location");
+const std::string HTTP_IN_HEADER_RETRY_AFTER("retry-after");
+const std::string HTTP_IN_HEADER_SET_COOKIE("set-cookie");
+const std::string HTTP_IN_HEADER_USER_AGENT("user-agent");
+const std::string HTTP_IN_HEADER_X_FORWARDED_FOR("x-forwarded-for");
+
+const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
+const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream");
+const std::string HTTP_CONTENT_XML("application/xml");
+const std::string HTTP_CONTENT_JSON("application/json");
+const std::string HTTP_CONTENT_TEXT_HTML("text/html");
+const std::string HTTP_CONTENT_TEXT_HTML_UTF8("text/html; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8("text/plain; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_LLSD("text/llsd");
+const std::string HTTP_CONTENT_TEXT_XML("text/xml");
+const std::string HTTP_CONTENT_TEXT_LSL("text/lsl");
+const std::string HTTP_CONTENT_TEXT_PLAIN("text/plain");
+const std::string HTTP_CONTENT_IMAGE_X_J2C("image/x-j2c");
+const std::string HTTP_CONTENT_IMAGE_J2C("image/j2c");
+const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg");
+const std::string HTTP_CONTENT_IMAGE_PNG("image/png");
+const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
+
+const std::string HTTP_NO_CACHE("no-cache");
+const std::string HTTP_NO_CACHE_CONTROL("no-cache, max-age=0");
+
+const std::string HTTP_VERB_INVALID("(invalid)");
+const std::string HTTP_VERB_HEAD("HEAD");
+const std::string HTTP_VERB_GET("GET");
+const std::string HTTP_VERB_PUT("PUT");
+const std::string HTTP_VERB_POST("POST");
+const std::string HTTP_VERB_DELETE("DELETE");
+const std::string HTTP_VERB_MOVE("MOVE");
+const std::string HTTP_VERB_OPTIONS("OPTIONS");
+const std::string HTTP_VERB_PATCH("PATCH");
+const std::string HTTP_VERB_COPY("COPY");
+
+const std::string& httpMethodAsVerb(EHTTPMethod method)
+{
+	static const std::string VERBS[] =
+	{
+		HTTP_VERB_INVALID,
+		HTTP_VERB_HEAD,
+		HTTP_VERB_GET,
+		HTTP_VERB_PUT,
+		HTTP_VERB_POST,
+		HTTP_VERB_DELETE,
+		HTTP_VERB_MOVE,
+		HTTP_VERB_OPTIONS,
+		HTTP_VERB_PATCH,
+		HTTP_VERB_COPY
+	};
+	if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT))
+	{
+		return VERBS[0];
+	}
+	return VERBS[method];
+}
+
+bool isHttpInformationalStatus(S32 status)
+{
+	// Check for status 1xx.
+	return((100 <= status) && (status < 200));
+}
+
+bool isHttpGoodStatus(S32 status)
+{
+	// Check for status 2xx.
+	return((200 <= status) && (status < 300));
+}
+
+bool isHttpRedirectStatus(S32 status)
+{
+	// Check for status 3xx.
+	return((300 <= status) && (status < 400));
+}
+
+bool isHttpClientErrorStatus(S32 status)
+{
+	// Status 499 is sometimes used for re-interpreted status 2xx errors
+	// based on body content.  Treat these as potentially retryable 'server' status errors,
+	// since we do not have enough context to know if this will always fail.
+	if (HTTP_INTERNAL_ERROR == status) return false;
+
+	// Check for status 5xx.
+	return((400 <= status) && (status < 500));
+}
+
+bool isHttpServerErrorStatus(S32 status)
+{
+	// Status 499 is sometimes used for re-interpreted status 2xx errors.
+	// Allow retry of these, since we don't have enough information in this
+	// context to know if this will always fail.
+	if (HTTP_INTERNAL_ERROR == status) return true;
+
+	// Check for status 5xx.
+	return((500 <= status) && (status < 600));
+}
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
+{
+	// *TODO:  This needs testing!   Not in use yet.
+	// Examples of Retry-After headers:
+	// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+	// Retry-After: 120
+
+	// Check for number of seconds version, first:
+	char* end = 0;
+	// Parse as double
+	double seconds = std::strtod(retry_after.c_str(), &end);
+	if ( end != 0 && *end == 0 )
+	{
+		// Successful parse
+		seconds_to_wait = (F32) seconds;
+		return true;
+	}
+
+	// Parse rfc1123 date.
+	time_t date = curl_getdate(retry_after.c_str(), NULL );
+	if (-1 == date) return false;
+
+	seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
+
+	return true;
+}
+
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
new file mode 100755
index 0000000000000000000000000000000000000000..4aa3cc639444c625872620a7eb4b11e5ad1c5eca
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.h
@@ -0,0 +1,225 @@
+/** 
+ * @file llhttpconstants.h
+ * @brief Constants for HTTP requests and responses
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2001-2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_HTTP_CONSTANTS_H
+#define LL_HTTP_CONSTANTS_H
+
+#include "stdtypes.h"
+
+/////// HTTP STATUS CODES ///////
+
+// Standard errors from HTTP spec:
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
+const S32 HTTP_CONTINUE = 100;
+const S32 HTTP_SWITCHING_PROTOCOLS = 101;
+
+// Success
+const S32 HTTP_OK = 200;
+const S32 HTTP_CREATED = 201;
+const S32 HTTP_ACCEPTED = 202;
+const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
+const S32 HTTP_NO_CONTENT = 204;
+const S32 HTTP_RESET_CONTENT = 205;
+const S32 HTTP_PARTIAL_CONTENT = 206;
+
+// Redirection
+const S32 HTTP_MULTIPLE_CHOICES = 300;
+const S32 HTTP_MOVED_PERMANENTLY = 301;
+const S32 HTTP_FOUND = 302;
+const S32 HTTP_SEE_OTHER = 303;
+const S32 HTTP_NOT_MODIFIED = 304;
+const S32 HTTP_USE_PROXY = 305;
+const S32 HTTP_TEMPORARY_REDIRECT = 307;
+
+// Client Error
+const S32 HTTP_BAD_REQUEST = 400;
+const S32 HTTP_UNAUTHORIZED = 401;
+const S32 HTTP_PAYMENT_REQUIRED = 402;
+const S32 HTTP_FORBIDDEN = 403;
+const S32 HTTP_NOT_FOUND = 404;
+const S32 HTTP_METHOD_NOT_ALLOWED = 405;
+const S32 HTTP_NOT_ACCEPTABLE = 406;
+const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
+const S32 HTTP_REQUEST_TIME_OUT = 408;
+const S32 HTTP_CONFLICT = 409;
+const S32 HTTP_GONE = 410;
+const S32 HTTP_LENGTH_REQUIRED = 411;
+const S32 HTTP_PRECONDITION_FAILED = 412;
+const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
+const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
+const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
+const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+const S32 HTTP_EXPECTATION_FAILED = 417;
+
+// Server Error
+const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
+const S32 HTTP_NOT_IMPLEMENTED = 501;
+const S32 HTTP_BAD_GATEWAY = 502;
+const S32 HTTP_SERVICE_UNAVAILABLE = 503;
+const S32 HTTP_GATEWAY_TIME_OUT = 504;
+const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
+
+// We combine internal process errors with status codes
+// These status codes should not be sent over the wire
+//   and indicate something went wrong internally.
+// If you get these they are not normal.
+const S32 HTTP_INTERNAL_CURL_ERROR = 498;
+const S32 HTTP_INTERNAL_ERROR = 499;
+
+
+////// HTTP Methods //////
+
+extern const std::string HTTP_VERB_INVALID;
+extern const std::string HTTP_VERB_HEAD;
+extern const std::string HTTP_VERB_GET;
+extern const std::string HTTP_VERB_PUT;
+extern const std::string HTTP_VERB_POST;
+extern const std::string HTTP_VERB_DELETE;
+extern const std::string HTTP_VERB_MOVE;
+extern const std::string HTTP_VERB_OPTIONS;
+
+enum EHTTPMethod
+{
+	HTTP_INVALID = 0,
+	HTTP_HEAD,
+	HTTP_GET,
+	HTTP_PUT,
+	HTTP_POST,
+	HTTP_DELETE,
+	HTTP_MOVE, // Caller will need to set 'Destination' header
+	HTTP_OPTIONS,
+	HTTP_PATCH,
+	HTTP_COPY,
+	HTTP_METHOD_COUNT
+};
+
+const std::string& httpMethodAsVerb(EHTTPMethod method);
+bool isHttpInformationalStatus(S32 status);
+bool isHttpGoodStatus(S32 status);
+bool isHttpRedirectStatus(S32 status);
+bool isHttpClientErrorStatus(S32 status);
+bool isHttpServerErrorStatus(S32 status);
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
+//// HTTP Headers /////
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+extern const std::string HTTP_OUT_HEADER_ACCEPT;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_RANGES;
+extern const std::string HTTP_OUT_HEADER_AGE;
+extern const std::string HTTP_OUT_HEADER_ALLOW;
+extern const std::string HTTP_OUT_HEADER_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_OUT_HEADER_CONNECTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ID;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_MD5;
+extern const std::string HTTP_OUT_HEADER_CONTENT_RANGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_OUT_HEADER_COOKIE;
+extern const std::string HTTP_OUT_HEADER_DATE;
+extern const std::string HTTP_OUT_HEADER_DESTINATION;
+extern const std::string HTTP_OUT_HEADER_ETAG;
+extern const std::string HTTP_OUT_HEADER_EXPECT;
+extern const std::string HTTP_OUT_HEADER_EXPIRES;
+extern const std::string HTTP_OUT_HEADER_FROM;
+extern const std::string HTTP_OUT_HEADER_HOST;
+extern const std::string HTTP_OUT_HEADER_IF_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_IF_NONE_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_RANGE;
+extern const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_KEEP_ALIVE;
+extern const std::string HTTP_OUT_HEADER_LAST_MODIFIED;
+extern const std::string HTTP_OUT_HEADER_LOCATION;
+extern const std::string HTTP_OUT_HEADER_MAX_FORWARDS;
+extern const std::string HTTP_OUT_HEADER_MIME_VERSION;
+extern const std::string HTTP_OUT_HEADER_PRAGMA;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_RANGE;
+extern const std::string HTTP_OUT_HEADER_REFERER;
+extern const std::string HTTP_OUT_HEADER_RETRY_AFTER;
+extern const std::string HTTP_OUT_HEADER_SERVER;
+extern const std::string HTTP_OUT_HEADER_SET_COOKIE;
+extern const std::string HTTP_OUT_HEADER_TE;
+extern const std::string HTTP_OUT_HEADER_TRAILER;
+extern const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_UPGRADE;
+extern const std::string HTTP_OUT_HEADER_USER_AGENT;
+extern const std::string HTTP_OUT_HEADER_VARY;
+extern const std::string HTTP_OUT_HEADER_VIA;
+extern const std::string HTTP_OUT_HEADER_WARNING;
+extern const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE;
+
+// Incoming headers are normalized to lower-case.
+extern const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_IN_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_IN_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_IN_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_IN_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_IN_HEADER_HOST;
+extern const std::string HTTP_IN_HEADER_LOCATION;
+extern const std::string HTTP_IN_HEADER_RETRY_AFTER;
+extern const std::string HTTP_IN_HEADER_SET_COOKIE;
+extern const std::string HTTP_IN_HEADER_USER_AGENT;
+extern const std::string HTTP_IN_HEADER_X_FORWARDED_FOR;
+
+//// HTTP Content Types ////
+
+extern const std::string HTTP_CONTENT_LLSD_XML;
+extern const std::string HTTP_CONTENT_OCTET_STREAM;
+extern const std::string HTTP_CONTENT_XML;
+extern const std::string HTTP_CONTENT_JSON;
+extern const std::string HTTP_CONTENT_TEXT_HTML;
+extern const std::string HTTP_CONTENT_TEXT_HTML_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_LLSD;
+extern const std::string HTTP_CONTENT_TEXT_XML;
+extern const std::string HTTP_CONTENT_TEXT_LSL;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN;
+extern const std::string HTTP_CONTENT_IMAGE_X_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_JPEG;
+extern const std::string HTTP_CONTENT_IMAGE_PNG;
+extern const std::string HTTP_CONTENT_IMAGE_BMP;
+
+//// HTTP Cache Settings ////
+extern const std::string HTTP_NO_CACHE;
+extern const std::string HTTP_NO_CACHE_CONTROL;
+
+#endif
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index f1f4a95005a8cbd9c7b30f94a7ac57b204898204..f235965879cf60118130839b7ef68885e95ca6bb 100755
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -30,9 +30,15 @@
 #include <boost/tokenizer.hpp>
 
 #include "llstl.h"
-#include "lliohttpserver.h" // for string constants
+#include "llhttpconstants.h"
 
-static const std::string CONTEXT_WILDCARD("wildcard");
+const std::string CONTEXT_HEADERS("headers");
+const std::string CONTEXT_PATH("path");
+const std::string CONTEXT_QUERY_STRING("query-string");
+const std::string CONTEXT_REQUEST("request");
+const std::string CONTEXT_RESPONSE("response");
+const std::string CONTEXT_VERB("verb");
+const std::string CONTEXT_WILDCARD("wildcard");
 
 /**
  * LLHTTPNode
@@ -173,21 +179,23 @@ LLSD LLHTTPNode::simpleDel(const LLSD&) const
 void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
 {
 	//LL_INFOS() << "options context: " << context << LL_ENDL;
+	LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
 
 	// default implementation constructs an url to the documentation.
+	// *TODO: Check for 'Host' header instead of 'host' header?
 	std::string host(
-		context[CONTEXT_REQUEST][CONTEXT_HEADERS]["host"].asString());
+		context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_IN_HEADER_HOST].asString());
 	if(host.empty())
 	{
-		response->status(400, "Bad Request -- need Host header");
+		response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
 		return;
 	}
 	std::ostringstream ostr;
 	ostr << "http://" << host << "/web/server/api";
-	ostr << context[CONTEXT_REQUEST]["path"].asString();
+	ostr << context[CONTEXT_REQUEST][CONTEXT_PATH].asString();
 	static const std::string DOC_HEADER("X-Documentation-URL");
 	response->addHeader(DOC_HEADER, ostr.str());
-	response->status(200, "OK");
+	response->status(HTTP_OK, "OK");
 }
 
 
@@ -389,17 +397,17 @@ void LLHTTPNode::Response::statusUnknownError(S32 code)
 
 void LLHTTPNode::Response::notFound(const std::string& message)
 {
-	status(404, message);
+	status(HTTP_NOT_FOUND, message);
 }
 
 void LLHTTPNode::Response::notFound()
 {
-	status(404, "Not Found");
+	status(HTTP_NOT_FOUND, "Not Found");
 }
 
 void LLHTTPNode::Response::methodNotAllowed()
 {
-	status(405, "Method Not Allowed");
+	status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed");
 }
 
 void LLHTTPNode::Response::addHeader(
@@ -467,7 +475,7 @@ LLSimpleResponse::~LLSimpleResponse()
 
 void LLSimpleResponse::result(const LLSD& result)
 {
-	status(200, "OK");
+	status(HTTP_OK, "OK");
 }
 
 void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers)
@@ -475,6 +483,11 @@ void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const L
 	status(code,body);
 }
 
+void LLSimpleResponse::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+	status(code,"(LLSD)");
+}
+
 void LLSimpleResponse::status(S32 code, const std::string& message)
 {
 	mCode = code;
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 148647ddde16ecbc76fb3fa4dc138a285a876933..1144d88be16dfb62864b36e4c85ae065efab14c7 100755
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -31,6 +31,17 @@
 #include "llrefcount.h"
 #include "llsd.h"
 
+// common strings use for populating the context. basically 'request',
+// 'wildcard', and 'headers'.
+extern const std::string CONTEXT_HEADERS;
+extern const std::string CONTEXT_PATH;
+extern const std::string CONTEXT_QUERY_STRING;
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_VERB;
+extern const std::string CONTEXT_WILDCARD;
+
+
 class LLChainIOFactory;
 
 /**
@@ -60,6 +71,8 @@ class LLChainIOFactory;
  */
 class LLHTTPNode
 {
+protected:
+    LOG_CLASS(LLHTTPNode);
 public:
 	LLHTTPNode();
 	virtual ~LLHTTPNode();
@@ -100,7 +113,12 @@ class LLHTTPNode
 		/**
 		 * @brief return status code and message with headers.
 		 */
-		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) = 0;
+		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0;
+
+		/**
+		 * @brief return status code and LLSD result with headers.
+		 */
+		virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0;
 
 		/**
 		 * @brief return status code and reason string on http header,
@@ -118,7 +136,7 @@ class LLHTTPNode
 		virtual void methodNotAllowed();
 
 		/**
-		* @breif Add a name: value http header.
+		* @brief Add a name: value http header.
 		*
 		* No effort is made to ensure the response is a valid http
 		* header.
@@ -187,15 +205,15 @@ class LLHTTPNode
 			 name, and return true if the name will construct to a valid url.
 			 For convenience, the <code>getChild()</code> method above will
 			 automatically insert the name in
-			 context["request"]["wildcard"][key] if this method returns true.
+			 context[CONTEXT_REQUEST][CONTEXT_WILDCARD][key] if this method returns true.
 			 For example, the node "agent/<agent_id>/detail" will set
-			 context["request"]["wildcard"]["agent_id"] eqaul to the value 
+			 context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["agent_id"] eqaul to the value 
 			 found during traversal.
 		*/
 		
 	const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
 		/**< find a node, if any, that can service this path
-			 set up context["request"] information 
+			 set up context[CONTEXT_REQUEST] information 
  		*/
  	//@}
  
@@ -287,7 +305,7 @@ class LLSimpleResponse : public LLHTTPNode::Response
 	
 	void result(const LLSD& result);
 	void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-	
+	void extendedResult(S32 code, const LLSD& result, const LLSD& headers);
 	void status(S32 code, const std::string& message);
 
 	void print(std::ostream& out) const;
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 23813c6edb56968d749608f5be4aa60cedef0072..d9042fa8b0320d01a0be63eb6b8a42fc4c17e8ca 100755
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -33,6 +33,7 @@
 #include "llapr.h"
 #include "llbuffer.h"
 #include "llbufferstream.h"
+#include "llhttpconstants.h"
 #include "llfasttimer.h"
 #include "llhttpnode.h"
 #include "lliopipe.h"
@@ -50,15 +51,6 @@
 #include <boost/tokenizer.hpp>
 
 static const char HTTP_VERSION_STR[] = "HTTP/1.0";
-const std::string CONTEXT_REQUEST("request");
-const std::string CONTEXT_RESPONSE("response");
-const std::string CONTEXT_VERB("verb");
-const std::string CONTEXT_HEADERS("headers");
-const std::string HTTP_VERB_GET("GET");
-const std::string HTTP_VERB_PUT("PUT");
-const std::string HTTP_VERB_POST("POST");
-const std::string HTTP_VERB_DELETE("DELETE");
-const std::string HTTP_VERB_OPTIONS("OPTIONS");
 
 static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
 static void* sTimingCallbackData = NULL;
@@ -103,7 +95,7 @@ class LLHTTPPipe : public LLIOPipe
 		// from LLHTTPNode::Response
 		virtual void result(const LLSD&);
 		virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-		
+		virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
 		virtual void status(S32 code, const std::string& message);
 
 		void nullPipe();
@@ -123,7 +115,8 @@ class LLHTTPPipe : public LLIOPipe
 		STATE_LOCKED,
 		STATE_GOOD_RESULT,
 		STATE_STATUS_RESULT,
-		STATE_EXTENDED_RESULT
+		STATE_EXTENDED_RESULT,
+		STATE_EXTENDED_LLSD_RESULT
 	};
 	State mState;
 
@@ -133,7 +126,7 @@ class LLHTTPPipe : public LLIOPipe
 	void lockChain(LLPumpIO*);
 	void unlockChain();
 
-	LLSD mGoodResult;
+	LLSD mResult;
 	S32 mStatusCode;
 	std::string mStatusMessage;	
 	LLSD mHeaders;
@@ -194,7 +187,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			}
 			else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
 			{
-				std::stringstream strstrm;
+				std::ostringstream strstrm;
 				strstrm << istr.rdbuf();
 				input = strstrm.str();
 			}
@@ -210,7 +203,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			}
 			else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
 			{
-				std::stringstream strstrm;
+				std::ostringstream strstrm;
 				strstrm << istr.rdbuf();
 				input = strstrm.str();
 			}
@@ -245,12 +238,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		// Log all HTTP transactions.
 		// TODO: Add a way to log these to their own file instead of indra.log
 		// It is just too spammy to be in indra.log.
-		LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
+		LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
 			<< " " << mStatusCode << " " <<  mStatusMessage << " " << delta
 			<< "s" << LL_ENDL;
 
 		// Log Internal Server Errors
-		//if(mStatusCode == 500)
+		//if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
 		//{
 		//	LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error" 
 		//			<< LL_ENDL;
@@ -272,10 +265,10 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_GOOD_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers["Content-Type"] = "application/llsd+xml";
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			LLBufferStream ostr(channels, buffer.get());
-			LLSDSerialize::toXML(mGoodResult, ostr);
+			LLSDSerialize::toXML(mResult, ostr);
 
 			return STATUS_DONE;
 		}
@@ -283,7 +276,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_STATUS_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers["Content-Type"] = "text/plain";
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
 			context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
@@ -301,6 +294,17 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 
 			return STATUS_DONE;
 		}
+		case STATE_EXTENDED_LLSD_RESULT:
+		{
+			LLSD headers = mHeaders;
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+			LLBufferStream ostr(channels, buffer.get());
+			LLSDSerialize::toXML(mResult, ostr);
+
+			return STATUS_DONE;
+		}
 		default:
 			LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
 				<< mState << LL_ENDL;
@@ -336,12 +340,28 @@ void LLHTTPPipe::Response::result(const LLSD& r)
 		return;
 	}
 
-	mPipe->mStatusCode = 200;
+	mPipe->mStatusCode = HTTP_OK;
 	mPipe->mStatusMessage = "OK";
-	mPipe->mGoodResult = r;
+	mPipe->mResult = r;
 	mPipe->mState = STATE_GOOD_RESULT;
 	mPipe->mHeaders = mHeaders;
-	mPipe->unlockChain();	
+	mPipe->unlockChain();
+}
+
+void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+	if(! mPipe)
+	{
+		LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
+		return;
+	}
+
+	mPipe->mStatusCode = code;
+	mPipe->mStatusMessage = "(LLSD)";
+	mPipe->mResult = r;
+	mPipe->mHeaders = headers;
+	mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
+	mPipe->unlockChain();
 }
 
 void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
@@ -455,9 +475,9 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 		std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
 		
 		int code = context[CONTEXT_RESPONSE]["statusCode"];
-		if (code < 200)
+		if (code < HTTP_OK)
 		{
-			code = 200;
+			code = HTTP_OK;
 			message = "OK";
 		}
 		
@@ -466,7 +486,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 		S32 content_length = buffer->countAfter(channels.in(), NULL);
 		if(0 < content_length)
 		{
-			ostr << "Content-Length: " << content_length << "\r\n";
+			ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
 		}
 		// *NOTE: This guard can go away once the LLSD static map
 		// iterator is available. Phoenix. 2008-05-09
@@ -772,7 +792,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 					std::string name(buf, pos_colon - buf);
 					std::string value(pos_colon + 2);
 					LLStringUtil::toLower(name);
-					if("content-length" == name)
+					if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
 					{
 						LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
 						mContentLength = atoi(value.c_str());
@@ -847,12 +867,12 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 			// HTTP headers.
 			LLPumpIO::chain_t chain;
 			chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
-			context[CONTEXT_REQUEST]["path"] = mPath;
-			context[CONTEXT_REQUEST]["query-string"] = mQuery;
-			context[CONTEXT_REQUEST]["remote-host"]
-				= mBuildContext["remote-host"];
-			context[CONTEXT_REQUEST]["remote-port"]
-				= mBuildContext["remote-port"];
+			context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
+			context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
+			context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
+				= mBuildContext[CONTEXT_REMOTE_HOST];
+			context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
+				= mBuildContext[CONTEXT_REMOTE_PORT];
 			context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
 
 			const LLChainIOFactory* protocolHandler
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 5c1b0531ff2693de45fd6b15147523e27f7e725f..a23eafe58a2c53cd3e5bd9b94681b7acbee89a3a 100755
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -33,18 +33,6 @@
 
 class LLPumpIO;
 
-// common strings use for populating the context. bascally 'request',
-// 'wildcard', and 'headers'.
-extern const std::string CONTEXT_REQUEST;
-extern const std::string CONTEXT_RESPONSE;
-extern const std::string CONTEXT_VERB;
-extern const std::string CONTEXT_HEADERS;
-extern const std::string HTTP_VERB_GET;
-extern const std::string HTTP_VERB_PUT;
-extern const std::string HTTP_VERB_POST;
-extern const std::string HTTP_VERB_DELETE;
-extern const std::string HTTP_VERB_OPTIONS;
-
 class LLIOHTTPServer
 {
 public:
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 4b8d1b44f62db2e97fa30281a8210723124a4d63..b7460df508caec0cdabfd22556c76c1786e35d39 100755
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -40,6 +40,9 @@
 // constants
 //
 
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+
 static const S32 LL_DEFAULT_LISTEN_BACKLOG = 10;
 static const S32 LL_SEND_BUFFER_SIZE = 40000;
 static const S32 LL_RECV_BUFFER_SIZE = 40000;
@@ -620,8 +623,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
 		apr_sockaddr_ip_get(&remote_host_string, remote_addr);
 
 		LLSD context;
-		context["remote-host"] = remote_host_string;
-		context["remote-port"] = remote_addr->port;
+		context[CONTEXT_REMOTE_HOST] = remote_host_string;
+		context[CONTEXT_REMOTE_PORT] = remote_addr->port;
 
 		LLPumpIO::chain_t chain;
 		chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index ec998552d02f7e71540b9afa4f7788ac61296cb3..f840f0275c12388e0eff23b8ff26c33b990f74bc 100755
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -43,6 +43,9 @@
 #include "apr_network_io.h"
 #include "llchainio.h"
 
+extern const std::string CONTEXT_REMOTE_HOST;
+extern const std::string CONTEXT_REMOTE_PORT;
+
 class LLHost;
 
 /** 
diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp
deleted file mode 100755
index 9d9c4ebd6899f8eb0c4292ae5b9d8bb3ad94f649..0000000000000000000000000000000000000000
--- a/indra/llmessage/llmime.cpp
+++ /dev/null
@@ -1,629 +0,0 @@
-/** 
- * @file llmime.cpp
- * @author Phoenix
- * @date 2006-12-20
- * @brief Implementation of mime tools.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llmime.h"
-
-#include <vector>
-
-#include "llmemorystream.h"
-
-/**
- * Useful constants.
- */
-// Headers specified in rfc-2045 will be canonicalized below.
-static const std::string CONTENT_LENGTH("Content-Length");
-static const std::string CONTENT_TYPE("Content-Type");
-static const S32 KNOWN_HEADER_COUNT = 6;
-static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
-{
-	CONTENT_LENGTH,
-	CONTENT_TYPE,
-	std::string("MIME-Version"),
-	std::string("Content-Transfer-Encoding"),
-	std::string("Content-ID"),
-	std::string("Content-Description"),
-};
-
-// parser helpers
-static const std::string MULTIPART("multipart");
-static const std::string BOUNDARY("boundary");
-static const std::string END_OF_CONTENT_PARAMETER("\r\n ;\t");
-static const std::string SEPARATOR_PREFIX("--");
-//static const std::string SEPARATOR_SUFFIX("\r\n");
-
-/*
-Content-Type: multipart/mixed; boundary="segment"
-Content-Length: 24832
-
---segment
-Content-Type: image/j2c
-Content-Length: 23715
-
-<data>
-
---segment
-Content-Type: text/xml; charset=UTF-8
-
-<meta data>
-EOF
-
-*/
-
-/**
- * LLMimeIndex
- */
-
-/** 
- * @class LLMimeIndex::Impl
- * @brief Implementation details of the mime index class.
- * @see LLMimeIndex
- */
-class LLMimeIndex::Impl
-{
-public:
-	Impl() : mOffset(-1), mUseCount(1)
-	{}
-	Impl(LLSD headers, S32 offset) :
-		mHeaders(headers), mOffset(offset), mUseCount(1)
-	{}
-public:
-	LLSD mHeaders;
-	S32 mOffset;
-	S32 mUseCount;
-
-	typedef std::vector<LLMimeIndex> sub_part_t;
-	sub_part_t mAttachments;
-};
-
-LLSD LLMimeIndex::headers() const
-{
-	return mImpl->mHeaders;
-}
-
-S32 LLMimeIndex::offset() const
-{
-	return mImpl->mOffset;
-}
-
-S32 LLMimeIndex::contentLength() const
-{
-	// Find the content length in the headers.
-	S32 length = -1;
-	LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH];
-	if(content_length.isDefined())
-	{
-		length = content_length.asInteger();
-	}
-	return length;
-}
-
-std::string LLMimeIndex::contentType() const
-{
-	std::string type;
-	LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
-	if(content_type.isDefined())
-	{
-		type = content_type.asString();
-	}
-	return type;
-}
-
-bool LLMimeIndex::isMultipart() const
-{
-	bool multipart = false;
-	LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
-	if(content_type.isDefined())
-	{
-		std::string type = content_type.asString();
-		int comp = type.compare(0, MULTIPART.size(), MULTIPART);
-		if(0 == comp)
-		{
-			multipart = true;
-		}
-	}
-	return multipart;
-}
-
-S32 LLMimeIndex::subPartCount() const
-{
-	return mImpl->mAttachments.size();
-}
-
-LLMimeIndex LLMimeIndex::subPart(S32 index) const
-{
-	LLMimeIndex part;
-	if((index >= 0) && (index < (S32)mImpl->mAttachments.size()))
-	{
-		part = mImpl->mAttachments[index];
-	}
-	return part;
-}
-
-LLMimeIndex::LLMimeIndex() : mImpl(new LLMimeIndex::Impl)
-{
-}
-
-LLMimeIndex::LLMimeIndex(LLSD headers, S32 content_offset) :
-	mImpl(new LLMimeIndex::Impl(headers, content_offset))
-{
-}
-
-LLMimeIndex::LLMimeIndex(const LLMimeIndex& mime) :
-	mImpl(mime.mImpl)
-{
-	++mImpl->mUseCount;
-}
-
-LLMimeIndex::~LLMimeIndex()
-{
-	if(0 == --mImpl->mUseCount)
-	{
-		delete mImpl;
-	}
-}
-
-LLMimeIndex& LLMimeIndex::operator=(const LLMimeIndex& mime)
-{
-	// Increment use count first so that we handle self assignment
-	// automatically.
-	++mime.mImpl->mUseCount;
-	if(0 == --mImpl->mUseCount)
-	{
-		delete mImpl;
-	}
-	mImpl = mime.mImpl;
-	return *this;
-}
-
-bool LLMimeIndex::attachSubPart(LLMimeIndex sub_part)
-{
-	// *FIX: Should we check for multi-part?
-	if(mImpl->mAttachments.size() < S32_MAX)
-	{
-		mImpl->mAttachments.push_back(sub_part);
-		return true;
-	}
-	return false;
-}
-
-/**
- * LLMimeParser
- */
-/** 
- * @class LLMimeParser::Impl
- * @brief Implementation details of the mime parser class.
- * @see LLMimeParser
- */
-class LLMimeParser::Impl
-{
-public:
-	// @brief Constructor.
-	Impl();
-
-	// @brief Reset this for a new parse.
-	void reset();
-
-	/** 
-	 * @brief Parse a mime entity to find the index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read, an EOF, or limit bytes have been scanned. The
-	 * istr will be modified by this parsing, so pass in a temporary
-	 * stream or rewind/reset the stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param limit The maximum number of bytes to scan.
-	 * @param separator The multipart separator if it is known.
-	 * @param is_subpart Set true if parsing a multipart sub part.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(
-		std::istream& istr,
-		S32 limit,
-		const std::string& separator,
-		bool is_subpart,
-		LLMimeIndex& index);
-
-protected:
-	/**
-	 * @brief parse the headers.
-	 *
-	 * At the end of a successful parse, mScanCount will be at the
-	 * start of the content.
-	 * @param istr The input stream.
-	 * @param limit maximum number of bytes to process
-	 * @param headers[out] A map of the headers found.
-	 * @return Returns true if the parse was successful.
-	 */
-	bool parseHeaders(std::istream& istr, S32 limit, LLSD& headers);
-
-	/**
-	 * @brief Figure out the separator string from a content type header.
-	 * 
-	 * @param multipart_content_type The content type value from the headers.
-	 * @return Returns the separator string.
-	 */
-	std::string findSeparator(std::string multipart_content_type);
-
-	/**
-	 * @brief Scan through istr past the separator.
-	 *
-	 * @param istr The input stream.
-	 * @param limit Maximum number of bytes to scan.
-	 * @param separator The multipart separator.
-	 */
-	void scanPastSeparator(
-		std::istream& istr,
-		S32 limit,
-		const std::string& separator);
-
-	/**
-	 * @brief Scan through istr past the content of the current mime part.
-	 *
-	 * @param istr The input stream.
-	 * @param limit Maximum number of bytes to scan.
-	 * @param headers The headers for this mime part.
-	 * @param separator The multipart separator if known.
-	 */
-	void scanPastContent(
-		std::istream& istr,
-		S32 limit,
-		LLSD headers,
-		const std::string separator);
-
-	/**
-	 * @brief Eat CRLF.
-	 *
-	 * This method has no concept of the limit, so ensure you have at
-	 * least 2 characters left to eat before hitting the limit. This
-	 * method will increment mScanCount as it goes.
-	 * @param istr The input stream.
-	 * @return Returns true if CRLF was found and consumed off of istr.
-	 */
-	bool eatCRLF(std::istream& istr);
-
-	// @brief Returns true if parsing should continue.
-	bool continueParse() const { return (!mError && mContinue); }
-
-	// @brief anonymous enumeration for parse buffer size.
-	enum
-	{
-		LINE_BUFFER_LENGTH = 1024
-	};
-
-protected:
-	S32 mScanCount;
-	bool mContinue;
-	bool mError;
-	char mBuffer[LINE_BUFFER_LENGTH];
-};
-
-LLMimeParser::Impl::Impl()
-{
-	reset();
-}
-
-void LLMimeParser::Impl::reset()
-{
-	mScanCount = 0;
-	mContinue = true;
-	mError = false;
-	mBuffer[0] = '\0';
-}
-
-bool LLMimeParser::Impl::parseIndex(
-	std::istream& istr,
-	S32 limit,
-	const std::string& separator,
-	bool is_subpart,
-	LLMimeIndex& index)
-{
-	LLSD headers;
-	bool parsed_something = false;
-	if(parseHeaders(istr, limit, headers))
-	{
-		parsed_something = true;
-		LLMimeIndex mime(headers, mScanCount);
-		index = mime;
-		if(index.isMultipart())
-		{
-			// Figure out the separator, scan past it, and recurse.
-			std::string ct = headers[CONTENT_TYPE].asString();
-			std::string sep = findSeparator(ct);
-			scanPastSeparator(istr, limit, sep);
-			while(continueParse() && parseIndex(istr, limit, sep, true, mime))
-			{
-				index.attachSubPart(mime);
-			}
-		}
-		else
-		{
-			// Scan to the end of content.
-			scanPastContent(istr, limit, headers, separator);
-			if(is_subpart)
-			{
-				scanPastSeparator(istr, limit, separator);
-			}
-		}
-	}
-	if(mError) return false;
-	return parsed_something;
-}
-
-bool LLMimeParser::Impl::parseHeaders(
-	std::istream& istr,
-	S32 limit,
-	LLSD& headers)
-{
-	while(continueParse())
-	{
-		// Get the next line.
-		// We subtract 1 from the limit so that we make sure
-		// not to read past limit when we get() the newline.
-		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
-		istr.getline(mBuffer, max_get, '\r');
-		mScanCount += (S32)istr.gcount();
-		int c = istr.get();
-		if(EOF == c)
-		{
-			mContinue = false;
-			return false;
-		}
-		++mScanCount;
-		if(c != '\n')
-		{
-			mError = true;
-			return false;
-		}
-		if(mScanCount >= limit)
-		{
-			mContinue = false;
-		}
-
-		// Check if that's the end of headers.
-		if('\0' == mBuffer[0])
-		{
-			break;
-		}
-
-		// Split out the name and value.
-		// *NOTE: The use of strchr() here is safe since mBuffer is
-		// guaranteed to be NULL terminated from the call to getline()
-		// above.
-		char* colon = strchr(mBuffer, ':');
-		if(!colon)
-		{
-			mError = true;
-			return false;
-		}
-
-		// Cononicalize the name part, and store the name: value in
-		// the headers structure. We do this by iterating through
-		// 'known' headers and replacing the value found with the
-		// correct one.
-		// *NOTE: Not so efficient, but iterating through a small
-		// subset should not be too much of an issue.
-		std::string name(mBuffer, colon++ - mBuffer);
-		while(isspace(*colon)) ++colon;
-		std::string value(colon);
-		for(S32 ii = 0; ii < KNOWN_HEADER_COUNT; ++ii)
-		{
-			if(0 == LLStringUtil::compareInsensitive(name, KNOWN_HEADER[ii]))
-			{
-				name = KNOWN_HEADER[ii];
-				break;
-			}
-		}
-		headers[name] = value;
-	}
-	if(headers.isUndefined()) return false;
-	return true;
-}
-
-std::string LLMimeParser::Impl::findSeparator(std::string header)
-{
-	//                               01234567890
-	//Content-Type: multipart/mixed; boundary="segment"
-	std::string separator;
-	std::string::size_type pos = header.find(BOUNDARY);
-	if(std::string::npos == pos) return separator;
-	pos += BOUNDARY.size() + 1;
-	std::string::size_type end;
-	if(header[pos] == '"')
-	{
-		// the boundary is quoted, find the end from pos, and take the
-		// substring.
-		end = header.find('"', ++pos);
-		if(std::string::npos == end)
-		{
-			// poorly formed boundary.
-			mError = true;
-		}
-	}
-	else
-	{
-		// otherwise, it's every character until a whitespace, end of
-		// line, or another parameter begins.
-		end = header.find_first_of(END_OF_CONTENT_PARAMETER, pos);
-		if(std::string::npos == end)
-		{
-			// it goes to the end of the string.
-			end = header.size();
-		}
-	}
-	if(!mError) separator = header.substr(pos, end - pos);
-	return separator;
-}
-
-void LLMimeParser::Impl::scanPastSeparator(
-	std::istream& istr,
-	S32 limit,
-	const std::string& sep)
-{
-	std::ostringstream ostr;
-	ostr << SEPARATOR_PREFIX << sep;
-	std::string separator = ostr.str();
-	bool found_separator = false;
-	while(!found_separator && continueParse())
-	{
-		// Subtract 1 from the limit so that we make sure not to read
-		// past limit when we get() the newline.
-		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
-		istr.getline(mBuffer, max_get, '\r');
-		mScanCount += (S32)istr.gcount();
-		if(istr.gcount() >= LINE_BUFFER_LENGTH - 1)
-		{
-			// that's way too long to be a separator, so ignore it.
-			continue;
-		}
-		int c = istr.get();
-		if(EOF == c)
-		{
-			mContinue = false;
-			return;
-		}
-		++mScanCount;
-		if(c != '\n')
-		{
-			mError = true;
-			return;
-		}
-		if(mScanCount >= limit)
-		{
-			mContinue = false;
-		}
-		if(0 == LLStringUtil::compareStrings(std::string(mBuffer), separator))
-		{
-			found_separator = true;
-		}
-	}
-}
-
-void LLMimeParser::Impl::scanPastContent(
-	std::istream& istr,
-	S32 limit,
-	LLSD headers,
-	const std::string separator)
-{
-	if(headers.has(CONTENT_LENGTH))
-	{
-		S32 content_length = headers[CONTENT_LENGTH].asInteger();
-		// Subtract 2 here for the \r\n after the content.
-		S32 max_skip = llmin(content_length, limit - mScanCount - 2);
-		istr.ignore(max_skip);
-		mScanCount += max_skip;
-
-		// *NOTE: Check for hitting the limit and eof here before
-		// checking for the trailing EOF, because our mime parser has
-		// to gracefully handle incomplete mime entites.
-		if((mScanCount >= limit) || istr.eof())
-		{
-			mContinue = false;
-		}
-		else if(!eatCRLF(istr))
-		{
-			mError = true;
-			return;
-		}
-	}
-}
-
-bool LLMimeParser::Impl::eatCRLF(std::istream& istr)
-{
-	int c = istr.get();
-	++mScanCount;
-	if(c != '\r')
-	{
-		return false;
-	}
-	c = istr.get();
-	++mScanCount;
-	if(c != '\n')
-	{
-		return false;
-	}
-	return true;
-}
-	
-
-LLMimeParser::LLMimeParser() : mImpl(* new LLMimeParser::Impl)
-{
-}
-
-LLMimeParser::~LLMimeParser()
-{
-	delete & mImpl;
-}
-
-void LLMimeParser::reset()
-{
-	mImpl.reset();
-}
-
-bool LLMimeParser::parseIndex(std::istream& istr, LLMimeIndex& index)
-{
-	std::string separator;
-	return mImpl.parseIndex(istr, S32_MAX, separator, false, index);
-}
-
-bool LLMimeParser::parseIndex(
-	const std::vector<U8>& buffer,
-	LLMimeIndex& index)
-{
-	LLMemoryStream mstr(&buffer[0], buffer.size());
-	return parseIndex(mstr, buffer.size() + 1, index);
-}
-
-bool LLMimeParser::parseIndex(
-	std::istream& istr,
-	S32 limit,
-	LLMimeIndex& index)
-{
-	std::string separator;
-	return mImpl.parseIndex(istr, limit, separator, false, index);
-}
-
-bool LLMimeParser::parseIndex(const U8* buffer, S32 length, LLMimeIndex& index)
-{
-	LLMemoryStream mstr(buffer, length);
-	return parseIndex(mstr, length + 1, index);
-}
-
-/*
-bool LLMimeParser::verify(std::istream& isr, LLMimeIndex& index) const
-{
-	return false;
-}
-
-bool LLMimeParser::verify(U8* buffer, S32 length, LLMimeIndex& index) const
-{
-	LLMemoryStream mstr(buffer, length);
-	return verify(mstr, index);
-}
-*/
diff --git a/indra/llmessage/llmime.h b/indra/llmessage/llmime.h
deleted file mode 100755
index e6617fb503b6e01d8e038cd93ddadc193b65a1e7..0000000000000000000000000000000000000000
--- a/indra/llmessage/llmime.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/** 
- * @file llmime.h
- * @author Phoenix
- * @date 2006-12-20
- * @brief Declaration of mime tools.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMIME_H
-#define LL_LLMIME_H
-
-#include <string>
-#include "llsd.h"
-
-/**
- * This file declares various tools for parsing and creating MIME
- * objects as described in RFCs 2045, 2046, 2047, 2048, and 2049.
- */
-
-/** 
- * @class LLMimeIndex
- * @brief Skeletal information useful for handling mime packages.
- * @see LLMimeParser
- *
- * An instance of this class is the parsed output from a LLMimeParser
- * which then allows for easy access into a data stream to find and
- * get what you want out of it.
- *
- * This class meant as a tool to quickly find what you seek in a
- * parsed mime entity. As such, it does not have useful support for
- * modification of a mime entity and specializes the interface toward
- * querying data from a fixed mime entity. Modifying an instance of
- * LLMimeIndx does not alter a mime entity and changes to a mime
- * entity itself are not propogated into an instance of a LLMimeIndex.
- *
- * Usage:<br>
- *  LLMimeIndex mime_index;<br>
- *  std::ifstream fstr("package.mime", ios::binary);<br>
- *  LLMimeParser parser;<br>
- *  if(parser.parseIndex(fstr, mime_index))<br>
- *  {<br>
- *    std::vector<U8> content;<br>
- *    content.resize(mime_index.contentLength());<br>
- *    fstr.seekg(mime_index.offset(), ios::beg);<br>
- *    // ...do work on fstr and content<br>
- *  }<br>
- */
-class LLMimeIndex
-{
-public:
-	/* @name Client interface.
-	 */
-	//@{
-	/** 
-	 * @brief Get the full parsed headers for this.
-	 *
-	 * If there are any headers, it will be a map of header name to
-	 * the value found on the line. The name is everything before the
-	 * colon, and the value is the string found after the colon to the
-	 * end of the line after trimming leading whitespace. So, for
-	 * example:
-	 * Content-Type:  text/plain
-	 * would become an entry in the headers of:
-	 * headers["Content-Type"] == "text/plain"
-	 *
-	 * If this instance of an index was generated by the
-	 * LLMimeParser::parseIndex() call, all header names in rfc2045
-	 * will be capitalized as in rfc, eg Content-Length and
-	 * MIME-Version, not content-length and mime-version.
-	 * @return Returns an LLSD map of header name to value. Returns
-	 * undef if there are no headers.
-	 */
-	LLSD headers() const;
-
-	/** 
-	 * @brief Get the content offset.
-	 *
-	 * @return Returns the number of bytes to the start of the data
-	 * segment from the start of serialized mime entity. Returns -1 if
-	 * offset is not known.
-	 */
-	S32 offset() const;
-
-	/** 
-	 * @brief Get the length of the data segment for this mime part.
-	 *
-	 * @return Returns the content length in bytes. Returns -1 if
-	 * length is not known.
-	 */
-	S32 contentLength() const;
-
-	/** 
-	 * @brief Get the mime type associated with this node.
-	 *
-	 * @return Returns the mimetype.
-	 */
-	std::string contentType() const;
-
-	/** 
-	 * @brief Helper method which simplifies parsing the return from type()
-	 *
-	 * @return Returns true if this is a multipart mime, and therefore
-	 * getting subparts will succeed.
-	 */
-	bool isMultipart() const;
-
-	/** 
-	 * @brief Get the number of atachments.
-	 *
-	 * @return Returns the number of sub-parts for this.
-	 */
-	S32 subPartCount() const;
-
-	/** 
-	 * @brief Get the indicated attachment.
-	 *
-	 * @param index Value from 0 to (subPartCount() - 1).
-	 * @return Returns the indicated sub-part, or an invalid mime
-	 * index on failure.
-	 */
-	LLMimeIndex subPart(S32 index) const;
-	//@}
-
-	/* @name Interface for building, testing, and helpers for typical use.
-	 */
-	//@{
-	/**
-	 * @brief Default constructor - creates a useless LLMimeIndex.
-	 */
-	LLMimeIndex();
-
-	/**
-	 * @brief Full constructor.
-	 *
-	 * @param headers The complete headers.
-	 * @param content_offset The number of bytes to the start of the
-	 * data segment of this mime entity from the start of the stream
-	 * or buffer.
-	 */
-	LLMimeIndex(LLSD headers, S32 content_offset);
-
-	/**
-	 * @brief Copy constructor.
-	 *
-	 * @param mime The other mime object.
-	 */
-	LLMimeIndex(const LLMimeIndex& mime);
-
-	// @brief Destructor.
-	~LLMimeIndex();
-
-	/*
-	 * @breif Assignment operator.
-	 *
-	 * @param mime The other mime object.
-	 * @return Returns this after assignment.
-	 */
-	LLMimeIndex& operator=(const LLMimeIndex& mime);
-
-	/** 
-	 * @brief Add attachment information as a sub-part to a multipart mime.
-	 *
-	 * @param sub_part the part to attach.
-	 * @return Returns true on success, false on failure.
-	 */
-	bool attachSubPart(LLMimeIndex sub_part);
-	//@}
-
-protected:
-	// Implementation.
-	class Impl;
-	Impl* mImpl;
-};
-
-
-/** 
- * @class LLMimeParser
- * @brief This class implements a MIME parser and verifier.
- *
- * THOROUGH_DESCRIPTION
- */
-class LLMimeParser
-{
-public:
-	// @brief Make a new mime parser.
-	LLMimeParser();
-	
-	// @brief Mime parser Destructor.
-	~LLMimeParser();
-
-	// @brief Reset internal state of this parser.
-	void reset();
-
-	
-	/* @name Index generation interface.
-	 */
-	//@{
-	/** 
-	 * @brief Parse a stream to find the mime index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read or EOF. The istr will be modified by this
-	 * parsing, so pass in a temporary stream or rewind/reset the
-	 * stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(std::istream& istr, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a vector to find the mime index information.
-	 *
-	 * @param buffer A vector with data to parse.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(const std::vector<U8>& buffer, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a stream to find the mime index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read, an EOF, or limit bytes have been scanned. The
-	 * istr will be modified by this parsing, so pass in a temporary
-	 * stream or rewind/reset the stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param limit The maximum number of bytes to scan.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(std::istream& istr, S32 limit, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a memory bufffer to find the mime index information.
-	 *
-	 * @param buffer The start of the buffer to parse.
-	 * @param buffer_length The length of the buffer.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(const U8* buffer, S32 buffer_length, LLMimeIndex& index);
-	//@}
-
-	/** 
-	 * @brief 
-	 *
-	 * @return
-	 */
-	//bool verify(std::istream& istr, LLMimeIndex& index) const;
-
-	/** 
-	 * @brief 
-	 *
-	 * @return
-	 */
-	//bool verify(U8* buffer, S32 buffer_length, LLMimeIndex& index) const;
-
-protected:
-	// Implementation.
-	class Impl;
-	Impl& mImpl;
-
-private:
-	// @brief Not implemneted to prevent copy consturction.
-	LLMimeParser(const LLMimeParser& parser);
-
-	// @brief Not implemneted to prevent assignment.
-	LLMimeParser& operator=(const LLMimeParser& mime);
-};
-
-#endif // LL_LLMIME_H
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
deleted file mode 100755
index e6ed37028a5c027a06f013175f4c578a58d231ed..0000000000000000000000000000000000000000
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/** 
- * @file llregionpresenceverifier.cpp
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llregionpresenceverifier.h"
-#include "llhttpclientinterface.h"
-#include <sstream>
-#include "net.h"
-#include "message.h"
-
-namespace boost
-{
-	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
-	{
-		++p->mReferenceCount;
-	}
-	
-	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
-	{
-		if(p && 0 == --p->mReferenceCount)
-		{
-			delete p;
-		}
-	}
-};
-
-LLRegionPresenceVerifier::Response::~Response()
-{
-}
-
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
-														   uri,
-														   ResponsePtr data,
-														   S32 retry_count) :
-	mUri(uri),
-	mSharedData(data),
-	mRetryCount(retry_count)
-{
-}
-
-//virtual
-LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
-{
-}
-
-void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
-{
-	std::string host = content["private_host"].asString();
-	U32 port = content["private_port"].asInteger();
-	LLHost destination(host, port);
-	LLUUID id = content["region_id"];
-
-	LL_DEBUGS() << "Verifying " << destination.getString() << " is region " << id << LL_ENDL;
-
-	std::stringstream uri;
-	uri << "http://" << destination.getString() << "/state/basic/";
-	mSharedData->getHttpClient().get(
-		uri.str(),
-		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
-}
-
-void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
-													 const std::string& reason)
-{
-	// TODO: babbage: distinguish between region presence service and
-	// region verification errors?
-	mSharedData->onRegionVerificationFailed();
-}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
-	S32 retry_count):
-	mUri(uri),
-	mSharedData(data),
-	mContent(content),
-	mRetryCount(retry_count) 
-{
-}
-
-//virtual
-LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
-{
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
-{
-	LLUUID actual_region_id = content["region_id"];
-	LLUUID expected_region_id = mContent["region_id"];
-
-	LL_DEBUGS() << "Actual region: " << content << LL_ENDL;
-	LL_DEBUGS() << "Expected region: " << mContent << LL_ENDL;
-
-	if (mSharedData->checkValidity(content) &&
-		(actual_region_id == expected_region_id))
-	{
-		mSharedData->onRegionVerified(mContent);
-	}
-	else if (mRetryCount > 0)
-	{
-		retry();
-	}
-	else
-	{
-		LL_WARNS() << "Simulator verification failed. Region: " << mUri << LL_ENDL;
-		mSharedData->onRegionVerificationFailed();
-	}
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
-{
-	LLSD headers;
-	headers["Cache-Control"] = "no-cache, max-age=0";
-	LL_INFOS() << "Requesting region information, get uncached for region "
-			<< mUri << LL_ENDL;
-	--mRetryCount;
-	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
-{
-	if(mRetryCount > 0)
-	{
-		retry();
-	}
-	else
-	{
-		LL_WARNS() << "Failed to contact simulator for verification. Region: " << mUri << LL_ENDL;
-		mSharedData->onRegionVerificationFailed();
-	}
-}
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
deleted file mode 100755
index 5e8251e519bc7b1a7b86adc2f592513935fbb0a8..0000000000000000000000000000000000000000
--- a/indra/llmessage/llregionpresenceverifier.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/** 
- * @file llregionpresenceverifier.cpp
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-/* Macro Definitions */
-#ifndef LL_LLREGIONPRESENCEVERIFIER_H
-#define LL_LLREGIONPRESENCEVERIFIER_H
-
-#include "llhttpclient.h"
-#include <string>
-#include "llsd.h"
-#include <boost/intrusive_ptr.hpp>
-
-class LLHTTPClientInterface;
-
-class LLRegionPresenceVerifier
-{
-public:
-	class Response
-	{
-	public:
-		virtual ~Response() = 0;
-
-		virtual bool checkValidity(const LLSD& content) const = 0;
-		virtual void onRegionVerified(const LLSD& region_details) = 0;
-		virtual void onRegionVerificationFailed() = 0;
-
-		virtual LLHTTPClientInterface& getHttpClient() = 0;
-
-	public: /* but not really -- don't touch this */
-		U32 mReferenceCount;		
-	};
-
-	typedef boost::intrusive_ptr<Response> ResponsePtr;
-
-	class RegionResponder : public LLHTTPClient::Responder
-	{
-	public:
-		RegionResponder(const std::string& uri, ResponsePtr data,
-						S32 retry_count);
-		virtual ~RegionResponder(); 
-		virtual void result(const LLSD& content);
-		virtual void error(U32 status, const std::string& reason);
-
-	private:
-		ResponsePtr mSharedData;
-		std::string mUri;
-		S32 mRetryCount;
-	};
-
-	class VerifiedDestinationResponder : public LLHTTPClient::Responder
-	{
-	public:
-		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
-									 const LLSD& content, S32 retry_count);
-		virtual ~VerifiedDestinationResponder();
-		virtual void result(const LLSD& content);
-		
-		virtual void error(U32 status, const std::string& reason);
-		
-	private:
-		void retry();
-		ResponsePtr mSharedData;
-		LLSD mContent;
-		std::string mUri;
-		S32 mRetryCount;
-	};
-};
-
-namespace boost
-{
-	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
-	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
-};
-
-#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp
index 4103ece33aaf320654a65bda64f139f37368a16f..4ca45267bd66ac7033eeeae3c4862a772a17e054 100755
--- a/indra/llmessage/llsdappservices.cpp
+++ b/indra/llmessage/llsdappservices.cpp
@@ -121,7 +121,7 @@ class LLHTTPConfigRuntimeSingleService : public LLHTTPNode
 	{
 		//LL_INFOS() << "validate: " << name << ", "
 		//	<< LLSDOStreamer<LLSDNotationFormatter>(context) << LL_ENDL;
-		if((std::string("PUT") == context["request"]["verb"].asString()) && !name.empty())
+		if((std::string("PUT") == context[CONTEXT_REQUEST][CONTEXT_VERB].asString()) && !name.empty())
 		{
 			return true;
 		}
@@ -139,7 +139,7 @@ class LLHTTPConfigRuntimeSingleService : public LLHTTPNode
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		response->result(options[name]);
@@ -150,7 +150,7 @@ class LLHTTPConfigRuntimeSingleService : public LLHTTPNode
 		const LLSD& context,
 		const LLSD& input) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		options[name] = input;
@@ -164,7 +164,7 @@ class LLHTTPConfigRuntimeSingleService : public LLHTTPNode
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		options.erase(name);
@@ -268,7 +268,7 @@ class LLHTTPLiveConfigSingleService : public LLHTTPNode
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		response->result(LLApp::instance()->getOption(name));
 	}
 };
diff --git a/indra/llmessage/llsdhttpserver.cpp b/indra/llmessage/llsdhttpserver.cpp
index 5c8fc7b2bb4e23608e9b09745a35cd709a23c9b4..8ac6b3cb12dcc2adc1a6e1d579b99623947e0f48 100755
--- a/indra/llmessage/llsdhttpserver.cpp
+++ b/indra/llmessage/llsdhttpserver.cpp
@@ -109,7 +109,7 @@ class LLAPIService : public LLHTTPNode
 
     virtual void get(ResponsePtr response, const LLSD& context) const
 	{
-		const LLSD& remainder = context["request"]["remainder"];
+		const LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
 		
 		if (remainder.size() > 0)
 		{
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
index 1d0904e3f18055e3cc1e29386ba11ae7ae8525c2..61fcc5dd2f1791bc5816e7ece4a7104bfd47f2b1 100755
--- a/indra/llmessage/llsdmessage.cpp
+++ b/indra/llmessage/llsdmessage.cpp
@@ -92,14 +92,14 @@ bool LLSDMessage::httpListener(const LLSD& request)
     return false;
 }
 
-void LLSDMessage::EventResponder::result(const LLSD& data)
+void LLSDMessage::EventResponder::httpSuccess()
 {
     // If our caller passed an empty replyPump name, they're not
     // listening: this is a fire-and-forget message. Don't bother posting
     // to the pump whose name is "".
     if (! mReplyPump.empty())
     {
-        LLSD response(data);
+        LLSD response(getContent());
         mReqID.stamp(response);
         mPumps.obtain(mReplyPump).post(response);
     }
@@ -111,7 +111,7 @@ void LLSDMessage::EventResponder::result(const LLSD& data)
     }
 }
 
-void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLSDMessage::EventResponder::httpFailure()
 {
     // If our caller passed an empty errorPump name, they're not
     // listening: "default error handling is acceptable." Only post to an
@@ -121,9 +121,9 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string
         LLSD info(mReqID.makeResponse());
         info["target"]  = mTarget;
         info["message"] = mMessage;
-        info["status"]  = LLSD::Integer(status);
-        info["reason"]  = reason;
-        info["content"] = content;
+        info["status"]  = getStatus();
+        info["reason"]  = getReason();
+        info["content"] = getContent();
         mPumps.obtain(mErrorPump).post(info);
     }
     else                        // default error handling
@@ -131,9 +131,7 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string
         // convention seems to be to use LL_INFOS(), but that seems a bit casual?
         LL_WARNS("LLSDMessage::EventResponder")
             << "'" << mMessage << "' to '" << mTarget
-            << "' failed with code " << status << ": " << reason << '\n'
-            << ll_pretty_print_sd(content)
-            << LL_ENDL;
+            << "' failed " << dumpResponse() << LL_ENDL;
     }
 }
 
@@ -151,11 +149,11 @@ bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
 {
     if (success)
     {
-        mResponder->result(payload);
+        mResponder->successResult(payload);
     }
     else
     {
-        mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
+        mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]);
     }
 
     /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
index 0d34847ff2d75108784659dfcf364620aec04f87..e5d532d6a42c100823a36bd36d617e9e01f894f0 100755
--- a/indra/llmessage/llsdmessage.h
+++ b/indra/llmessage/llsdmessage.h
@@ -123,6 +123,7 @@ class LLSDMessage
     /// LLCapabilityListener. Others should use higher-level APIs.
     class EventResponder: public LLHTTPClient::Responder
     {
+        LOG_CLASS(EventResponder);
     public:
         /**
          * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
@@ -149,8 +150,9 @@ class LLSDMessage
             mErrorPump(errorPump)
         {}
     
-        virtual void result(const LLSD& data);
-        virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+    protected:
+        virtual void httpSuccess();
+        virtual void httpFailure();
     
     private:
         LLEventPumps& mPumps;
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 8eb7a08620ac849cf04a431484f016213bcd5cf4..c4e0333ca3250f6ca733a24c7cb0b5ed561b6bdf 100755
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -240,7 +240,7 @@ class LLSDRPCClientFactory : public LLChainIOFactory
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
 		LL_DEBUGS() << "LLSDRPCClientFactory::build" << LL_ENDL;
-		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		LLURLRequest* http(new LLURLRequest(HTTP_POST));
 		if(!http->isValid())
 		{
 			LL_WARNS() << "Creating LLURLRequest failed." << LL_ENDL ;
@@ -251,7 +251,7 @@ class LLSDRPCClientFactory : public LLChainIOFactory
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader("Content-Type: text/llsd");
+		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
@@ -291,7 +291,7 @@ class LLXMLSDRPCClientFactory : public LLChainIOFactory
 	{
 		LL_DEBUGS() << "LLXMLSDRPCClientFactory::build" << LL_ENDL;
 
-		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		LLURLRequest* http(new LLURLRequest(HTTP_POST));
 		if(!http->isValid())
 		{
 			LL_WARNS() << "Creating LLURLRequest failed." << LL_ENDL ;
@@ -301,7 +301,7 @@ class LLXMLSDRPCClientFactory : public LLChainIOFactory
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader("Content-Type: text/xml");
+		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index 151d02a156e4f0aa6ac3d0be7a80ee5f4e43aad7..5bd1112cfe85dd2010478f7a3ef5432a96e8a2b3 100755
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -42,9 +42,9 @@ void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
 								   const LLSD& context,
 								   const LLSD& input) const
 {
-	std::string name = context["request"]["wildcard"]["message-name"];
-	std::string senderIP = context["request"]["remote-host"];
-	std::string senderPort = context["request"]["headers"]
+	std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
+	std::string senderIP = context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST];
+	std::string senderPort = context[CONTEXT_REQUEST][CONTEXT_HEADERS]
 		["x-secondlife-udp-listen-port"];
 
 	LLSD message_data;
@@ -64,7 +64,7 @@ void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
 		LL_WARNS("Messaging") << "trusted message POST to /trusted-message/" 
 				<< name << " from unknown or untrusted sender "
 				<< sender << LL_ENDL;
-		response->status(403, "Unknown or untrusted sender");
+		response->status(HTTP_FORBIDDEN, "Unknown or untrusted sender");
 	}
 	else
 	{
diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h
index 688937ac2c242538d36bea2b39145f02b5ec38eb..12a37bb535254425e59a10c05c4391dda2d627ab 100755
--- a/indra/llmessage/lltrustedmessageservice.h
+++ b/indra/llmessage/lltrustedmessageservice.h
@@ -30,6 +30,10 @@
 #include "linden_common.h"
 #include "llhttpnode.h"
 
+// These are defined in lliosocket.h/lliosocket.cpp  
+extern const std::string CONTEXT_REMOTE_HOST;
+extern const std::string CONTEXT_REMOTE_PORT;
+
 class LLSD;
 
 class LLTrustedMessageService
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 8e4ee85c1753cd1f2932e9ba2604af7d5e14ce46..1294379eca2ab77ce6e6ab41b0f7daf74a6ceab0 100755
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -41,7 +41,6 @@
 #include "llstring.h"
 #include "apr_env.h"
 #include "llapr.h"
-static const U32 HTTP_STATUS_PIPE_ERROR = 499;
 
 /**
  * String constants
@@ -49,11 +48,12 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
 const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
 const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
+// These are defined in llhttpnode.h/llhttpnode.cpp
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
 
-
-
 /**
  * class LLURLRequestDetail
  */
@@ -131,27 +131,8 @@ CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param)
  * class LLURLRequest
  */
 
-// static
-std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
-{
-	static const std::string VERBS[] =
-	{
-		"(invalid)",
-		"HEAD",
-		"GET",
-		"PUT",
-		"POST",
-		"DELETE",
-		"MOVE"
-	};
-	if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT))
-	{
-		return VERBS[0];
-	}
-	return VERBS[action];
-}
 
-LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, bool follow_redirects /* = true */) :
+LLURLRequest::LLURLRequest(EHTTPMethod action, bool follow_redirects /* = true */) :
 	mAction(action),
 	mFollowRedirects(follow_redirects)
 {
@@ -159,7 +140,7 @@ LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, bool follow_redi
 }
 
 LLURLRequest::LLURLRequest(
-	LLURLRequest::ERequestAction action,
+	EHTTPMethod action,
 	const std::string& url,
 	bool follow_redirects /* = true */) :
 	mAction(action),
@@ -184,12 +165,17 @@ void LLURLRequest::setURL(const std::string& url)
 	}
 }
 
-std::string LLURLRequest::getURL() const
+const std::string& LLURLRequest::getURL() const
 {
 	return mDetail->mURL;
 }
 
-void LLURLRequest::addHeader(const char* header)
+void LLURLRequest::addHeader(const std::string& header, const std::string& value /* = "" */)
+{
+	mDetail->mCurlRequest->slist_append(header, value);
+}
+
+void LLURLRequest::addHeaderRaw(const char* header)
 {
 	mDetail->mCurlRequest->slist_append(header);
 }
@@ -276,7 +262,7 @@ LLIOPipe::EStatus LLURLRequest::handleError(
 		LLURLRequestComplete* complete = NULL;
 		complete = (LLURLRequestComplete*)mCompletionCallback.get();
 		complete->httpStatus(
-			HTTP_STATUS_PIPE_ERROR,
+			HTTP_INTERNAL_ERROR,
 			LLIOPipe::lookupStatusString(status));
 		complete->responseStatus(status);
 		pump->respond(complete);
@@ -504,21 +490,32 @@ bool LLURLRequest::configure()
 	case HTTP_PUT:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader("Expect:");
+		addHeader(HTTP_OUT_HEADER_EXPECT);
+
+		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
+		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
+		rv = true;
+		break;
+
+	case HTTP_PATCH:
+		// Disable the expect http 1.1 extension. POST and PUT default
+		// to turning this on, and I am not too sure what it means.
+		addHeader(HTTP_OUT_HEADER_EXPECT);
 
 		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
 		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
+		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "PATCH");
 		rv = true;
 		break;
 
 	case HTTP_POST:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader("Expect:");
+		addHeader(HTTP_OUT_HEADER_EXPECT);
 
 		// Disable the content type http header.
 		// *FIX: what should it be?
-		addHeader("Content-Type:");
+		addHeader(HTTP_OUT_HEADER_CONTENT_TYPE);
 
 		// Set the handle for an http post
 		mDetail->mCurlRequest->setPost(NULL, bytes);
@@ -529,13 +526,19 @@ bool LLURLRequest::configure()
 		break;
 
 	case HTTP_DELETE:
-		// Set the handle for an http post
+		// Set the handle for an http delete
 		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
 		rv = true;
 		break;
 
+	case HTTP_COPY:
+		// Set the handle for an http copy
+		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "COPY");
+		rv = true;
+		break;
+
 	case HTTP_MOVE:
-		// Set the handle for an http post
+		// Set the handle for an http move
 		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
 		// *NOTE: should we check for the Destination header?
 		rv = true;
@@ -648,7 +651,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
 		S32 status_code = atoi(status.c_str());
 		if (status_code > 0)
 		{
-			complete->httpStatus((U32)status_code, reason);
+			complete->httpStatus(status_code, reason);
 			return header_len;
 		}
 	}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 20d6e30d1771fad5c36c34d415340e9a7b3dd5ae..88fccd4bf693c8d93e515e036be9327bf0a931f2 100755
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -42,9 +42,10 @@
 #include "llcurl.h"
 
 
-extern const std::string CONTEXT_REQUEST;
+/**
+ * External constants
+ */
 extern const std::string CONTEXT_DEST_URI_SD_LABEL;
-extern const std::string CONTEXT_RESPONSE;
 extern const std::string CONTEXT_TRANSFERED_BYTES;
 
 class LLURLRequestDetail;
@@ -68,42 +69,22 @@ class LLURLRequest : public LLIOPipe
 {
 	LOG_CLASS(LLURLRequest);
 public:
-
 	typedef int (* SSLCertVerifyCallback)(X509_STORE_CTX *ctx, void *param);
-	/** 
-	 * @brief This enumeration is for specifying the type of request.
-	 */
-	enum ERequestAction
-	{
-		INVALID,
-		HTTP_HEAD,
-		HTTP_GET,
-		HTTP_PUT,
-		HTTP_POST,
-		HTTP_DELETE,
-		HTTP_MOVE, // Caller will need to set 'Destination' header
-		REQUEST_ACTION_COUNT
-	};
-
-	/**
-	 * @brief Turn the requst action into an http verb.
-	 */
-	static std::string actionAsVerb(ERequestAction action);
 
 	/** 
 	 * @brief Constructor.
 	 *
-	 * @param action One of the ERequestAction enumerations.
+	 * @param action One of the EHTTPMethod enumerations.
 	 */
-	LLURLRequest(ERequestAction action, bool follow_redirects = true);
+	LLURLRequest(EHTTPMethod action, bool follow_redirects = true);
 
 	/** 
 	 * @brief Constructor.
 	 *
-	 * @param action One of the ERequestAction enumerations.
+	 * @param action One of the EHTTPMethod enumerations.
 	 * @param url The url of the request. It should already be encoded.
 	 */
-	LLURLRequest(ERequestAction action, const std::string& url, bool follow_redirects = true);
+	LLURLRequest(EHTTPMethod action, const std::string& url, bool follow_redirects = true);
 
 	/** 
 	 * @brief Destructor.
@@ -123,17 +104,17 @@ class LLURLRequest : public LLIOPipe
 	 * 
 	 */
 	void setURL(const std::string& url);
-	std::string getURL() const;
+	const std::string& getURL() const;
 	/** 
 	 * @brief Add a header to the http post.
 	 *
-	 * The header must be correctly formatted for HTTP requests. This
-	 * provides a raw interface if you know what kind of request you
+	 * This provides a raw interface if you know what kind of request you
 	 * will be making during construction of this instance. All
 	 * required headers will be automatically constructed, so this is
 	 * usually useful for encoding parameters.
 	 */
-	void addHeader(const char* header);
+	void addHeader(const std::string& header, const std::string& value = "");
+	void addHeaderRaw(const char* header);
 
 	/**
 	 * @brief Check remote server certificate signed by a known root CA.
@@ -218,7 +199,7 @@ class LLURLRequest : public LLIOPipe
 		STATE_HAVE_RESPONSE,
 	};
 	EState mState;
-	ERequestAction mAction;
+	EHTTPMethod mAction;
 	bool mFollowRedirects;
 	LLURLRequestDetail* mDetail;
 	LLIOPipe::ptr_t mCompletionCallback;
@@ -316,7 +297,7 @@ class LLURLRequestComplete : public LLIOPipe
 	// May be called more than once, particularly for redirects and proxy madness.
 	// Ex. a 200 for a connection to https through a proxy, followed by the "real" status
 	//     a 3xx for a redirect followed by a "real" status, or more redirects.
-	virtual void httpStatus(U32 status, const std::string& reason) { }
+	virtual void httpStatus(S32 status, const std::string& reason) { }
 
 	virtual void complete(
 		const LLChannelDescriptors& channels,
@@ -369,15 +350,8 @@ class LLURLRequestComplete : public LLIOPipe
 	//@}
 
 	// value to note if we actually got the response. This value
-	// depends on correct useage from the LLURLRequest instance.
+	// depends on correct usage from the LLURLRequest instance.
 	EStatus mRequestStatus;
 };
 
-
-
-/**
- * External constants
- */
-extern const std::string CONTEXT_DEST_URI_SD_LABEL;
-
 #endif // LL_LLURLREQUEST_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 4e4dcc1d815ffd284d576c60e0ff97cc66104858..cc2d5d66ad6200fba2ad069a25b04e805b2c4055 100755
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -110,20 +110,20 @@ namespace
 		{
 		}
 
-		virtual void error(U32 status, const std::string& reason)
+	protected:
+		virtual void httpFailure()
 		{
 			// don't spam when agent communication disconnected already
-			if (status != 410)
+			if (HTTP_GONE != getStatus())
 			{
-				LL_WARNS("Messaging") << "error status " << status
-						<< " for message " << mMessageName
-						<< " reason " << reason << LL_ENDL;
+				LL_WARNS("Messaging") << "error for message " << mMessageName
+									  << " " << dumpResponse() << LL_ENDL;
 			}
 			// TODO: Map status in to useful error code.
 			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
 		}
 		
-		virtual void result(const LLSD& content)
+		virtual void httpSuccess()
 		{
 			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
 		}
@@ -149,7 +149,7 @@ class LLMessageHandlerBridge : public LLHTTPNode
 void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response, 
 							const LLSD& context, const LLSD& input) const
 {
-	std::string name = context["request"]["wildcard"]["message-name"];
+	std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
 	char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
 	
 	LL_DEBUGS() << "Setting mLastSender " << input["sender"].asString() << LL_ENDL;
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 9b298d0c049ef5177018393c3d200d3ea2e51957..b7fdf4f437b075ae07977d1bc107a05e6d32e5f9 100755
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -24,55 +24,76 @@
  * $/LicenseInfo$
  */
 
+#ifndef LL_CURL_STUB_CPP
+#define LL_CURL_STUB_CPP
+
+
 #include "linden_common.h"
 #include "llcurl.h"
+#include "llhttpconstants.cpp"
 
 LLCurl::Responder::Responder()
 {
 }
 
-void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const &reason,
-								  LLSD const& mContent)
+void LLCurl::Responder::httpCompleted()
 {
-	if (isGoodStatus(status))
+	if (isGoodStatus())
 	{
-		result(mContent);
+		httpSuccess();
 	}
 	else
 	{
-		errorWithContent(status, reason, mContent);
+		httpFailure();
 	}
 }
 
-void LLCurl::Responder::completedHeader(unsigned,
-										std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-										LLSD const&)
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const&,
+									 boost::shared_ptr<LLBufferArray> const&)
 {
 }
 
-void LLCurl::Responder::completedRaw(unsigned,
-									 std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-									 LLChannelDescriptors const&,
-									 boost::shared_ptr<LLBufferArray> const&)
+void LLCurl::Responder::httpFailure()
 {
 }
 
-void LLCurl::Responder::errorWithContent(unsigned,
-							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-							  LLSD const&)
+LLCurl::Responder::~Responder ()
 {
 }
 
-LLCurl::Responder::~Responder ()
+void LLCurl::Responder::httpSuccess()
+{
+}
+
+std::string LLCurl::Responder::dumpResponse() const
+{
+	return "dumpResponse()";
+}
+
+void LLCurl::Responder::successResult(const LLSD& content)
 {
+	setResult(HTTP_OK, "", content);
+	httpSuccess();
 }
 
-void LLCurl::Responder::error(unsigned,
-							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content)
+{
+	setResult(status, reason, content);
+	httpFailure();
+}
+
+
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content)
 {
+	setResult(status, reason, content);
+	httpCompleted();
 }
 
-void LLCurl::Responder::result(LLSD const&)
+void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
 {
+	mStatus = status;
+	mReason = reason;
+	mContent = content;
 }
 
+#endif
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index 559001d0797a351ef9bcd9a1b3946ec516ce45f3..a32bfa59ce8d046bf443c85d1e49cbd519e3a0d3 100755
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -40,8 +40,6 @@
 #include "llproxy.h"
 #include "llpumpio.h"
 
-#include "llsdhttpserver.h"
-#include "lliohttpserver.h"
 #include "lliosocket.h"
 #include "stringize.h"
 
@@ -101,7 +99,7 @@ namespace tut
 			if (mSawError)
 			{
 				std::string msg =
-					llformat("error() called when not expected, status %d",
+					llformat("httpFailure() called when not expected, status %d",
 						mStatus);
 				fail(msg);
 			}
@@ -111,7 +109,7 @@ namespace tut
 		{
 			if (!mSawError)
 			{
-				fail("error() wasn't called");
+				fail("httpFailure() wasn't called");
 			}
 		}
 
@@ -153,33 +151,26 @@ namespace tut
 				mClient.mResultDeleted = true;
 			}
 
-			virtual void error(U32 status, const std::string& reason)
+		protected:
+			virtual void httpFailure()
 			{
 				mClient.mSawError = true;
-				mClient.mStatus = status;
-				mClient.mReason = reason;
+				mClient.mStatus = getStatus();
+				mClient.mReason = getReason();
 			}
 
-			virtual void result(const LLSD& content)
+			virtual void httpSuccess()
 			{
-				mClient.mResult = content;
+				mClient.mResult = getContent();
 			}
 
-			virtual void completed(
-							U32 status, const std::string& reason,
-							const LLSD& content)
+			virtual void httpCompleted()
 			{
-				LLHTTPClient::Responder::completed(status, reason, content);
-
+				LLHTTPClient::Responder::httpCompleted();
+				
 				mClient.mSawCompleted = true;
-			}
-
-			virtual void completedHeader(
-				U32 status, const std::string& reason,
-				const LLSD& content)
-			{
-				mClient.mHeader = content;
 				mClient.mSawCompletedHeader = true;
+				mClient.mHeader = getResponseHeaders();
 			}
 
 		private:
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
index 13ce0a0edd85638f296da15b021636d145010c96..e9ce116bb38cb2053ea266a26fbdfb30f34ff92f 100755
--- a/indra/llmessage/tests/llhttpclientadapter_test.cpp
+++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp
@@ -1,6 +1,6 @@
 /** 
- * @file 
- * @brief 
+ * @file llhttpclientadapter_test.cpp
+ * @brief Tests for LLHTTPClientAdapter
  *
  * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -33,8 +33,8 @@
 float const HTTP_REQUEST_EXPIRY_SECS = 1.0F;
 
 std::vector<std::string> get_urls;
-std::vector<boost::intrusive_ptr<LLCurl::Responder> > get_responders;
-void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
+std::vector< LLCurl::ResponderPtr > get_responders;
+void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout, bool follow_redirects)
 {
 	get_urls.push_back(url);
 	get_responders.push_back(responder);
@@ -42,16 +42,30 @@ void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Resp
 
 std::vector<std::string> put_urls;
 std::vector<LLSD> put_body;
-std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders;
+std::vector<LLSD> put_headers;
+std::vector<LLCurl::ResponderPtr> put_responders;
 
-void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
+void LLHTTPClient::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout)
 {
 	put_urls.push_back(url);
 	put_responders.push_back(responder);
 	put_body.push_back(body);
+	put_headers.push_back(headers);
 
 }
 
+std::vector<std::string> delete_urls;
+std::vector<LLCurl::ResponderPtr> delete_responders;
+
+void LLHTTPClient::del(
+	const std::string& url,
+	LLCurl::ResponderPtr responder,
+	const LLSD& headers,
+	const F32 timeout)
+{
+	delete_urls.push_back(url);
+	delete_responders.push_back(responder);
+}
 
 namespace tut
 {
@@ -64,6 +78,9 @@ namespace tut
 			put_urls.clear();
 			put_responders.clear();
 			put_body.clear();
+			put_headers.clear();
+			delete_urls.clear();
+			delete_responders.clear();
 		}
 	};
 
@@ -73,7 +90,7 @@ namespace tut
 
 namespace
 {
-	tut::factory tf("LLHTTPClientAdapterData test");
+	tut::factory tf("LLHTTPClientAdapterData");
 }
 
 namespace tut
@@ -91,7 +108,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		adapter.get("Made up URL", responder);
 		ensure_equals(get_urls.size(), 1);
@@ -103,7 +120,7 @@ namespace tut
 	void object::test<3>()
 	{
 		LLHTTPClientAdapter adapter;
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		adapter.get("Made up URL", responder);
 
@@ -117,7 +134,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -133,7 +150,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -150,7 +167,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -160,5 +177,45 @@ namespace tut
 		ensure_equals(put_body.size(), 1);
 		ensure_equals(put_body[0]["TestBody"].asString(), "Foobar");
 	}
+
+	// Ensure that headers are passed through put properly
+	template<> template<>
+	void object::test<7>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
+
+		LLSD body = LLSD::emptyMap();
+		body["TestBody"] = "Foobar";
+
+		LLSD headers = LLSD::emptyMap();
+		headers["booger"] = "omg";
+
+		adapter.put("Made up URL", body, responder, headers);
+
+		ensure_equals("Header count", put_headers.size(), 1);
+		ensure_equals(
+			"First header",
+			put_headers[0]["booger"].asString(),
+			"omg");
+	}
+
+	// Ensure that del() passes appropriate arguments to the LLHTTPClient
+	template<> template<>
+	void object::test<8>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
+
+		adapter.del("Made up URL", responder);
+
+		ensure_equals("URL count", delete_urls.size(), 1);
+		ensure_equals("Received URL", delete_urls[0], "Made up URL");
+
+		ensure_equals("Responder count", delete_responders.size(), 1);
+		//ensure_equals("Responder", delete_responders[0], responder);
+	}
 }
 
diff --git a/indra/llmessage/tests/llhttpnode_stub.cpp b/indra/llmessage/tests/llhttpnode_stub.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..479a256bdd7f75c1b1110abbf59151e6b53bc64a
--- /dev/null
+++ b/indra/llmessage/tests/llhttpnode_stub.cpp
@@ -0,0 +1,107 @@
+/** 
+ * @file llhttpnode_stub.cpp
+ * @brief STUB Implementation of classes for generic HTTP/LSL/REST handling.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * 
+ * Second Life Viewer Source Code
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpnode.h"
+
+const std::string CONTEXT_VERB("verb");
+const std::string CONTEXT_REQUEST("request");
+const std::string CONTEXT_WILDCARD("wildcard");
+const std::string CONTEXT_PATH("path");
+const std::string CONTEXT_QUERY_STRING("query-string");
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+const std::string CONTEXT_HEADERS("headers");
+const std::string CONTEXT_RESPONSE("response");
+
+/**
+ * LLHTTPNode
+ */
+class LLHTTPNode::Impl
+{
+    // dummy
+};
+
+LLHTTPNode::LLHTTPNode(): impl(*new Impl) {}
+LLHTTPNode::~LLHTTPNode() {}
+LLSD LLHTTPNode::simpleGet() const { return LLSD(); }
+LLSD LLHTTPNode::simplePut(const LLSD& input) const { return LLSD(); }
+LLSD LLHTTPNode::simplePost(const LLSD& input) const { return LLSD(); }
+LLSD LLHTTPNode::simpleDel(const LLSD&) const { return LLSD(); }
+void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const {}
+void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {}
+void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {}
+void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) const {}
+void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const {}
+LLHTTPNode* LLHTTPNode::getChild(const std::string& name, LLSD& context) const { return NULL; }
+bool LLHTTPNode::handles(const LLSD& remainder, LLSD& context) const { return false; }
+bool LLHTTPNode::validate(const std::string& name, LLSD& context) const { return false; }
+const LLHTTPNode* LLHTTPNode::traverse(const std::string& path, LLSD& context) const { return NULL; }
+void LLHTTPNode::addNode(const std::string& path, LLHTTPNode* nodeToAdd) { }
+LLSD LLHTTPNode::allNodePaths() const { return LLSD(); }
+const LLHTTPNode* LLHTTPNode::rootNode() const { return NULL; }
+const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const { return NULL; }
+
+LLHTTPNode::Response::~Response(){}
+void LLHTTPNode::Response::notFound(const std::string& message)
+{
+	status(404, message);
+}
+void LLHTTPNode::Response::notFound()
+{
+	status(404, "Not Found");
+}
+void LLHTTPNode::Response::methodNotAllowed()
+{
+	status(405, "Method Not Allowed");
+}
+void LLHTTPNode::Response::statusUnknownError(S32 code)
+{
+	status(code, "Unknown Error");
+}
+
+void LLHTTPNode::Response::status(S32 code, const std::string& message)
+{
+}
+
+void LLHTTPNode::Response::addHeader(const std::string& name,const std::string& value) 
+{
+	mHeaders[name] = value;
+}
+void LLHTTPNode::describe(Description& desc) const { }
+
+
+const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const { return NULL; }
+
+
+LLHTTPRegistrar::NodeFactory::~NodeFactory() { }
+
+void LLHTTPRegistrar::registerFactory(
+    const std::string& path, NodeFactory& factory) {}
+void LLHTTPRegistrar::buildAllServices(LLHTTPNode& root) {}
+
+
diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp
deleted file mode 100755
index ea48561ae9c1eb754b65c325d9ed59c38a9481d8..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/llmime_test.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-/** 
- * @file llmime_test.cpp
- * @author Phoenix
- * @date 2006-12-24
- * @brief BRIEF_DESC of llmime_test.cpp
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llsdserialize.h"
-
-#include "../llmime.h"
-
-#include "../test/lltut.h"
-
-namespace tut
-{
-	struct mime_index
-	{
-	};
-	typedef test_group<mime_index> mime_index_t;
-	typedef mime_index_t::object mime_index_object_t;
-	tut::mime_index_t tut_mime_index("LLMime");
-
-	template<> template<>
-	void mime_index_object_t::test<1>()
-	{
-		LLMimeIndex mime;
-		ensure("no headers", mime.headers().isUndefined());
-		ensure_equals("invalid offset", mime.offset(), -1);
-		ensure_equals("invalid content length", mime.contentLength(), -1);
-		ensure("no content type", mime.contentType().empty());
-		ensure("not multipart", !mime.isMultipart());
-		ensure_equals("no attachments", mime.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<2>()
-	{
-		const S32 CONTENT_LENGTH = 6000;
-		const S32 CONTENT_OFFSET = 100;
-		const std::string CONTENT_TYPE = std::string("image/j2c");
-		LLSD headers;
-		headers["Content-Length"] = CONTENT_LENGTH;
-		headers["Content-Type"] = CONTENT_TYPE;
-		LLMimeIndex mime(headers, CONTENT_OFFSET);
-		ensure("headers are map", mime.headers().isMap());
-		ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
-		ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
-		ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
-		ensure("not multipart", !mime.isMultipart());
-		ensure_equals("no attachments", mime.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<3>()
-	{
-		const S32 MULTI_CONTENT_LENGTH = 8000;
-		const S32 MULTI_CONTENT_OFFSET = 100;
-		const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
-		LLSD headers;
-		headers["Content-Length"] = MULTI_CONTENT_LENGTH;
-		headers["Content-Type"] = MULTI_CONTENT_TYPE;
-		LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
-		LL_INFOS() << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
-			<< LL_ENDL;
-
-
-		const S32 META_CONTENT_LENGTH = 700;
-		const S32 META_CONTENT_OFFSET = 69;
-		const std::string META_CONTENT_TYPE = std::string(
-			"text/llsd+xml");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = META_CONTENT_LENGTH;
-		headers["Content-Type"] = META_CONTENT_TYPE;
-		LLMimeIndex meta(headers, META_CONTENT_OFFSET);
-		mime.attachSubPart(meta);
-
-		const S32 IMAGE_CONTENT_LENGTH = 6000;
-		const S32 IMAGE_CONTENT_OFFSET = 200;
-		const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
-		headers["Content-Type"] = IMAGE_CONTENT_TYPE;
-		LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
-		mime.attachSubPart(image);
-
-		// make sure we have a valid multi-part
-		ensure("is multipart", mime.isMultipart());
-		ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
-		ensure_equals(
-			"multi content length",
-			mime.contentLength(),
-			MULTI_CONTENT_LENGTH);
-		ensure_equals("two attachments", mime.subPartCount(), 2);
-
-		// make sure ranged gets do the right thing with out of bounds
-		// sub-parts.
-		LLMimeIndex invalid_child(mime.subPart(-1));
-		ensure("no headers", invalid_child.headers().isUndefined());
-		ensure_equals("invalid offset", invalid_child.offset(), -1);
-		ensure_equals(
-			"invalid content length", invalid_child.contentLength(), -1);
-		ensure("no content type", invalid_child.contentType().empty());
-		ensure("not multipart", !invalid_child.isMultipart());
-		ensure_equals("no attachments", invalid_child.subPartCount(), 0);
-
-		invalid_child = mime.subPart(2);
-		ensure("no headers", invalid_child.headers().isUndefined());
-		ensure_equals("invalid offset", invalid_child.offset(), -1);
-		ensure_equals(
-			"invalid content length", invalid_child.contentLength(), -1);
-		ensure("no content type", invalid_child.contentType().empty());
-		ensure("not multipart", !invalid_child.isMultipart());
-		ensure_equals("no attachments", invalid_child.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<4>()
-	{
-		const S32 MULTI_CONTENT_LENGTH = 8000;
-		const S32 MULTI_CONTENT_OFFSET = 100;
-		const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
-		LLSD headers;
-		headers["Content-Length"] = MULTI_CONTENT_LENGTH;
-		headers["Content-Type"] = MULTI_CONTENT_TYPE;
-		LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
-
-		const S32 META_CONTENT_LENGTH = 700;
-		const S32 META_CONTENT_OFFSET = 69;
-		const std::string META_CONTENT_TYPE = std::string(
-			"application/llsd+xml");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = META_CONTENT_LENGTH;
-		headers["Content-Type"] = META_CONTENT_TYPE;
-		LLMimeIndex meta(headers, META_CONTENT_OFFSET);
-		mime.attachSubPart(meta);
-
-		const S32 IMAGE_CONTENT_LENGTH = 6000;
-		const S32 IMAGE_CONTENT_OFFSET = 200;
-		const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
-		headers["Content-Type"] = IMAGE_CONTENT_TYPE;
-		LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
-		mime.attachSubPart(image);
-
-		// check what we have
-		ensure("is multipart", mime.isMultipart());
-		ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
-		ensure_equals(
-			"multi content length",
-			mime.contentLength(),
-			MULTI_CONTENT_LENGTH);
-		ensure_equals("two attachments", mime.subPartCount(), 2);
-
-		LLMimeIndex actual_meta = mime.subPart(0);
-		ensure_equals(
-			"meta type", actual_meta.contentType(), META_CONTENT_TYPE);
-		ensure_equals(
-			"meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
-		ensure_equals(
-			"meta content length",
-			actual_meta.contentLength(),
-			META_CONTENT_LENGTH);
-
-		LLMimeIndex actual_image = mime.subPart(1);
-		ensure_equals(
-			"image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
-		ensure_equals(
-			"image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
-		ensure_equals(
-			"image content length",
-			actual_image.contentLength(),
-			IMAGE_CONTENT_LENGTH);
-	}
-
-/*
-	template<> template<>
-	void mime_index_object_t::test<5>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<6>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<7>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<8>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<>()
-	{
-	}
-*/
-}
-
-
-namespace tut
-{
-	struct mime_parse
-	{
-	};
-	typedef test_group<mime_parse> mime_parse_t;
-	typedef mime_parse_t::object mime_parse_object_t;
-	tut::mime_parse_t tut_mime_parse("LLMimeParse");
-
-	template<> template<>
-	void mime_parse_object_t::test<1>()
-	{
-		// parse one mime object
-		const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure_equals("content type", mime.contentType(), "text/plain");
-		ensure_equals("content length", mime.contentLength(), 200);
-		ensure_equals("offset", mime.offset(), 49);
- 	}
-
-	template<> template<>
-	void mime_parse_object_t::test<2>()
-	{
-		// make sure we only parse one.
-		const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("not multipart.", !mime.isMultipart());
-		ensure_equals("content type", mime.contentType(), "text/plain");
-		ensure_equals("content length", mime.contentLength(), 200);
-		ensure_equals("offset", mime.offset(), 49);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<3>()
-	{
-		// test multi-part and lack of content length for some of it.
-		/*
-Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
-		 */
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 150);
-		ensure_equals("data offset for multipart", mime.offset(), 74);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length not known.",
-			mime_plain.contentLength(),
-			-1);
-		ensure_equals("first part offset", mime_plain.offset(), 113);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 198);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<4>()
-	{
-		// test multi-part, unquoted separator, and premature eof conditions
-		/*
-Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn		 */
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 220);
-		ensure_equals("data offset for multipart", mime.offset(), 72);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-		ensure_equals("first part offset", mime_plain.offset(), 131);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 262);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<5>()
-	{
-		// test multi-part with multiple params
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 220);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<6>()
-	{
-		// test multi-part with no specified boundary and eof
-/*
-Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
-*/
-		const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 500);
-		ensure_equals("data offset for multipart", mime.offset(), 56);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-		ensure_equals("first part offset", mime_plain.offset(), 108);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 232);
-	}
-
-/*
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-*/
-}
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
deleted file mode 100755
index 5b89f2a8c672d2a089d59497c4c9a2981aa9ca79..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/llregionpresenceverifier_test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/** 
- * @file 
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "../test/lltut.h"
-#include "llregionpresenceverifier.h"
-#include "llcurl_stub.cpp"
-#include "llhost.cpp"
-#include "net.cpp"
-#include "lltesthttpclientadapter.cpp"
-
-class LLTestResponse : public LLRegionPresenceVerifier::Response
-{
-public:
-
-	virtual bool checkValidity(const LLSD& content) const
-	{
-		return true;
-	}
-
-	virtual void onRegionVerified(const LLSD& region_details)
-	{
-	}
-
-	virtual void onRegionVerificationFailed()
-	{
-	}
-	
-	virtual LLHTTPClientInterface& getHttpClient()
-	{
-		return mHttpInterface;
-	}
-
-	LLTestHTTPClientAdapter mHttpInterface;
-};
-
-namespace tut
-{
-	struct LLRegionPresenceVerifierData
-	{
-		LLRegionPresenceVerifierData() :
-			mResponse(new LLTestResponse()),
-			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
-					   LLSD(), 3)
-		{
-		}
-		
-		LLTestResponse* mResponse;
-		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
-	};
-
-	typedef test_group<LLRegionPresenceVerifierData> factory;
-	typedef factory::object object;
-}
-
-namespace
-{
-	tut::factory tf("LLRegionPresenceVerifier");
-}
-
-namespace tut
-{
-	// Test that VerifiedDestinationResponder does retry
-    // on error when shouldRetry returns true.
-	template<> template<>
-	void object::test<1>()
-	{
-		mResponder.error(500, "Internal server error");
-		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
-	}
-
-	// Test that VerifiedDestinationResponder only retries
-	// on error until shouldRetry returns false.
-	template<> template<>
-	void object::test<2>()
-	{
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
-	}
-}
-
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index b287a2984199429f4f7b3d4904dd319f560b4187..55748ad27e36d2c4fc0c34fea63bea8bd6995f09 100755
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -32,6 +32,7 @@
 
 #include "message.h"
 #include "llmessageconfig.h"
+#include "llhttpnode_stub.cpp"
 
 LLMessageSystem* gMessageSystem = NULL;
 
diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp
index f64b26422201e162d0fe286e339e4d0c0377f87b..a5d717389d52a9484ff68cb55bd5646e30c670bc 100755
--- a/indra/llplugin/llplugincookiestore.cpp
+++ b/indra/llplugin/llplugincookiestore.cpp
@@ -27,6 +27,7 @@
  */
 
 #include "linden_common.h"
+#include "llstl.h"
 #include "indra_constants.h"
 
 #include "llplugincookiestore.h"
@@ -654,12 +655,8 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
 
 void LLPluginCookieStore::clearCookies()
 {
-	while(!mCookies.empty())
-	{
-		cookie_map_t::iterator iter = mCookies.begin();
-		delete iter->second;
-		mCookies.erase(iter);
-	}
+	std::for_each(mCookies.begin(), mCookies.end(), DeletePairedPointer());
+	mCookies.clear();
 }
 
 void LLPluginCookieStore::removeCookie(const std::string &key)
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index ea0d2b81f1b3de6c17e710855bb446372a7af22d..b5a2588e1e70a152e1fc8fac8a1dbdc4789120c0 100755
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -131,6 +131,8 @@ LLPluginProcessParent::~LLPluginProcessParent()
 	{
 		// destroy the shared memory region
 		iter->second->destroy();
+		delete iter->second;
+		iter->second = NULL;
 		
 		// and remove it from our map
 		mSharedMemoryRegions.erase(iter);
@@ -960,6 +962,8 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 			{
 				// destroy the shared memory region
 				iter->second->destroy();
+				delete iter->second;
+				iter->second = NULL;
 				
 				// and remove it from our map
 				mSharedMemoryRegions.erase(iter);
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 44e6b97b315830c3ee5ef820d5581be15efca02a..e24d3bb5ba2388ebbe4e7585d394b445c648b7ec 100755
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -610,6 +610,7 @@ bool LLGLManager::initGL()
 	if (mGLVendor.substr(0,4) == "ATI ")
 	{
 		mGLVendorShort = "ATI";
+		// *TODO: Fix this?
 		mIsATI = TRUE;
 
 #if LL_WINDOWS && !LL_MESA_HEADLESS
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ddf38c674567b9d78f6a2ca1891d8b7245afc7eb..ebed4542712a03625b12d2862252e75305a19993 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -390,9 +390,7 @@ LLImageGL::~LLImageGL()
 {
 	LLImageGL::cleanup();
 	sImageList.erase(this);
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
+	freePickMask();
 	sCount--;
 }
 
@@ -461,6 +459,8 @@ void LLImageGL::cleanup()
 	{
 		destroyGLTexture();
 	}
+	freePickMask();
+
 	mSaveData = NULL; // deletes data
 }
 
@@ -504,10 +504,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
 		}
 
 		// pickmask validity depends on old image size, delete it
-		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-		delete [] mPickMask;
-		mPickMask = NULL;
-		mPickMaskWidth = mPickMaskHeight = 0;
+		freePickMask();
 
 		mWidth = width;
 		mHeight = height;
@@ -1885,6 +1882,37 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
 	}
 }
 
+//----------------------------------------------------------------------------
+U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
+{
+	U32 pick_width = pWidth/2 + 1;
+	U32 pick_height = pHeight/2 + 1;
+
+	U32 size = pick_width * pick_height;
+	size = (size + 7) / 8; // pixelcount-to-bits
+	mPickMask = new U8[size];
+	claimMem(size);
+	mPickMaskWidth = pick_width - 1;
+	mPickMaskHeight = pick_height - 1;
+
+	memset(mPickMask, 0, sizeof(U8) * size);
+
+	return size;
+}
+
+//----------------------------------------------------------------------------
+void LLImageGL::freePickMask()
+{
+	// pickmask validity depends on old image size, delete it
+	if (mPickMask != NULL)
+	{
+		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
+		delete [] mPickMask;
+	}
+	mPickMask = NULL;
+	mPickMaskWidth = mPickMaskHeight = 0;
+}
+
 //----------------------------------------------------------------------------
 void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 {
@@ -1893,10 +1921,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return ;
 	}
 
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
-	mPickMaskWidth = mPickMaskHeight = 0;
+	freePickMask();
 
 	if (mFormatType != GL_UNSIGNED_BYTE ||
 	    mFormatPrimary != GL_RGBA)
@@ -1905,17 +1930,11 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return;
 	}
 
-	U32 pick_width = width/2 + 1;
-	U32 pick_height = height/2 + 1;
-
-	U32 size = pick_width * pick_height;
-	size = (size + 7) / 8; // pixelcount-to-bits
-	mPickMask = new U8[size];
-	claimMem(size);
-	mPickMaskWidth = pick_width - 1;
-	mPickMaskHeight = pick_height - 1;
-
-	memset(mPickMask, 0, sizeof(U8) * size);
+#ifdef SHOW_ASSERT
+	const U32 pickSize = createPickMask(width, height);
+#else // SHOW_ASSERT
+	createPickMask(width, height);
+#endif // SHOW_ASSERT
 
 	U32 pick_bit = 0;
 	
@@ -1929,7 +1948,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 			{
 				U32 pick_idx = pick_bit/8;
 				U32 pick_offset = pick_bit%8;
-				llassert(pick_idx < size);
+				llassert(pick_idx < pickSize);
 
 				mPickMask[pick_idx] |= 1 << pick_offset;
 			}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6ca814af6fc6732bcbe174cdfc1d634d84bcb2b5..21982eab1dd8276a575399dafa364b00be4a0e91 100755
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -186,6 +186,9 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>
 	mutable F32  mLastBindTime;	// last time this was bound, by discard level
 	
 private:
+	U32 createPickMask(S32 pWidth, S32 pHeight);
+	void freePickMask();
+
 	LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
 	U8* mPickMask;  //downsampled bitmap approximation of alpha channel.  NULL if no alpha channel
 	U16 mPickMaskWidth;
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
index 1860a05eddc2b7a6fadea30ce4fbf6c6ace14ef1..55e64bb9405a3a57ca91966c415c2d63d86e2978 100755
--- a/indra/llui/llbadgeowner.cpp
+++ b/indra/llui/llbadgeowner.cpp
@@ -35,8 +35,9 @@
 //
 
 LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
-	: mBadge(NULL)
-	, mBadgeOwnerView(viewHandle)
+	: mHasBadgeHolderParent(false),
+	mBadge(NULL),
+	mBadgeOwnerView(viewHandle)
 {
 }
 
@@ -45,31 +46,12 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
 	if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
 	{
 		mBadge = createBadge(p);
-	}
-}
-
-void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
-{
-	if (mBadge == NULL)
-	{
-		mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
-
-		addBadgeToParentPanel();
-	}
-
-	if (mBadge)
-	{
-		mBadge->setLabel(label);
-
-		//
-		// Push the badge to the front so it renders on top
-		//
-
-		LLView * parent = mBadge->getParent();
+		mHasBadgeHolderParent = false;
 
-		if (parent)
+		LLView * owner_view = mBadgeOwnerView.get();
+		if (owner_view)
 		{
-			parent->sendChildToFront(mBadge);
+			mBadge->addToView(owner_view);
 		}
 	}
 }
@@ -82,10 +64,8 @@ void LLBadgeOwner::setBadgeVisibility(bool visible)
 	}
 }
 
-bool LLBadgeOwner::addBadgeToParentPanel()
+void LLBadgeOwner::addBadgeToParentHolder()
 {
-	bool badge_added = false;
-
 	LLView * owner_view = mBadgeOwnerView.get();
 	
 	if (mBadge && owner_view)
@@ -110,16 +90,9 @@ bool LLBadgeOwner::addBadgeToParentPanel()
 
 		if (badge_holder)
 		{
-			badge_added = badge_holder->addBadge(mBadge);
-		}
-		else
-		{
-			// Badge parent is fallback badge owner if no valid holder exists in the hierarchy
-			badge_added = mBadge->addToView(owner_view);
+			mHasBadgeHolderParent = badge_holder->addBadge(mBadge);
 		}
 	}
-
-	return badge_added;
 }
 
 LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
index 8d03e30645089aa1bf373dba40021f0cc9cea016..53c2de95c8d8131b34655861672101800739c42b 100755
--- a/indra/llui/llbadgeowner.h
+++ b/indra/llui/llbadgeowner.h
@@ -41,11 +41,9 @@ class LLBadgeOwner
 	LLBadgeOwner(LLHandle< LLView > viewHandle);
 
 	void initBadgeParams(const LLBadge::Params& p);
-	bool addBadgeToParentPanel();
+	void addBadgeToParentHolder();
 	
-	bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
-
-	void setBadgeLabel(const LLStringExplicit& label);
+	bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; };
 	void setBadgeVisibility(bool visible);
 
 private:
@@ -53,7 +51,7 @@ class LLBadgeOwner
 	LLBadge* createBadge(const LLBadge::Params& p);
 
 private:
-
+	bool				mHasBadgeHolderParent;
 	LLBadge*			mBadge;
 	LLHandle< LLView >	mBadgeOwnerView;
 };
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 093d91d44deecb7e9d42f83c4570540365d67fd2..ce8383857c33eb40920ba05caf565856e32b5571 100755
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -384,7 +384,7 @@ BOOL LLButton::postBuild()
 {
 	autoResize();
 
-	addBadgeToParentPanel();
+	addBadgeToParentHolder();
 
 	return LLUICtrl::postBuild();
 }
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 62c923f6f01669c53d894418641230f77a217ac5..3dbc9a5902d530ae0bfb2c66c22ccd301faaee40 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1634,7 +1634,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
 
 
 // virtual
-void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
+void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
 {
 	LLMultiFloater* hostp = getHost();
 	if (hostp)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 199db85747949007842f60f9ecad54a194ca00f7..ef7c6180d25e579d5d828d60d9bae226cdad7cde 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -311,7 +311,7 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
 	/*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override
 	
 	void			setFrontmost(BOOL take_focus = TRUE);
-    virtual void	setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());    
+     virtual void	setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
 	
 	// Defaults to false.
 	virtual BOOL	canSaveAs() const { return FALSE; }
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index b92e29834892085a836652bb11b926e720f31528..bc2388dd280aee390d42a41d0f774888ef1cfda5 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -227,10 +227,11 @@ LLFolderView::LLFolderView(const Params& p)
 	mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p);
 	mStatusTextBox->setFollowsLeft();
 	mStatusTextBox->setFollowsTop();
-	//addChild(mStatusTextBox);
+	addChild(mStatusTextBox);
 
 
 	// make the popup menu available
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 	if (!menu)
 	{
@@ -703,8 +704,9 @@ void LLFolderView::finishRenamingItem( void )
 
 	closeRenamer();
 
+	// This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611).
 	// List is re-sorted alphabetically, so scroll to make sure the selected item is visible.
-	scrollToShowSelection();
+	//scrollToShowSelection();
 }
 
 void LLFolderView::closeRenamer( void )
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index d410a2de3394ed7daa909b9fd544890e4ffe6ce1..b09c9277828f94b8d1d6c40972d510a71192a6d1 100755
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -192,6 +192,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
 	setPrevalidateInput(p.prevalidate_input_callback());
 	setPrevalidate(p.prevalidate_callback());
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
 		("menu_text_editor.xml",
 		 LLMenuGL::sMenuContainer,
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 0609cd8b423c28a2492e9d0dda44ac976f275063..303afcda15154d000fe36a35c92c2463902f9c6c 100755
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -93,6 +93,7 @@ void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition posit
 		return;
 	}
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 	if (!menu)
 	{
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 7383a8c3076f77ce21c25771b75eb644b1cfe821..604dc92789be66ee8df1fc851998f28d35cb45a3 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -63,6 +63,7 @@
 
 // static
 LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL;
+view_listener_t::listener_map_t view_listener_t::sListeners;
 
 S32 MENU_BAR_HEIGHT = 0;
 S32 MENU_BAR_WIDTH = 0;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index feafaab199951d674bce1cc92b79c93a47ddbda1..ae9b169691493e280167a0475bbc58fe3d95219d 100755
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -895,7 +895,8 @@ class view_listener_t : public boost::signals2::trackable
 {
 public:
 	virtual bool handleEvent(const LLSD& userdata) = 0;
-	virtual ~view_listener_t() {}
+	view_listener_t() { sListeners.insert(this); }
+	virtual ~view_listener_t() { sListeners.erase(this); }
 	
 	static void addEnable(view_listener_t* listener, const std::string& name)
 	{
@@ -913,6 +914,20 @@ class view_listener_t : public boost::signals2::trackable
 		addEnable(listener, name);
 		addCommit(listener, name);
 	}
+
+	static void cleanup()
+	{
+		listener_vector_t listeners(sListeners.begin(), sListeners.end());
+		sListeners.clear();
+
+		std::for_each(listeners.begin(), listeners.end(), DeletePointer());
+		listeners.clear();
+	}
+
+private:
+	typedef std::set<view_listener_t*> listener_map_t;
+	typedef std::vector<view_listener_t*> listener_vector_t;
+	static listener_map_t sListeners;
 };
 
 #endif // LL_LLMENUGL_H
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 3708071e11aba72501e8d36045e3dc73427ae3f7..5f72ee3ac637e99133e37d0399a41027cc95bf9e 100755
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1815,6 +1815,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
 			// create the context menu from the XUI file and display it
 			std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
 			delete mPopupMenu;
+			llassert(LLMenuGL::sMenuContainer != NULL);
 			mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 				menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 			if (mPopupMenu)
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index ebc6183b8befc8ba577471949b9ef5899805318a..6f858cdeb36b558bb4033d5df7d24e0ef6890208 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1140,6 +1140,17 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			addChild( btn, 0 );
 		}
 	}
+	else
+	{
+		if (textbox)
+		{
+			LLUICtrl::addChild(textbox, 0);
+		}
+		if (btn)
+		{
+			LLUICtrl::addChild(btn, 0);
+		}
+	}
 
 	if (child)
 	{
@@ -1636,16 +1647,26 @@ void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
 {
 	LLTabTuple* tuple = getTabByPanel(child);
 	LLCustomButtonIconCtrl* button;
+	bool hasButton = false;
 
 	if(tuple)
 	{
 		button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
 		if(button)
 		{
+			hasButton = true;
 			button->setIcon(icon);
 			reshapeTuple(tuple);
 		}
 	}
+
+	if (!hasButton && (icon != NULL))
+	{
+		// It was assumed that the tab's button would take ownership of the icon pointer.
+		// But since the tab did not have a button, kill the icon to prevent the memory
+		// leak.
+		icon->die();
+	}
 }
 
 void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 62edbadb0776e4dbde38cf6090261c9845086a6e..8906a6e736f11bdcefe13792cd840e2e44083343 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1955,6 +1955,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
 
 	// create and return the context menu from the XUI file
 	delete mPopupMenu;
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
 																		 LLMenuHolderGL::child_registry_t::instance());	
 	if (mIsFriendSignal)
@@ -2037,7 +2038,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 		LLUrlMatch match;
 		std::string text = new_text;
 		while ( LLUrlRegistry::instance().findUrl(text, match,
-				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
+				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted()))
 		{
 			start = match.getStart();
 			end = match.getEnd()+1;
@@ -2074,7 +2075,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 					}
 			}
 
-			LLTextUtil::processUrlMatch(&match,this);
+			LLTextUtil::processUrlMatch(&match,this,isContentTrusted());
 
 			// move on to the rest of the text after the Url
 			if (end < (S32)text.length()) 
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d1f66b6cfe002fb28fa65b8d6328b61f6e3ed43f..ecbfdaf84c0c34e95a00d157ce231b6361c60d5e 100755
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -367,7 +367,9 @@ class LLTextBase
 	bool					getWordWrap() { return mWordWrap; }
 	bool					getUseEllipses() { return mUseEllipses; }
 	bool					truncate(); // returns true of truncation occurred
+
 	bool					isContentTrusted() {return mTrustedContent;}
+	void					setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; }
 
 	// TODO: move into LLTextSegment?
 	void					createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index c797b6acc557d91e2e5861ad145f61fba24becd1..b4ebed084963c5c7799ee751e00b332992e45b94 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2031,6 +2031,7 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)
 {
 	if (!mContextMenu)
 	{
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml", 
 																				LLMenuGL::sMenuContainer, 
 																				LLMenuHolderGL::child_registry_t::instance());
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index 4df2c3363f333f7bfdcedab1712b94ea5401172f..fff04b34f28d68b6df80c1268da80c85da02cf30 100755
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -72,7 +72,7 @@ const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
 	return formatted_phone_str;
 }
 
-bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
+bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted)
 {
 	if (match == 0 || text_base == 0)
 		return false;
@@ -85,7 +85,7 @@ bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
 	}
 
 	// output an optional icon before the Url
-	if (!match->getIcon().empty() )
+	if (is_content_trusted && !match->getIcon().empty() )
 	{
 		LLUIImagePtr image = LLUI::getUIImage(match->getIcon());
 		if (image)
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index bf7dbb58ce0144930352012cc3678ef5c412d6c6..798f14d086bf5f0a9f3eb76d7e8f5dc9bf69664d 100755
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -64,7 +64,7 @@ namespace LLTextUtil
 	 */
 	const std::string& formatPhoneNumber(const std::string& phone_str);
 
-	bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base);
+	bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted);
 
 	class TextHelpers
 	{
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index f9bdd87087af3b331d7131461bf6130939235f5c..abc2b6e9cac2025efa9983566c81e7d9a81d99d1 100755
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -148,6 +148,7 @@ void LLToolBar::createContextMenu()
 		enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2));
 
 		// Create the context menu
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_toolbars.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 
 		if (menu)
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 523ee5d78c6534c1682d4aee4f166b52c92b4bab..bccc646821198499fedad53d6dba908748809941 100755
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -41,7 +41,8 @@ LLUrlRegistry::LLUrlRegistry()
 
 	// Urls are matched in the order that they were registered
 	registerUrl(new LLUrlEntryNoLink());
-	registerUrl(new LLUrlEntryIcon());
+	mUrlEntryIcon = new LLUrlEntryIcon();
+	registerUrl(mUrlEntryIcon);
 	registerUrl(new LLUrlEntrySLURL());
 	registerUrl(new LLUrlEntryHTTP());
 	registerUrl(new LLUrlEntryHTTPLabel());
@@ -145,7 +146,7 @@ static bool stringHasUrl(const std::string &text)
 			text.find("<icon") != std::string::npos);
 }
 
-bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted)
 {
 	// avoid costly regexes if there is clearly no URL in the text
 	if (! stringHasUrl(text))
@@ -160,6 +161,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
 	std::vector<LLUrlEntryBase *>::iterator it;
 	for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
 	{
+		//Skip for url entry icon if content is not trusted
+		if(!is_content_trusted && (mUrlEntryIcon == *it))
+		{
+			continue;
+		}
+
 		LLUrlEntryBase *url_entry = *it;
 
 		U32 start = 0, end = 0;
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index da16171a9753f9c0c76fc2ab573481d45dcbc888..6270df1bbbf22a7cb57733aded8bbd4dc28d205d 100755
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -73,7 +73,8 @@ class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
 	/// get the next Url in an input string, starting at a given character offset
 	/// your callback is invoked if the matched Url's label changes in the future
 	bool findUrl(const std::string &text, LLUrlMatch &match,
-				 const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+				 const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback,
+				 bool is_content_trusted = false);
 
 	/// a slightly less efficient version of findUrl for wide strings
 	bool findUrl(const LLWString &text, LLUrlMatch &match,
@@ -92,6 +93,7 @@ class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
 	friend class LLSingleton<LLUrlRegistry>;
 
 	std::vector<LLUrlEntryBase *> mUrlEntry;
+	LLUrlEntryBase*	mUrlEntryIcon;
 };
 
 #endif
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 0637572f6710101ba1ccd875402c9cdcb4e67c0f..19961d5759088a355fea472da70029f16fc6489e 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -657,7 +657,7 @@ LLWindowWin32::~LLWindowWin32()
 	delete [] mSupportedResolutions;
 	mSupportedResolutions = NULL;
 
-	delete mWindowClassName;
+	delete [] mWindowClassName;
 	mWindowClassName = NULL;
 }
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 02b7b02c98af25c60206edeaab52dd9e212aef18..6757e6c66666fa4f856c53b13183b212e8ccb21d 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -99,6 +99,7 @@ include_directories(SYSTEM
 set(viewer_SOURCE_FILES
     groupchatlistener.cpp
     llaccountingcostmanager.cpp
+    llaisapi.cpp
     llagent.cpp
     llagentaccess.cpp
     llagentcamera.cpp
@@ -109,7 +110,6 @@ set(viewer_SOURCE_FILES
     llagentpilot.cpp
     llagentui.cpp
     llagentwearables.cpp
-    llagentwearablesfetch.cpp
     llanimstatelabels.cpp
     llappcorehttp.cpp
     llappearancemgr.cpp
@@ -317,6 +317,7 @@ set(viewer_SOURCE_FILES
     llhasheduniqueid.cpp
     llhints.cpp
     llhomelocationresponder.cpp
+    llhttpretrypolicy.cpp
     llhudeffect.cpp
     llhudeffectbeam.cpp
     llhudeffectlookat.cpp
@@ -695,6 +696,7 @@ set(viewer_HEADER_FILES
     groupchatlistener.h
     llaccountingcost.h
     llaccountingcostmanager.h
+    llaisapi.h
     llagent.h
     llagentaccess.h
     llagentcamera.h
@@ -705,7 +707,6 @@ set(viewer_HEADER_FILES
     llagentpilot.h
     llagentui.h
     llagentwearables.h
-    llagentwearablesfetch.h
     llanimstatelabels.h
     llappcorehttp.h
     llappearance.h
@@ -915,6 +916,7 @@ set(viewer_HEADER_FILES
     llgroupmgr.h
     llhasheduniqueid.h
     llhints.h
+    llhttpretrypolicy.h
     llhomelocationresponder.h
     llhudeffect.h
     llhudeffectbeam.h
@@ -2178,10 +2180,21 @@ if (LL_TESTS)
     #llviewertexturelist.cpp
   )
 
+  set(test_libs
+    ${JSONCPP_LIBRARIES}
+    ${CURL_LIBRARIES}
+    )
+
   set_source_files_properties(
     lltranslate.cpp
     PROPERTIES
-    LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}"
+    LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
+  )
+
+  set_source_files_properties(
+    llmediadataclient.cpp
+    PROPERTIES
+    LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}"
   )
 
   set_source_files_properties(
@@ -2262,6 +2275,7 @@ if (LL_TESTS)
 
   set(test_libs
     ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
@@ -2302,6 +2316,8 @@ if (LL_TESTS)
     "${test_libs}"
     )
 
+  LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}")
+
   #ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
   #ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
   #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index c77a7de85cc8816ef82364aadd61a614b8650ce0..f06fb9e9156b751b9baf03ccda308f325d4cb825 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.9
+3.7.10
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 7da047aed5ae7d068d2713d37d23fcea61e045df..15cb5bc0ebd8f47778ca03807261ccc44c50d1eb 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,6 +43,7 @@
 					<key>tags</key>
 						<array>
 						<!-- sample entry for debugging specific items	
+						     <string>Inventory</string>
 						     <string>SceneLoadTiming</string>
 						     <string>Avatar</string>
 						     <string>Voice</string>		
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4a5e1229d114de999b54c85ab0052c0ba99ea358..7dde3ec84b0e6cddfe700a59127040ce6fdf47fc 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11759,6 +11759,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>TextureFetchFakeFailureRate</key>
+  <map>
+    <key>Comment</key>
+    <string>Simulate HTTP fetch failures for some server bake textures.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <integer>0.0</integer>
+  </map>
     <key>TextureFetchSource</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 6de5b18c3c8c7cd81839f7142029142d4115c804..9ec6428ee65df8a029ba00ab7d055d1bef17a5f1 100755
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -4480,7 +4480,7 @@
      group="1"
      sex="female"
      name="Breast_Physics_UpDown_Driven"
-     wearable="shape"
+     wearable="physics"
      edit_group="driven"
      value_default="0"
      value_min="-3"
@@ -4502,7 +4502,7 @@
      group="1"
      sex="female"
      name="Breast_Physics_InOut_Driven"
-     wearable="shape"
+     wearable="physics"
      edit_group="driven"
      value_default="0"
      value_min="-1.25"
@@ -4524,7 +4524,6 @@
      group="1"
      name="Belly_Physics_Torso_UpDown_Driven"
      wearable="physics"
-     cross_wearable="true"
      edit_group="driven"
      value_default="0"
      value_min="-1"
@@ -4542,7 +4541,6 @@
      group="1"
      name="Breast_Physics_LeftRight_Driven"
      wearable="physics"
-     cross_wearable="true"
      edit_group="driven"
      value_default="0"
      value_min="-2"
@@ -7716,7 +7714,7 @@ render_pass="bump">
 
       <param
        id="868"
-       group="0"
+       group="3"
        wearable="shirt"
        edit_group="shirt"
        edit_group_order="8"
@@ -8839,7 +8837,7 @@ render_pass="bump">
 
       <param
        id="869"
-       group="0"
+       group="3"
        wearable="pants"
        edit_group="pants"
        edit_group_order="6"
@@ -9760,7 +9758,7 @@ render_pass="bump">
 
     <param
      id="163"
-     group="0"
+     group="3"
      wearable="skin"
      edit_group="skin_facedetail"
      edit_group_order="3"
@@ -11819,7 +11817,7 @@ render_pass="bump">
 
     <param
      id="877"
-     group="0"
+     group="3"
      name="Jacket Wrinkles"
      label="Jacket Wrinkles"
      wearable="jacket"
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index 150b97baa5e6ad44dbba99c7d302636b52ebf711..a42286a9e4aabc2fb9b5c7e58df02537784acd98 100755
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -36,6 +36,7 @@ LLAccountingCostManager::LLAccountingCostManager()
 //===============================================================================
 class LLAccountingCostResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLAccountingCostResponder);
 public:
 	LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
 	: mObjectIDs( objectIDs ),
@@ -56,24 +57,27 @@ class LLAccountingCostResponder : public LLCurl::Responder
 		}
 	}
 	
-	void errorWithContent( U32 statusNum, const std::string& reason, const LLSD& content )
+protected:
+	void httpFailure()
 	{
-		LL_WARNS() << "Transport error [status:" << statusNum << "]: " << content <<LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 		clearPendingRequests();
 
 		LLAccountingCostObserver* observer = mObserverHandle.get();
 		if (observer && observer->getTransactionID() == mTransactionID)
 		{
-			observer->setErrorStatus(statusNum, reason);
+			observer->setErrorStatus(getStatus(), getReason());
 		}
 	}
 	
-	void result( const LLSD& content )
+	void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		//Check for error
 		if ( !content.isMap() || content.has("error") )
 		{
-			LL_WARNS()	<< "Error on fetched data"<< LL_ENDL;
+			failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content);
+			return;
 		}
 		else if (content.has("selected"))
 		{
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 0bca1f54ef76a7b078c72d63dd5405bdb27c0bba..3ade34c81d0a6c7a1be2faa010e7ffd06df4427c 100755
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -38,7 +38,7 @@ class LLAccountingCostObserver
 	LLAccountingCostObserver() { mObserverHandle.bind(this); }
 	virtual ~LLAccountingCostObserver() {}
 	virtual void onWeightsUpdate(const SelectionCost& selection_cost) = 0;
-	virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setErrorStatus(S32 status, const std::string& reason) = 0;
 	const LLHandle<LLAccountingCostObserver>& getObserverHandle() const { return mObserverHandle; }
 	const LLUUID& getTransactionID() { return mTransactionID; }
 
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index eb9ca542a3622fdc8f72b743a65266f0b0fdd077..aa8e0bad76daa42558963aec51fdd9c1c023ffed 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -406,7 +406,7 @@ LLAgent::LLAgent() :
 	mNextFidgetTime(0.f),
 	mCurrentFidget(0),
 	mFirstLogin(FALSE),
-	mGenderChosen(FALSE),
+	mOutfitChosen(FALSE),
 	
 	mVoiceConnected(false),
 
@@ -809,30 +809,6 @@ void LLAgent::standUp()
 	setControlFlags(AGENT_CONTROL_STAND_UP);
 }
 
-
-void LLAgent::handleServerBakeRegionTransition(const LLUUID& region_id)
-{
-	LL_INFOS() << "called" << LL_ENDL;
-
-
-	// Old-style appearance entering a server-bake region.
-	if (isAgentAvatarValid() &&
-		!gAgentAvatarp->isUsingServerBakes() &&
-		(mRegionp->getCentralBakeVersion()>0))
-	{
-		LL_INFOS() << "update requested due to region transition" << LL_ENDL;
-		LLAppearanceMgr::instance().requestServerAppearanceUpdate();
-	}
-	// new-style appearance entering a non-bake region,
-	// need to check for existence of the baking service.
-	else if (isAgentAvatarValid() &&
-			 gAgentAvatarp->isUsingServerBakes() &&
-			 mRegionp->getCentralBakeVersion()==0)
-	{
-		gAgentAvatarp->checkForUnsupportedServerBakeAppearance();
-	}
-}
-
 void LLAgent::changeParcels()
 {
 	LL_DEBUGS("AgentLocation") << "Calling ParcelChanged callbacks" << LL_ENDL;
@@ -934,19 +910,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
 
 	LLFloaterMove::sUpdateFlyingStatus();
 
-	// If the newly entered region is using server bakes, and our
-	// current appearance is non-baked, request appearance update from
-	// server.
-	if (mRegionp->capabilitiesReceived())
-	{
-		handleServerBakeRegionTransition(mRegionp->getRegionID());
-	}
-	else
-	{
-		// Need to handle via callback after caps arrive.
-		mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::handleServerBakeRegionTransition,this,_1));
-	}
-
 	if (notifyRegionChange)
 	{
 		LL_DEBUGS("AgentLocation") << "Calling RegionChanged callbacks" << LL_ENDL;
@@ -1917,7 +1880,7 @@ BOOL LLAgent::needsRenderAvatar()
 		return FALSE;
 	}
 
-	return mShowAvatar && mGenderChosen;
+	return mShowAvatar && mOutfitChosen;
 }
 
 // TRUE if we need to render your own avatar's head.
@@ -2565,17 +2528,19 @@ int LLAgent::convertTextToMaturity(char text)
 
 class LLMaturityPreferencesResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLMaturityPreferencesResponder);
 public:
 	LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity);
 	virtual ~LLMaturityPreferencesResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
+protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 protected:
 
 private:
-	U8 parseMaturityFromServerResponse(const LLSD &pContent);
+	U8 parseMaturityFromServerResponse(const LLSD &pContent) const;
 
 	LLAgent                                  *mAgent;
 	U8                                       mPreferredMaturity;
@@ -2594,39 +2559,43 @@ LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder()
 {
 }
 
-void LLMaturityPreferencesResponder::result(const LLSD &pContent)
+void LLMaturityPreferencesResponder::httpSuccess()
 {
-	U8 actualMaturity = parseMaturityFromServerResponse(pContent);
+	U8 actualMaturity = parseMaturityFromServerResponse(getContent());
 
 	if (actualMaturity != mPreferredMaturity)
 	{
-		LL_WARNS() << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
-			<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '"
-			<< LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:"
-			<< pContent << "]" << LL_ENDL;
+		LL_WARNS() << "while attempting to change maturity preference from '"
+				   << LLViewerRegion::accessToString(mPreviousMaturity)
+				   << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
+				   << "', the server responded with '"
+				   << LLViewerRegion::accessToString(actualMaturity) 
+				   << "' [value:" << static_cast<U32>(actualMaturity) 
+				   << "], " << dumpResponse() << LL_ENDL;
 	}
 	mAgent->handlePreferredMaturityResult(actualMaturity);
 }
 
-void LLMaturityPreferencesResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void LLMaturityPreferencesResponder::httpFailure()
 {
-	LL_WARNS() << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
-		<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error with [status:"
-		<< pStatus << "]: " << (pContent.isDefined() ? pContent : LLSD(pReason)) << LL_ENDL;
+	LL_WARNS() << "while attempting to change maturity preference from '" 
+			   << LLViewerRegion::accessToString(mPreviousMaturity)
+			   << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
+			<< "', " << dumpResponse() << LL_ENDL;
 	mAgent->handlePreferredMaturityError();
 }
 
-U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent)
+U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const
 {
 	U8 maturity = SIM_ACCESS_MIN;
 
-	llassert(!pContent.isUndefined());
+	llassert(pContent.isDefined());
 	llassert(pContent.isMap());
 	llassert(pContent.has("access_prefs"));
 	llassert(pContent.get("access_prefs").isMap());
 	llassert(pContent.get("access_prefs").has("max"));
 	llassert(pContent.get("access_prefs").get("max").isString());
-	if (!pContent.isUndefined() && pContent.isMap() && pContent.has("access_prefs")
+	if (pContent.isDefined() && pContent.isMap() && pContent.has("access_prefs")
 		&& pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max")
 		&& pContent.get("access_prefs").get("max").isString())
 	{
@@ -2772,7 +2741,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
 		// If we don't have a region, report it as an error
 		if (getRegion() == NULL)
 		{
-			responderPtr->errorWithContent(0U, "region is not defined", LLSD());
+			responderPtr->failureResult(0U, "region is not defined", LLSD());
 		}
 		else
 		{
@@ -2782,7 +2751,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
 			// If the capability is not defined, report it as an error
 			if (url.empty())
 			{
-				responderPtr->errorWithContent(0U, 
+				responderPtr->failureResult(0U, 
 							"capability 'UpdateAgentInformation' is not defined for region", LLSD());
 			}
 			else
@@ -3330,8 +3299,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
 			!input.has("body") )
 		{
 			//what to do with badly formed message?
-			response->statusUnknownError(400);
-			response->result(LLSD("Invalid message parameters"));
+			response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters"));
 		}
 
 		LLSD body = input["body"];
@@ -3400,8 +3368,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
 		else
 		{
 			//what to do with badly formed message?
-			response->statusUnknownError(400);
-			response->result(LLSD("Invalid message parameters"));
+			response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters"));
 		}
 	}
 };
@@ -3683,82 +3650,6 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
 }
 */
 
-//static
-void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
-{
-	gAgentQueryManager.mNumPendingQueries--;
-	if (gAgentQueryManager.mNumPendingQueries == 0)
-	{
-		selfStopPhase("fetch_texture_cache_entries");
-	}
-
-	if (!isAgentAvatarValid() || gAgentAvatarp->isDead())
-	{
-		LL_WARNS() << "No avatar for user in cached texture update!" << LL_ENDL;
-		return;
-	}
-
-	if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance())
-	{
-		// ignore baked textures when in customize mode
-		return;
-	}
-
-	S32 query_id;
-	mesgsys->getS32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, query_id);
-
-	S32 num_texture_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_WearableData);
-
-
-	S32 num_results = 0;
-	for (S32 texture_block = 0; texture_block < num_texture_blocks; texture_block++)
-	{
-		LLUUID texture_id;
-		U8 texture_index;
-
-		mesgsys->getUUIDFast(_PREHASH_WearableData, _PREHASH_TextureID, texture_id, texture_block);
-		mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block);
-
-
-		if ((S32)texture_index < TEX_NUM_INDICES )
-		{	
-			const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index);
-			if (texture_entry)
-			{
-				EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex;
-
-				if (gAgentQueryManager.mActiveCacheQueries[baked_index] == query_id)
-				{
-					if (texture_id.notNull())
-					{
-						//LL_INFOS() << "Received cached texture " << (U32)texture_index << ": " << texture_id << LL_ENDL;
-						gAgentAvatarp->setCachedBakedTexture((ETextureIndex)texture_index, texture_id);
-						//gAgentAvatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id );
-						gAgentQueryManager.mActiveCacheQueries[baked_index] = 0;
-						num_results++;
-					}
-					else
-					{
-						// no cache of this bake. request upload.
-						gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE);
-					}
-				}
-			}
-		}
-	}
-	LL_INFOS() << "Received cached texture response for " << num_results << " textures." << LL_ENDL;
-	gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
-
-	gAgentAvatarp->updateMeshTextures();
-
-	if (gAgentQueryManager.mNumPendingQueries == 0)
-	{
-		// RN: not sure why composites are disabled at this point
-		gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
-		gAgent.sendAgentSetAppearance();
-	}
-}
-
 BOOL LLAgent::anyControlGrabbed() const
 {
 	for (U32 i = 0; i < TOTAL_CONTROLS; i++)
@@ -4351,192 +4242,6 @@ void LLAgent::requestLeaveGodMode()
 	sendReliableMessage();
 }
 
-// For debugging, trace agent state at times appearance message are sent out.
-void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
-{
-	std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml");
-
-	LLAPRFile outfile;
-	std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
-	outfile.open(fullpath, LL_APR_WB );
-	apr_file_t* file = outfile.getFileHandle();
-	if (!file)
-	{
-		return;
-	}
-	else
-	{
-		LL_DEBUGS("Avatar") << "dumping sent appearance message to " << fullpath << LL_ENDL;
-	}
-
-	LLVisualParam* appearance_version_param = gAgentAvatarp->getVisualParam(11000);
-	if (appearance_version_param)
-	{
-		F32 value = appearance_version_param->getWeight();
-		dump_visual_param(file, appearance_version_param, value);
-	}
-	for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
-		 iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
-		 ++iter)
-	{
-		const ETextureIndex index = iter->first;
-		const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
-		if (texture_dict->mIsBakedTexture)
-		{
-			LLTextureEntry* entry = gAgentAvatarp->getTE((U8) index);
-			const LLUUID& uuid = entry->getID();
-			apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", index, uuid.asString().c_str());
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-// sendAgentSetAppearance()
-//-----------------------------------------------------------------------------
-void LLAgent::sendAgentSetAppearance()
-{
-	if (gAgentQueryManager.mNumPendingQueries > 0) 
-	{
-		return;
-	}
-
-	if (!isAgentAvatarValid() || (getRegion() && getRegion()->getCentralBakeVersion())) return;
-
-	// At this point we have a complete appearance to send and are in a non-baking region.
-	// DRANO FIXME
-	//gAgentAvatarp->setIsUsingServerBakes(FALSE);
-	S32 sb_count, host_count, both_count, neither_count;
-	gAgentAvatarp->bakedTextureOriginCounts(sb_count, host_count, both_count, neither_count);
-	if (both_count != 0 || neither_count != 0)
-	{
-		LL_WARNS() << "bad bake texture state " << sb_count << "," << host_count << "," << both_count << "," << neither_count << LL_ENDL;
-	}
-	if (sb_count != 0 && host_count == 0)
-	{
-		gAgentAvatarp->setIsUsingServerBakes(true);
-	}
-	else if (sb_count == 0 && host_count != 0)
-	{
-		gAgentAvatarp->setIsUsingServerBakes(false);
-	}
-	else if (sb_count + host_count > 0)
-	{
-		LL_WARNS() << "unclear baked texture state, not sending appearance" << LL_ENDL;
-		return;
-	}
-	
-	
-	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL;
-	//dumpAvatarTEs( "sendAgentSetAppearance()" );
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_AgentSetAppearance);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, getID());
-	msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
-
-	// correct for the collision tolerance (to make it look like the 
-	// agent is actually walking on the ground/object)
-	// NOTE -- when we start correcting all of the other Havok geometry 
-	// to compensate for the COLLISION_TOLERANCE ugliness we will have 
-	// to tweak this number again
-	const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset;
-	msg->addVector3Fast(_PREHASH_Size, body_size);	
-
-	// To guard against out of order packets
-	// Note: always start by sending 1.  This resets the server's count. 0 on the server means "uninitialized"
-	mAppearanceSerialNum++;
-	msg->addU32Fast(_PREHASH_SerialNum, mAppearanceSerialNum );
-
-	// is texture data current relative to wearables?
-	// KLW - TAT this will probably need to check the local queue.
-	BOOL textures_current = gAgentAvatarp->areTexturesCurrent();
-
-	for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
-	{
-		const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
-
-		// if we're not wearing a skirt, we don't need the texture to be baked
-		if (texture_index == TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
-		{
-			continue;
-		}
-
-		// IMG_DEFAULT_AVATAR means not baked. 0 index should be ignored for baked textures
-		if (!gAgentAvatarp->isTextureDefined(texture_index, 0))
-		{
-			LL_DEBUGS("Avatar") << "texture not current for baked " << (S32)baked_index << " local " << (S32)texture_index << LL_ENDL;
-			textures_current = FALSE;
-			break;
-		}
-	}
-
-	// only update cache entries if we have all our baked textures
-
-	// FIXME DRANO need additional check for not in appearance editing
-	// mode, if still using local composites need to set using local
-	// composites to false, and update mesh textures.
-	if (textures_current)
-	{
-		bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
-		std::string dump_prefix = gAgentAvatarp->getFullname() + "_sent_appearance";
-		if (enable_verbose_dumps)
-		{
-			dumpSentAppearance(dump_prefix);
-		}
-		LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL;
-		for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
-		{
-			BOOL generate_valid_hash = TRUE;
-			if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLAvatarAppearanceDefines::EBakedTextureIndex)baked_index))
-			{
-				generate_valid_hash = FALSE;
-				LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL;
-			}
-
-			const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);
-			if (hash.notNull())
-			{
-				ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index);
-				msg->nextBlockFast(_PREHASH_WearableData);
-				msg->addUUIDFast(_PREHASH_CacheID, hash);
-				msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index);
-			}
-		}
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		gAgentAvatarp->sendAppearanceMessage( gMessageSystem );
-	}
-	else
-	{
-		// If the textures aren't baked, send NULL for texture IDs
-		// This means the baked texture IDs on the server will be untouched.
-		// Once all textures are baked, another AvatarAppearance message will be sent to update the TEs
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0);
-	}
-
-
-	S32 transmitted_params = 0;
-	for (LLViewerVisualParam* param = (LLViewerVisualParam*)gAgentAvatarp->getFirstVisualParam();
-		 param;
-		 param = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam())
-	{
-		if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
-		{
-			msg->nextBlockFast(_PREHASH_VisualParam );
-			
-			// We don't send the param ids.  Instead, we assume that the receiver has the same params in the same sequence.
-			const F32 param_value = param->getWeight();
-			const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight());
-			msg->addU8Fast(_PREHASH_ParamValue, new_weight );
-			transmitted_params++;
-		}
-	}
-
-	//LL_INFOS() << "Avatar XML num VisualParams transmitted = " << transmitted_params << LL_ENDL;
-	sendReliableMessage();
-}
-
 void LLAgent::sendAgentDataUpdateRequest()
 {
 	gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest);
@@ -4679,23 +4384,6 @@ void LLAgent::renderAutoPilotTarget()
 
 /********************************************************************************/
 
-LLAgentQueryManager gAgentQueryManager;
-
-LLAgentQueryManager::LLAgentQueryManager() :
-	mWearablesCacheQueryID(0),
-	mNumPendingQueries(0),
-	mUpdateSerialNum(0)
-{
-	for (U32 i = 0; i < BAKED_NUM_INDICES; i++)
-	{
-		mActiveCacheQueries[i] = 0;
-	}
-}
-
-LLAgentQueryManager::~LLAgentQueryManager()
-{
-}
-
 //-----------------------------------------------------------------------------
 // LLTeleportRequest
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 1a573d32ce67cac68079157ae7d68c8d883651c5..a2e9cedd8841cf4ba11f0d8759859e30923fa905 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -161,12 +161,13 @@ class LLAgent : public LLOldEvents::LLObservable
 	// Gender
 	//--------------------------------------------------------------------
 public:
-	// On the very first login, gender isn't chosen until the user clicks
-	// in a dialog.  We don't render the avatar until they choose.
-	BOOL 			isGenderChosen() const 	{ return mGenderChosen; }
-	void			setGenderChosen(BOOL b)	{ mGenderChosen = b; }
+	// On the very first login, outfit needs to be chosen by some
+	// mechanism, usually by loading the requested initial outfit.  We
+	// don't render the avatar until the choice is made.
+	BOOL 			isOutfitChosen() const 	{ return mOutfitChosen; }
+	void			setOutfitChosen(BOOL b)	{ mOutfitChosen = b; }
 private:
-	BOOL			mGenderChosen;
+	BOOL			mOutfitChosen;
 
 /**                    Identity
  **                                                                            **
@@ -652,7 +653,6 @@ class LLAgent : public LLOldEvents::LLObservable
 
 	void            handleTeleportFinished();
 	void            handleTeleportFailed();
-	void			handleServerBakeRegionTransition(const LLUUID& region_id);
 
 	//--------------------------------------------------------------------
 	// Teleport State
@@ -888,8 +888,6 @@ class LLAgent : public LLOldEvents::LLObservable
 public:
 	void			sendMessage(); // Send message to this agent's region
 	void			sendReliableMessage();
-	void 			dumpSentAppearance(const std::string& dump_prefix);
-	void			sendAgentSetAppearance();
 	void 			sendAgentDataUpdateRequest();
 	void 			sendAgentUserInfoRequest();
 	// IM to Email and Online visibility
@@ -903,7 +901,6 @@ class LLAgent : public LLOldEvents::LLObservable
 	static void		processAgentGroupDataUpdate(LLMessageSystem *msg, void **);
 	static void		processAgentDropGroup(LLMessageSystem *msg, void **);
 	static void		processScriptControlChange(LLMessageSystem *msg, void **);
-	static void		processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data);
 	
 /**                    Messaging
  **                                                                            **
@@ -932,24 +929,4 @@ inline bool operator==(const LLGroupData &a, const LLGroupData &b)
 	return (a.mID == b.mID);
 }
 
-class LLAgentQueryManager
-{
-	friend class LLAgent;
-	friend class LLAgentWearables;
-	
-public:
-	LLAgentQueryManager();
-	virtual ~LLAgentQueryManager();
-	
-	BOOL 			hasNoPendingQueries() const 	{ return getNumPendingQueries() == 0; }
-	S32 			getNumPendingQueries() const 	{ return mNumPendingQueries; }
-private:
-	S32				mNumPendingQueries;
-	S32				mWearablesCacheQueryID;
-	U32				mUpdateSerialNum;
-	S32		    	mActiveCacheQueries[LLAvatarAppearanceDefines::BAKED_NUM_INDICES];
-};
-
-extern LLAgentQueryManager gAgentQueryManager;
-
 #endif
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 58981d0e063765514930994d0c19e127d3a69236..26626ad8947dbb49e9026a66137dab8ed0a9a5f2 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -30,7 +30,6 @@
 #include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentcamera.h"
-#include "llagentwearablesfetch.h"
 #include "llappearancemgr.h"
 #include "llcallbacklist.h"
 #include "llfloatersidepanelcontainer.h"
@@ -70,7 +69,7 @@ void wear_and_edit_cb(const LLUUID& inv_item)
 	gAgentWearables.requestEditingWearable(inv_item);
 	
 	// Wear it.
-	LLAppearanceMgr::instance().wearItemOnAvatar(inv_item);
+	LLAppearanceMgr::instance().wearItemOnAvatar(inv_item,true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -127,13 +126,6 @@ void LLAgentWearables::dump()
 			
 		}
 	}
-	LL_INFOS() << "Total items awaiting wearable update " << mItemsAwaitingWearableUpdate.size() << LL_ENDL;
-	for (std::set<LLUUID>::iterator it = mItemsAwaitingWearableUpdate.begin();
-		 it != mItemsAwaitingWearableUpdate.end();
-		 ++it)
-	{
-		LL_INFOS() << (*it).asString() << LL_ENDL;
-	}
 }
 
 struct LLAgentDumper
@@ -183,23 +175,9 @@ void LLAgentWearables::initClass()
 void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
 {
 	llassert(avatar);
-	avatar->outputRezTiming("Sending wearables request");
-	sendAgentWearablesRequest();
 	setAvatarAppearance(avatar);
 }
 
-// wearables
-LLAgentWearables::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback()
-{
-	LL_INFOS() << "destructor - all done?" << LL_ENDL;
-	gAgentWearables.createStandardWearablesAllDone();
-}
-
-LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback()
-{
-	gAgentWearables.sendAgentWearablesUpdate();
-}
-
 /**
  * @brief Construct a callback for dealing with the wearables.
  *
@@ -210,7 +188,7 @@ LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCal
  * @param wearable The wearable data.
  * @param todo Bitmask of actions to take on completion.
  */
-LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
+LLAgentWearables::AddWearableToAgentInventoryCallback::AddWearableToAgentInventoryCallback(
 	LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo, const std::string description) :
 	mType(type),
 	mIndex(index),	
@@ -222,42 +200,24 @@ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInvento
 	LL_INFOS() << "constructor" << LL_ENDL;
 }
 
-void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
+void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
 {
-	if (mTodo & CALL_CREATESTANDARDDONE)
-	{
-		LL_INFOS() << "callback fired, inv_item " << inv_item.asString() << LL_ENDL;
-	}
-
 	if (inv_item.isNull())
 		return;
 
 	gAgentWearables.addWearabletoAgentInventoryDone(mType, mIndex, inv_item, mWearable);
 
-	if (mTodo & CALL_UPDATE)
-	{
-		gAgentWearables.sendAgentWearablesUpdate();
-	}
-	if (mTodo & CALL_RECOVERDONE)
-	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item,false);
-		gAgentWearables.recoverMissingWearableDone();
-	}
 	/*
 	 * Do this for every one in the loop
 	 */
-	if (mTodo & CALL_CREATESTANDARDDONE)
-	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item,false);
-		gAgentWearables.createStandardWearablesDone(mType, mIndex);
-	}
 	if (mTodo & CALL_MAKENEWOUTFITDONE)
 	{
 		gAgentWearables.makeNewOutfitDone(mType, mIndex);
 	}
 	if (mTodo & CALL_WEARITEM)
 	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription);
+		LLAppearanceMgr::instance().addCOFItemLink(inv_item, 
+			new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription);
 	}
 }
 
@@ -304,81 +264,7 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
 	gInventory.notifyObservers();
 }
 
-void LLAgentWearables::sendAgentWearablesUpdate()
-{
-	// First make sure that we have inventory items for each wearable
-	for (S32 type=0; type < LLWearableType::WT_COUNT; ++type)
-	{
-		for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index)
-		{
-			LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type,index);
-			if (wearable)
-			{
-				if (wearable->getItemID().isNull())
-				{
-					LLPointer<LLInventoryCallback> cb =
-						new addWearableToAgentInventoryCallback(
-							LLPointer<LLRefCount>(NULL),
-							(LLWearableType::EType)type,
-							index,
-							wearable,
-							addWearableToAgentInventoryCallback::CALL_NONE);
-					addWearableToAgentInventory(cb, wearable);
-				}
-				else
-				{
-					gInventory.addChangedMask(LLInventoryObserver::LABEL,
-											  wearable->getItemID());
-				}
-			}
-		}
-	}
-
-	// Then make sure the inventory is in sync with the avatar.
-	gInventory.notifyObservers();
-
-	// Send the AgentIsNowWearing 
-	gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
-
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
-	LL_DEBUGS() << "sendAgentWearablesUpdate()" << LL_ENDL;
-	// MULTI-WEARABLE: DEPRECATED: HACK: index to 0- server database tables don't support concept of multiwearables.
-	for (S32 type=0; type < LLWearableType::WT_COUNT; ++type)
-	{
-		gMessageSystem->nextBlockFast(_PREHASH_WearableData);
-
-		U8 type_u8 = (U8)type;
-		gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8);
-
-		LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type, 0);
-		if (wearable)
-		{
-			//LL_INFOS() << "Sending wearable " << wearable->getName() << LL_ENDL;
-			LLUUID item_id = wearable->getItemID();
-			const LLViewerInventoryItem *item = gInventory.getItem(item_id);
-			if (item && item->getIsLinkType())
-			{
-				// Get the itemID that this item points to.  i.e. make sure
-				// we are storing baseitems, not their links, in the database.
-				item_id = item->getLinkedUUID();
-			}
-			gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);			
-		}
-		else
-		{
-			//LL_INFOS() << "Not wearing wearable type " << LLWearableType::getTypeName((LLWearableType::EType)i) << LL_ENDL;
-			gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
-		}
-
-		LL_DEBUGS() << "       " << LLWearableType::getTypeLabel((LLWearableType::EType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << LL_ENDL;
-	}
-	gAgent.sendReliableMessage();
-}
-
-void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update,
+void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index,
 									const std::string new_name)
 {
 	LLViewerWearable* old_wearable = getViewerWearable(type, index);
@@ -419,23 +305,14 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 										  item->getFlags(),
 										  item->getCreationDate());
 			template_item->setTransactionID(new_wearable->getTransactionID());
-			template_item->updateServer(FALSE);
-			gInventory.updateItem(template_item);
-			if (name_changed)
-			{
-				gInventory.notifyObservers();
-			}
+			update_inventory_item(template_item, gAgentAvatarp->mEndCustomizeCallback);
 		}
 		else
 		{
 			// Add a new inventory item (shouldn't ever happen here)
-			U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
-			if (send_update)
-			{
-				todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
-			}
+			U32 todo = AddWearableToAgentInventoryCallback::CALL_NONE;
 			LLPointer<LLInventoryCallback> cb =
-				new addWearableToAgentInventoryCallback(
+				new AddWearableToAgentInventoryCallback(
 					LLPointer<LLRefCount>(NULL),
 					type,
 					index,
@@ -445,12 +322,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 			return;
 		}
 
-		gAgentAvatarp->wearableUpdated( type, TRUE );
-
-		if (send_update)
-		{
-			sendAgentWearablesUpdate();
-		}
+		gAgentAvatarp->wearableUpdated(type);
 	}
 }
 
@@ -484,12 +356,12 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
 		old_wearable,
 		trunc_name);
 	LLPointer<LLInventoryCallback> cb =
-		new addWearableToAgentInventoryCallback(
+		new AddWearableToAgentInventoryCallback(
 			LLPointer<LLRefCount>(NULL),
 			type,
 			index,
 			new_wearable,
-			addWearableToAgentInventoryCallback::CALL_WEARITEM,
+			AddWearableToAgentInventoryCallback::CALL_WEARITEM,
 			description
 			);
 	LLUUID category_id;
@@ -526,8 +398,6 @@ void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U3
 	{
 		wearable->revertValues();
 	}
-
-	gAgent.sendAgentSetAppearance();
 }
 
 void LLAgentWearables::saveAllWearables()
@@ -540,9 +410,8 @@ void LLAgentWearables::saveAllWearables()
 	for (S32 i=0; i < LLWearableType::WT_COUNT; i++)
 	{
 		for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++)
-			saveWearable((LLWearableType::EType)i, j, FALSE);
+			saveWearable((LLWearableType::EType)i, j);
 	}
-	sendAgentWearablesUpdate();
 }
 
 // Called when the user changes the name of a wearable inventory item that is currently being worn.
@@ -571,7 +440,6 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string&
 				old_wearable->setName(old_name);
 
 				setWearable((LLWearableType::EType)i,j,new_wearable);
-				sendAgentWearablesUpdate();
 				break;
 			}
 		}
@@ -692,15 +560,6 @@ LLViewerWearable*	LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_i
 	return NULL;
 }
 
-void LLAgentWearables::sendAgentWearablesRequest()
-{
-	gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest);
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	gAgent.sendReliableMessage();
-}
-
 LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/)
 {
 	return dynamic_cast<LLViewerWearable*> (getWearable(type, index));
@@ -722,8 +581,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
 {
 	if (isAgentAvatarValid())
 	{
-		const BOOL upload_result = removed;
-		gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result);
+		gAgentAvatarp->wearableUpdated(wearable->getType());
 	}
 
 	LLWearableData::wearableUpdated(wearable, removed);
@@ -743,23 +601,13 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
 			wearable->setDefinitionVersion(22);
 			U32 index = getWearableIndex(wearable);
 			LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
-			saveWearable(wearable->getType(),index,TRUE);
+			saveWearable(wearable->getType(),index);
 		}
 
 		checkWearableAgainstInventory(viewer_wearable);
 	}
 }
 
-BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const
-{
-	return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end();
-}
-
-U32 LLAgentWearables::itemUpdatePendingCount() const
-{
-	return mItemsAwaitingWearableUpdate.size();
-}
-
 const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const
 {
 	const LLViewerWearable *wearable = getViewerWearable(type,index);
@@ -783,157 +631,6 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
 	return getWearableFromItemID(item_id) != NULL;
 }
 
-// MULTI-WEARABLE: DEPRECATED (see backwards compatibility)
-// static
-// ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
-// that viewers have a Current Outfit Folder and won't need this message, and thus
-// we can remove/ignore this whole function. EXCEPT gAgentWearables.notifyLoadingStarted
-void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data)
-{
-	// We should only receive this message a single time.  Ignore subsequent AgentWearablesUpdates
-	// that may result from AgentWearablesRequest having been sent more than once.
-	if (mInitialWearablesUpdateReceived)
-		return;
-
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->startPhase("process_initial_wearables_update");
-		gAgentAvatarp->outputRezTiming("Received initial wearables update");
-	}
-
-	// notify subscribers that wearables started loading. See EXT-7777
-	// *TODO: find more proper place to not be called from deprecated method.
-	// Seems such place is found: LLInitialWearablesFetch::processContents()
-	gAgentWearables.notifyLoadingStarted();
-
-	mInitialWearablesUpdateReceived = true;
-
-	LLUUID agent_id;
-	gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
-
-	if (isAgentAvatarValid() && (agent_id == gAgentAvatarp->getID()))
-	{
-		gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum);
-		
-		const S32 NUM_BODY_PARTS = 4;
-		S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
-		if (num_wearables < NUM_BODY_PARTS)
-		{
-			// Transitional state.  Avatars should always have at least their body parts (hair, eyes, shape and skin).
-			// The fact that they don't have any here (only a dummy is sent) implies that either:
-			// 1. This account existed before we had wearables
-			// 2. The database has gotten messed up
-			// 3. This is the account's first login (i.e. the wearables haven't been generated yet).
-			return;
-		}
-
-		// Get the UUID of the current outfit folder (will be created if it doesn't exist)
-		const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-		LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch(current_outfit_id);
-		
-		//LL_DEBUGS() << "processAgentInitialWearablesUpdate()" << LL_ENDL;
-		// Add wearables
-		// MULTI-WEARABLE: DEPRECATED: Message only supports one wearable per type, will be ignored in future.
-		gAgentWearables.mItemsAwaitingWearableUpdate.clear();
-		for (S32 i=0; i < num_wearables; i++)
-		{
-			// Parse initial wearables data from message system
-			U8 type_u8 = 0;
-			gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i);
-			if (type_u8 >= LLWearableType::WT_COUNT)
-			{
-				continue;
-			}
-			const LLWearableType::EType type = (LLWearableType::EType) type_u8;
-			
-			LLUUID item_id;
-			gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i);
-			
-			LLUUID asset_id;
-			gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i);
-			if (asset_id.isNull())
-			{
-				LLViewerWearable::removeFromAvatar(type, FALSE);
-			}
-			else
-			{
-				LLAssetType::EType asset_type = LLWearableType::getAssetType(type);
-				if (asset_type == LLAssetType::AT_NONE)
-				{
-					continue;
-				}
-				
-				// MULTI-WEARABLE: DEPRECATED: this message only supports one wearable per type. Should be ignored in future versions
-				
-				// Store initial wearables data until we know whether we have the current outfit folder or need to use the data.
-				LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id);
-				outfit->add(wearable_data);
-			}
-			
-			LL_DEBUGS() << "       " << LLWearableType::getTypeLabel(type) << LL_ENDL;
-		}
-		
-		// Get the complete information on the items in the inventory and set up an observer
-		// that will trigger when the complete information is fetched.
-		outfit->startFetch();
-		if(outfit->isFinished())
-		{
-			// everything is already here - call done.
-			outfit->done();
-		}
-		else
-		{
-			// it's all on it's way - add an observer, and the inventory
-			// will call done for us when everything is here.
-			gInventory.addObserver(outfit);
-		}
-		
-	}
-}
-
-// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
-// database.  If for some reason, we can't load one of those assets, we can try to reconstruct it so that
-// the user isn't left without a shape, for example.  (We can do that only after the inventory has loaded.)
-void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type, U32 index)
-{
-	// Try to recover by replacing missing wearable with a new one.
-	LLNotificationsUtil::add("ReplacedMissingWearable");
-	LL_DEBUGS() << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded.  Replaced inventory item with default wearable." << LL_ENDL;
-	LLViewerWearable* new_wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
-
-	setWearable(type,index,new_wearable);
-	//new_wearable->writeToAvatar(TRUE);
-
-	// Add a new one in the lost and found folder.
-	// (We used to overwrite the "not found" one, but that could potentially
-	// destory content.) JC
-	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
-	LLPointer<LLInventoryCallback> cb =
-		new addWearableToAgentInventoryCallback(
-			LLPointer<LLRefCount>(NULL),
-			type,
-			index,
-			new_wearable,
-			addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
-	addWearableToAgentInventory(cb, new_wearable, lost_and_found_id, TRUE);
-}
-
-void LLAgentWearables::recoverMissingWearableDone()
-{
-	// Have all the wearables that the avatar was wearing at log-in arrived or been fabricated?
-	updateWearablesLoaded();
-	if (areWearablesLoaded())
-	{
-		// Make sure that the server's idea of the avatar's wearables actually match the wearables.
-		gAgent.sendAgentSetAppearance();
-	}
-	else
-	{
-		gInventory.addChangedMask(LLInventoryObserver::LABEL, LLUUID::null);
-		gInventory.notifyObservers();
-	}
-}
-
 void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index)
 {
 	LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)wearable_type, wearable_index);
@@ -957,7 +654,7 @@ class OnWearableItemCreatedCB: public LLInventoryCallback
 	/* virtual */ void fire(const LLUUID& inv_item)
 	{
 		LL_INFOS() << "One item created " << inv_item.asString() << LL_ENDL;
-		LLViewerInventoryItem *item = gInventory.getItem(inv_item);
+		LLConstPointer<LLInventoryObject> item = gInventory.getItem(inv_item);
 		mItemsToLink.push_back(item);
 		updatePendingWearable(inv_item);
 	}
@@ -965,9 +662,9 @@ class OnWearableItemCreatedCB: public LLInventoryCallback
 	{
 		LL_INFOS() << "All items created" << LL_ENDL;
 		LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-		LLAppearanceMgr::instance().linkAll(LLAppearanceMgr::instance().getCOF(),
-											mItemsToLink,
-											link_waiter);
+		link_inventory_array(LLAppearanceMgr::instance().getCOF(),
+							 mItemsToLink,
+							 link_waiter);
 	}
 	void addPendingWearable(LLViewerWearable *wearable)
 	{
@@ -1016,7 +713,7 @@ class OnWearableItemCreatedCB: public LLInventoryCallback
 	}
 	
 private:
-	LLInventoryModel::item_array_t mItemsToLink;
+	LLInventoryObject::const_object_list_t mItemsToLink;
 	std::vector<LLViewerWearable*> mWearablesAwaitingItems;
 };
 
@@ -1068,28 +765,38 @@ void LLAgentWearables::createStandardWearables()
 	}
 }
 
-void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
+// We no longer need this message in the current viewer, but send
+// it for now to maintain compatibility with release viewers. Can
+// remove this function once the SH-3455 changesets are universally deployed.
+void LLAgentWearables::sendDummyAgentWearablesUpdate()
 {
-	LL_INFOS() << "type " << type << " index " << index << LL_ENDL;
+	LL_DEBUGS("Avatar") << "sendAgentWearablesUpdate()" << LL_ENDL;
 
-	if (!isAgentAvatarValid()) return;
-	gAgentAvatarp->updateVisualParams();
-}
+	// Send the AgentIsNowWearing 
+	gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
+	
+	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 
-void LLAgentWearables::createStandardWearablesAllDone()
-{
-	// ... because sendAgentWearablesUpdate will notify inventory
-	// observers.
-	LL_INFOS() << "all done?" << LL_ENDL;
+	// Send 4 standardized nonsense item ids (same as returned by the modified sim, not that it especially matters).
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(1));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("db5a4e5f-9da3-44c8-992d-1181c5795498"));			
 
-	mWearablesLoaded = TRUE; 
-	checkWearablesLoaded();
-	notifyLoadingFinished();
-	
-	updateServer();
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(2));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("6969c7cc-f72f-4a76-a19b-c293cce8ce4f"));			
+
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(3));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("7999702b-b291-48f9-8903-c91dfb828408"));			
 
-	// Treat this as the first texture entry message, if none received yet
-	gAgentAvatarp->onFirstTEMessageReceived();
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(4));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("566cb59e-ef60-41d7-bfa6-e0f293fbea40"));			
+
+	gAgent.sendReliableMessage();
 }
 
 void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
@@ -1205,11 +912,10 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 		for (S32 i=max_entry; i>=0; i--)
 		{
 			LLViewerWearable* old_wearable = getViewerWearable(type,i);
-			//queryWearableCache(); // moved below
 			if (old_wearable)
 			{
 				popWearable(old_wearable);
-				old_wearable->removeFromAvatar(TRUE);
+				old_wearable->removeFromAvatar();
 			}
 		}
 		clearWearableType(type);
@@ -1217,48 +923,99 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 	else
 	{
 		LLViewerWearable* old_wearable = getViewerWearable(type, index);
-		//queryWearableCache(); // moved below
 
 		if (old_wearable)
 		{
 			popWearable(old_wearable);
-			old_wearable->removeFromAvatar(TRUE);
+			old_wearable->removeFromAvatar();
 		}
 	}
 
-	queryWearableCache();
-
-	// Update the server
-	updateServer();
 	gInventory.notifyObservers();
 }
 
 // Assumes existing wearables are not dirty.
 void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items,
-										 const std::vector< LLViewerWearable* >& wearables,
-										 BOOL remove)
+										 const std::vector< LLViewerWearable* >& wearables)
 {
 	LL_INFOS() << "setWearableOutfit() start" << LL_ENDL;
 
+	S32 count = wearables.size();
+	llassert(items.size() == count);
+
+	// Check for whether outfit already matches the one requested
+	S32 matched = 0, mismatched = 0;
+	const S32 arr_size = LLWearableType::WT_COUNT;
+	S32 type_counts[arr_size];
+	std::fill(type_counts,type_counts+arr_size,0);
+	for (S32 i = 0; i < count; i++)
+	{
+		LLViewerWearable* new_wearable = wearables[i];
+		LLPointer<LLInventoryItem> new_item = items[i];
+
+		const LLWearableType::EType type = new_wearable->getType();
+		if (type < 0 || type>=LLWearableType::WT_COUNT)
+		{
+			LL_WARNS() << "invalid type " << type << LL_ENDL;
+			mismatched++;
+			continue;
+		}
+		S32 index = type_counts[type];
+		type_counts[type]++;
+
+		LLViewerWearable *curr_wearable = dynamic_cast<LLViewerWearable*>(getWearable(type,index));
+		if (!new_wearable || !curr_wearable ||
+			new_wearable->getAssetID() != curr_wearable->getAssetID())
+		{
+			LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index
+								<< " names " << (curr_wearable ? curr_wearable->getName() : "NONE")  << ","
+								<< " names " << (new_wearable ? new_wearable->getName() : "NONE")  << LL_ENDL;
+			mismatched++;
+			continue;
+		}
+
+		if (curr_wearable->getName() != new_item->getName() ||
+			curr_wearable->getItemID() != new_item->getUUID())
+		{
+			LL_DEBUGS("Avatar") << "mismatch on name or inventory id, names "
+								<< curr_wearable->getName() << " vs " << new_item->getName()
+								<< " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID()
+								<< LL_ENDL;
+			mismatched++;
+			continue;
+		}
+		// If we got here, everything matches.
+		matched++;
+	}
+	LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << LL_ENDL;
+	for (S32 j=0; j<LLWearableType::WT_COUNT; j++)
+	{
+		LLWearableType::EType type = (LLWearableType::EType) j;
+		if (getWearableCount(type) != type_counts[j])
+		{
+			LL_DEBUGS("Avatar") << "count mismatch for type " << j << " current " << getWearableCount(j) << " requested " << type_counts[j] << LL_ENDL; 
+			mismatched++;
+		}
+	}
+	if (mismatched == 0)
+	{
+		LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL;
+		return;
+	}
+	
+	
 	// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
-	if (remove)
+	// note: shirt is the first non-body part wearable item. Update if wearable order changes.
+	// This loop should remove all clothing, but not any body parts
+	for (S32 j = 0; j < (S32)LLWearableType::WT_COUNT; j++)
 	{
-		// note: shirt is the first non-body part wearable item. Update if wearable order changes.
-		// This loop should remove all clothing, but not any body parts
-		for (S32 type = 0; type < (S32)LLWearableType::WT_COUNT; type++)
+		if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)
 		{
-			if (LLWearableType::getAssetType((LLWearableType::EType)type) == LLAssetType::AT_CLOTHING)
-			{
-				removeWearable((LLWearableType::EType)type, true, 0);
-			}
+			removeWearable((LLWearableType::EType)j, true, 0);
 		}
 	}
 
-	S32 count = wearables.size();
-	llassert(items.size() == count);
-
-	S32 i;
-	for (i = 0; i < count; i++)
+	for (S32 i = 0; i < count; i++)
 	{
 		LLViewerWearable* new_wearable = wearables[i];
 		LLPointer<LLInventoryItem> new_item = items[i];
@@ -1305,14 +1062,12 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 
 	// Start rendering & update the server
 	mWearablesLoaded = TRUE; 
-	checkWearablesLoaded();
+
 	notifyLoadingFinished();
-	queryWearableCache();
-	updateServer();
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
 
-	LL_DEBUGS() << "setWearableOutfit() end" << LL_ENDL;
+	LL_DEBUGS("Avatar") << "setWearableOutfit() end" << LL_ENDL;
 }
 
 
@@ -1429,79 +1184,6 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 		LL_INFOS() << "Replaced current element 0 for type " << type
 				<< " size is now " << getWearableCount(type) << LL_ENDL;
 	}
-
-	//LL_INFOS() << "LLVOAvatar::setWearableItem()" << LL_ENDL;
-	queryWearableCache();
-	//new_wearable->writeToAvatar(TRUE);
-
-	updateServer();
-}
-
-void LLAgentWearables::queryWearableCache()
-{
-	if (!areWearablesLoaded() || (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()))
-	{
-		return;
-	}
-
-	// Look up affected baked textures.
-	// If they exist:
-	//		disallow updates for affected layersets (until dataserver responds with cache request.)
-	//		If cache miss, turn updates back on and invalidate composite.
-	//		If cache hit, modify baked texture entries.
-	//
-	// Cache requests contain list of hashes for each baked texture entry.
-	// Response is list of valid baked texture assets. (same message)
-
-	gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture);
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	gMessageSystem->addS32Fast(_PREHASH_SerialNum, gAgentQueryManager.mWearablesCacheQueryID);
-
-	S32 num_queries = 0;
-	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
-	{
-		LLUUID hash_id = computeBakedTextureHash((EBakedTextureIndex) baked_index);
-		if (hash_id.notNull())
-		{
-			num_queries++;
-			// *NOTE: make sure at least one request gets packed
-
-			ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
-
-			//LL_INFOS() << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << LL_ENDL;
-			gMessageSystem->nextBlockFast(_PREHASH_WearableData);
-			gMessageSystem->addUUIDFast(_PREHASH_ID, hash_id);
-			gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)te_index);
-		}
-
-		gAgentQueryManager.mActiveCacheQueries[baked_index] = gAgentQueryManager.mWearablesCacheQueryID;
-	}
-	//VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout
-	if(gAgent.getRegion())
-	{
-		if (isAgentAvatarValid())
-		{
-			selfStartPhase("fetch_texture_cache_entries");
-			gAgentAvatarp->outputRezTiming("Fetching textures from cache");
-		}
-
-		LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL;
-		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
-		gAgentQueryManager.mNumPendingQueries++;
-		gAgentQueryManager.mWearablesCacheQueryID++;
-	}
-}
-
-// virtual
-void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const
-{
-	// Add some garbage into the hash so that it becomes invalid.
-	if (isAgentAvatarValid())
-	{
-		hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES);
-	}
 }
 
 // User has picked "remove from avatar" from a menu.
@@ -1687,17 +1369,6 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
 	}
 }
 
-void LLAgentWearables::checkWearablesLoaded() const
-{
-#ifdef SHOW_ASSERT
-	U32 item_pend_count = itemUpdatePendingCount();
-	if (mWearablesLoaded)
-	{
-		llassert(item_pend_count==0);
-	}
-#endif
-}
-
 // Returns false if the given wearable is already topmost/bottommost
 // (depending on closer_to_body parameter).
 bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const
@@ -1714,20 +1385,9 @@ bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_bod
 
 BOOL LLAgentWearables::areWearablesLoaded() const
 {
-	checkWearablesLoaded();
 	return mWearablesLoaded;
 }
 
-// MULTI-WEARABLE: DEPRECATED: item pending count relies on old messages that don't support multi-wearables. do not trust to be accurate
-void LLAgentWearables::updateWearablesLoaded()
-{
-	mWearablesLoaded = (itemUpdatePendingCount()==0);
-	if (mWearablesLoaded)
-	{
-		notifyLoadingFinished();
-	}
-}
-
 bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) const
 {
 	if (!wearable) return false;
@@ -1737,7 +1397,7 @@ bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) co
 	return !(((type == LLWearableType::WT_SHAPE) || (type == LLWearableType::WT_SKIN) || (type == LLWearableType::WT_HAIR) || (type == LLWearableType::WT_EYES))
 			 && (getWearableCount(type) <= 1) );		  
 }
-void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
+void LLAgentWearables::animateAllWearableParams(F32 delta)
 {
 	for( S32 type = 0; type < LLWearableType::WT_COUNT; ++type )
 	{
@@ -1747,7 +1407,7 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
 			llassert(wearable);
 			if (wearable)
 			{
-				wearable->animateParams(delta, upload_bake);
+				wearable->animateParams(delta);
 			}
 		}
 	}
@@ -1870,30 +1530,6 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id)
 	}
 }
 
-void LLAgentWearables::updateServer()
-{
-	sendAgentWearablesUpdate();
-	gAgent.sendAgentSetAppearance();
-}
-
-void LLAgentWearables::populateMyOutfitsFolder(void)
-{	
-	LL_INFOS() << "starting outfit population" << LL_ENDL;
-
-	const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(my_outfits_id);
-	outfits->mMyOutfitsID = my_outfits_id;
-	
-	// Get the complete information on the items in the inventory and 
-	// setup an observer that will wait for that to happen.
-	gInventory.addObserver(outfits);
-	outfits->startFetch();
-	if (outfits->isFinished())
-	{
-		outfits->done();
-	}
-}
-
 boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
 {
 	return mLoadingStartedSignal.connect(cb);
@@ -1912,6 +1548,7 @@ bool LLAgentWearables::changeInProgress() const
 void LLAgentWearables::notifyLoadingStarted()
 {
 	mCOFChangeInProgress = true;
+	mCOFChangeTimer.reset();
 	mLoadingStartedSignal();
 }
 
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 02d24892b5e5e9bbd2e11ffc55bf4295c088633c..cdb1bdbe0593fb035cfb4dbdcea0866c915f01b2 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -42,7 +42,6 @@
 class LLInventoryItem;
 class LLVOAvatarSelf;
 class LLViewerWearable;
-class LLInitialWearablesFetch;
 class LLViewerObject;
 
 class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearableData
@@ -51,7 +50,6 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	// Constructors / destructors / Initializers
 	//--------------------------------------------------------------------
 public:
-	friend class LLInitialWearablesFetch;
 
 	LLAgentWearables();
 	virtual ~LLAgentWearables();
@@ -62,9 +60,6 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 
 	// LLInitClass interface
 	static void initClass();
-protected:
-	void			createStandardWearablesDone(S32 type, U32 index/* = 0*/);
-	void			createStandardWearablesAllDone();
 	
 	//--------------------------------------------------------------------
 	// Queries
@@ -77,6 +72,7 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	BOOL			isWearableCopyable(LLWearableType::EType type, U32 index /*= 0*/) const;
 	BOOL			areWearablesLoaded() const;
 	bool			isCOFChangeInProgress() const { return mCOFChangeInProgress; }
+	F32				getCOFChangeTime() const { return mCOFChangeTimer.getElapsedTimeF32(); }
 	void			updateWearablesLoaded();
 	void			checkWearablesLoaded() const;
 	bool			canMoveWearable(const LLUUID& item_id, bool closer_to_body) const;
@@ -84,7 +80,7 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	// Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
 	bool			canWearableBeRemoved(const LLViewerWearable* wearable) const;
 
-	void			animateAllWearableParams(F32 delta, BOOL upload_bake);
+	void			animateAllWearableParams(F32 delta);
 
 	//--------------------------------------------------------------------
 	// Accessors
@@ -107,7 +103,7 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	/*virtual*/void	wearableUpdated(LLWearable *wearable, BOOL removed);
 public:
 	void			setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false);
-	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables, BOOL remove);
+	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables);
 	void			setWearableName(const LLUUID& item_id, const std::string& new_name);
 	// *TODO: Move this into llappearance/LLWearableData ?
 	void			addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index);
@@ -151,31 +147,10 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	void			removeWearableFinal(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/);
 protected:
 	static bool		onRemoveWearableDialog(const LLSD& notification, const LLSD& response);
-	
-	//--------------------------------------------------------------------
-	// Server Communication
-	//--------------------------------------------------------------------
-public:
-	// Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
-	static void		processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
-
-protected:
-	/*virtual*/ void	invalidateBakedTextureHash(LLMD5& hash) const;
-	void			sendAgentWearablesUpdate();
-	void			sendAgentWearablesRequest();
-	void			queryWearableCache();
-	void 			updateServer();
-	static void		onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata);
 
 	//--------------------------------------------------------------------
 	// Outfits
 	//--------------------------------------------------------------------
-public:
-	
-	// Should only be called if we *know* we've never done so before, since users may
-	// not want the Library outfits to stay in their quick outfit selector and can delete them.
-	void			populateMyOutfitsFolder();
-
 private:
 	void			makeNewOutfitDone(S32 type, U32 index); 
 
@@ -184,11 +159,16 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	//--------------------------------------------------------------------
 public:	
 	void			saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, const std::string& description, BOOL save_in_lost_and_found);
-	void			saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE,
+	void			saveWearable(const LLWearableType::EType type, const U32 index,
 								 const std::string new_name = "");
 	void			saveAllWearables();
 	void			revertWearable(const LLWearableType::EType type, const U32 index);
 
+	// We no longer need this message in the current viewer, but send
+	// it for now to maintain compatibility with release viewers. Can
+	// remove this function once the SH-3455 changesets are universally deployed.
+	void			sendDummyAgentWearablesUpdate();
+
 	//--------------------------------------------------------------------
 	// Static UI hooks
 	//--------------------------------------------------------------------
@@ -202,9 +182,6 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	static void		userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
 	static void		userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
 
-	BOOL			itemUpdatePending(const LLUUID& item_id) const;
-	U32				itemUpdatePendingCount() const;
-
 	//--------------------------------------------------------------------
 	// Signals
 	//--------------------------------------------------------------------
@@ -231,29 +208,18 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 private:
 	static BOOL		mInitialWearablesUpdateReceived;
 	BOOL			mWearablesLoaded;
-	std::set<LLUUID>	mItemsAwaitingWearableUpdate;
 
 	/**
 	 * True if agent's outfit is being changed now.
 	 */
 	BOOL			mCOFChangeInProgress;
+	LLTimer			mCOFChangeTimer;
 	
 	//--------------------------------------------------------------------------------
 	// Support classes
 	//--------------------------------------------------------------------------------
 private:
-	class createStandardWearablesAllDoneCallback : public LLRefCount
-	{
-	protected:
-		~createStandardWearablesAllDoneCallback();
-	};
-	class sendAgentWearablesUpdateCallback : public LLRefCount
-	{
-	protected:
-		~sendAgentWearablesUpdateCallback();
-	};
-
-	class addWearableToAgentInventoryCallback : public LLInventoryCallback
+	class AddWearableToAgentInventoryCallback : public LLInventoryCallback
 	{
 	public:
 		enum ETodo
@@ -266,7 +232,7 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 			CALL_WEARITEM = 16
 		};
 
-		addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
+		AddWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
 											LLWearableType::EType type,
 											U32 index,
 											LLViewerWearable* wearable,
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
deleted file mode 100755
index af0f02861de0e7f7c8bc7d447ba768f7533b84f1..0000000000000000000000000000000000000000
--- a/indra/newview/llagentwearablesfetch.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-/** 
- * @file llagentwearablesfetch.cpp
- * @brief LLAgentWearblesFetch class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llagentwearablesfetch.h"
-
-#include "llagent.h"
-#include "llagentwearables.h"
-#include "llappearancemgr.h"
-#include "llinventoryfunctions.h"
-#include "llstartup.h"
-#include "llvoavatarself.h"
-
-
-void order_my_outfits_cb()
-	{
-		if (!LLApp::isRunning())
-		{
-			LL_WARNS() << "called during shutdown, skipping" << LL_ENDL;
-			return;
-		}
-		
-		const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-		if (my_outfits_id.isNull()) return;
-
-		LLInventoryModel::cat_array_t* cats;
-		LLInventoryModel::item_array_t* items;
-		gInventory.getDirectDescendentsOf(my_outfits_id, cats, items);
-		if (!cats) return;
-
-		//My Outfits should at least contain saved initial outfit and one another outfit
-		if (cats->size() < 2)
-		{
-			LL_WARNS() << "My Outfits category was not populated properly" << LL_ENDL;
-			return;
-		}
-
-		LL_INFOS() << "Starting updating My Outfits with wearables ordering information" << LL_ENDL;
-
-		for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin();
-			outfit_iter != cats->end(); ++outfit_iter)
-		{
-			const LLUUID& cat_id = (*outfit_iter)->getUUID();
-			if (cat_id.isNull()) continue;
-
-			// saved initial outfit already contains wearables ordering information
-			if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue;
-
-			LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id);
-		}
-
-		LL_INFOS() << "Finished updating My Outfits with wearables ordering information" << LL_ENDL;
-	}
-
-LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
-	LLInventoryFetchDescendentsObserver(cof_id)
-{
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->startPhase("initial_wearables_fetch");
-		gAgentAvatarp->outputRezTiming("Initial wearables fetch started");
-	}
-}
-
-LLInitialWearablesFetch::~LLInitialWearablesFetch()
-{
-}
-
-// virtual
-void LLInitialWearablesFetch::done()
-{
-	// Delay processing the actual results of this so it's not handled within
-	// gInventory.notifyObservers.  The results will be handled in the next
-	// idle tick instead.
-	gInventory.removeObserver(this);
-	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->stopPhase("initial_wearables_fetch");
-		gAgentAvatarp->outputRezTiming("Initial wearables fetch done");
-	}
-}
-
-void LLInitialWearablesFetch::add(InitialWearableData &data)
-
-{
-	mAgentInitialWearables.push_back(data);
-}
-
-void LLInitialWearablesFetch::processContents()
-{
-	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted.
-	{
-		delete this;
-		return ;
-	}
-
-	// Fetch the wearable items from the Current Outfit Folder
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	LLFindWearables is_wearable;
-	llassert_always(mComplete.size() != 0);
-	gInventory.collectDescendentsIf(mComplete.front(), cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH, is_wearable);
-
-	LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
-	if (wearable_array.size() > 0)
-	{
-		gAgentWearables.notifyLoadingStarted();
-		LLAppearanceMgr::instance().updateAppearanceFromCOF();
-	}
-	else
-	{
-		// if we're constructing the COF from the wearables message, we don't have a proper outfit link
-		LLAppearanceMgr::instance().setOutfitDirty(true);
-		processWearablesMessage();
-	}
-	delete this;
-}
-
-class LLFetchAndLinkObserver: public LLInventoryFetchItemsObserver
-{
-public:
-	LLFetchAndLinkObserver(uuid_vec_t& ids):
-		LLInventoryFetchItemsObserver(ids)
-	{
-	}
-	~LLFetchAndLinkObserver()
-	{
-	}
-	virtual void done()
-	{
-		gInventory.removeObserver(this);
-
-		// Link to all fetched items in COF.
-		LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-		for (uuid_vec_t::iterator it = mIDs.begin();
-			 it != mIDs.end();
-			 ++it)
-		{
-			LLUUID id = *it;
-			LLViewerInventoryItem *item = gInventory.getItem(*it);
-			if (!item)
-			{
-				LL_WARNS() << "fetch failed!" << LL_ENDL;
-				continue;
-			}
-
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								LLAppearanceMgr::instance().getCOF(),
-								item->getName(),
-								item->getDescription(),
-								LLAssetType::AT_LINK,
-								link_waiter);
-		}
-	}
-};
-
-void LLInitialWearablesFetch::processWearablesMessage()
-{
-	if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
-	{
-		const LLUUID current_outfit_id = LLAppearanceMgr::instance().getCOF();
-		uuid_vec_t ids;
-		for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
-		{
-			// Populate the current outfit folder with links to the wearables passed in the message
-			InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback.
-			
-			if (wearable_data->mAssetID.notNull())
-			{
-				ids.push_back(wearable_data->mItemID);
-			}
-			else
-			{
-				LL_INFOS() << "Invalid wearable, type " << wearable_data->mType << " itemID "
-				<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << LL_ENDL;
-				delete wearable_data;
-			}
-		}
-
-		// Add all current attachments to the requested items as well.
-		if (isAgentAvatarValid())
-		{
-			for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
-				 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
-			{
-				LLViewerJointAttachment* attachment = iter->second;
-				if (!attachment) continue;
-				for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-					 attachment_iter != attachment->mAttachedObjects.end();
-					 ++attachment_iter)
-				{
-					LLViewerObject* attached_object = (*attachment_iter);
-					if (!attached_object) continue;
-					const LLUUID& item_id = attached_object->getAttachmentItemID();
-					if (item_id.isNull()) continue;
-					ids.push_back(item_id);
-				}
-			}
-		}
-
-		// Need to fetch the inventory items for ids, then create links to them after they arrive.
-		LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids);
-		fetcher->startFetch();
-		// If no items to be fetched, done will never be triggered.
-		// TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition.
-		if (fetcher->isFinished())
-		{
-			fetcher->done();
-		}
-		else
-		{
-			gInventory.addObserver(fetcher);
-		}
-	}
-	else
-	{
-		LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
-	}
-}
-
-LLLibraryOutfitsFetch::LLLibraryOutfitsFetch(const LLUUID& my_outfits_id) : 
-	LLInventoryFetchDescendentsObserver(my_outfits_id),
-	mCurrFetchStep(LOFS_FOLDER), 
-	mOutfitsPopulated(false) 
-{
-	LL_INFOS() << "created" << LL_ENDL;
-
-	mMyOutfitsID = LLUUID::null;
-	mClothingID = LLUUID::null;
-	mLibraryClothingID = LLUUID::null;
-	mImportedClothingID = LLUUID::null;
-	mImportedClothingName = "Imported Library Clothing";
-}
-
-LLLibraryOutfitsFetch::~LLLibraryOutfitsFetch()
-{
-	LL_INFOS() << "destroyed" << LL_ENDL;
-}
-
-void LLLibraryOutfitsFetch::done()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	// Delay this until idle() routine, since it's a heavy operation and
-	// we also can't have it run within notifyObservers.
-	doOnIdleOneTime(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
-	gInventory.removeObserver(this); // Prevent doOnIdleOneTime from being added twice.
-}
-
-void LLLibraryOutfitsFetch::doneIdle()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	gInventory.addObserver(this); // Add this back in since it was taken out during ::done()
-	
-	switch (mCurrFetchStep)
-	{
-		case LOFS_FOLDER:
-			folderDone();
-			mCurrFetchStep = LOFS_OUTFITS;
-			break;
-		case LOFS_OUTFITS:
-			outfitsDone();
-			mCurrFetchStep = LOFS_LIBRARY;
-			break;
-		case LOFS_LIBRARY:
-			libraryDone();
-			mCurrFetchStep = LOFS_IMPORTED;
-			break;
-		case LOFS_IMPORTED:
-			importedFolderDone();
-			mCurrFetchStep = LOFS_CONTENTS;
-			break;
-		case LOFS_CONTENTS:
-			contentsDone();
-			break;
-		default:
-			LL_WARNS() << "Got invalid state for outfit fetch: " << mCurrFetchStep << LL_ENDL;
-			mOutfitsPopulated = TRUE;
-			break;
-	}
-
-	// We're completely done.  Cleanup.
-	if (mOutfitsPopulated)
-	{
-		gInventory.removeObserver(this);
-		delete this;
-		return;
-	}
-}
-
-void LLLibraryOutfitsFetch::folderDone()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	// Early out if we already have items in My Outfits
-	// except the case when My Outfits contains just initial outfit
-	if (cat_array.size() > 1)
-	{
-		mOutfitsPopulated = true;
-		return;
-	}
-
-	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
-	mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);
-
-	// If Library->Clothing->Initial Outfits exists, use that.
-	LLNameCategoryCollector matchFolderFunctor("Initial Outfits");
-	cat_array.clear();
-	gInventory.collectDescendentsIf(mLibraryClothingID,
-									cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH,
-									matchFolderFunctor);
-	if (cat_array.size() > 0)
-	{
-		const LLViewerInventoryCategory *cat = cat_array.at(0);
-		mLibraryClothingID = cat->getUUID();
-	}
-
-	mComplete.clear();
-	
-	// Get the complete information on the items in the inventory.
-	uuid_vec_t folders;
-	folders.push_back(mClothingID);
-	folders.push_back(mLibraryClothingID);
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::outfitsDone()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	uuid_vec_t folders;
-	
-	// Collect the contents of the Library's Clothing folder
-	gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	llassert(cat_array.size() > 0);
-	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
-		 iter != cat_array.end();
-		 ++iter)
-	{
-		const LLViewerInventoryCategory *cat = iter->get();
-		
-		// Get the names and id's of every outfit in the library, skip "Ruth"
-		// because it's a low quality legacy outfit
-		if (cat->getName() != "Ruth")
-		{
-			// Get the name of every outfit in the library 
-			folders.push_back(cat->getUUID());
-			mLibraryClothingFolders.push_back(cat->getUUID());
-		}
-	}
-	cat_array.clear();
-	wearable_array.clear();
-
-	// Check if you already have an "Imported Library Clothing" folder
-	LLNameCategoryCollector matchFolderFunctor(mImportedClothingName);
-	gInventory.collectDescendentsIf(mClothingID, 
-									cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH,
-									matchFolderFunctor);
-	if (cat_array.size() > 0)
-	{
-		const LLViewerInventoryCategory *cat = cat_array.at(0);
-		mImportedClothingID = cat->getUUID();
-	}
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-class LLLibraryOutfitsCopyDone: public LLInventoryCallback
-{
-public:
-	LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher):
-	mFireCount(0), mLibraryOutfitsFetcher(fetcher)
-	{
-	}
-	
-	virtual ~LLLibraryOutfitsCopyDone()
-	{
-		if (!LLApp::isExiting() && mLibraryOutfitsFetcher)
-		{
-			gInventory.addObserver(mLibraryOutfitsFetcher);
-			mLibraryOutfitsFetcher->done();
-		}
-	}
-	
-	/* virtual */ void fire(const LLUUID& inv_item)
-	{
-		mFireCount++;
-	}
-private:
-	U32 mFireCount;
-	LLLibraryOutfitsFetch * mLibraryOutfitsFetcher;
-};
-
-// Copy the clothing folders from the library into the imported clothing folder
-void LLLibraryOutfitsFetch::libraryDone()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	if (mImportedClothingID != LLUUID::null)
-	{
-		// Skip straight to fetching the contents of the imported folder
-		importedFolderFetch();
-		return;
-	}
-
-	// Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone.
-	gInventory.removeObserver(this);
-	
-	LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
-	mImportedClothingID = gInventory.createNewCategory(mClothingID,
-													   LLFolderType::FT_NONE,
-													   mImportedClothingName);
-	// Copy each folder from library into clothing unless it already exists.
-	for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
-		 iter != mLibraryClothingFolders.end();
-		 ++iter)
-	{
-		const LLUUID& src_folder_id = (*iter); // Library clothing folder ID
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id);
-		if (!cat)
-		{
-			LL_WARNS() << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << LL_ENDL;
-			continue;
-		}
-		
-		if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id))
-		{
-			LL_INFOS() << "Skipping non-outfit folder name:" << cat->getName() << LL_ENDL;
-			continue;
-		}
-		
-		// Don't copy the category if it already exists.
-		LLNameCategoryCollector matchFolderFunctor(cat->getName());
-		LLInventoryModel::cat_array_t cat_array;
-		LLInventoryModel::item_array_t wearable_array;
-		gInventory.collectDescendentsIf(mImportedClothingID, 
-										cat_array, wearable_array, 
-										LLInventoryModel::EXCLUDE_TRASH,
-										matchFolderFunctor);
-		if (cat_array.size() > 0)
-		{
-			continue;
-		}
-
-		LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID,
-															LLFolderType::FT_NONE,
-															cat->getName());
-		LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter);
-	}
-}
-
-void LLLibraryOutfitsFetch::importedFolderFetch()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	// Fetch the contents of the Imported Clothing Folder
-	uuid_vec_t folders;
-	folders.push_back(mImportedClothingID);
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::importedFolderDone()
-{
-	LL_INFOS() << "start" << LL_ENDL;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	uuid_vec_t folders;
-	
-	// Collect the contents of the Imported Clothing folder
-	gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
-		 iter != cat_array.end();
-		 ++iter)
-	{
-		const LLViewerInventoryCategory *cat = iter->get();
-		
-		// Get the name of every imported outfit
-		folders.push_back(cat->getUUID());
-		mImportedClothingFolders.push_back(cat->getUUID());
-	}
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::contentsDone()
-{		
-	LL_INFOS() << "start" << LL_ENDL;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	
-	LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb);
-
-	for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
-		 folder_iter != mImportedClothingFolders.end();
-		 ++folder_iter)
-	{
-		const LLUUID &folder_id = (*folder_iter);
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
-		if (!cat)
-		{
-			LL_WARNS() << "Library folder import for uuid:" << folder_id << " failed to find folder." << LL_ENDL;
-			continue;
-		}
-
-		//initial outfit should be already in My Outfits
-		if (cat->getName() == LLStartUp::getInitialOutfitName()) continue;
-		
-		// First, make a folder in the My Outfits directory.
-		LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName());
-		
-		cat_array.clear();
-		wearable_array.clear();
-		// Collect the contents of each imported clothing folder, so we can create new outfit links for it
-		gInventory.collectDescendents(folder_id, cat_array, wearable_array, 
-									  LLInventoryModel::EXCLUDE_TRASH);
-		
-		for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
-			 wearable_iter != wearable_array.end();
-			 ++wearable_iter)
-		{
-			const LLViewerInventoryItem *item = wearable_iter->get();
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								new_outfit_folder_id,
-								item->getName(),
-								item->getDescription(),
-								LLAssetType::AT_LINK,
-								order_myoutfits_on_destroy);
-		}
-	}
-
-	mOutfitsPopulated = true;
-}
-
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
deleted file mode 100755
index bedc445c0ebe76eaa480e40d7dd4afc39e3f18e5..0000000000000000000000000000000000000000
--- a/indra/newview/llagentwearablesfetch.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/** 
- * @file llagentwearablesinitialfetch.h
- * @brief LLAgentWearablesInitialFetch class header file
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAGENTWEARABLESINITIALFETCH_H
-#define LL_LLAGENTWEARABLESINITIALFETCH_H
-
-#include "llinventoryobserver.h"
-#include "llwearabletype.h"
-#include "lluuid.h"
-
-//--------------------------------------------------------------------
-// InitialWearablesFetch
-// 
-// This grabs contents from the COF and processes them.
-// The processing is handled in idle(), i.e. outside of done(),
-// to avoid gInventory.notifyObservers recursion.
-//--------------------------------------------------------------------
-class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
-{
-	LOG_CLASS(LLInitialWearablesFetch);
-
-public:
-	LLInitialWearablesFetch(const LLUUID& cof_id);
-	~LLInitialWearablesFetch();
-	virtual void done();
-
-	struct InitialWearableData
-	{
-		LLWearableType::EType mType;
-		LLUUID mItemID;
-		LLUUID mAssetID;
-		InitialWearableData(LLWearableType::EType type, LLUUID& itemID, LLUUID& assetID) :
-			mType(type),
-			mItemID(itemID),
-			mAssetID(assetID)
-		{}
-	};
-
-	void add(InitialWearableData &data);
-
-protected:
-	void processWearablesMessage();
-	void processContents();
-
-private:
-	typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
-	initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
-};
-
-//--------------------------------------------------------------------
-// InitialWearablesFetch
-// 
-// This grabs outfits from the Library and copies those over to the user's
-// outfits folder, typically during first-ever login.
-//--------------------------------------------------------------------
-class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
-	enum ELibraryOutfitFetchStep
-	{
-		LOFS_FOLDER = 0,
-		LOFS_OUTFITS,
-		LOFS_LIBRARY,
-		LOFS_IMPORTED,
-		LOFS_CONTENTS
-	};
-
-	LLLibraryOutfitsFetch(const LLUUID& my_outfits_id);
-	~LLLibraryOutfitsFetch();
-
-	virtual void done();
-	void doneIdle();
-	LLUUID mMyOutfitsID;
-	void importedFolderFetch();
-protected:
-	void folderDone();
-	void outfitsDone();
-	void libraryDone();
-	void importedFolderDone();
-	void contentsDone();
-	enum ELibraryOutfitFetchStep mCurrFetchStep;
-	uuid_vec_t mLibraryClothingFolders;
-	uuid_vec_t mImportedClothingFolders;
-	bool mOutfitsPopulated;
-	LLUUID mClothingID;
-	LLUUID mLibraryClothingID;
-	LLUUID mImportedClothingID;
-	std::string mImportedClothingName;
-};
-
-#endif // LL_AGENTWEARABLESINITIALFETCH_H
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..da66ea357a8a754e187bfb5d6253c3451530daff
--- /dev/null
+++ b/indra/newview/llaisapi.cpp
@@ -0,0 +1,867 @@
+/** 
+ * @file llaisapi.cpp
+ * @brief classes and functions for interfacing with the v3+ ais inventory service. 
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "llaisapi.h"
+
+#include "llagent.h"
+#include "llcallbacklist.h"
+#include "llinventorymodel.h"
+#include "llsdutil.h"
+#include "llviewerregion.h"
+#include "llinventoryobserver.h"
+
+///----------------------------------------------------------------------------
+/// Classes for AISv3 support.
+///----------------------------------------------------------------------------
+
+// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
+AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
+	mCommandFunc(NULL),
+	mCallback(callback)
+{
+	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+}
+
+bool AISCommand::run_command()
+{
+	if (NULL == mCommandFunc)
+	{
+		// This may happen if a command failed to initiate itself.
+		LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL;
+		return false;
+	}
+	else
+	{
+		mCommandFunc();
+		return true;
+	}
+}
+
+void AISCommand::setCommandFunc(command_func_type command_func)
+{
+	mCommandFunc = command_func;
+}
+	
+// virtual
+bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id)
+{
+	return false;
+}
+	
+/* virtual */
+void AISCommand::httpSuccess()
+{
+	// Command func holds a reference to self, need to release it
+	// after a success or final failure.
+	setCommandFunc(no_op);
+		
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	mRetryPolicy->onSuccess();
+		
+	gInventory.onAISUpdateReceived("AISCommand", content);
+
+	if (mCallback)
+	{
+		LLUUID id; // will default to null if parse fails.
+		getResponseUUID(content,id);
+		mCallback->fire(id);
+	}
+}
+
+/*virtual*/
+void AISCommand::httpFailure()
+{
+	LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
+	S32 status = getStatus();
+	const LLSD& headers = getResponseHeaders();
+	mRetryPolicy->onFailure(status, headers);
+	F32 seconds_to_wait;
+	if (mRetryPolicy->shouldRetry(seconds_to_wait))
+	{
+		doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
+	}
+	else
+	{
+		// Command func holds a reference to self, need to release it
+		// after a success or final failure.
+		// *TODO: Notify user?  This seems bad.
+		setCommandFunc(no_op);
+	}
+}
+
+//static
+bool AISCommand::isAPIAvailable()
+{
+	if (gAgent.getRegion())
+	{
+		return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3");
+	}
+	return false;
+}
+
+//static
+bool AISCommand::getInvCap(std::string& cap)
+{
+	if (gAgent.getRegion())
+	{
+		cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+	}
+	if (!cap.empty())
+	{
+		return true;
+	}
+	return false;
+}
+
+//static
+bool AISCommand::getLibCap(std::string& cap)
+{
+	if (gAgent.getRegion())
+	{
+		cap = gAgent.getRegion()->getCapability("LibraryAPIv3");
+	}
+	if (!cap.empty())
+	{
+		return true;
+	}
+	return false;
+}
+
+//static
+void AISCommand::getCapabilityNames(LLSD& capabilityNames)
+{
+	capabilityNames.append("InventoryAPIv3");
+	capabilityNames.append("LibraryAPIv3");
+}
+
+RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
+									 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	std::string url = cap + std::string("/item/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLHTTPClient::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
+											 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLHTTPClient::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
+												 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
+									 const LLSD& updates,
+									 LLPointer<LLInventoryCallback> callback):
+	mUpdates(updates),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	std::string url = cap + std::string("/item/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
+											 const LLSD& updates,
+											 LLPointer<LLInventoryCallback> callback):
+	mUpdates(updates),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + cat_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
+							 				   const LLSD& new_inventory,
+							 				   LLPointer<LLInventoryCallback> callback):
+	mNewInventory(new_inventory),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
+	mContents(contents),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
+	LL_INFOS() << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
+													   const LLUUID& dest_id,
+													   LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getLibCap(cap))
+	{
+		LL_WARNS() << "No cap found" << LL_ENDL;
+		return;
+	}
+	LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
+	LL_INFOS() << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id)
+{
+	if (content.has("category_id"))
+	{
+		id = content["category_id"];
+		return true;
+	}
+	return false;
+}
+
+AISUpdate::AISUpdate(const LLSD& update)
+{
+	parseUpdate(update);
+}
+
+void AISUpdate::clearParseResults()
+{
+	mCatDescendentDeltas.clear();
+	mCatDescendentsKnown.clear();
+	mCatVersionsUpdated.clear();
+	mItemsCreated.clear();
+	mItemsUpdated.clear();
+	mCategoriesCreated.clear();
+	mCategoriesUpdated.clear();
+	mObjectsDeletedIds.clear();
+	mItemIds.clear();
+	mCategoryIds.clear();
+}
+
+void AISUpdate::parseUpdate(const LLSD& update)
+{
+	clearParseResults();
+	parseMeta(update);
+	parseContent(update);
+}
+
+void AISUpdate::parseMeta(const LLSD& update)
+{
+	// parse _categories_removed -> mObjectsDeletedIds
+	uuid_list_t cat_ids;
+	parseUUIDArray(update,"_categories_removed",cat_ids);
+	for (uuid_list_t::const_iterator it = cat_ids.begin();
+		 it != cat_ids.end(); ++it)
+	{
+		LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
+		mCatDescendentDeltas[cat->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
+	}
+
+	// parse _categories_items_removed -> mObjectsDeletedIds
+	uuid_list_t item_ids;
+	parseUUIDArray(update,"_category_items_removed",item_ids);
+	parseUUIDArray(update,"_removed_items",item_ids);
+	for (uuid_list_t::const_iterator it = item_ids.begin();
+		 it != item_ids.end(); ++it)
+	{
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDescendentDeltas[item->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
+	}
+
+	// parse _broken_links_removed -> mObjectsDeletedIds
+	uuid_list_t broken_link_ids;
+	parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
+	for (uuid_list_t::const_iterator it = broken_link_ids.begin();
+		 it != broken_link_ids.end(); ++it)
+	{
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDescendentDeltas[item->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
+	}
+
+	// parse _created_items
+	parseUUIDArray(update,"_created_items",mItemIds);
+
+	// parse _created_categories
+	parseUUIDArray(update,"_created_categories",mCategoryIds);
+
+	// Parse updated category versions.
+	const std::string& ucv = "_updated_category_versions";
+	if (update.has(ucv))
+	{
+		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
+				end = update[ucv].endMap();
+			it != end; ++it)
+		{
+			const LLUUID id((*it).first);
+			S32 version = (*it).second.asInteger();
+			mCatVersionsUpdated[id] = version;
+		}
+	}
+}
+
+void AISUpdate::parseContent(const LLSD& update)
+{
+	if (update.has("linked_id"))
+	{
+		parseLink(update);
+	}
+	else if (update.has("item_id"))
+	{
+		parseItem(update);
+	}
+
+	if (update.has("category_id"))
+	{
+		parseCategory(update);
+	}
+	else
+	{
+		if (update.has("_embedded"))
+		{
+			parseEmbedded(update["_embedded"]);
+		}
+	}
+}
+
+void AISUpdate::parseItem(const LLSD& item_map)
+{
+	LLUUID item_id = item_map["item_id"].asUUID();
+	LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+	LLViewerInventoryItem *curr_item = gInventory.getItem(item_id);
+	if (curr_item)
+	{
+		// Default to current values where not provided.
+		new_item->copyViewerItem(curr_item);
+	}
+	BOOL rv = new_item->unpackMessage(item_map);
+	if (rv)
+	{
+		if (curr_item)
+		{
+			mItemsUpdated[item_id] = new_item;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDescendentDeltas[new_item->getParentUUID()];
+		}
+		else
+		{
+			mItemsCreated[item_id] = new_item;
+			mCatDescendentDeltas[new_item->getParentUUID()]++;
+		}
+	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		LL_ERRS() << "unpack failed" << LL_ENDL;
+	}
+}
+
+void AISUpdate::parseLink(const LLSD& link_map)
+{
+	LLUUID item_id = link_map["item_id"].asUUID();
+	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+	LLViewerInventoryItem *curr_link = gInventory.getItem(item_id);
+	if (curr_link)
+	{
+		// Default to current values where not provided.
+		new_link->copyViewerItem(curr_link);
+	}
+	BOOL rv = new_link->unpackMessage(link_map);
+	if (rv)
+	{
+		const LLUUID& parent_id = new_link->getParentUUID();
+		if (curr_link)
+		{
+			mItemsUpdated[item_id] = new_link;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDescendentDeltas[parent_id];
+		}
+		else
+		{
+			LLPermissions default_perms;
+			default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
+			default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
+			new_link->setPermissions(default_perms);
+			LLSaleInfo default_sale_info;
+			new_link->setSaleInfo(default_sale_info);
+			//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL;
+			mItemsCreated[item_id] = new_link;
+			mCatDescendentDeltas[parent_id]++;
+		}
+	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		LL_ERRS() << "unpack failed" << LL_ENDL;
+	}
+}
+
+
+void AISUpdate::parseCategory(const LLSD& category_map)
+{
+	LLUUID category_id = category_map["category_id"].asUUID();
+
+	// Check descendent count first, as it may be needed
+	// to populate newly created categories
+	if (category_map.has("_embedded"))
+	{
+		parseDescendentCount(category_id, category_map["_embedded"]);
+	}
+
+	LLPointer<LLViewerInventoryCategory> new_cat(new LLViewerInventoryCategory(category_id));
+	LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
+	if (curr_cat)
+	{
+		// Default to current values where not provided.
+		new_cat->copyViewerCategory(curr_cat);
+	}
+	BOOL rv = new_cat->unpackMessage(category_map);
+	// *NOTE: unpackMessage does not unpack version or descendent count.
+	//if (category_map.has("version"))
+	//{
+	//	mCatVersionsUpdated[category_id] = category_map["version"].asInteger();
+	//}
+	if (rv)
+	{
+		if (curr_cat)
+		{
+			mCategoriesUpdated[category_id] = new_cat;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDescendentDeltas[new_cat->getParentUUID()];
+			// Capture update for the category itself as well.
+			mCatDescendentDeltas[category_id];
+		}
+		else
+		{
+			// Set version/descendents for newly created categories.
+			if (category_map.has("version"))
+			{
+				S32 version = category_map["version"].asInteger();
+				LL_DEBUGS("Inventory") << "Setting version to " << version
+									   << " for new category " << category_id << LL_ENDL;
+				new_cat->setVersion(version);
+			}
+			uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id);
+			if (mCatDescendentsKnown.end() != lookup_it)
+			{
+				S32 descendent_count = lookup_it->second;
+				LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count 
+									   << " for new category " << category_id << LL_ENDL;
+				new_cat->setDescendentCount(descendent_count);
+			}
+			mCategoriesCreated[category_id] = new_cat;
+			mCatDescendentDeltas[new_cat->getParentUUID()]++;
+		}
+	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		LL_ERRS() << "unpack failed" << LL_ENDL;
+	}
+
+	// Check for more embedded content.
+	if (category_map.has("_embedded"))
+	{
+		parseEmbedded(category_map["_embedded"]);
+	}
+}
+
+void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embedded)
+{
+	// We can only determine true descendent count if this contains all descendent types.
+	if (embedded.has("categories") &&
+		embedded.has("links") &&
+		embedded.has("items"))
+	{
+		mCatDescendentsKnown[category_id]  = embedded["categories"].size();
+		mCatDescendentsKnown[category_id] += embedded["links"].size();
+		mCatDescendentsKnown[category_id] += embedded["items"].size();
+	}
+}
+
+void AISUpdate::parseEmbedded(const LLSD& embedded)
+{
+	if (embedded.has("links")) // _embedded in a category
+	{
+		parseEmbeddedLinks(embedded["links"]);
+	}
+	if (embedded.has("items")) // _embedded in a category
+	{
+		parseEmbeddedItems(embedded["items"]);
+	}
+	if (embedded.has("item")) // _embedded in a link
+	{
+		parseEmbeddedItem(embedded["item"]);
+	}
+	if (embedded.has("categories")) // _embedded in a category
+	{
+		parseEmbeddedCategories(embedded["categories"]);
+	}
+	if (embedded.has("category")) // _embedded in a link
+	{
+		parseEmbeddedCategory(embedded["category"]);
+	}
+}
+
+void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids)
+{
+	if (content.has(name))
+	{
+		for(LLSD::array_const_iterator it = content[name].beginArray(),
+				end = content[name].endArray();
+				it != end; ++it)
+		{
+			ids.insert((*it).asUUID());
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedLinks(const LLSD& links)
+{
+	for(LLSD::map_const_iterator linkit = links.beginMap(),
+			linkend = links.endMap();
+		linkit != linkend; ++linkit)
+	{
+		const LLUUID link_id((*linkit).first);
+		const LLSD& link_map = (*linkit).second;
+		if (mItemIds.end() == mItemIds.find(link_id))
+		{
+			LL_DEBUGS("Inventory") << "Ignoring link not in items list " << link_id << LL_ENDL;
+		}
+		else
+		{
+			parseLink(link_map);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedItem(const LLSD& item)
+{
+	// a single item (_embedded in a link)
+	if (item.has("item_id"))
+	{
+		if (mItemIds.end() != mItemIds.find(item["item_id"].asUUID()))
+		{
+			parseItem(item);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedItems(const LLSD& items)
+{
+	// a map of items (_embedded in a category)
+	for(LLSD::map_const_iterator itemit = items.beginMap(),
+			itemend = items.endMap();
+		itemit != itemend; ++itemit)
+	{
+		const LLUUID item_id((*itemit).first);
+		const LLSD& item_map = (*itemit).second;
+		if (mItemIds.end() == mItemIds.find(item_id))
+		{
+			LL_DEBUGS("Inventory") << "Ignoring item not in items list " << item_id << LL_ENDL;
+		}
+		else
+		{
+			parseItem(item_map);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedCategory(const LLSD& category)
+{
+	// a single category (_embedded in a link)
+	if (category.has("category_id"))
+	{
+		if (mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID()))
+		{
+			parseCategory(category);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
+{
+	// a map of categories (_embedded in a category)
+	for(LLSD::map_const_iterator categoryit = categories.beginMap(),
+			categoryend = categories.endMap();
+		categoryit != categoryend; ++categoryit)
+	{
+		const LLUUID category_id((*categoryit).first);
+		const LLSD& category_map = (*categoryit).second;
+		if (mCategoryIds.end() == mCategoryIds.find(category_id))
+		{
+			LL_DEBUGS("Inventory") << "Ignoring category not in categories list " << category_id << LL_ENDL;
+		}
+		else
+		{
+			parseCategory(category_map);
+		}
+	}
+}
+
+void AISUpdate::doUpdate()
+{
+	// Do version/descendent accounting.
+	for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
+		 catit != mCatDescendentDeltas.end(); ++catit)
+	{
+		LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL;
+
+		const LLUUID cat_id(catit->first);
+		// Don't account for update if we just created this category.
+		if (mCategoriesCreated.find(cat_id) != mCategoriesCreated.end())
+		{
+			LL_DEBUGS("Inventory") << "Skipping version increment for new category " << cat_id << LL_ENDL;
+			continue;
+		}
+
+		// Don't account for update unless AIS told us it updated that category.
+		if (mCatVersionsUpdated.find(cat_id) == mCatVersionsUpdated.end())
+		{
+			LL_DEBUGS("Inventory") << "Skipping version increment for non-updated category " << cat_id << LL_ENDL;
+			continue;
+		}
+
+		// If we have a known descendent count, set that now.
+		LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+		if (cat)
+		{
+			S32 descendent_delta = catit->second;
+			S32 old_count = cat->getDescendentCount();
+			LL_DEBUGS("Inventory") << "Updating descendent count for "
+								   << cat->getName() << " " << cat_id
+								   << " with delta " << descendent_delta << " from "
+								   << old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
+			LLInventoryModel::LLCategoryUpdate up(cat_id, descendent_delta);
+			gInventory.accountForUpdate(up);
+		}
+		else
+		{
+			LL_DEBUGS("Inventory") << "Skipping version accounting for unknown category " << cat_id << LL_ENDL;
+		}
+	}
+
+	// CREATE CATEGORIES
+	for (deferred_category_map_t::const_iterator create_it = mCategoriesCreated.begin();
+		 create_it != mCategoriesCreated.end(); ++create_it)
+	{
+		LLUUID category_id(create_it->first);
+		LLPointer<LLViewerInventoryCategory> new_category = create_it->second;
+
+		gInventory.updateCategory(new_category, LLInventoryObserver::CREATE);
+		LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL;
+	}
+
+	// UPDATE CATEGORIES
+	for (deferred_category_map_t::const_iterator update_it = mCategoriesUpdated.begin();
+		 update_it != mCategoriesUpdated.end(); ++update_it)
+	{
+		LLUUID category_id(update_it->first);
+		LLPointer<LLViewerInventoryCategory> new_category = update_it->second;
+		// Since this is a copy of the category *before* the accounting update, above,
+		// we need to transfer back the updated version/descendent count.
+		LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID());
+		if (NULL == curr_cat)
+		{
+			LL_WARNS("Inventory") << "Failed to update unknown category " << new_category->getUUID() << LL_ENDL;
+		}
+		else
+		{
+			new_category->setVersion(curr_cat->getVersion());
+			new_category->setDescendentCount(curr_cat->getDescendentCount());
+			gInventory.updateCategory(new_category);
+			LL_DEBUGS("Inventory") << "updated category " << new_category->getName() << " " << category_id << LL_ENDL;
+		}
+	}
+
+	// CREATE ITEMS
+	for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin();
+		 create_it != mItemsCreated.end(); ++create_it)
+	{
+		LLUUID item_id(create_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = create_it->second;
+
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is create.
+		LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL;
+		gInventory.updateItem(new_item, LLInventoryObserver::CREATE);
+	}
+	
+	// UPDATE ITEMS
+	for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin();
+		 update_it != mItemsUpdated.end(); ++update_it)
+	{
+		LLUUID item_id(update_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = update_it->second;
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is update.
+		LL_DEBUGS("Inventory") << "updated item " << item_id << LL_ENDL;
+		//LL_DEBUGS("Inventory") << ll_pretty_print_sd(new_item->asLLSD()) << LL_ENDL;
+		gInventory.updateItem(new_item);
+	}
+
+	// DELETE OBJECTS
+	for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin();
+		 del_it != mObjectsDeletedIds.end(); ++del_it)
+	{
+		LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
+		gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
+	}
+
+	// TODO - how can we use this version info? Need to be sure all
+	// changes are going through AIS first, or at least through
+	// something with a reliable responder.
+	for (uuid_int_map_t::iterator ucv_it = mCatVersionsUpdated.begin();
+		 ucv_it != mCatVersionsUpdated.end(); ++ucv_it)
+	{
+		const LLUUID id = ucv_it->first;
+		S32 version = ucv_it->second;
+		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+		LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << LL_ENDL;
+		if (cat->getVersion() != version)
+		{
+			LL_WARNS() << "Possible version mismatch for category " << cat->getName()
+					<< ", viewer version " << cat->getVersion()
+					<< " server version " << version << LL_ENDL;
+		}
+	}
+
+	gInventory.notifyObservers();
+}
+
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
new file mode 100755
index 0000000000000000000000000000000000000000..5a2ec94af989d279ac1fba5374b6cce4f395e3e4
--- /dev/null
+++ b/indra/newview/llaisapi.h
@@ -0,0 +1,183 @@
+/** 
+ * @file llaisapi.h
+ * @brief classes and functions for interfacing with the v3+ ais inventory service. 
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAISAPI_H
+#define LL_LLAISAPI_H
+
+#include "lluuid.h"
+#include <map>
+#include <set>
+#include <string>
+#include "llcurl.h"
+#include "llhttpclient.h"
+#include "llhttpretrypolicy.h"
+#include "llviewerinventory.h"
+
+class AISCommand: public LLHTTPClient::Responder
+{
+public:
+	typedef boost::function<void()> command_func_type;
+
+	AISCommand(LLPointer<LLInventoryCallback> callback);
+
+	virtual ~AISCommand() {}
+
+	bool run_command();
+
+	void setCommandFunc(command_func_type command_func);
+	
+	// Need to do command-specific parsing to get an id here, for
+	// LLInventoryCallback::fire().  May or may not need to bother,
+	// since most LLInventoryCallbacks do their work in the
+	// destructor.
+	
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+
+	static bool isAPIAvailable();
+	static bool getInvCap(std::string& cap);
+	static bool getLibCap(std::string& cap);
+	static void getCapabilityNames(LLSD& capabilityNames);
+
+protected:
+	virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
+
+private:
+	command_func_type mCommandFunc;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
+	LLPointer<LLInventoryCallback> mCallback;
+};
+
+class RemoveItemCommand: public AISCommand
+{
+public:
+	RemoveItemCommand(const LLUUID& item_id,
+					  LLPointer<LLInventoryCallback> callback);
+};
+
+class RemoveCategoryCommand: public AISCommand
+{
+public:
+	RemoveCategoryCommand(const LLUUID& item_id,
+						  LLPointer<LLInventoryCallback> callback);
+};
+
+class PurgeDescendentsCommand: public AISCommand
+{
+public:
+	PurgeDescendentsCommand(const LLUUID& item_id,
+							LLPointer<LLInventoryCallback> callback);
+};
+
+class UpdateItemCommand: public AISCommand
+{
+public:
+	UpdateItemCommand(const LLUUID& item_id,
+					  const LLSD& updates,
+					  LLPointer<LLInventoryCallback> callback);
+private:
+	LLSD mUpdates;
+};
+
+class UpdateCategoryCommand: public AISCommand
+{
+public:
+	UpdateCategoryCommand(const LLUUID& cat_id,
+						  const LLSD& updates,
+						  LLPointer<LLInventoryCallback> callback);
+private:
+	LLSD mUpdates;
+};
+
+class SlamFolderCommand: public AISCommand
+{
+public:
+	SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback);
+	
+private:
+	LLSD mContents;
+};
+
+class CopyLibraryCategoryCommand: public AISCommand
+{
+public:
+	CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback);
+
+protected:
+	/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
+};
+
+class CreateInventoryCommand: public AISCommand
+{
+public:
+	CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer<LLInventoryCallback> callback);
+
+private:
+	LLSD mNewInventory;
+};
+
+class AISUpdate
+{
+public:
+	AISUpdate(const LLSD& update);
+	void parseUpdate(const LLSD& update);
+	void parseMeta(const LLSD& update);
+	void parseContent(const LLSD& update);
+	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
+	void parseLink(const LLSD& link_map);
+	void parseItem(const LLSD& link_map);
+	void parseCategory(const LLSD& link_map);
+	void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
+	void parseEmbedded(const LLSD& embedded);
+	void parseEmbeddedLinks(const LLSD& links);
+	void parseEmbeddedItems(const LLSD& items);
+	void parseEmbeddedCategories(const LLSD& categories);
+	void parseEmbeddedItem(const LLSD& item);
+	void parseEmbeddedCategory(const LLSD& category);
+	void doUpdate();
+private:
+	void clearParseResults();
+
+	typedef std::map<LLUUID,S32> uuid_int_map_t;
+	uuid_int_map_t mCatDescendentDeltas;
+	uuid_int_map_t mCatDescendentsKnown;
+	uuid_int_map_t mCatVersionsUpdated;
+
+	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
+	deferred_item_map_t mItemsCreated;
+	deferred_item_map_t mItemsUpdated;
+	typedef std::map<LLUUID,LLPointer<LLViewerInventoryCategory> > deferred_category_map_t;
+	deferred_category_map_t mCategoriesCreated;
+	deferred_category_map_t mCategoriesUpdated;
+
+	// These keep track of uuid's mentioned in meta values.
+	// Useful for filtering out which content we are interested in.
+	uuid_list_t mObjectsDeletedIds;
+	uuid_list_t mItemIds;
+	uuid_list_t mCategoryIds;
+};
+
+#endif
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 81f713502f6545248de1c303248f482dd28ba449..a4c430bada9c81cf6cbf09813fa3c654f7851ee5 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -52,6 +52,8 @@
 #include "llwearablelist.h"
 #include "llsdutil.h"
 #include "llsdserialize.h"
+#include "llhttpretrypolicy.h"
+#include "llaisapi.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -196,7 +198,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 		LLEventTimer(5.0)
 	{
 		if (!mTrackingPhase.empty())
-	{
+		{
 			selfStartPhase(mTrackingPhase);
 		}
 	}
@@ -212,23 +214,22 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 			addItem(item->getUUID());
 		}
 	}
-		
+
 	// Request or re-request operation for specified item.
 	void addItem(const LLUUID& item_id)
 	{
 		LL_DEBUGS("Avatar") << "item_id " << item_id << LL_ENDL;
-
 		if (!requestOperation(item_id))
 		{
 			LL_DEBUGS("Avatar") << "item_id " << item_id << " requestOperation false, skipping" << LL_ENDL;
 			return;
-	}
+		}
 
 		mPendingRequests++;
 		// On a re-request, this will reset the timer.
 		mWaitTimes[item_id] = LLTimer();
 		if (mRetryCounts.find(item_id) == mRetryCounts.end())
-	{
+		{
 			mRetryCounts[item_id] = 0;
 		}
 		else
@@ -242,7 +243,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 	void onOp(const LLUUID& src_id, const LLUUID& dst_id, LLTimer timestamp)
 	{
 		if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateLateOpRate"))
-	{
+		{
 			LL_WARNS() << "Simulating late operation by punting handling to later" << LL_ENDL;
 			doAfterInterval(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,src_id,dst_id,timestamp),
 							mRetryAfter);
@@ -265,12 +266,12 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 			onCompletionOrFailure();
 		}
 	}
-		
+
 	void onCompletionOrFailure()
 	{
 		assert (!mCompletionOrFailureCalled);
 		mCompletionOrFailureCalled = true;
-
+		
 		// Will never call onCompletion() if any item has been flagged as
 		// a failure - otherwise could wind up with corrupted
 		// outfit, involuntary nudity, etc.
@@ -288,7 +289,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 			onFailure();
 		}
 	}
-		
+
 	void onFailure()
 	{
 		LL_INFOS() << "failed" << LL_ENDL;
@@ -300,7 +301,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 		LL_INFOS() << "done" << LL_ENDL;
 		mOnCompletionFunc();
 	}
-
+	
 	// virtual
 	// Will be deleted after returning true - only safe to do this if all callbacks have fired.
 	BOOL tick()
@@ -313,7 +314,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 		// been serviced, since it will result in this object being
 		// deleted.
 		bool all_done = (mPendingRequests==0);
-		
+
 		if (!mWaitTimes.empty())
 		{
 			LL_WARNS() << "still waiting on " << mWaitTimes.size() << " items" << LL_ENDL;
@@ -323,20 +324,20 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 				// Use a copy of iterator because it may be erased/invalidated.
 				std::map<LLUUID,LLTimer>::iterator curr_it = it;
 				++it;
-
+				
 				F32 time_waited = curr_it->second.getElapsedTimeF32();
 				S32 retries = mRetryCounts[curr_it->first];
 				if (time_waited > mRetryAfter)
 				{
 					if (retries < mMaxRetries)
-		{
+					{
 						LL_DEBUGS("Avatar") << "Waited " << time_waited <<
 							" for " << curr_it->first << ", retrying" << LL_ENDL;
 						mRetryCount++;
 						addItem(curr_it->first);
-		}
-		else
-		{
+					}
+					else
+					{
 						LL_WARNS() << "Giving up on " << curr_it->first << " after too many retries" << LL_ENDL;
 						mWaitTimes.erase(curr_it);
 						mFailCount++;
@@ -347,8 +348,8 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 					onCompletionOrFailure();
 				}
 
+			}
 		}
-	}
 		return all_done;
 	}
 
@@ -360,7 +361,7 @@ class LLCallAfterInventoryBatchMgr: public LLEventTimer
 		LL_DEBUGS("Avatar") << "Times: n " << mTimeStats.getCount() << " min " << mTimeStats.getMinValue() << " max " << mTimeStats.getMaxValue() << LL_ENDL;
 		LL_DEBUGS("Avatar") << "Mean " << mTimeStats.getMean() << " stddev " << mTimeStats.getStdDev() << LL_ENDL;
 	}
-
+	
 	virtual ~LLCallAfterInventoryBatchMgr()
 	{
 		LL_DEBUGS("Avatar") << "deleting" << LL_ENDL;
@@ -396,10 +397,16 @@ class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr
 		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries)
 	{
 		addItems(src_items);
+		sInstanceCount++;
 	}
 
+	~LLCallAfterInventoryCopyMgr()
+	{
+		sInstanceCount--;
+	}
+	
 	virtual bool requestOperation(const LLUUID& item_id)
-		{
+	{
 		LLViewerInventoryItem *item = gInventory.getItem(item_id);
 		llassert(item);
 		LL_DEBUGS("Avatar") << "copying item " << item_id << LL_ENDL;
@@ -418,95 +425,86 @@ class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr
 			);
 		return true;
 	}
+
+	static S32 getInstanceCount() { return sInstanceCount; }
+	
+private:
+	static S32 sInstanceCount;
 };
 
-class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr
+S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
+
+class LLWearCategoryAfterCopy: public LLInventoryCallback
 {
 public:
-	LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items,
-								const LLUUID& dst_cat_id,
-								const std::string& phase_name,
-								nullary_func_t on_completion_func,
-								nullary_func_t on_failure_func = no_op,
-								 F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL,
-								 S32 max_retries = DEFAULT_MAX_RETRIES
-		):
-		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries)
+	LLWearCategoryAfterCopy(bool append):
+		mAppend(append)
+	{}
+
+	// virtual
+	void fire(const LLUUID& id)
 	{
-		addItems(src_items);
+		// Wear the inventory category.
+		LLInventoryCategory* cat = gInventory.getCategory(id);
+		LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(cat, mAppend);
 	}
-	
-	virtual bool requestOperation(const LLUUID& item_id)
-	{
-		bool request_sent = false;
-		LLViewerInventoryItem *item = gInventory.getItem(item_id);
-		if (item)
-		{
-			if (item->getParentUUID() == mDstCatID)
-			{
-				LL_DEBUGS("Avatar") << "item " << item_id << " name " << item->getName() << " is already a child of " << mDstCatID << LL_ENDL;
-				return false;
-			}
-			LL_DEBUGS("Avatar") << "linking item " << item_id << " name " << item->getName() << " to " << mDstCatID << LL_ENDL;
-			// create an inventory item link.
-			if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate"))
-			{
-				LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << LL_ENDL;
-				return true;
-			}
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								mDstCatID,
-								item->getName(),
-								item->getActualDescription(),
-								LLAssetType::AT_LINK,
-								new LLBoostFuncInventoryCallback(
-									boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer())));
-			return true;
-		}
-		else
-		{
-			// create a base outfit link if appropriate.
-			LLViewerInventoryCategory *catp = gInventory.getCategory(item_id);
-			if (!catp)
-			{
-				LL_WARNS() << "link request failed, id not found as inventory item or category " << item_id << LL_ENDL;
-				return false;
-			}
-			const LLUUID cof = LLAppearanceMgr::instance().getCOF();
-			std::string new_outfit_name = "";
 
-			LLAppearanceMgr::instance().purgeBaseOutfitLink(cof);
+private:
+	bool mAppend;
+};
+
+class LLTrackPhaseWrapper : public LLInventoryCallback
+{
+public:
+	LLTrackPhaseWrapper(const std::string& phase_name, LLPointer<LLInventoryCallback> cb = NULL):
+		mTrackingPhase(phase_name),
+		mCB(cb)
+	{
+		selfStartPhase(mTrackingPhase);
+	}
 
-			if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+	// virtual
+	void fire(const LLUUID& id)
 	{
-				if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate"))
+		if (mCB)
 		{
-					LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << LL_ENDL;
-					return true;
-				}
-				LL_DEBUGS("Avatar") << "linking folder " << item_id << " name " << catp->getName() << " to cof " << cof << LL_ENDL;
-				link_inventory_item(gAgent.getID(), item_id, cof, catp->getName(), "",
-									LLAssetType::AT_LINK_FOLDER, 
-									new LLBoostFuncInventoryCallback(
-										boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer())));
-				new_outfit_name = catp->getName();
-				request_sent = true;
-			}
-	
-			LLAppearanceMgr::instance().updatePanelOutfitName(new_outfit_name);
+			mCB->fire(id);
 		}
-		return request_sent;
 	}
+
+	// virtual
+	~LLTrackPhaseWrapper()
+	{
+		selfStopPhase(mTrackingPhase);
+	}
+
+protected:
+	std::string mTrackingPhase;
+	LLPointer<LLInventoryCallback> mCB;
 };
 
-LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering):
+LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions,
+														 bool enforce_ordering,
+														 nullary_func_t post_update_func 
+	):
 	mFireCount(0),
-	mUpdateBaseOrder(update_base_outfit_ordering)
+	mEnforceItemRestrictions(enforce_item_restrictions),
+	mEnforceOrdering(enforce_ordering),
+	mPostUpdateFunc(post_update_func)
 {
 	selfStartPhase("update_appearance_on_destroy");
 }
 
+void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
+{
+	LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
+	const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
+#endif
+	mFireCount++;
+}
+
 LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 {
 	if (!LLApp::isExiting())
@@ -516,20 +514,46 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder);
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions,
+															mEnforceOrdering,
+															mPostUpdateFunc);
 	}
 }
 
-void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
+LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id):
+	mItemID(item_id)
 {
-	LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
-	const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
-#endif
-	mFireCount++;
 }
 
+void edit_wearable_and_customize_avatar(LLUUID item_id)
+{
+	// Start editing the item if previously requested.
+	gAgentWearables.editWearableIfRequested(item_id);
+	
+	// TODO: camera mode may not be changed if a debug setting is tweaked
+	if( gAgentCamera.cameraCustomizeAvatar() )
+	{
+		// If we're in appearance editing mode, the current tab may need to be refreshed
+		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
+			LLFloaterSidePanelContainer::getPanel("appearance"));
+		if (panel)
+		{
+			panel->showDefaultSubpart();
+		}
+	}
+}
+
+LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy()
+{
+	if (!LLApp::isExiting())
+	{
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(
+			true,true,
+			boost::bind(edit_wearable_and_customize_avatar, mItemID));
+	}
+}
+
+
 struct LLFoundData
 {
 	LLFoundData() :
@@ -593,6 +617,8 @@ class LLWearableHoldingPattern
 	bool isMostRecent();
 	void handleLateArrivals();
 	void resetTime(F32 timeout);
+	static S32 countActive() { return sActiveHoldingPatterns.size(); }
+	S32 index() { return mIndex; }
 	
 private:
 	found_list_t mFoundList;
@@ -606,12 +632,15 @@ class LLWearableHoldingPattern
 	bool mFired;
 	typedef std::set<LLWearableHoldingPattern*> type_set_hp;
 	static type_set_hp sActiveHoldingPatterns;
+	static S32 sNextIndex;
+	S32 mIndex;
 	bool mIsMostRecent;
 	std::set<LLViewerWearable*> mLateArrivals;
 	bool mIsAllComplete;
 };
 
 LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPatterns;
+S32 LLWearableHoldingPattern::sNextIndex = 0;
 
 LLWearableHoldingPattern::LLWearableHoldingPattern():
 	mResolved(0),
@@ -619,13 +648,13 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
 	mIsMostRecent(true),
 	mIsAllComplete(false)
 {
-	if (sActiveHoldingPatterns.size()>0)
+	if (countActive()>0)
 	{
 		LL_INFOS() << "Creating LLWearableHoldingPattern when "
-				<< sActiveHoldingPatterns.size()
-				<< " other attempts are active."
-				<< " Flagging others as invalid."
-				<< LL_ENDL;
+				   << countActive()
+				   << " other attempts are active."
+				   << " Flagging others as invalid."
+				   << LL_ENDL;
 		for (type_set_hp::iterator it = sActiveHoldingPatterns.begin();
 			 it != sActiveHoldingPatterns.end();
 			 ++it)
@@ -634,7 +663,9 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
 		}
 			 
 	}
+	mIndex = sNextIndex++;
 	sActiveHoldingPatterns.insert(this);
+	LL_DEBUGS("Avatar") << "HP " << index() << " created" << LL_ENDL;
 	selfStartPhase("holding_pattern");
 }
 
@@ -645,6 +676,7 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern()
 	{
 		selfStopPhase("holding_pattern");
 	}
+	LL_DEBUGS("Avatar") << "HP " << index() << " deleted" << LL_ENDL;
 }
 
 bool LLWearableHoldingPattern::isMostRecent()
@@ -733,7 +765,10 @@ void LLWearableHoldingPattern::checkMissingWearables()
 
 	resetTime(60.0F);
 
-	selfStartPhase("get_missing_wearables");
+	if (isMostRecent())
+	{
+		selfStartPhase("get_missing_wearables_2");
+	}
 	if (!pollMissingWearables())
 	{
 		doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this));
@@ -773,8 +808,8 @@ void LLWearableHoldingPattern::onAllComplete()
 	}
 
 	// Update wearables.
-	LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
-	LLAppearanceMgr::instance().updateAgentWearables(this, false);
+	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
+	LLAppearanceMgr::instance().updateAgentWearables(this);
 	
 	// Update attachments to match those requested.
 	if (isAgentAvatarValid())
@@ -797,7 +832,10 @@ void LLWearableHoldingPattern::onAllComplete()
 
 void LLWearableHoldingPattern::onFetchCompletion()
 {
-	selfStopPhase("get_wearables");
+	if (isMostRecent())
+	{
+		selfStopPhase("get_wearables_2");
+	}
 		
 	if (!isMostRecent())
 	{
@@ -823,7 +861,7 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
 
 	if (done)
 	{
-		LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out
+		LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " polling, done status: " << completed << " timed out " << timed_out
 				<< " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL;
 
 		mFired = true;
@@ -841,69 +879,64 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
 void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder)
 {
 	if (!holder->isMostRecent())
-		{
-			LL_WARNS() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
-			// runway skip here?
-		}
+	{
+		LL_WARNS() << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
+		// runway skip here?
+	}
 
-	LL_INFOS() << "Recovered item link for type " << type << LL_ENDL;
+	LL_INFOS() << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL;
 	holder->eraseTypeToLink(type);
-		// Add wearable to FoundData for actual wearing
-		LLViewerInventoryItem *item = gInventory.getItem(item_id);
-		LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
+	// Add wearable to FoundData for actual wearing
+	LLViewerInventoryItem *item = gInventory.getItem(item_id);
+	LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
 
-		if (linked_item)
-		{
-			gInventory.addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+	if (linked_item)
+	{
+		gInventory.addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
 			
-			if (item)
-			{
-				LLFoundData found(linked_item->getUUID(),
-								  linked_item->getAssetUUID(),
-								  linked_item->getName(),
-								  linked_item->getType(),
-								  linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID,
-								  true // is replacement
-					);
+		if (item)
+		{
+			LLFoundData found(linked_item->getUUID(),
+							  linked_item->getAssetUUID(),
+							  linked_item->getName(),
+							  linked_item->getType(),
+							  linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID,
+							  true // is replacement
+				);
 			found.mWearable = wearable;
 			holder->getFoundList().push_front(found);
-			}
-			else
-			{
-				LL_WARNS() << self_av_string() << "inventory item not found for recovered wearable" << LL_ENDL;
-			}
 		}
 		else
 		{
 			LL_WARNS() << self_av_string() << "inventory link not found for recovered wearable" << LL_ENDL;
 		}
 	}
+	else
+	{
+		LL_WARNS() << self_av_string() << "HP " << holder->index() << " inventory link not found for recovered wearable" << LL_ENDL;
+	}
+}
 
 void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder)
 {
 	if (!holder->isMostRecent())
-		{
-			// runway skip here?
-			LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
-		}
+	{
+		// runway skip here?
+		LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
+	}
 
 	LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL;
-		LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
+	LLConstPointer<LLInventoryObject> itemp = gInventory.getItem(item_id);
 	wearable->setItemID(item_id);
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_link_cb,_1,type,wearable,holder));
 	holder->eraseTypeToRecover(type);
-		llassert(itemp);
-		if (itemp)
-		{
-			link_inventory_item( gAgent.getID(),
-					     item_id,
-					     LLAppearanceMgr::instance().getCOF(),
-					     itemp->getName(),
-						 itemp->getDescription(),
-					     LLAssetType::AT_LINK,
-					     cb);
-		}
+	llassert(itemp);
+	if (itemp)
+	{
+		LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_link_cb,_1,type,wearable,holder));
+
+		link_inventory_object(LLAppearanceMgr::instance().getCOF(), itemp, cb);
 	}
+}
 
 void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type)
 {
@@ -916,7 +949,7 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
 		// Try to recover by replacing missing wearable with a new one.
 	LLNotificationsUtil::add("ReplacedMissingWearable");
 	LL_DEBUGS() << "Wearable " << LLWearableType::getTypeLabel(type)
-			 << " could not be downloaded.  Replaced inventory item with default wearable." << LL_ENDL;
+				<< " could not be downloaded.  Replaced inventory item with default wearable." << LL_ENDL;
 	LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
 
 	// Add a new one in the lost and found folder.
@@ -949,7 +982,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
 		if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
 		{
 			// Wearable link that was never resolved; remove links to it from COF
-			LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
+			LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
 			LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID);
 		}
 	}
@@ -969,7 +1002,7 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 
 	if (!done)
 	{
-		LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size()
+		LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " polling missing wearables, waiting for items " << mTypesToRecover.size()
 				<< " links " << mTypesToLink.size()
 				<< " wearables, timed out " << timed_out
 				<< " elapsed " << mWaitTime.getElapsedTimeF32()
@@ -978,7 +1011,10 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 
 	if (done)
 	{
-		selfStopPhase("get_missing_wearables");
+		if (isMostRecent())
+		{
+			selfStopPhase("get_missing_wearables_2");
+		}
 
 		gAgentAvatarp->debugWearablesLoaded();
 
@@ -1016,7 +1052,7 @@ void LLWearableHoldingPattern::handleLateArrivals()
 		LL_WARNS() << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << LL_ENDL;
 	}
 
-	LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
+	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
 
 	// Update mFoundList using late-arriving wearables.
 	std::set<LLWearableType::EType> replaced_types;
@@ -1079,7 +1115,7 @@ void LLWearableHoldingPattern::handleLateArrivals()
 	mLateArrivals.clear();
 
 	// Update appearance based on mFoundList
-	LLAppearanceMgr::instance().updateAgentWearables(this, false);
+	LLAppearanceMgr::instance().updateAgentWearables(this);
 }
 
 void LLWearableHoldingPattern::resetTime(F32 timeout)
@@ -1096,7 +1132,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable)
 	}
 	
 	mResolved += 1;  // just counting callbacks, not successes.
-	LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
+	LL_DEBUGS("Avatar") << self_av_string() << "HP " << index() << " resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
 	if (!wearable)
 	{
 		LL_WARNS() << self_av_string() << "no wearable found" << LL_ENDL;
@@ -1203,8 +1239,7 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink()
 									cat_array,
 									item_array,
 									false,
-									is_category,
-									false);
+									is_category);
 	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
 		 iter != item_array.end();
 		 iter++)
@@ -1270,8 +1305,12 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false)
 	}
 }
 
-bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer<LLInventoryCallback> cb)
+bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
+									   bool do_update,
+									   bool replace,
+									   LLPointer<LLInventoryCallback> cb)
 {
+
 	if (item_id_to_wear.isNull()) return false;
 
 	// *TODO: issue with multi-wearable should be fixed:
@@ -1290,7 +1329,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 	if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
 	{
 		LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace));
-		copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb);
+		copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb);
 		return false;
 	} 
 	else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
@@ -1310,15 +1349,22 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 	switch (item_to_wear->getType())
 	{
 	case LLAssetType::AT_CLOTHING:
-		if (gAgentWearables.areWearablesLoaded())
+	if (gAgentWearables.areWearablesLoaded())
 		{
+			if (!cb && do_update)
+			{
+				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+			}
 			S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
 			if ((replace && wearable_count != 0) ||
 				(wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
 			{
-				removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1));
+				LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(),
+																   wearable_count-1);
+				removeCOFItemLinks(item_id, cb);
 			}
-			addCOFItemLink(item_to_wear, do_update, cb);
+
+			addCOFItemLink(item_to_wear, cb);
 		} 
 		break;
 	case LLAssetType::AT_BODYPART:
@@ -1327,8 +1373,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 		// Remove the existing wearables of the same type.
 		// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
 		removeCOFLinksOfType(item_to_wear->getWearableType());
-
-		addCOFItemLink(item_to_wear, do_update, cb);
+		if (!cb && do_update)
+		{
+			cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+		}
+		addCOFItemLink(item_to_wear, cb);
 		break;
 	case LLAssetType::AT_OBJECT:
 		rez_attachment(item_to_wear, NULL, replace);
@@ -1457,6 +1506,58 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
 	gInventory.notifyObservers();
 }
 
+void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+										bool include_folder_links, LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::cat_array_t* cats;
+	LLInventoryModel::item_array_t* items;
+	LLSD contents = LLSD::emptyArray();
+	gInventory.getDirectDescendentsOf(src_id, cats, items);
+	LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL;
+	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
+		 iter != items->end();
+		 ++iter)
+	{
+		const LLViewerInventoryItem* item = (*iter);
+		switch (item->getActualType())
+		{
+			case LLAssetType::AT_LINK:
+			{
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << LL_ENDL;
+				//getActualDescription() is used for a new description 
+				//to propagate ordering information saved in descriptions of links
+				LLSD item_contents;
+				item_contents["name"] = item->getName();
+				item_contents["desc"] = item->getActualDescription();
+				item_contents["linked_id"] = item->getLinkedUUID();
+				item_contents["type"] = LLAssetType::AT_LINK; 
+				contents.append(item_contents);
+				break;
+			}
+			case LLAssetType::AT_LINK_FOLDER:
+			{
+				LLViewerInventoryCategory *catp = item->getLinkedCategory();
+				if (catp && include_folder_links)
+				{
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << LL_ENDL;
+					LLSD base_contents;
+					base_contents["name"] = catp->getName();
+					base_contents["desc"] = ""; // categories don't have descriptions.
+					base_contents["linked_id"] = catp->getLinkedUUID();
+					base_contents["type"] = LLAssetType::AT_LINK_FOLDER; 
+					contents.append(base_contents);
+				}
+				break;
+			}
+			default:
+			{
+				// Linux refuses to compile unless all possible enums are handled. Really, Linux?
+				break;
+			}
+		}
+	}
+	slam_inventory_folder(dst_id, contents, cb);
+}
 // Copy contents of src_id to dst_id.
 void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
 													  LLPointer<LLInventoryCallback> cb)
@@ -1465,6 +1566,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 	LLInventoryModel::item_array_t* items;
 	gInventory.getDirectDescendentsOf(src_id, cats, items);
 	LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL;
+	LLInventoryObject::const_object_list_t link_array;
 	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
 		 iter != items->end();
 		 ++iter)
@@ -1474,14 +1576,8 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 		{
 			case LLAssetType::AT_LINK:
 			{
-				//getActualDescription() is used for a new description 
-				//to propagate ordering information saved in descriptions of links
-				link_inventory_item(gAgent.getID(),
-									item->getLinkedUUID(),
-									dst_id,
-									item->getName(),
-									item->getActualDescription(),
-									LLAssetType::AT_LINK, cb);
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << LL_ENDL;
+				link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				break;
 			}
 			case LLAssetType::AT_LINK_FOLDER:
@@ -1490,12 +1586,8 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				// Skip copying outfit links.
 				if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
 				{
-					link_inventory_item(gAgent.getID(),
-										item->getLinkedUUID(),
-										dst_id,
-										item->getName(),
-										item->getDescription(),
-										LLAssetType::AT_LINK_FOLDER, cb);
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << LL_ENDL;
+					link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				}
 				break;
 			}
@@ -1504,7 +1596,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 			case LLAssetType::AT_BODYPART:
 			case LLAssetType::AT_GESTURE:
 			{
-				LL_INFOS() << "copying inventory item " << item->getName() << LL_ENDL;
+				LL_DEBUGS("Avatar") << "copying inventory item " << item->getName() << LL_ENDL;
 				copy_inventory_item(gAgent.getID(),
 									item->getPermissions().getOwner(),
 									item->getUUID(),
@@ -1518,6 +1610,10 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				break;
 		}
 	}
+	if (!link_array.empty())
+	{
+		link_inventory_array(dst_id, link_array, cb);
+	}
 }
 
 BOOL LLAppearanceMgr::getCanMakeFolderIntoOutfit(const LLUUID& folder_id)
@@ -1582,15 +1678,13 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
 // static
 bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id)
 {
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
+	if (gAgentWearables.isCOFChangeInProgress())
+	{
+		return false;
+	}
+
 	LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		is_worn);
-	return items.size() > 0;
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn);
 }
 
 // static
@@ -1601,15 +1695,8 @@ bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id)
 		return false;
 	}
 
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
 	LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		not_worn);
-	return items.size() > 0;
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn);
 }
 
 bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
@@ -1627,18 +1714,11 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
 	}
 
 	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
-	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		is_worn);
-	return items.size() > 0;
+	LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn);
 }
 
-void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
+void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLInventoryModel::item_array_t items;
@@ -1649,43 +1729,11 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
 		LLViewerInventoryItem *item = items.at(i);
 		if (item->getActualType() != LLAssetType::AT_LINK_FOLDER)
 			continue;
-		if (item->getIsLinkType())
-		{
-			LLViewerInventoryCategory* catp = item->getLinkedCategory();
-			if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
-			{
-				gInventory.purgeObject(item->getUUID());
-			}
-		}
-	}
-}
-
-void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items)
-{
-	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())
+		LLViewerInventoryCategory* catp = item->getLinkedCategory();
+		if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 		{
-#if 0
-			if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL)
-			{
-				LL_INFOS() << "preserved item" << LL_ENDL;
-			}
-			else
-			{
-			gInventory.purgeObject(item->getUUID());
-		}
-#else
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
-#endif
 	}
 }
 
@@ -1713,33 +1761,14 @@ void LLAppearanceMgr::filterWearableItems(
 	}
 }
 
-// Create links to all listed items.
-void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
-							  LLInventoryModel::item_array_t& items,
-							  LLPointer<LLInventoryCallback> cb)
+void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 {
-	for (S32 i=0; i<items.size(); i++)
+	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
+	if (!pcat)
 	{
-		const LLInventoryItem* item = items.at(i).get();
-		link_inventory_item(gAgent.getID(),
-							item->getLinkedUUID(),
-							cat_uuid,
-							item->getName(),
-							item->getActualDescription(),
-							LLAssetType::AT_LINK,
-							cb);
-
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
-		const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL;
-#endif
+		LL_WARNS() << "no category found for id " << category << LL_ENDL;
+		return;
 	}
-}
-
-void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
-{
-	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
 	LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL;
 
 	const LLUUID cof = getCOF();
@@ -1748,7 +1777,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	if (!append)
 	{
 		LLInventoryModel::item_array_t gest_items;
-		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
+		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE);
 		for(S32 i = 0; i  < gest_items.size(); ++i)
 		{
 			LLViewerInventoryItem *gest_item = gest_items.at(i);
@@ -1765,8 +1794,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// required parts are missing.
 	// Preserve body parts from COF if appending.
 	LLInventoryModel::item_array_t body_items;
-	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false);
-	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false);
+	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART);
+	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART);
 	if (append)
 		reverse(body_items.begin(), body_items.end());
 	// Reduce body items to max of one per type.
@@ -1776,8 +1805,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// - Wearables: include COF contents only if appending.
 	LLInventoryModel::item_array_t wear_items;
 	if (append)
-		getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false);
-	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false);
+		getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING);
+	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING);
 	// Reduce wearables to max of one per type.
 	removeDuplicateItems(wear_items);
 	filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
@@ -1785,15 +1814,15 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// - Attachments: include COF contents only if appending.
 	LLInventoryModel::item_array_t obj_items;
 	if (append)
-		getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false);
-	getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false);
+		getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
+	getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT);
 	removeDuplicateItems(obj_items);
 
 	// - Gestures: include COF contents only if appending.
 	LLInventoryModel::item_array_t gest_items;
 	if (append)
-		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
-	getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false);
+		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE);
+	getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE);
 	removeDuplicateItems(gest_items);
 	
 	// Create links to new COF contents.
@@ -1803,23 +1832,56 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	std::copy(obj_items.begin(), obj_items.end(), std::back_inserter(all_items));
 	std::copy(gest_items.begin(), gest_items.end(), std::back_inserter(all_items));
 
+	// Find any wearables that need description set to enforce ordering.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
 	// Will link all the above items.
-	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-	linkAll(cof,all_items,link_waiter);
+	// link_waiter enforce flags are false because we've already fixed everything up in updateCOF().
+	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);
+	LLSD contents = LLSD::emptyArray();
 
-	// Add link to outfit if category is an outfit. 
-	if (!append)
+	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
+		 it != all_items.end(); ++it)
 	{
-		createBaseOutfitLink(category, link_waiter);
-	}
+		LLSD item_contents;
+		LLInventoryItem *item = *it;
 
-	// Remove current COF contents.  Have to do this after creating
-	// the link_waiter so links can be followed for any items that get
-	// carried over (e.g. keeping old shape if the new outfit does not
-	// contain one)
-	bool keep_outfit_links = append;
-	purgeCategory(cof, keep_outfit_links, &all_items);
-	gInventory.notifyObservers();
+		std::string desc;
+		desc_map_t::const_iterator desc_iter = desc_map.find(item->getUUID());
+		if (desc_iter != desc_map.end())
+		{
+			desc = desc_iter->second;
+			LL_DEBUGS("Avatar") << item->getName() << " overriding desc to: " << desc
+								<< " (was: " << item->getActualDescription() << ")" << LL_ENDL;
+		}
+		else
+		{
+			desc = item->getActualDescription();
+		}
+
+		item_contents["name"] = item->getName();
+		item_contents["desc"] = desc;
+		item_contents["linked_id"] = item->getLinkedUUID();
+		item_contents["type"] = LLAssetType::AT_LINK; 
+		contents.append(item_contents);
+	}
+	const LLUUID& base_id = append ? getBaseOutfitUUID() : category;
+	LLViewerInventoryCategory *base_cat = gInventory.getCategory(base_id);
+	if (base_cat)
+	{
+		LLSD base_contents;
+		base_contents["name"] = base_cat->getName();
+		base_contents["desc"] = "";
+		base_contents["linked_id"] = base_cat->getLinkedUUID();
+		base_contents["type"] = LLAssetType::AT_LINK_FOLDER; 
+		contents.append(base_contents);
+	}
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);
+	}
+	slam_inventory_folder(getCOF(), contents, link_waiter);
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
 }
@@ -1840,21 +1902,20 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointer<LLI
 	LLViewerInventoryCategory* catp = gInventory.getCategory(category);
 	std::string new_outfit_name = "";
 
-	purgeBaseOutfitLink(cof);
+	purgeBaseOutfitLink(cof, link_waiter);
 
 	if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 	{
-		link_inventory_item(gAgent.getID(), category, cof, catp->getName(), "",
-							LLAssetType::AT_LINK_FOLDER, link_waiter);
+		link_inventory_object(cof, catp, link_waiter);
 		new_outfit_name = catp->getName();
 	}
 	
 	updatePanelOutfitName(new_outfit_name);
 }
 
-void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
+void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder)
 {
-	LL_DEBUGS() << "updateAgentWearables()" << LL_ENDL;
+	LL_DEBUGS("Avatar") << "updateAgentWearables()" << LL_ENDL;
 	LLInventoryItem::item_array_t items;
 	std::vector< LLViewerWearable* > wearables;
 	wearables.reserve(32);
@@ -1881,10 +1942,15 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo
 
 	if(wearables.size() > 0)
 	{
-		gAgentWearables.setWearableOutfit(items, wearables, !append);
+		gAgentWearables.setWearableOutfit(items, wearables);
 	}
 }
 
+S32 LLAppearanceMgr::countActiveHoldingPatterns()
+{
+	return LLWearableHoldingPattern::countActive();
+}
+
 static void remove_non_link_items(LLInventoryModel::item_array_t &items)
 {
 	LLInventoryModel::item_array_t pruned_items;
@@ -1933,12 +1999,12 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list,
 S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 												 LLAssetType::EType type,
 												 S32 max_items,
-												 LLInventoryModel::item_array_t& items_to_kill)
+												 LLInventoryObject::object_list_t& items_to_kill)
 {
 	S32 to_kill_count = 0;
 
 	LLInventoryModel::item_array_t items;
-	getDescendentsOfAssetType(cat_id, items, type, false);
+	getDescendentsOfAssetType(cat_id, items, type);
 	LLInventoryModel::item_array_t curr_items = items;
 	removeDuplicateItems(items);
 	if (max_items > 0)
@@ -1951,40 +2017,39 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 		 it != kill_items.end();
 		 ++it)
 	{
-		items_to_kill.push_back(*it);
+		items_to_kill.push_back(LLPointer<LLInventoryObject>(*it));
 		to_kill_count++;
 	}
 	return to_kill_count;
 }
 	
-												 
-void LLAppearanceMgr::enforceItemRestrictions()
-{
-	S32 purge_count = 0;
-	LLInventoryModel::item_array_t items_to_kill;
 
-	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);
+void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
+													LLInventoryObject::object_list_t& items_to_kill)
+{
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART,
+							   1, items_to_kill);
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING,
+							   LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT,
+							   -1, items_to_kill);
+}
 
+void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryObject::object_list_t items_to_kill;
+	findAllExcessOrDuplicateItems(getCOF(), 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;
-			LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL;
-			gInventory.purgeObject(item->getUUID());
-		}
-		gInventory.notifyObservers();
+		// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
+		// this should catch anything that gets through.
+		remove_inventory_items(items_to_kill, cb);
 	}
 }
 
-void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
+void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
+											  bool enforce_ordering,
+											  nullary_func_t post_update_func)
 {
 	if (mIsInUpdateAppearanceFromCOF)
 	{
@@ -1992,19 +2057,43 @@ 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;
 
-	//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_item_restrictions)
+	{
+		// 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(false, enforce_ordering, post_update_func));
+		enforceCOFItemRestrictions(cb);
+		return;
+	}
+
+	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, post_update_func));
+		updateClothingOrderingInfo(LLUUID::null, cb);
+		return;
+	}
+
+	if (!validateClothingOrderingInfo())
+	{
+		LL_WARNS() << "Clothing ordering error" << LL_ENDL;
+	}
+
+	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
+	selfStartPhase("update_appearance_from_cof");
 
-	// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
-	// this should catch anything that gets through.
-	enforceItemRestrictions();
-	
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
 	updateIsDirty();
@@ -2014,13 +2103,7 @@ 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");
 
-	bool follow_folder_links = false;
 	LLUUID current_outfit_id = getCOF();
 
 	// Find all the wearables that are in the COF's subtree.
@@ -2028,7 +2111,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	LLInventoryModel::item_array_t wear_items;
 	LLInventoryModel::item_array_t obj_items;
 	LLInventoryModel::item_array_t gest_items;
-	getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
+	getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items);
 	// Get rid of non-links in case somehow the COF was corrupted.
 	remove_non_link_items(wear_items);
 	remove_non_link_items(obj_items);
@@ -2037,6 +2120,13 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	dumpItemArray(wear_items,"asset_dump: wear_item");
 	dumpItemArray(obj_items,"asset_dump: obj_item");
 
+	LLViewerInventoryCategory *cof = gInventory.getCategory(current_outfit_id);
+	if (!gInventory.isCategoryComplete(current_outfit_id))
+	{
+		LL_WARNS() << "COF info is not complete. Version " << cof->getVersion()
+				<< " descendent_count " << cof->getDescendentCount()
+				<< " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL;
+	}
 	if(!wear_items.size())
 	{
 		LLNotificationsUtil::add("CouldNotPutOnOutfit");
@@ -2047,6 +2137,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	sortItemsByActualDescription(wear_items);
 
 
+	LL_DEBUGS("Avatar") << "HP block starts" << LL_ENDL;
+	LLTimer hp_block_timer;
 	LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
 
 	holder->setObjItems(obj_items);
@@ -2096,7 +2188,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 		}
 	}
 
-	selfStartPhase("get_wearables");
+	selfStartPhase("get_wearables_2");
 
 	for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin();
 		 it != holder->getFoundList().end(); ++it)
@@ -2120,12 +2212,14 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	{
 		doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollFetchCompletion,holder));
 	}
+	post_update_func();
+
+	LL_DEBUGS("Avatar") << "HP block ends, elapsed " << hp_block_timer.getElapsedTimeF32() << LL_ENDL;
 }
 
 void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
 													LLInventoryModel::item_array_t& items,
-													LLAssetType::EType type,
-													bool follow_folder_links)
+													LLAssetType::EType type)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLIsType is_of_type(type);
@@ -2133,15 +2227,13 @@ void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
 									cats,
 									items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_of_type,
-									follow_folder_links);
+									is_of_type);
 }
 
 void LLAppearanceMgr::getUserDescendents(const LLUUID& category, 
 											 LLInventoryModel::item_array_t& wear_items,
 											 LLInventoryModel::item_array_t& obj_items,
-											 LLInventoryModel::item_array_t& gest_items,
-											 bool follow_folder_links)
+											 LLInventoryModel::item_array_t& gest_items)
 {
 	LLInventoryModel::cat_array_t wear_cats;
 	LLFindWearables is_wearable;
@@ -2149,8 +2241,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									wear_cats,
 									wear_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_wearable,
-									follow_folder_links);
+									is_wearable);
 
 	LLInventoryModel::cat_array_t obj_cats;
 	LLIsType is_object( LLAssetType::AT_OBJECT );
@@ -2158,8 +2249,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									obj_cats,
 									obj_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_object,
-									follow_folder_links);
+									is_object);
 
 	// Find all gestures in this folder
 	LLInventoryModel::cat_array_t gest_cats;
@@ -2168,8 +2258,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									gest_cats,
 									gest_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_gesture,
-									follow_folder_links);
+									is_gesture);
 }
 
 void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
@@ -2184,10 +2273,36 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 	LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName()
 			 << " )" << LL_ENDL;
 
-	selfStartPhase("wear_inventory_category_fetch");
-	callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
-														   &LLAppearanceMgr::instance(),
-														   category->getUUID(), copy, append));
+	// If we are copying from library, attempt to use AIS to copy the category.
+	bool ais_ran=false;
+	if (copy && AISCommand::isAPIAvailable())
+	{
+		LLUUID parent_id;
+		parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+		if (parent_id.isNull())
+		{
+			parent_id = gInventory.getRootFolderID();
+		}
+
+		LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append);
+		LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper(
+													std::string("wear_inventory_category_callback"), copy_cb);
+		LLPointer<AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb);
+		ais_ran=cmd_ptr->run_command();
+	}
+
+	if (!ais_ran)
+	{
+		selfStartPhase("wear_inventory_category_fetch");
+		callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
+															   &LLAppearanceMgr::instance(),
+															   category->getUUID(), copy, append));
+	}
+}
+
+S32 LLAppearanceMgr::getActiveCopyOperations() const
+{
+	return LLCallAfterInventoryCopyMgr::getInstanceCount(); 
 }
 
 void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
@@ -2268,7 +2383,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
 	// Avoid unintentionally overwriting old wearables.  We have to do
 	// this up front to avoid having to deal with the case of multiple
 	// wearables being dirty.
-	if(!category) return;
+	if (!category) return;
 
 	if ( !LLInventoryCallbackManager::is_instantiated() )
 	{
@@ -2288,6 +2403,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
 	LLAppearanceMgr::changeOutfit(TRUE, category->getUUID(), append);
 }
 
+// FIXME do we really want to search entire inventory for matching name?
 void LLAppearanceMgr::wearOutfitByName(const std::string& name)
 {
 	LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL;
@@ -2341,9 +2457,8 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor
 class LLDeferredCOFLinkObserver: public LLInventoryObserver
 {
 public:
-	LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer<LLInventoryCallback> cb = NULL, std::string description = ""):
+	LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb, const std::string& description):
 		mItemID(item_id),
-		mDoUpdate(do_update),
 		mCallback(cb),
 		mDescription(description)
 	{
@@ -2359,14 +2474,13 @@ class LLDeferredCOFLinkObserver: public LLInventoryObserver
 		if (item)
 		{
 			gInventory.removeObserver(this);
-			LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback);
+			LLAppearanceMgr::instance().addCOFItemLink(item, mCallback, mDescription);
 			delete this;
 		}
 	}
 
 private:
 	const LLUUID mItemID;
-	bool mDoUpdate;
 	std::string mDescription;
 	LLPointer<LLInventoryCallback> mCallback;
 };
@@ -2374,42 +2488,26 @@ class LLDeferredCOFLinkObserver: public LLInventoryObserver
 
 // BAP - note that this runs asynchronously if the item is not already loaded from inventory.
 // Dangerous if caller assumes link will exist after calling the function.
-void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description)
+void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id,
+									 LLPointer<LLInventoryCallback> cb,
+									 const std::string description)
 {
 	const LLInventoryItem *item = gInventory.getItem(item_id);
 	if (!item)
 	{
-		LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description);
+		LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, cb, description);
 		gInventory.addObserver(observer);
 	}
 	else
 	{
-		addCOFItemLink(item, do_update, cb, description);
+		addCOFItemLink(item, cb, description);
 	}
 }
 
-void modified_cof_cb(const LLUUID& inv_item)
-{		
-	LLAppearanceMgr::instance().updateAppearanceFromCOF();
-
-	// Start editing the item if previously requested.
-	gAgentWearables.editWearableIfRequested(inv_item);
-
-	// TODO: camera mode may not be changed if a debug setting is tweaked
-	if( gAgentCamera.cameraCustomizeAvatar() )
-	{
-		// If we're in appearance editing mode, the current tab may need to be refreshed
-		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
-		if (panel)
-		{
-			panel->showDefaultSubpart();
-		}
-	}
-}
-
-void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description)
-{		
-	std::string link_description = description;
+void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
+									 LLPointer<LLInventoryCallback> cb,
+									 const std::string description)
+{
 	const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item);
 	if (!vitem)
 	{
@@ -2449,43 +2547,23 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
 			++count;
 			if (is_body_part && inv_item->getIsLinkType()  && (vitem->getWearableType() == wearable_type))
 			{
-				gInventory.purgeObject(inv_item->getUUID());
+				remove_inventory_item(inv_item->getUUID(), cb);
 			}
 			else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
 			{
 				// MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
-				gInventory.purgeObject(inv_item->getUUID());
+				remove_inventory_item(inv_item->getUUID(), cb);
 			}
 		}
 	}
 
-	if (linked_already)
-	{
-		if (do_update)
-		{	
-			LLAppearanceMgr::updateAppearanceFromCOF();
-		}
-		return;
-	}
-	else
+	if (!linked_already)
 	{
-		if(do_update && cb.isNull())
-		{
-			cb = new LLBoostFuncInventoryCallback(modified_cof_cb);
-		}
-		if (vitem->getIsLinkType())
-		{
-			link_description = vitem->getActualDescription();
-		}
-		link_inventory_item( gAgent.getID(),
-							 vitem->getLinkedUUID(),
-							 getCOF(),
-							 vitem->getName(),
-							 link_description,
-							 LLAssetType::AT_LINK,
-							 cb);
+		LLViewerInventoryItem *copy_item = new LLViewerInventoryItem;
+		copy_item->copyViewerItem(vitem);
+		copy_item->setDescription(description);
+		link_inventory_object(getCOF(), copy_item, cb);
 	}
-	return;
 }
 
 LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id)
@@ -2515,6 +2593,12 @@ LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& i
 	return result;
 }
 
+bool LLAppearanceMgr::isLinkedInCOF(const LLUUID& item_id)
+{
+	LLInventoryModel::item_array_t links = LLAppearanceMgr::instance().findCOFItemLinks(item_id);
+	return links.size() > 0;
+}
+
 void LLAppearanceMgr::removeAllClothesFromAvatar()
 {
 	// Fetch worn clothes (i.e. the ones in COF).
@@ -2525,8 +2609,7 @@ void LLAppearanceMgr::removeAllClothesFromAvatar()
 									dummy,
 									clothing_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_clothing,
-									false);
+									is_clothing);
 	uuid_vec_t item_ids;
 	for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin();
 		it != clothing_items.end(); ++it)
@@ -2570,7 +2653,7 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar()
 	removeItemsFromAvatar(ids_to_remove);
 }
 
-void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id)
+void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb)
 {
 	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
@@ -2585,12 +2668,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id)
 		const LLInventoryItem* item = item_array.at(i).get();
 		if (item->getIsLinkType() && item->getLinkedUUID() == item_id)
 		{
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
 	}
 }
 
-void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type)
+void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, LLPointer<LLInventoryCallback> cb)
 {
 	LLFindWearablesOfType filter_wearables_of_type(type);
 	LLInventoryModel::cat_array_t cats;
@@ -2603,7 +2686,7 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type)
 		const LLViewerInventoryItem* item = *it;
 		if (item->getIsLinkType()) // we must operate on links only
 		{
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
 	}
 }
@@ -2642,7 +2725,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 	if (base_outfit.notNull())
 	{
-		LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK);
+		LLIsValidItemLink collector;
 
 		LLInventoryModel::cat_array_t cof_cats;
 		LLInventoryModel::item_array_t cof_items;
@@ -2656,6 +2739,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 		if(outfit_items.size() != cof_items.size())
 		{
+			LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL;
 			// Current outfit folder should have one more item than the outfit folder.
 			// this one item is the link back to the outfit folder itself.
 			mOutfitIsDirty = true;
@@ -2675,11 +2759,30 @@ void LLAppearanceMgr::updateIsDirty()
 				item1->getName() != item2->getName() ||
 				item1->getActualDescription() != item2->getActualDescription())
 			{
+				if (item1->getLinkedUUID() != item2->getLinkedUUID())
+				{
+					LL_DEBUGS("Avatar") << "link id different " << LL_ENDL;
+				}
+				else
+				{
+					if (item1->getName() != item2->getName())
+					{
+						LL_DEBUGS("Avatar") << "name different " << item1->getName() << " " << item2->getName() << LL_ENDL;
+					}
+					if (item1->getActualDescription() != item2->getActualDescription())
+					{
+						LL_DEBUGS("Avatar") << "desc different " << item1->getActualDescription()
+											<< " " << item2->getActualDescription() 
+											<< " names " << item1->getName() << " " << item2->getName() << LL_ENDL;
+					}
+				}
 				mOutfitIsDirty = true;
 				return;
 			}
 		}
 	}
+	llassert(!mOutfitIsDirty);
+	LL_DEBUGS("Avatar") << "clean" << LL_ENDL;
 }
 
 // *HACK: Must match name in Library or agent inventory
@@ -2761,23 +2864,6 @@ void LLAppearanceMgr::copyLibraryGestures()
 	}
 }
 
-void LLAppearanceMgr::autopopulateOutfits()
-{
-	// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
-	// then auto-populate outfits from the library into the My Outfits folder.
-
-	LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL;
-
-	static bool check_populate_my_outfits = true;
-	if (check_populate_my_outfits && 
-		(LLInventoryModel::getIsFirstTimeInViewer2() 
-		 || gSavedSettings.getBOOL("MyOutfitsAutofill")))
-	{
-		gAgentWearables.populateMyOutfitsFolder();
-	}
-	check_populate_my_outfits = false;
-}
-
 // Handler for anything that's deferred until avatar de-clouds.
 void LLAppearanceMgr::onFirstFullyVisible()
 {
@@ -2785,10 +2871,6 @@ void LLAppearanceMgr::onFirstFullyVisible()
 	gAgentAvatarp->reportAvatarRezTime();
 	gAgentAvatarp->debugAvatarVisible();
 
-	// The auto-populate is failing at the point of generating outfits
-	// folders, so don't do the library copy until that is resolved.
-	// autopopulateOutfits();
-
 	// If this is the first time we've ever logged in,
 	// then copy default gestures from the library.
 	if (gAgent.isFirstLogin()) {
@@ -2803,9 +2885,27 @@ void appearance_mgr_update_dirty_state()
 	if (LLAppearanceMgr::instanceExists())
 	{
 		LLAppearanceMgr::getInstance()->updateIsDirty();
+		LLAppearanceMgr::getInstance()->setOutfitLocked(false);
+		gAgentWearables.notifyLoadingFinished();
 	}
 }
 
+void update_base_outfit_after_ordering()
+{
+	LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+	
+	LLPointer<LLInventoryCallback> dirty_state_updater =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
+
+	//COF contains only links so we copy to the Base Outfit only links
+	const LLUUID base_outfit_id = app_mgr.getBaseOutfitUUID();
+	bool copy_folder_links = false;
+	app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
+
+}
+
+// Save COF changes - update the contents of the current base outfit
+// to match the current COF. Fails if no current base outfit is set.
 bool LLAppearanceMgr::updateBaseOutfit()
 {
 	if (isOutfitLocked())
@@ -2814,23 +2914,20 @@ bool LLAppearanceMgr::updateBaseOutfit()
 		llassert(!isOutfitLocked());
 		return false;
 	}
+
 	setOutfitLocked(true);
 
 	gAgentWearables.notifyLoadingStarted();
 
 	const LLUUID base_outfit_id = getBaseOutfitUUID();
 	if (base_outfit_id.isNull()) return false;
+	LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << LL_ENDL;
 
-	updateClothingOrderingInfo();
-
-	// in a Base Outfit we do not remove items, only links
-	purgeCategory(base_outfit_id, false);
-
-	LLPointer<LLInventoryCallback> dirty_state_updater =
-		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
-
-	//COF contains only links so we copy to the Base Outfit only links
-	shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater);
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering);
+	// Really shouldn't be needed unless there's a race condition -
+	// updateAppearanceFromCOF() already calls updateClothingOrderingInfo.
+	updateClothingOrderingInfo(LLUUID::null, cb);
 
 	return true;
 }
@@ -2878,12 +2975,6 @@ struct WearablesOrderComparator
 
 	bool operator()(const LLInventoryItem* item1, const LLInventoryItem* item2)
 	{
-		if (!item1 || !item2)
-		{
-			LL_WARNS() << "either item1 or item2 is NULL" << LL_ENDL;
-			return true;
-		}
-		
 		const std::string& desc1 = item1->getActualDescription();
 		const std::string& desc2 = item2->getActualDescription();
 		
@@ -2897,260 +2988,373 @@ struct WearablesOrderComparator
 		//items with ordering information but not for the associated wearables type
 		if (!item1_valid && item2_valid) 
 			return false;
+		else if (item1_valid && !item2_valid)
+			return true;
 
-		return true;
+		return item1->getName() < item2->getName();
 	}
 
 	U32 mControlSize;
 };
 
-void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base_outfit_ordering)
+void LLAppearanceMgr::getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items,
+													 desc_map_t& desc_map)
 {
-	if (cat_id.isNull())
-	{
-		cat_id = getCOF();
-		if (update_base_outfit_ordering)
-		{
-			const LLUUID base_outfit_id = getBaseOutfitUUID();
-			if (base_outfit_id.notNull())
-			{
-				updateClothingOrderingInfo(base_outfit_id,false);
-			}
-		}
-	}
-
-	// COF is processed if cat_id is not specified
-	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING, false);
-
 	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++)
 	{
-		
 		U32 size = items_by_type[type].size();
 		if (!size) continue;
-
+		
 		//sinking down invalid items which need reordering
 		std::sort(items_by_type[type].begin(), items_by_type[type].end(), WearablesOrderComparator((LLWearableType::EType) type));
-
+		
 		//requesting updates only for those links which don't have "valid" descriptions
 		for (U32 i = 0; i < size; i++)
 		{
 			LLViewerInventoryItem* item = items_by_type[type][i];
 			if (!item) continue;
-
+			
 			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;
+			desc_map[item->getUUID()] = new_order_str;
 		}
 	}
-
-	//*TODO do we really need to notify observers?
-	if (inventory_changed) gInventory.notifyObservers();
 }
 
-// This is intended for use with HTTP Clients/Responders, but is not
-// specifically coupled with those classes.
-class LLHTTPRetryPolicy: public LLThreadSafeRefCount
+bool LLAppearanceMgr::validateClothingOrderingInfo(LLUUID cat_id)
 {
-public:
-	LLHTTPRetryPolicy() {}
-	virtual ~LLHTTPRetryPolicy() {}
-	virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0;
-};
+	// COF is processed if cat_id is not specified
+	if (cat_id.isNull())
+	{
+		cat_id = getCOF();
+	}
 
-// Example of simplest possible policy, not necessarily recommended.
-class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy
-{
-public:
-	LLAlwaysRetryImmediatelyPolicy() {}
-	bool shouldRetry(U32 status, F32& seconds_to_wait)
+	LLInventoryModel::item_array_t wear_items;
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+	// Identify items for which desc needs to change.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
+	for (desc_map_t::const_iterator it = desc_map.begin();
+		 it != desc_map.end(); ++it)
 	{
-		seconds_to_wait = 0.0;
-		return true;
+		const LLUUID& item_id = it->first;
+		const std::string& new_order_str = it->second;
+		LLViewerInventoryItem *item = gInventory.getItem(item_id);
+		LL_WARNS() << "Order validation fails: " << item->getName()
+				<< " needs to update desc to: " << new_order_str
+				<< " (from: " << item->getActualDescription() << ")" << LL_ENDL;
 	}
-};
+	
+	return desc_map.size() == 0;
+}
 
-// Very general policy with geometric back-off after failures,
-// up to a maximum delay, and maximum number of retries.
-class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
+												 LLPointer<LLInventoryCallback> cb)
 {
-public:
-	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
-		mMinDelay(min_delay),
-		mMaxDelay(max_delay),
-		mBackoffFactor(backoff_factor),
-		mMaxRetries(max_retries),
-		mDelay(min_delay),
-		mRetryCount(0)
+	// COF is processed if cat_id is not specified
+	if (cat_id.isNull())
 	{
+		cat_id = getCOF();
 	}
 
-	bool shouldRetry(U32 status, F32& seconds_to_wait)
+	LLInventoryModel::item_array_t wear_items;
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+	// Identify items for which desc needs to change.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
+	for (desc_map_t::const_iterator it = desc_map.begin();
+		 it != desc_map.end(); ++it)
 	{
-		seconds_to_wait = mDelay;
-		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
-		mRetryCount++;
-		return (mRetryCount<=mMaxRetries);
+		LLSD updates;
+		const LLUUID& item_id = it->first;
+		const std::string& new_order_str = it->second;
+		LLViewerInventoryItem *item = gInventory.getItem(item_id);
+		LL_DEBUGS("Avatar") << item->getName() << " updating desc to: " << new_order_str
+			<< " (was: " << item->getActualDescription() << ")" << LL_ENDL;
+		updates["desc"] = new_order_str;
+		update_inventory_item(item_id,updates,cb);
 	}
+		
+}
+
+class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
+{
+	LOG_CLASS(RequestAgentUpdateAppearanceResponder);
+
+	friend class LLAppearanceMgr;
+	
+public:
+	RequestAgentUpdateAppearanceResponder();
+
+	virtual ~RequestAgentUpdateAppearanceResponder();
 
 private:
-	F32 mMinDelay; // delay never less than this value
-	F32 mMaxDelay; // delay never exceeds this value
-	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
-	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
-	F32 mDelay; // current delay.
-	U32 mRetryCount; // number of times shouldRetry has been called.
+	// Called when sendServerAppearanceUpdate called. May or may not
+	// trigger a request depending on various bits of state.
+	void onRequestRequested();
+
+	// Post the actual appearance request to cap.
+	void sendRequest();
+
+	void debugCOF(const LLSD& content);
+
+protected:
+	// Successful completion.
+	/* virtual */ void httpSuccess();
+
+	// Error
+	/*virtual*/ void httpFailure();
+
+	void onFailure();
+	void onSuccess();
+
+	S32 mInFlightCounter;
+	LLTimer mInFlightTimer;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
 };
 
-class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
+RequestAgentUpdateAppearanceResponder::RequestAgentUpdateAppearanceResponder()
 {
-public:
-	RequestAgentUpdateAppearanceResponder()
+	bool retry_on_4xx = true;
+	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
+	mInFlightCounter = 0;
+}
+
+RequestAgentUpdateAppearanceResponder::~RequestAgentUpdateAppearanceResponder()
+{
+}
+
+void RequestAgentUpdateAppearanceResponder::onRequestRequested()
+{
+	// If we have already received an update for this or higher cof version, ignore.
+	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+	S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
+	S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
+	LL_DEBUGS("Avatar") << "cof_version " << cof_version
+						<< " last_rcv " << last_rcv
+						<< " last_req " << last_req
+						<< " in flight " << mInFlightCounter << LL_ENDL;
+	if ((mInFlightCounter>0) && (mInFlightTimer.hasExpired()))
 	{
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+		LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
+		mInFlightCounter = 0;
+	}
+	if (cof_version < last_rcv)
+	{
+		LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
+							<< " will not request for " << cof_version << LL_ENDL;
+		return;
+	}
+	if (mInFlightCounter>0 && last_req >= cof_version)
+	{
+		LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req 
+							<< " will not request for " << cof_version << LL_ENDL;
+		return;
 	}
 
-	virtual ~RequestAgentUpdateAppearanceResponder()
+	// Actually send the request.
+	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
+	mRetryPolicy->reset();
+	sendRequest();
+}
+	
+void RequestAgentUpdateAppearanceResponder::sendRequest()
+{
+	if (gAgentAvatarp->isEditingAppearance()) 
 	{
+		// don't send out appearance updates if in appearance editing mode
+		return;
 	}
 
-	// Successful completion.
-	/* virtual */ void result(const LLSD& content)
+	if (!gAgent.getRegion())
+	{
+		LL_WARNS() << "Region not set, cannot request server appearance update" << LL_ENDL;
+		return;
+	}
+	if (gAgent.getRegion()->getCentralBakeVersion()==0)
+	{
+		LL_WARNS() << "Region does not support baking" << LL_ENDL;
+	}
+	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
+	if (url.empty())
+	{
+		LL_WARNS() << "No cap for UpdateAvatarAppearance." << LL_ENDL;
+		return;
+	}
+	
+	LLSD body;
+	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
+	{
+		body = LLAppearanceMgr::instance().dumpCOF();
+	}
+	else
+	{
+		body["cof_version"] = cof_version;
+		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
+		{
+			body["cof_version"] = cof_version+999;
+		}
+	}
+	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
+
+	mInFlightCounter++;
+	mInFlightTimer.setTimerExpirySec(60.0);
+	LLHTTPClient::post(url, body, this);
+	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
+	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+}
+
+void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
+{
+	LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
+					   << " ================================= " << LL_ENDL;
+	std::set<LLUUID> ais_items, local_items;
+	const LLSD& cof_raw = content["cof_raw"];
+	for (LLSD::array_const_iterator it = cof_raw.beginArray();
+		 it != cof_raw.endArray(); ++it)
 	{
-		LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL;
-		if (content["success"].asBoolean())
+		const LLSD& item = *it;
+		if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
 		{
-			LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
-			if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+			ais_items.insert(item["item_id"].asUUID());
+			if (item["type"].asInteger() == 24) // link
+			{
+				LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << LL_ENDL; 
+			}
+			else if (item["type"].asInteger() == 25) // folder link
 			{
-				dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
+				LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << LL_ENDL; 
+			}
+			else
+			{
+				LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << " type: " << item["type"].asInteger()
+								   << LL_ENDL; 
 			}
 		}
-		else
+	}
+	LL_INFOS("Avatar") << LL_ENDL;
+	LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
+					   << " ================================= " << LL_ENDL;
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
+	gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
+								  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
+	for (S32 i=0; i<item_array.size(); i++)
+	{
+		const LLViewerInventoryItem* inv_item = item_array.at(i).get();
+		local_items.insert(inv_item->getUUID());
+		LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
+						   << " linked_item_id: " << inv_item->getLinkedUUID()
+						   << " name: " << inv_item->getName()
+						   << " parent: " << inv_item->getParentUUID()
+						   << LL_ENDL;
+	}
+	LL_INFOS("Avatar") << " ================================= " << LL_ENDL;
+	S32 local_only = 0, ais_only = 0;
+	for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
+	{
+		if (ais_items.find(*it) == ais_items.end())
 		{
-			onFailure(200);
+			LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL;
+			local_only++;
 		}
 	}
-
-	// Error
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
 	{
-		LL_WARNS() << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << LL_ENDL;
-		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+		if (local_items.find(*it) == local_items.end())
 		{
-			dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
-			debugCOF(content);
-		
+			LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL;
+			ais_only++;
 		}
-		onFailure(status);
-	}	
+	}
+	if (local_only==0 && ais_only==0)
+	{
+		LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
+						   << content["observed"].asInteger()
+						   << " rcv " << content["expected"].asInteger()
+						   << ")" << LL_ENDL;
+	}
+}
 
-	void onFailure(U32 status)
+/* virtual */ void RequestAgentUpdateAppearanceResponder::httpSuccess()
+{
+	const LLSD& content = getContent();
+	if (!content.isMap())
 	{
-		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(status,seconds_to_wait))
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	if (content["success"].asBoolean())
+	{
+		LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
+		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
-			LL_INFOS() << "retrying" << LL_ENDL;
-			doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate,
-										LLAppearanceMgr::getInstance(),
-										LLCurl::ResponderPtr(this)),
-							seconds_to_wait);
+			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
 		}
-		else
-		{
-			LL_WARNS() << "giving up after too many retries" << LL_ENDL;
-		}
-	}	
 
-	void dumpContents(const std::string outprefix, const LLSD& content)
+		onSuccess();
+	}
+	else
 	{
-		std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
-		std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
-		std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
-		ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
-		LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
+		failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
 	}
+}
+
+void RequestAgentUpdateAppearanceResponder::onSuccess()
+{
+	mInFlightCounter = llmax(mInFlightCounter-1,0);
+}
 
-	void debugCOF(const LLSD& content)
+/*virtual*/ void RequestAgentUpdateAppearanceResponder::httpFailure()
+{
+	LL_WARNS("Avatar") << "appearance update request failed, status "
+					   << getStatus() << " reason " << getReason() << LL_ENDL;
+
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 	{
-		LL_DEBUGS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << LL_ENDL;
-		std::set<LLUUID> ais_items, local_items;
-		const LLSD& cof_raw = content["cof_raw"];
-		for (LLSD::array_const_iterator it = cof_raw.beginArray();
-			 it != cof_raw.endArray(); ++it)
-		{
-			const LLSD& item = *it;
-			if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
-			{
-				ais_items.insert(item["item_id"].asUUID());
-				if (item["type"].asInteger() == 24) // link
-				{
-					LL_DEBUGS("Avatar") << "Link: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< LL_ENDL; 
-				}
-				else if (item["type"].asInteger() == 25) // folder link
-				{
-					LL_DEBUGS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< LL_ENDL; 
-					
-				}
-				else
-				{
-					LL_DEBUGS("Avatar") << "Other: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< LL_ENDL; 
-				}
-			}
-		}
-		LL_DEBUGS("Avatar") << LL_ENDL;
-		LL_DEBUGS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << LL_ENDL;
-		LLInventoryModel::cat_array_t cat_array;
-		LLInventoryModel::item_array_t item_array;
-		gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
-									  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
-		for (S32 i=0; i<item_array.size(); i++)
-		{
-			const LLViewerInventoryItem* inv_item = item_array.at(i).get();
-			local_items.insert(inv_item->getUUID());
-			LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID()
-								<< " linked_item_id: " << inv_item->getLinkedUUID()
-								<< " name: " << inv_item->getName()
-								<< LL_ENDL;
-		}
-		LL_DEBUGS("Avatar") << LL_ENDL;
-		for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
-		{
-			if (ais_items.find(*it) == ais_items.end())
-			{
-				LL_DEBUGS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL;
-			}
-		}
-		for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
-		{
-			if (local_items.find(*it) == local_items.end())
-			{
-				LL_DEBUGS("Avatar") << "AIS ONLY: " << *it << LL_ENDL;
-			}
-		}
+		const LLSD& content = getContent();
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
+		debugCOF(content);
 	}
+	onFailure();
+}
+
+void RequestAgentUpdateAppearanceResponder::onFailure()
+{
+	mInFlightCounter = llmax(mInFlightCounter-1,0);
+
+	F32 seconds_to_wait;
+	mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
+	if (mRetryPolicy->shouldRetry(seconds_to_wait))
+	{
+		LL_INFOS() << "retrying" << LL_ENDL;
+		doAfterInterval(boost::bind(&RequestAgentUpdateAppearanceResponder::sendRequest,this),
+						seconds_to_wait);
+	}
+	else
+	{
+		LL_WARNS() << "giving up after too many retries" << LL_ENDL;
+	}
+}	
 
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
 
 LLSD LLAppearanceMgr::dumpCOF() const
 {
@@ -3215,58 +3419,14 @@ LLSD LLAppearanceMgr::dumpCOF() const
 	return result;
 }
 
-void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr)
+void LLAppearanceMgr::requestServerAppearanceUpdate()
 {
-	if (gAgentAvatarp->isEditingAppearance()) 
-	{
-		// don't send out appearance updates if in appearance editing mode
-		return;
-	}
-
-	if (!gAgent.getRegion())
-	{
-		LL_WARNS() << "Region not set, cannot request server appearance update" << LL_ENDL;
-		return;
-	}
-	if (gAgent.getRegion()->getCentralBakeVersion()==0)
-	{
-		LL_WARNS() << "Region does not support baking" << LL_ENDL;
-	}
-	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
-	if (url.empty())
-	{
-		LL_WARNS() << "No cap for UpdateAvatarAppearance." << LL_ENDL;
-		return;
-	}
-
-	LLSD body;
-	S32 cof_version = getCOFVersion();
-	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
-	{
-		body = dumpCOF();
-	}
-	else
-	{
-		body["cof_version"] = cof_version;
-		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
-		{
-			body["cof_version"] = cof_version+999;
-		}
-	}
-	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
-
-	//LLCurl::ResponderPtr responder_ptr;
-	if (!responder_ptr.get())
-	{
-		responder_ptr = new RequestAgentUpdateAppearanceResponder;
-	}
-	LLHTTPClient::post(url, body, responder_ptr);
-	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
-	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+	mAppearanceResponder->onRequestRequested();
 }
 
 class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLIncrementCofVersionResponder);
 public:
 	LLIncrementCofVersionResponder() : LLHTTPClient::Responder()
 	{
@@ -3277,22 +3437,31 @@ class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
 	{
 	}
 
-	virtual void result(const LLSD &pContent)
+protected:
+	virtual void httpSuccess()
 	{
 		LL_INFOS() << "Successfully incremented agent's COF." << LL_ENDL;
-		S32 new_version = pContent["category"]["version"].asInteger();
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		S32 new_version = content["category"]["version"].asInteger();
 
 		// cof_version should have increased
 		llassert(new_version > gAgentAvatarp->mLastUpdateRequestCOFVersion);
 
 		gAgentAvatarp->mLastUpdateRequestCOFVersion = new_version;
 	}
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content)
+
+	virtual void httpFailure()
 	{
-		LL_WARNS() << "While attempting to increment the agent's cof we got an error with [status:"
-				<< pStatus << "]: " << content << LL_ENDL;
+		LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
+						   << dumpResponse() << LL_ENDL;
 		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait))
+		mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
+		if (mRetryPolicy->shouldRetry(seconds_to_wait))
 		{
 			LL_INFOS() << "retrying" << LL_ENDL;
 			doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
@@ -3306,6 +3475,7 @@ class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
 		}
 	}
 
+private:
 	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
 };
 
@@ -3338,6 +3508,15 @@ void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_p
 	LLHTTPClient::get(url, body, responder_ptr, headers, 30.0f);
 }
 
+U32 LLAppearanceMgr::getNumAttachmentsInCOF()
+{
+	const LLUUID cof = getCOF();
+	LLInventoryModel::item_array_t obj_items;
+	getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
+	return obj_items.size();
+}
+
+
 std::string LLAppearanceMgr::getAppearanceServiceURL() const
 {
 	if (gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride").empty())
@@ -3348,57 +3527,91 @@ std::string LLAppearanceMgr::getAppearanceServiceURL() const
 }
 
 void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
+{
+	if (!LLApp::isRunning())
 	{
-		if (!LLApp::isRunning())
-		{
-			LL_WARNS() << "called during shutdown, skipping" << LL_ENDL;
-			return;
-		}
-
-		LLSD key;
-		
+		LL_WARNS() << "called during shutdown, skipping" << LL_ENDL;
+		return;
+	}
+	
+	LL_DEBUGS("Avatar") << "called" << LL_ENDL;
+	LLSD key;
+	
 	//EXT-7727. For new accounts inventory callback is created during login process
 	// and may be processed after login process is finished
 	if (show_panel)
-		{
-			LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key);
-
-		}
-		LLOutfitsList *outfits_list =
-			dynamic_cast<LLOutfitsList*>(LLFloaterSidePanelContainer::getPanel("appearance", "outfitslist_tab"));
-		if (outfits_list)
-		{
+	{
+		LL_DEBUGS("Avatar") << "showing panel" << LL_ENDL;
+		LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key);
+		
+	}
+	LLOutfitsList *outfits_list =
+		dynamic_cast<LLOutfitsList*>(LLFloaterSidePanelContainer::getPanel("appearance", "outfitslist_tab"));
+	if (outfits_list)
+	{
 		outfits_list->setSelectedOutfitByUUID(folder_id);
-		}
-
-		LLAppearanceMgr::getInstance()->updateIsDirty();
-		gAgentWearables.notifyLoadingFinished(); // New outfit is saved.
-		LLAppearanceMgr::getInstance()->updatePanelOutfitName("");
 	}
+	
+	LLAppearanceMgr::getInstance()->updateIsDirty();
+	gAgentWearables.notifyLoadingFinished(); // New outfit is saved.
+	LLAppearanceMgr::getInstance()->updatePanelOutfitName("");
+
+	// For SSB, need to update appearance after we add a base outfit
+	// link, since, the COF version has changed. There is a race
+	// condition in initial outfit setup which can lead to rez
+	// failures - SH-3860.
+	LL_DEBUGS("Avatar") << "requesting appearance update after createBaseOutfitLink" << LL_ENDL;
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
+	LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb);
+}
 
-LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
+void LLAppearanceMgr::onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel)
 {
-	if (!isAgentAvatarValid()) return LLUUID::null;
-
-	gAgentWearables.notifyLoadingStarted();
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,folder_id,show_panel));
+	updateClothingOrderingInfo(LLUUID::null, cb);
+}
 
-	// First, make a folder in the My Outfits directory.
-	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	LLUUID folder_id = gInventory.createNewCategory(
-		parent_id,
-		LLFolderType::FT_OUTFIT,
-		new_folder_name);
+void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel)
+{
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(show_created_outfit,folder_id,show_panel));
+	bool copy_folder_links = false;
+	slamCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
+}
 
-	updateClothingOrderingInfo();
+void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
+{
+	if (!isAgentAvatarValid()) return;
 
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
-																		 boost::bind(show_created_outfit,folder_id,show_panel));
-	shallowCopyCategoryContents(getCOF(),folder_id, cb);
-	createBaseOutfitLink(folder_id, cb);
+	LL_DEBUGS("Avatar") << "creating new outfit" << LL_ENDL;
 
-	dumpCat(folder_id,"COF, new outfit");
+	gAgentWearables.notifyLoadingStarted();
 
-	return folder_id;
+	// First, make a folder in the My Outfits directory.
+	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+	if (AISCommand::isAPIAvailable())
+	{
+		// cap-based category creation was buggy until recently. use
+		// existence of AIS as an indicator the fix is present. Does
+		// not actually use AIS to create the category.
+		inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
+		LLUUID folder_id = gInventory.createNewCategory(
+			parent_id,
+			LLFolderType::FT_OUTFIT,
+			new_folder_name,
+			func);
+	}
+	else
+	{		
+		LLUUID folder_id = gInventory.createNewCategory(
+			parent_id,
+			LLFolderType::FT_OUTFIT,
+			new_folder_name);
+		onOutfitFolderCreated(folder_id, show_panel);
+	}
 }
 
 void LLAppearanceMgr::wearBaseOutfit()
@@ -3414,23 +3627,24 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
 	if (ids_to_remove.empty())
 	{
 		LL_WARNS() << "called with empty list, nothing to do" << LL_ENDL;
+		return;
 	}
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it)
 	{
 		const LLUUID& id_to_remove = *it;
 		const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove);
-		removeCOFItemLinks(linked_item_id);
+		removeCOFItemLinks(linked_item_id, cb);
 		addDoomedTempAttachment(linked_item_id);
 	}
-	updateAppearanceFromCOF();
 }
 
 void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
 {
 	LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);
-	removeCOFItemLinks(linked_item_id);
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
+	removeCOFItemLinks(linked_item_id, cb);
 	addDoomedTempAttachment(linked_item_id);
-	updateAppearanceFromCOF();
 }
 
 
@@ -3490,7 +3704,12 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b
 	swap_item->setDescription(item->getActualDescription());
 	item->setDescription(tmp);
 
+	// LL_DEBUGS("Inventory") << "swap, item "
+	// 					   << ll_pretty_print_sd(item->asLLSD())
+	// 					   << " swap_item "
+	// 					   << ll_pretty_print_sd(swap_item->asLLSD()) << LL_ENDL;
 
+	// FIXME switch to use AISv3 where supported.
 	//items need to be updated on a dataserver
 	item->setComplete(TRUE);
 	item->updateServer(FALSE);
@@ -3504,7 +3723,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b
 	bool result = false;
 	if (result = gAgentWearables.moveWearable(item, closer_to_body))
 	{
-		gAgentAvatarp->wearableUpdated(item->getWearableType(), FALSE);
+		gAgentAvatarp->wearableUpdated(item->getWearableType());
 	}
 
 	setOutfitDirty(true);
@@ -3566,7 +3785,8 @@ LLAppearanceMgr::LLAppearanceMgr():
 	mAttachmentInvLinkEnabled(false),
 	mOutfitIsDirty(false),
 	mOutfitLocked(false),
-	mIsInUpdateAppearanceFromCOF(false)
+	mIsInUpdateAppearanceFromCOF(false),
+	mAppearanceResponder(new RequestAgentUpdateAppearanceResponder)
 {
 	LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
 
@@ -3616,7 +3836,11 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 		   // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF.
 		   // it will trigger gAgentWariables.notifyLoadingFinished()
 		   // But it is not acceptable solution. See EXT-7777
-		   LLAppearanceMgr::addCOFItemLink(item_id, false);  // Add COF link for item.
+		   if (!isLinkedInCOF(item_id))
+		   {
+			   LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy();
+			   LLAppearanceMgr::addCOFItemLink(item_id, cb);  // Add COF link for item.
+		   }
 	   }
 	   else
 	   {
@@ -3640,22 +3864,21 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
 
 BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
 {
-	return gInventory.isObjectDescendentOf(obj_id, getCOF());
+	const LLUUID& cof = getCOF();
+	if (obj_id == cof)
+		return TRUE;
+	const LLInventoryObject* obj = gInventory.getObject(obj_id);
+	if (obj && obj->getParentUUID() == cof)
+		return TRUE;
+	return FALSE;
 }
 
 // static
 bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
 {
-	 LLInventoryModel::cat_array_t cats;
-	 LLInventoryModel::item_array_t items;
-	 LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id));
-	 gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
-									 cats,
-									 items,
-	 LLInventoryModel::EXCLUDE_TRASH,
-	 find_links);
-
-	 return !items.empty();
+	const LLUUID& target_id = gInventory.getLinkedItemID(obj_id);
+	LLLinkedItemIDMatches find_links(target_id);
+	return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links);
 }
 
 BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
@@ -3672,18 +3895,6 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
 	// For now, don't allow direct deletion from the COF.  Instead, force users
 	// to choose "Detach" or "Take Off".
 	return TRUE;
-	/*
-	const LLInventoryObject *obj = gInventory.getObject(obj_id);
-	if (!obj) return FALSE;
-
-	// Can't delete bodyparts, since this would be equivalent to removing the item.
-	if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE;
-
-	// Can't delete the folder link, since this is saved for bookkeeping.
-	if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
-
-	return FALSE;
-	*/
 }
 
 class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
@@ -3824,7 +4035,7 @@ class LLWearFolderHandler : public LLCommandHandler
 			LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);
 
 			// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
-			gAgent.setGenderChosen(TRUE);
+			gAgent.setOutfitChosen(TRUE);
 		}
 
 		// release avatar picker keyboard focus
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index b5ef0bd935dd5c08d4410506ca0f57257bc74c1e..7742a19c07f2bc0636405f8bb5b022d3c1b1d02b 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -39,6 +39,7 @@
 class LLWearableHoldingPattern;
 class LLInventoryCallback;
 class LLOutfitUnLockTimer;
+class RequestAgentUpdateAppearanceResponder;
 
 class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 {
@@ -50,7 +51,9 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 public:
 	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
 
-	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false);
+	void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
+								 bool enforce_ordering = true,
+								 nullary_func_t post_update_func = no_op);
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -65,9 +68,18 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
 								   LLAssetType::EType type,
 								   S32 max_items,
-								   LLInventoryModel::item_array_t& items_to_kill);
-	void enforceItemRestrictions();
-
+								   LLInventoryObject::object_list_t& items_to_kill);
+	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
+									  LLInventoryObject::object_list_t& items_to_kill);
+	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
+
+	S32 getActiveCopyOperations() const;
+
+	// Replace category contents with copied links via the slam_inventory_folder
+	// command (single inventory operation where supported)
+	void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+						   bool include_folder_links, LLPointer<LLInventoryCallback> cb);
+ 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
 							 LLPointer<LLInventoryCallback> cb);
@@ -106,15 +118,18 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	const LLUUID getBaseOutfitUUID();
 
 	// Wear/attach an item (from a user's inventory) on the agent
-	bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update = true, bool replace = false, LLPointer<LLInventoryCallback> cb = NULL);
+	bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
+						  LLPointer<LLInventoryCallback> cb = NULL);
 
 	// Update the displayed outfit name in UI.
 	void updatePanelOutfitName(const std::string& name);
 
-	void purgeBaseOutfitLink(const LLUUID& category);
+	void purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb = NULL);
 	void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter);
 
-	void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
+	void updateAgentWearables(LLWearableHoldingPattern* holder);
+
+	S32 countActiveHoldingPatterns();
 
 	// For debugging - could be moved elsewhere.
 	void dumpCat(const LLUUID& cat_id, const std::string& msg);
@@ -125,21 +140,17 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void registerAttachment(const LLUUID& item_id);
 	void setAttachmentInvLinkEnable(bool val);
 
-	// utility function for bulk linking.
-	void linkAll(const LLUUID& category,
-				 LLInventoryModel::item_array_t& items,
-				 LLPointer<LLInventoryCallback> cb);
-
 	// Add COF link to individual item.
-	void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
-	void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
+	void addCOFItemLink(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
+	void addCOFItemLink(const LLInventoryItem *item, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
 
 	// Find COF entries referencing the given item.
 	LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id);
+	bool isLinkedInCOF(const LLUUID& item_id);
 
 	// Remove COF entries
-	void removeCOFItemLinks(const LLUUID& item_id);
-	void removeCOFLinksOfType(LLWearableType::EType type);
+	void removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL);
+	void removeCOFLinksOfType(LLWearableType::EType type, LLPointer<LLInventoryCallback> cb = NULL);
 	void removeAllClothesFromAvatar();
 	void removeAllAttachmentsFromAvatar();
 
@@ -156,12 +167,11 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	// should only be necessary to do on initial login.
 	void updateIsDirty();
 
+	void setOutfitLocked(bool locked);
+
 	// Called when self avatar is first fully visible.
 	void onFirstFullyVisible();
 
-	// Create initial outfits from library.
-	void autopopulateOutfits();
-
 	// Copy initial gestures from library.
 	void copyLibraryGestures();
 	
@@ -176,7 +186,10 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void removeItemFromAvatar(const LLUUID& item_id);
 
 
-	LLUUID makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
+	void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
+	void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
+
+	void makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
 
@@ -185,18 +198,27 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	//Divvy items into arrays by wearable type
 	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
 
+	typedef std::map<LLUUID,std::string> desc_map_t;
+
+	void getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, desc_map_t& desc_map);
+
 	//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);
+	bool validateClothingOrderingInfo(LLUUID cat_id = LLUUID::null);
+	
+	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
+									LLPointer<LLInventoryCallback> cb = NULL);
 
 	bool isOutfitLocked() { return mOutfitLocked; }
 
 	bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; }
 
-	void requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr = NULL);
+	void requestServerAppearanceUpdate();
 
 	void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
 
+	U32 getNumAttachmentsInCOF();
+
 	// *HACK Remove this after server side texture baking is deployed on all sims.
 	void incrementCofVersionLegacy();
 
@@ -217,24 +239,21 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	
 	void getDescendentsOfAssetType(const LLUUID& category, 
 										  LLInventoryModel::item_array_t& items,
-										  LLAssetType::EType type,
-										  bool follow_folder_links);
+										  LLAssetType::EType type);
 
 	void getUserDescendents(const LLUUID& category, 
 								   LLInventoryModel::item_array_t& wear_items,
 								   LLInventoryModel::item_array_t& obj_items,
-								   LLInventoryModel::item_array_t& gest_items,
-								   bool follow_folder_links);
+								   LLInventoryModel::item_array_t& gest_items);
 
-	void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items = NULL);
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
 
-	void setOutfitLocked(bool locked);
-
 	bool mAttachmentInvLinkEnabled;
 	bool mOutfitIsDirty;
 	bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
 
+	LLPointer<RequestAgentUpdateAppearanceResponder> mAppearanceResponder;
+
 	/**
 	 * Lock for blocking operations on outfit until server reply or timeout exceed
 	 * to avoid unsynchronized outfit state or performing duplicate operations.
@@ -266,17 +285,31 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 {
 public:
-	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false);
+	LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions = true,
+								bool enforce_ordering = true,
+								nullary_func_t post_update_func = no_op);
 	virtual ~LLUpdateAppearanceOnDestroy();
 	/* virtual */ void fire(const LLUUID& inv_item);
 
 private:
 	U32 mFireCount;
-	bool mUpdateBaseOrder;
+	bool mEnforceItemRestrictions;
+	bool mEnforceOrdering;
+	nullary_func_t mPostUpdateFunc;
 };
 
+class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
+{
+public:
+	LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id);
+
+	/* virtual */ void fire(const LLUUID& item_id) {}
 
-#define SUPPORT_ENSEMBLES 0
+	~LLUpdateAppearanceAndEditWearableOnDestroy();
+	
+private:
+	LLUUID mItemID;
+};
 
 LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f98ec697327da500631b6c90e69874ee7e443c33..f52e6625c1291ae97f1c7a6c2fb17b5ac6256a54 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2019,6 +2019,9 @@ bool LLAppViewer::cleanup()
 	// Non-LLCurl libcurl library
 	mAppCoreHttp.cleanup();
 
+	// NOTE The following call is not thread safe. 
+	ll_cleanup_ares();
+
 	LLFilePickerThread::cleanupClass();
 
 	//MUST happen AFTER LLCurl::cleanupClass
@@ -2114,6 +2117,8 @@ bool LLAppViewer::cleanup()
 
 	ll_close_fail_log();
 
+	LLError::LLCallStacks::cleanup();
+
 	removeMarkerFiles();
 	
     LL_INFOS() << "Goodbye!" << LL_ENDL;
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 06f081e92046ff1af0aaf983511c253c3d7e4a60..57fb84bbf139651b15fd1921fac0d798ebaf11dc 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -438,7 +438,7 @@ void LLAppViewerWin32::disableWinErrorReporting()
 
 const S32 MAX_CONSOLE_LINES = 500;
 
-void create_console()
+static bool create_console()
 {
 	int h_con_handle;
 	long l_std_handle;
@@ -447,7 +447,7 @@ void create_console()
 	FILE *fp;
 
 	// allocate a console for this app
-	AllocConsole();
+	const bool isConsoleAllocated = AllocConsole();
 
 	// set the screen buffer to be big enough to let us scroll text
 	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
@@ -495,10 +495,13 @@ void create_console()
 		*stderr = *fp;
 		setvbuf( stderr, NULL, _IONBF, 0 );
 	}
+
+    return isConsoleAllocated;
 }
 
 LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
-    mCmdLine(cmd_line)
+	mCmdLine(cmd_line),
+	mIsConsoleAllocated(false)
 {
 }
 
@@ -542,6 +545,16 @@ bool LLAppViewerWin32::cleanup()
 
 	gDXHardware.cleanup();
 
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	LLWinDebug::instance().cleanup();
+#endif
+
+	if (mIsConsoleAllocated)
+	{
+		FreeConsole();
+		mIsConsoleAllocated = false;
+	}
+
 	return result;
 }
 
@@ -553,7 +566,7 @@ void LLAppViewerWin32::initLoggingAndGetLastDuration()
 void LLAppViewerWin32::initConsole()
 {
 	// pop up debug console
-	create_console();
+	mIsConsoleAllocated = create_console();
 	return LLAppViewer::initConsole();
 }
 
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index fb37df1a2f0df52ec54d5ff6fca324579ec6b417..59d1ddaa3df21d661e03789da7e58428a3f7e355 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -61,7 +61,8 @@ class LLAppViewerWin32 : public LLAppViewer
 private:
 	void disableWinErrorReporting();
 
-    std::string mCmdLine;
+	std::string mCmdLine;
+	bool mIsConsoleAllocated;
 };
 
 #endif // LL_LLAPPVIEWERWIN32_H
diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp
index 2b428aec4b05ee4a7a9566e8a95bb9c156b3f6e9..8833c5794839c6e6c16a831d2cdf8dbd2f65b716 100755
--- a/indra/newview/llassetuploadqueue.cpp
+++ b/indra/newview/llassetuploadqueue.cpp
@@ -36,6 +36,7 @@
 
 class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder
 {
+	LOG_CLASS(LLAssetUploadChainResponder);
 public:
 	
 	LLAssetUploadChainResponder(const LLSD& post_data,
@@ -51,52 +52,54 @@ class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder
 		mDataSize(data_size),
 		mScriptName(script_name)
 	{
- 	}
+	}
 
 	virtual ~LLAssetUploadChainResponder() 
-   	{
-   		if(mSupplier)
-   		{
-   			LLAssetUploadQueue *queue = mSupplier->get();
-   			if (queue)
-   			{
-   				// Give ownership of supplier back to queue.
-   				queue->mSupplier = mSupplier;
-   				mSupplier = NULL;
-   			}
-   		}
-   		delete mSupplier;
+	{
+		if(mSupplier)
+		{
+			LLAssetUploadQueue *queue = mSupplier->get();
+			if (queue)
+			{
+				// Give ownership of supplier back to queue.
+				queue->mSupplier = mSupplier;
+				mSupplier = NULL;
+			}
+		}
+		delete mSupplier;
 		delete mData;
-   	}
+	}
 	
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-   	{
-		LL_WARNS() << "LLAssetUploadChainResponder Error [status:" 
-				<< statusNum << "]: " << content << LL_ENDL;
-		LLUpdateTaskInventoryResponder::errorWithContent(statusNum, reason, content);
-   		LLAssetUploadQueue *queue = mSupplier->get();
-   		if (queue)
+protected:
+	virtual void httpFailure()
+	{
+		// Parent class will spam the failure.
+		//LL_WARNS() << dumpResponse() << LL_ENDL;
+		LLUpdateTaskInventoryResponder::httpFailure();
+		LLAssetUploadQueue *queue = mSupplier->get();
+		if (queue)
+		{
+			queue->request(&mSupplier);
+		}
+	}
+
+	virtual void httpSuccess()
+	{
+		LLUpdateTaskInventoryResponder::httpSuccess();
+		LLAssetUploadQueue *queue = mSupplier->get();
+		if (queue)
 		{
-   			queue->request(&mSupplier);
-   		}
-   	}
-
-	virtual void result(const LLSD& content)
-   	{
-		LLUpdateTaskInventoryResponder::result(content);
-   		LLAssetUploadQueue *queue = mSupplier->get();
-   		if (queue)
-   		{
-   			// Responder is reused across 2 phase upload,
-   			// so only start next upload after 2nd phase complete.
-   			std::string state = content["state"];
-   			if(state == "complete")
-   			{
-   				queue->request(&mSupplier);
-   			}
-   		}	
-   	}
+			// Responder is reused across 2 phase upload,
+			// so only start next upload after 2nd phase complete.
+			const std::string& state = getContent()["state"].asStringRef();
+			if(state == "complete")
+			{
+				queue->request(&mSupplier);
+			}
+		}
+	}
 	
+public:
 	virtual void uploadUpload(const LLSD& content)
 	{
 		std::string uploader = content["uploader"];
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index d86e63589fd5c3b87d363ce2553543ff7895d7b4..a98ff64d0a452b2580aa883012e7a2df45a03d0c 100755
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -225,37 +225,41 @@ LLAssetUploadResponder::~LLAssetUploadResponder()
 }
 
 // virtual
-void LLAssetUploadResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+void LLAssetUploadResponder::httpFailure()
 {
-	LL_INFOS() << "LLAssetUploadResponder::error [status:" 
-			<< statusNum << "]: " << content << LL_ENDL;
+	// *TODO: Add adaptive retry policy?
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	LLSD args;
-	switch(statusNum)
+	if (isHttpClientErrorStatus(getStatus()))
 	{
-		case 400:
-			args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-			args["REASON"] = "Error in upload request.  Please visit "
-				"http://secondlife.com/support for help fixing this problem.";
-			LLNotificationsUtil::add("CannotUploadReason", args);
-			break;
-		case 500:
-		default:
-			args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-			args["REASON"] = "The server is experiencing unexpected "
-				"difficulties.";
-			LLNotificationsUtil::add("CannotUploadReason", args);
-			break;
+		args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+		args["REASON"] = "Error in upload request.  Please visit "
+			"http://secondlife.com/support for help fixing this problem.";
+		LLNotificationsUtil::add("CannotUploadReason", args);
+	}
+	else
+	{
+		args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+		args["REASON"] = "The server is experiencing unexpected "
+			"difficulties.";
+		LLNotificationsUtil::add("CannotUploadReason", args);
 	}
 	LLUploadDialog::modalUploadFinished();
 	LLFilePicker::instance().reset();  // unlock file picker when bulk upload fails
 }
 
 //virtual 
-void LLAssetUploadResponder::result(const LLSD& content)
+void LLAssetUploadResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LL_DEBUGS() << "LLAssetUploadResponder::result from capabilities" << LL_ENDL;
 
-	std::string state = content["state"];
+	const std::string& state = content["state"].asStringRef();
 
 	if (state == "upload")
 	{
@@ -280,7 +284,7 @@ void LLAssetUploadResponder::result(const LLSD& content)
 
 void LLAssetUploadResponder::uploadUpload(const LLSD& content)
 {
-	std::string uploader = content["uploader"];
+	const std::string& uploader = content["uploader"].asStringRef();
 	if (mFileName.empty())
 	{
 		LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this);
@@ -293,6 +297,7 @@ void LLAssetUploadResponder::uploadUpload(const LLSD& content)
 
 void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 {
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	// remove the "Uploading..." message
 	LLUploadDialog::modalUploadFinished();
 	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
@@ -301,7 +306,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
 	}
 	
-	std::string reason = content["state"];
+	const std::string& reason = content["state"].asStringRef();
 	// deal with L$ errors
 	if (reason == "insufficient funds")
 	{
@@ -340,9 +345,9 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
 }
 
 // virtual
-void LLNewAgentInventoryResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+void LLNewAgentInventoryResponder::httpFailure()
 {
-	LLAssetUploadResponder::errorWithContent(statusNum, reason, content);
+	LLAssetUploadResponder::httpFailure();
 	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE);
 }
 
@@ -445,58 +450,6 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
 	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);
 }
 
-LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
-												 const LLUUID& vfile_id,
-												 LLAssetType::EType asset_type,
-												 LLBakedUploadData * baked_upload_data) : 
-	LLAssetUploadResponder(post_data, vfile_id, asset_type),
-	mBakedUploadData(baked_upload_data)
-{
-}
-
-LLSendTexLayerResponder::~LLSendTexLayerResponder()
-{
-	// mBakedUploadData is normally deleted by calls to LLViewerTexLayerSetBuffer::onTextureUploadComplete() below
-	if (mBakedUploadData)
-	{	// ...but delete it in the case where uploadComplete() is never called
-		delete mBakedUploadData;
-		mBakedUploadData = NULL;
-	}
-}
-
-
-// Baked texture upload completed
-void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
-{
-	LLUUID item_id = mPostData["item_id"];
-
-	std::string result = content["state"];
-	LLUUID new_id = content["new_asset"];
-
-	LL_INFOS() << "result: " << result << " new_id: " << new_id << LL_ENDL;
-	if (result == "complete"
-		&& mBakedUploadData != NULL)
-	{	// Invoke 
-		LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE);
-		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-	}
-	else
-	{	// Invoke the original callback with an error result
-		LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
-		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-	}
-}
-
-void LLSendTexLayerResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-{
-	LL_INFOS() << "LLSendTexLayerResponder error [status:"
-			<< statusNum << "]: " << content << LL_ENDL;
-	
-	// Invoke the original callback with an error result
-	LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
-	mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-}
-
 LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
 	const LLSD& post_data,
 	const LLUUID& vfile_id,
@@ -1009,19 +962,14 @@ LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResp
 	delete mImpl;
 }
 
-void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
-	U32 statusNum,
-	const std::string& reason,
-	const LLSD& content)
+void LLNewAgentInventoryVariablePriceResponder::httpFailure()
 {
-	LL_DEBUGS() 
-		<< "LLNewAgentInventoryVariablePrice::error " << statusNum 
-		<< " reason: " << reason << LL_ENDL;
+	const LLSD& content = getContent();
+	LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 
-	if ( content.has("error") )
+	static const std::string _ERROR = "error";
+	if ( content.has(_ERROR) )
 	{
-		static const std::string _ERROR = "error";
-
 		mImpl->onTransportError(content[_ERROR]);
 	}
 	else
@@ -1030,8 +978,14 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
 	}
 }
 
-void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
+void LLNewAgentInventoryVariablePriceResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	// Parse out application level errors and the appropriate
 	// responses for them
 	static const std::string _ERROR = "error";
@@ -1047,6 +1001,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
 	// Check for application level errors
 	if ( content.has(_ERROR) )
 	{
+		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 		onApplicationLevelError(content[_ERROR]);
 		return;
 	}
@@ -1090,6 +1045,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
 	}
 	else
 	{
+		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 		onApplicationLevelError("");
 	}
 }
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index a6d1016136c6a49f86578e4077bf1acc010a822d..7fbebc7481c1f585dacf23f1c13be02276da9aee 100755
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -33,6 +33,8 @@
 // via capabilities
 class LLAssetUploadResponder : public LLHTTPClient::Responder
 {
+protected:
+	LOG_CLASS(LLAssetUploadResponder);
 public:
 	LLAssetUploadResponder(const LLSD& post_data,
 							const LLUUID& vfile_id,
@@ -42,8 +44,11 @@ class LLAssetUploadResponder : public LLHTTPClient::Responder
 							LLAssetType::EType asset_type);
 	~LLAssetUploadResponder();
 
-    virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+protected:
+	virtual void httpFailure();
+	virtual void httpSuccess();
+
+public:
 	virtual void uploadUpload(const LLSD& content);
 	virtual void uploadComplete(const LLSD& content);
 	virtual void uploadFailure(const LLSD& content);
@@ -58,6 +63,7 @@ class LLAssetUploadResponder : public LLHTTPClient::Responder
 // TODO*: Remove this once deprecated
 class LLNewAgentInventoryResponder : public LLAssetUploadResponder
 {
+	LOG_CLASS(LLNewAgentInventoryResponder);
 public:
 	LLNewAgentInventoryResponder(
 		const LLSD& post_data,
@@ -67,9 +73,10 @@ class LLNewAgentInventoryResponder : public LLAssetUploadResponder
 		const LLSD& post_data,
 		const std::string& file_name,
 		LLAssetType::EType asset_type);
-    virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
 	virtual void uploadComplete(const LLSD& content);
 	virtual void uploadFailure(const LLSD& content);
+protected:
+	virtual void httpFailure();
 };
 
 // A base class which goes through and performs some default
@@ -79,6 +86,7 @@ class LLNewAgentInventoryResponder : public LLAssetUploadResponder
 class LLNewAgentInventoryVariablePriceResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLNewAgentInventoryVariablePriceResponder);
 public:
 	LLNewAgentInventoryVariablePriceResponder(
 		const LLUUID& vfile_id,
@@ -91,12 +99,11 @@ class LLNewAgentInventoryVariablePriceResponder :
 		const LLSD& inventory_info);
 	virtual ~LLNewAgentInventoryVariablePriceResponder();
 
-	void errorWithContent(
-		U32 statusNum,
-		const std::string& reason,
-		const LLSD& content);
-	void result(const LLSD& content);
+private:
+	/* virtual */ void httpFailure();
+	/* virtual */ void httpSuccess();
 
+public:
 	virtual void onApplicationLevelError(
 		const LLSD& error);
 	virtual void showConfirmationDialog(
@@ -109,24 +116,6 @@ class LLNewAgentInventoryVariablePriceResponder :
 	Impl* mImpl;
 };
 
-struct LLBakedUploadData;
-class LLSendTexLayerResponder : public LLAssetUploadResponder
-{
-	LOG_CLASS(LLSendTexLayerResponder);
-public:
-	LLSendTexLayerResponder(const LLSD& post_data,
-							const LLUUID& vfile_id,
-							LLAssetType::EType asset_type,
-							LLBakedUploadData * baked_upload_data);
-
-	~LLSendTexLayerResponder();
-
-	virtual void uploadComplete(const LLSD& content);
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
-
-	LLBakedUploadData * mBakedUploadData;
-};
-
 class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder
 {
 public:
diff --git a/indra/newview/llbreastmotion.cpp b/indra/newview/llbreastmotion.cpp
index 9a8cd5ceae0ceea0313889dfeee2841a8e738f20..3a88bab3b3621ac8b9ad9f90b26c8fe2a4ceb30a 100755
--- a/indra/newview/llbreastmotion.cpp
+++ b/indra/newview/llbreastmotion.cpp
@@ -340,8 +340,7 @@ BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask)
 		if (mBreastParamsDriven[i])
 		{
 			mCharacter->setVisualParamWeight(mBreastParamsDriven[i],
-											 new_local_pt[i],
-											 FALSE);
+											 new_local_pt[i]);
 		}
 	}
 
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 05c4181714b5728c8f612db91e19b10b6345aef9..84b9ac756a1ac91e44413b32ce950761ac54fd76 100755
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -107,6 +107,7 @@ class LLChatHistoryHeader: public LLPanel
 public:
 	LLChatHistoryHeader()
 	:	LLPanel(),
+		mInfoCtrl(NULL),
 		mPopupMenuHandleAvatar(),
 		mPopupMenuHandleObject(),
 		mAvatarID(),
@@ -129,9 +130,6 @@ class LLChatHistoryHeader: public LLPanel
 
 	~LLChatHistoryHeader()
 	{
-		// Detach the info button so that it doesn't get destroyed (EXT-8463).
-		hideInfoCtrl();
-
 		if (mAvatarNameCacheConnection.connected())
 		{
 			mAvatarNameCacheConnection.disconnect();
@@ -292,6 +290,11 @@ class LLChatHistoryHeader: public LLPanel
 		mUserNameTextBox = getChild<LLTextBox>("user_name");
 		mTimeBoxTextBox = getChild<LLTextBox>("time_box");
 
+		mInfoCtrl = LLUICtrlFactory::getInstance()->createFromFile<LLUICtrl>("inspector_info_ctrl.xml", this, LLPanel::child_registry_t::instance());
+		llassert(mInfoCtrl != NULL);
+		mInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, mInfoCtrl));
+		mInfoCtrl->setVisible(FALSE);
+
 		return LLPanel::postBuild();
 	}
 
@@ -589,39 +592,19 @@ class LLChatHistoryHeader: public LLPanel
 
 	void showInfoCtrl()
 	{
-		if (mAvatarID.isNull() || mFrom.empty() || CHAT_SOURCE_SYSTEM == mSourceType) return;
-				
-		if (!sInfoCtrl)
-		{
-			// *TODO: Delete the button at exit.
-			sInfoCtrl = LLUICtrlFactory::createFromFile<LLUICtrl>("inspector_info_ctrl.xml", NULL, LLPanel::child_registry_t::instance());
-			if (sInfoCtrl)
-			{
-				sInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, sInfoCtrl));
-			}
-		}
-
-		if (!sInfoCtrl)
+		const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType;
+		if (isVisible)
 		{
-			llassert(sInfoCtrl != NULL);
-			return;
+			const LLRect sticky_rect = mUserNameTextBox->getRect();
+			S32 icon_x = llmin(sticky_rect.mLeft + mUserNameTextBox->getTextBoundingRect().getWidth() + 7, sticky_rect.mRight - 3);
+			mInfoCtrl->setOrigin(icon_x, sticky_rect.getCenterY() - mInfoCtrl->getRect().getHeight() / 2 ) ;
 		}
-
-		LLTextBox* name = getChild<LLTextBox>("user_name");
-		LLRect sticky_rect = name->getRect();
-		S32 icon_x = llmin(sticky_rect.mLeft + name->getTextBoundingRect().getWidth() + 7, sticky_rect.mRight - 3);
-		sInfoCtrl->setOrigin(icon_x, sticky_rect.getCenterY() - sInfoCtrl->getRect().getHeight() / 2 ) ;
-		addChild(sInfoCtrl);
+		mInfoCtrl->setVisible(isVisible);
 	}
 
 	void hideInfoCtrl()
 	{
-		if (!sInfoCtrl) return;
-
-		if (sInfoCtrl->getParent() == this)
-		{
-			removeChild(sInfoCtrl);
-		}
+		mInfoCtrl->setVisible(FALSE);
 	}
 
 private:
@@ -692,7 +675,7 @@ class LLChatHistoryHeader: public LLPanel
 	LLHandle<LLView>	mPopupMenuHandleAvatar;
 	LLHandle<LLView>	mPopupMenuHandleObject;
 
-	static LLUICtrl*	sInfoCtrl;
+	LLUICtrl*			mInfoCtrl;
 
 	LLUUID			    mAvatarID;
 	LLSD				mObjectData;
@@ -709,8 +692,6 @@ class LLChatHistoryHeader: public LLPanel
 	boost::signals2::connection mAvatarNameCacheConnection;
 };
 
-LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
-
 LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 :	LLUICtrl(p),
 	mMessageHeaderFilename(p.message_header),
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index bb6d4fb59cefc4a07434caad95c6e2dee0dd652c..44736a04895d7cd81257265c166a51e0c02b6ebe 100755
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -93,14 +93,15 @@ class LLChatHistory : public LLUICtrl
 		 * @return pointer to LLView separator object.
 		 */
 		LLView* getSeparator();
+
+		void onClickMoreText();
+
+	private:
 		/**
 		 * Builds a message header.
 		 * @return pointer to LLView header object.
 		 */
 		LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params, const LLSD& args);
-
-		void onClickMoreText();
-
 	public:
 		~LLChatHistory();
 		LLSD getValue() const;   
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index fd4f17b69439ab3321af1c0626c7e5d60d570340..cfc62c07b6e073a8ee36e930cb74ec6fcd465a1c 100755
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -29,7 +29,6 @@
 #include "llchatitemscontainerctrl.h"
 #include "lltextbox.h"
 
-#include "llchatmsgbox.h"
 #include "llavatariconctrl.h"
 #include "llcommandhandler.h"
 #include "llfloaterreg.h"
@@ -130,7 +129,6 @@ void LLFloaterIMNearbyChatToastPanel::addMessage(LLSD& notification)
 {
 	std::string		messageText = notification["message"].asString();		// UTF-8 line of text
 
-	LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
 
 	std::string color_name = notification["text_color"].asString();
 	
@@ -171,7 +169,7 @@ void LLFloaterIMNearbyChatToastPanel::addMessage(LLSD& notification)
 		{
 			style_params.font.style = "ITALIC";
 		}
-		msg_text->appendText(messageText, TRUE, style_params);
+		mMsgText->appendText(messageText, TRUE, style_params);
 	}
 
 	snapToMessageHeight();
@@ -204,9 +202,10 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 		case 2:	messageFont = LLFontGL::getFontSansSerifBig();	break;
 	}
 	
-	LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
+	mMsgText = getChild<LLChatMsgBox>("msg_text", false);
+	mMsgText->setContentTrusted(false);
 
-	msg_text->setText(std::string(""));
+	mMsgText->setText(std::string(""));
 
 	if ( notification["chat_style"].asInteger() != CHAT_STYLE_IRC )
 	{
@@ -232,12 +231,12 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 			style_params_name.link_href = notification["sender_slurl"].asString();
 			style_params_name.is_link = true;
 
-			msg_text->appendText(str_sender, FALSE, style_params_name);
+			mMsgText->appendText(str_sender, FALSE, style_params_name);
 
 		}
 		else
 		{
-			msg_text->appendText(str_sender, false);
+			mMsgText->appendText(str_sender, false);
 		}
 	}
 
@@ -264,7 +263,7 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 		{
 			style_params.font.style = "ITALIC";
 		}
-		msg_text->appendText(messageText, FALSE, style_params);
+		mMsgText->appendText(messageText, FALSE, style_params);
 	}
 
 
@@ -275,8 +274,7 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 
 void	LLFloaterIMNearbyChatToastPanel::snapToMessageHeight	()
 {
-	LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
-	S32 new_height = llmax (text_box->getTextPixelHeight() + 2*text_box->getVPad() + 2*msg_height_pad, 25);
+	S32 new_height = llmax (mMsgText->getTextPixelHeight() + 2*mMsgText->getVPad() + 2*msg_height_pad, 25);
 	
 	LLRect panel_rect = getRect();
 
@@ -312,14 +310,13 @@ BOOL	LLFloaterIMNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)
 		return LLPanel::handleMouseUp(x,y,mask);
     */
 
-	LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
-	S32 local_x = x - text_box->getRect().mLeft;
-	S32 local_y = y - text_box->getRect().mBottom;
+	S32 local_x = x - mMsgText->getRect().mLeft;
+	S32 local_y = y - mMsgText->getRect().mBottom;
 	
 	//if text_box process mouse up (ussually this is click on url) - we didn't show nearby_chat.
-	if (text_box->pointInView(local_x, local_y) )
+	if (mMsgText->pointInView(local_x, local_y) )
 	{
-		if (text_box->handleMouseUp(local_x,local_y,mask) == TRUE)
+		if (mMsgText->handleMouseUp(local_x,local_y,mask) == TRUE)
 			return TRUE;
 		else
 		{
diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h
index 54b6499d52ff721768d9769625608094c1157b7e..f66670ec8c83a91c3ac61fce643b925261906abb 100755
--- a/indra/newview/llchatitemscontainerctrl.h
+++ b/indra/newview/llchatitemscontainerctrl.h
@@ -28,6 +28,7 @@
 #define LL_LLCHATITEMSCONTAINERCTRL_H_
 
 #include "llchat.h"
+#include "llchatmsgbox.h"
 #include "llpanel.h"
 #include "llscrollbar.h"
 #include "llviewerchat.h"
@@ -85,6 +86,7 @@ class LLFloaterIMNearbyChatToastPanel : public LLPanel
 	LLUUID			mFromID;	// agent id or object id
 	std::string		mFromName;
 	EChatSourceType	mSourceType;
+	LLChatMsgBox* 	mMsgText;
 	
 
 
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index b1dce42dfd6e0292a87b94dfbaae6c2583cb52ac..c0823182c040ac90e43a463f625f1a0456bc2ee3 100755
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -204,6 +204,7 @@ void LLNotificationChiclet::createMenu()
 	enable_registrar.add("NotificationWellChicletMenu.EnableItem",
 		boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
 		("menu_notification_well_button.xml",
 		 LLMenuGL::sMenuContainer,
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
index bc7815fba23682d026ee683f76f1d134a6b7302c..f1ef8e9a035a404a881fa93d156649909d2fdb02 100755
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ b/indra/newview/llclassifiedstatsresponder.cpp
@@ -42,8 +42,14 @@ LLClassifiedStatsResponder::LLClassifiedStatsResponder(LLUUID classified_id)
 {}
 
 /*virtual*/
-void LLClassifiedStatsResponder::result(const LLSD& content)
+void LLClassifiedStatsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	S32 teleport = content["teleport_clicks"].asInteger();
 	S32 map = content["map_clicks"].asInteger();
 	S32 profile = content["profile_clicks"].asInteger();
@@ -59,7 +65,8 @@ void LLClassifiedStatsResponder::result(const LLSD& content)
 }
 
 /*virtual*/
-void LLClassifiedStatsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLClassifiedStatsResponder::httpFailure()
 {
-	LL_INFOS() << "LLClassifiedStatsResponder::error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 }
+
diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h
index 06dcb62fd055e6ad4fadf8ccdae343e01602c920..efa4d82411d2df7dd4d598476a02ef107ed206d9 100755
--- a/indra/newview/llclassifiedstatsresponder.h
+++ b/indra/newview/llclassifiedstatsresponder.h
@@ -33,13 +33,15 @@
 
 class LLClassifiedStatsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLClassifiedStatsResponder);
 public:
 	LLClassifiedStatsResponder(LLUUID classified_id);
+
+protected:
 	//If we get back a normal response, handle it here
-	virtual void result(const LLSD& content);
+	virtual void httpSuccess();
 	//If we get back an error (not found, etc...), handle it here
-	
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	virtual void httpFailure();
 
 protected:
 	LLUUID mClassifiedID;
diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp
index 510ff69acf72d663ae89542b386315662d6e47b1..b9ef297c0050908e9cac2fc3395097f6edb95017 100755
--- a/indra/newview/llemote.cpp
+++ b/indra/newview/llemote.cpp
@@ -79,13 +79,13 @@ BOOL LLEmote::onActivate()
 	LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
 	if( default_param )
 	{
-		default_param->setWeight( default_param->getMaxWeight(), FALSE );
+		default_param->setWeight( default_param->getMaxWeight());
 	}
 
 	mParam = mCharacter->getVisualParam(mName.c_str());
 	if (mParam)
 	{
-		mParam->setWeight(0.f, FALSE);
+		mParam->setWeight(0.f);
 		mCharacter->updateVisualParams();
 	}
 	
@@ -101,7 +101,7 @@ BOOL LLEmote::onUpdate(F32 time, U8* joint_mask)
 	if( mParam )
 	{
 		F32 weight = mParam->getMinWeight() + mPose.getWeight() * (mParam->getMaxWeight() - mParam->getMinWeight());
-		mParam->setWeight(weight, FALSE);
+		mParam->setWeight(weight);
 
 		// Cross fade against the default parameter
 		LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
@@ -110,7 +110,7 @@ BOOL LLEmote::onUpdate(F32 time, U8* joint_mask)
 			F32 default_param_weight = default_param->getMinWeight() + 
 				(1.f - mPose.getWeight()) * ( default_param->getMaxWeight() - default_param->getMinWeight() );
 			
-			default_param->setWeight( default_param_weight, FALSE );
+			default_param->setWeight( default_param_weight);
 		}
 
 		mCharacter->updateVisualParams();
@@ -127,13 +127,13 @@ void LLEmote::onDeactivate()
 {
 	if( mParam )
 	{
-		mParam->setWeight( mParam->getDefaultWeight(), FALSE );
+		mParam->setWeight( mParam->getDefaultWeight());
 	}
 
 	LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
 	if( default_param )
 	{
-		default_param->setWeight( default_param->getMaxWeight(), FALSE );
+		default_param->setWeight( default_param->getMaxWeight());
 	}
 
 	mCharacter->updateVisualParams();
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 761adc59424690c98363d3306e796a6e7b95c2b8..78d619a315b1a17f113a410c21c2d359c9fcc94d 100755
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -112,19 +112,19 @@ void LLEstateInfoModel::notifyCommit()
 
 class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 {
-public:
-
+	LOG_CLASS(LLEstateChangeInfoResponder);
+protected:
 	// if we get a normal response, handle it here
-	virtual void result(const LLSD& content)
+	virtual void httpSuccesss()
 	{
 		LL_INFOS() << "Committed estate info" << LL_ENDL;
 		LLEstateInfoModel::instance().notifyCommit();
 	}
 
 	// if we get an error response
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	virtual void httpFailure()
 	{
-		LL_WARNS() << "Failed to commit estate info [status:" << status << "]: " << content << LL_ENDL;
+		LL_WARNS() << "Failed to commit estate info " << dumpResponse() << LL_ENDL;
 	}
 };
 
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index fbd9466afe3360a204aafef7f0e06eda4d53ff84..4de6ad4d2f4bc75bc89c3cbcc16d343710539216 100755
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -31,7 +31,7 @@
 #include "llagent.h"
 
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llsdserialize.h"
 #include "lleventtimer.h"
 #include "llviewerregion.h"
@@ -49,6 +49,7 @@ namespace
 
 	class LLEventPollResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLEventPollResponder);
 	public:
 		
 		static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender);
@@ -56,19 +57,19 @@ namespace
 		
 		void makeRequest();
 
+		/* virtual */ void completedRaw(const LLChannelDescriptors& channels,
+								  const LLIOPipe::buffer_ptr_t& buffer);
+
 	private:
 		LLEventPollResponder(const std::string&	pollURL, const LLHost& sender);
 		~LLEventPollResponder();
 
 		
 		void handleMessage(const LLSD& content);
-		virtual	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-		virtual	void result(const LLSD&	content);
 
-		virtual void completedRaw(U32 status,
-									const std::string& reason,
-									const LLChannelDescriptors& channels,
-									const LLIOPipe::buffer_ptr_t& buffer);
+		/* virtual */ void httpFailure();
+		/* virtual */ void httpSuccess();
+
 	private:
 
 		bool	mDone;
@@ -149,20 +150,18 @@ namespace
 	}
 
 	// virtual 
-	void LLEventPollResponder::completedRaw(U32 status,
-									const std::string& reason,
-									const LLChannelDescriptors& channels,
-									const LLIOPipe::buffer_ptr_t& buffer)
+	void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels,
+											const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (status == HTTP_BAD_GATEWAY)
+		if (getStatus() == HTTP_BAD_GATEWAY)
 		{
 			// These errors are not parsable as LLSD, 
 			// which LLHTTPClient::Responder::completedRaw will try to do.
-			completed(status, reason, LLSD());
+			httpCompleted();
 		}
 		else
 		{
-			LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer);
+			LLHTTPClient::Responder::completedRaw(channels,buffer);
 		}
 	}
 
@@ -187,13 +186,13 @@ namespace
 	}
 
 	//virtual
-	void LLEventPollResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void LLEventPollResponder::httpFailure()
 	{
 		if (mDone) return;
 
 		// A HTTP_BAD_GATEWAY (502) error is our standard timeout response
 		// we get this when there are no events.
-		if ( status == HTTP_BAD_GATEWAY )	
+		if ( getStatus() == HTTP_BAD_GATEWAY )
 		{
 			mErrorCount = 0;
 			makeRequest();
@@ -207,13 +206,13 @@ namespace
 										+ mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC
 									, this);
 
-			LL_WARNS() << "LLEventPollResponder error [status:" << status << "]: " << content << LL_ENDL;
+			LL_WARNS() << dumpResponse() << LL_ENDL;
 		}
 		else
 		{
-			LL_WARNS() << "LLEventPollResponder error <" << mCount 
-					<< "> [status:" << status << "]: " << content
-					<<	(mDone ? " -- done"	: "") << LL_ENDL;
+			LL_WARNS() << dumpResponse()
+					   << " [count:" << mCount << "] "
+					   << (mDone ? " -- done" : "") << LL_ENDL;
 			stop();
 
 			// At this point we have given up and the viewer will not receive HTTP messages from the simulator.
@@ -234,7 +233,7 @@ namespace
 	}
 
 	//virtual
-	void LLEventPollResponder::result(const LLSD& content)
+	void LLEventPollResponder::httpSuccess()
 	{
 		LL_DEBUGS() <<	"LLEventPollResponder::result <" << mCount	<< ">"
 				 <<	(mDone ? " -- done"	: "") << LL_ENDL;
@@ -243,10 +242,12 @@ namespace
 
 		mErrorCount = 0;
 
-		if (!content.get("events") ||
+		const LLSD& content = getContent();
+		if (!content.isMap() ||
+			!content.get("events") ||
 			!content.get("id"))
 		{
-			LL_WARNS() << "received event poll with no events or id key" << LL_ENDL;
+			LL_WARNS() << "received event poll with no events or id key: " << dumpResponse() << LL_ENDL;
 			makeRequest();
 			return;
 		}
@@ -260,8 +261,8 @@ namespace
 		}
 		
 		// was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
-		LL_DEBUGS()  << "LLEventPollResponder::completed <" <<	mCount << "> " << events.size() << "events (id "
-				 <<	LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL;
+		LL_DEBUGS()  << "LLEventPollResponder::httpSuccess <" <<	mCount << "> " << events.size() << "events (id "
+					 <<	LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL;
 		
 		LLSD::array_const_iterator i = events.beginArray();
 		LLSD::array_const_iterator end = events.endArray();
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
old mode 100644
new mode 100755
index 11b98eea5071050d9134280e47ee6566593f98d0..1b741ecc0efc3d2b65ebcb3027d68409cc2924f2
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -135,28 +135,36 @@ class LLFacebookConnectResponder : public LLHTTPClient::Responder
         LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
     }
     
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+		LL_DEBUGS("FacebookConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
+	}
+
+	/* virtual */ void httpFailure()
+	{
+		if ( HTTP_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL;
-			
-            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
+							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+				LLFacebookConnect::instance().openFacebookWeb(location);
+			}
 		}
-		else if (status != 302)
+		else
 		{
-            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
-            log_facebook_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
+			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Connect", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLFacebookConnect::instance().openFacebookWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -170,34 +178,42 @@ class LLFacebookShareResponder : public LLHTTPClient::Responder
 	{
 		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTING);
 	}
-	
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+
+	/* virtual */ void httpSuccess()
+	{
+		toast_user_for_success();
+		LL_DEBUGS("FacebookConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
+		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
+	}
+
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		if ( HTTP_FOUND == getStatus() )
 		{
-            toast_user_for_facebook_success();
-			LL_DEBUGS("FacebookConnect") << "Post successful. content: " << content << LL_ENDL;
-			
-			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
+							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+				LLFacebookConnect::instance().openFacebookWeb(location);
+			}
 		}
-		else if (status == 404)
+		else if ( HTTP_NOT_FOUND == getStatus() )
 		{
 			LLFacebookConnect::instance().connectToFacebook();
 		}
 		else
 		{
-            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POST_FAILED);
-            log_facebook_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
+			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POST_FAILED);
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Share", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLFacebookConnect::instance().openFacebookWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -221,24 +237,27 @@ class LLFacebookDisconnectResponder : public LLHTTPClient::Responder
 		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
 	}
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status)) 
-		{
-			LL_DEBUGS("FacebookConnect") << "Disconnect successful. content: " << content << LL_ENDL;
-			setUserDisconnected();
+		LL_DEBUGS("FacebookConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
+		setUserDisconnected();
+	}
 
-		}
+	/* virtual */ void httpFailure()
+	{
 		//User not found so already disconnected
-		else if(status == 404)
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FacebookConnect") << "Already disconnected. content: " << content << LL_ENDL;
+			LL_DEBUGS("FacebookConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
 			setUserDisconnected();
 		}
 		else
 		{
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
 			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
-            log_facebook_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Disconnect", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
@@ -254,34 +273,35 @@ class LLFacebookConnectedResponder : public LLHTTPClient::Responder
     {
 		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
     }
-    
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+		LL_DEBUGS("FacebookConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
+	}
+
+	/* virtual */ void httpFailure()
+	{
+		// show the facebook login page if not connected yet
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL;
-            
-            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
+			LL_DEBUGS("FacebookConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
+			if (mAutoConnect)
+			{
+				LLFacebookConnect::instance().connectToFacebook();
+			}
+			else
+			{
+				LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
+			}
 		}
 		else
 		{
-			// show the facebook login page if not connected yet
-			if (status == 404)
-			{
-				if (mAutoConnect)
-				{
-					LLFacebookConnect::instance().connectToFacebook();
-				}
-				else
-				{
-					LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
-				}
-			}
-            else
-            {
-                LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
-				log_facebook_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
-            }
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
+			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Connected", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
     
@@ -296,25 +316,27 @@ class LLFacebookInfoResponder : public LLHTTPClient::Responder
 	LOG_CLASS(LLFacebookInfoResponder);
 public:
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& info)
+	/* virtual */ void httpSuccess()
+	{
+		LL_INFOS("FacebookConnect") << "Facebook: Info received" << LL_ENDL;
+		LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. " << dumpResponse() << LL_ENDL;
+		LLFacebookConnect::instance().storeInfo(getContent());
+	}
+
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		if ( HTTP_FOUND == getStatus() )
 		{
 			LL_INFOS() << "Facebook: Info received" << LL_ENDL;
-			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << info << LL_ENDL;
-			LLFacebookConnect::instance().storeInfo(info);
+			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << getContent() << LL_ENDL;
+			LLFacebookConnect::instance().storeInfo(getContent());
 		}
 		else
 		{
-			log_facebook_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
-		}
-	}
-
-	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		if (status == 302)
-		{
-			LLFacebookConnect::instance().openFacebookWeb(content["location"]);
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Info", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
@@ -325,27 +347,36 @@ class LLFacebookFriendsResponder : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLFacebookFriendsResponder);
 public:
+    
+	/* virtual */ void httpSuccess()
+	{
+		LL_DEBUGS("FacebookConnect") << "Getting Facebook friends successful. " << dumpResponse() << LL_ENDL;
+		LLFacebookConnect::instance().storeContent(getContent());
+	}
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		if ( HTTP_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FacebookConnect") << "Getting Facebook friends successful. content: " << content << LL_ENDL;
-			LLFacebookConnect::instance().storeContent(content);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
+							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+				LLFacebookConnect::instance().openFacebookWeb(location);
+			}
 		}
 		else
 		{
-            log_facebook_connect_error("Friends", status, reason, content.get("error_code"), content.get("error_description"));
+			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
+			const LLSD& content = getContent();
+			log_facebook_connect_error("Friends", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
-
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLFacebookConnect::instance().openFacebookWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 8c3a4bb5c0b590c2c73183850aa60361311c9dfe..d0555477eacbdf3aa51220c3ea0432e386d85c95 100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -39,6 +39,7 @@
 #include "llgl.h"
 
 #include "llappviewer.h"
+#include "llbufferstream.h"
 #include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llviewercontrol.h"
@@ -609,6 +610,7 @@ bool LLFeatureManager::parseGPUTable(std::string filename)
 // responder saves table into file
 class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLHTTPFeatureTableResponder);
 public:
 
 	LLHTTPFeatureTableResponder(std::string filename) :
@@ -617,11 +619,10 @@ class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
 	}
 
 	
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (isGoodStatus(status))
+		if (isGoodStatus())
 		{
 			// write to file
 
@@ -640,7 +641,18 @@ class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
 				out.close();
 			}
 		}
-		
+		else
+		{
+			char body[1025]; 
+			body[1024] = '\0';
+			LLBufferStream istr(channels, buffer.get());
+			istr.get(body,1024);
+			if (strlen(body) > 0)
+			{
+				mContent["body"] = body;
+			}
+			LL_WARNS() << dumpResponse() << LL_ENDL;
+		}
 	}
 	
 private:
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index dfc246b61b2768a2a4bcae9ce99cab516125279a..5debf7174473ea99a6a6168cd124a50a979afc0e 100755
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -1110,9 +1110,9 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
 {
 	GtkFileFilter *gfilter = gtk_file_filter_new();
 	gtk_file_filter_add_pattern(gfilter, "*.tga");
-	gtk_file_filter_add_mime_type(gfilter, "image/jpeg");
-	gtk_file_filter_add_mime_type(gfilter, "image/png");
-	gtk_file_filter_add_mime_type(gfilter, "image/bmp");
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
 	std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
 	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
 	return filtername;
@@ -1120,13 +1120,13 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
  
 static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
+	return add_simple_mime_filter_to_gtkchooser(picker,  HTTP_CONTENT_TEXT_PLAIN,
 							LLTrans::getString("script_files") + " (*.lsl)");
 }
 
 static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
+	return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
 							LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
 }
 
@@ -1182,7 +1182,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
 			break;
 		case FFSAVE_BMP:
 			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)");
+				(picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
 			suggest_ext = ".bmp";
 			break;
 		case FFSAVE_PNG:
@@ -1216,6 +1216,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
 			suggest_ext = ".raw";
 			break;
 		case FFSAVE_J2C:
+			// *TODO: Should this be 'image/j2c' ?
 			caption += add_simple_mime_filter_to_gtkchooser
 				(picker, "images/jp2",
 				 LLTrans::getString("compressed_image_files") + " (*.j2c)");
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index efaba1d7a46e379f2913bb96fc847b010770191c..15b94034bb49bf74cc536be94d168d3f7ad62e79 100755
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -76,14 +76,9 @@ class LLServerReleaseNotesURLFetcher : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLServerReleaseNotesURLFetcher);
 public:
-
 	static void startFetch();
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content);
-	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer);
+private:
+	/* virtual */ void httpCompleted();
 };
 
 ///----------------------------------------------------------------------------
@@ -303,16 +298,15 @@ void LLServerReleaseNotesURLFetcher::startFetch()
 }
 
 // virtual
-void LLServerReleaseNotesURLFetcher::completedHeader(U32 status, const std::string& reason, const LLSD& content)
+void LLServerReleaseNotesURLFetcher::httpCompleted()
 {
-	LL_DEBUGS() << "Status: " << status << LL_ENDL;
-	LL_DEBUGS() << "Reason: " << reason << LL_ENDL;
-	LL_DEBUGS() << "Headers: " << content << LL_ENDL;
+	LL_DEBUGS("ServerReleaseNotes") << dumpResponse() 
+									<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
 
 	LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
 	if (floater_about)
 	{
-		std::string location = content["location"].asString();
+		std::string location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
 		if (location.empty())
 		{
 			location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
@@ -321,14 +315,3 @@ void LLServerReleaseNotesURLFetcher::completedHeader(U32 status, const std::stri
 	}
 }
 
-// virtual
-void LLServerReleaseNotesURLFetcher::completedRaw(
-	U32 status,
-	const std::string& reason,
-	const LLChannelDescriptors& channels,
-	const LLIOPipe::buffer_ptr_t& buffer)
-{
-	// Do nothing.
-	// We're overriding just because the base implementation tries to
-	// deserialize LLSD which triggers warnings.
-}
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index c1e66734067593dc6ef52e1746d8cf7906cf0b4f..3e032d0e4ad0d2b91ce0acd86d08a9fb913e68c3 100755
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -458,13 +458,15 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
 
 class LLAvatarPickerResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLAvatarPickerResponder);
 public:
 	LLUUID mQueryID;
     std::string mName;
 
 	LLAvatarPickerResponder(const LLUUID& id, const std::string& name) : mQueryID(id), mName(name) { }
 
-	/*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
+protected:
+	/*virtual*/ void httpCompleted()
 	{
 		//std::ostringstream ss;
 		//LLSDSerialize::toPrettyXML(content, ss);
@@ -472,19 +474,18 @@ class LLAvatarPickerResponder : public LLHTTPClient::Responder
 
 		// in case of invalid characters, the avatar picker returns a 400
 		// just set it to process so it displays 'not found'
-		if (isGoodStatus(status) || status == 400)
+		if (isGoodStatus() || getStatus() == HTTP_BAD_REQUEST)
 		{
 			LLFloaterAvatarPicker* floater =
 				LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker", mName);
 			if (floater)
 			{
-				floater->processResponse(mQueryID, content);
+				floater->processResponse(mQueryID, getContent());
 			}
 		}
 		else
 		{
-			LL_WARNS() << "avatar picker failed [status:" << status << "]: " << content << LL_ENDL;
-			
+			LL_WARNS() << "avatar picker failed " << dumpResponse() << LL_ENDL;
 		}
 	}
 };
diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp
index 0c408f556d726547ff95a0905310a73718fe41ed..a69aa8d227afd9d0123c5d070bcfb9dcc3d44388 100755
--- a/indra/newview/llfloaterbuycurrencyhtml.cpp
+++ b/indra/newview/llfloaterbuycurrencyhtml.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llfloaterbuycurrencyhtml.h"
+#include "llhttpconstants.h"
 #include "llstatusbar.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -85,7 +86,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL()
 	LL_INFOS() << "Buy currency HTML parsed URL is " << buy_currency_url << LL_ENDL;
 
 	// kick off the navigation
-	mBrowser->navigateTo( buy_currency_url, "text/html" );
+	mBrowser->navigateTo( buy_currency_url, HTTP_CONTENT_TEXT_HTML );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 1452d53265274d510b7d7944d69e01b8460c550c..9797b5c062190717336a8e0e0e996e5f1f2139f2 100755
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -617,9 +617,10 @@ void LLFloaterGesture::addToCurrentOutFit()
 	uuid_vec_t ids;
 	getSelectedIds(ids);
 	LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
 	{
-		am->addCOFItemLink(*it);
+		am->addCOFItemLink(*it, cb);
 	}
 }
 
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 4cb632bd6abf0c16b905d86aa9601e75c385b45a..c0bb2135405a1eae0414479714b48146b2637e3f 100755
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -29,6 +29,7 @@
 #include "llfloaterhelpbrowser.h"
 
 #include "llfloaterreg.h"
+#include "llhttpconstants.h"
 #include "llpluginclassmedia.h"
 #include "llmediactrl.h"
 #include "llviewerwindow.h"
@@ -37,7 +38,6 @@
 #include "llui.h"
 
 #include "llurlhistory.h"
-#include "llmediactrl.h"
 #include "llviewermedia.h"
 #include "llviewerhelp.h"
 
@@ -148,7 +148,7 @@ void LLFloaterHelpBrowser::openMedia(const std::string& media_url)
 {
 	// explicitly make the media mime type for this floater since it will
 	// only ever display one type of content (Web).
-	mBrowser->setHomePageUrl(media_url, "text/html");
-	mBrowser->navigateTo(media_url, "text/html");
+	mBrowser->setHomePageUrl(media_url, HTTP_CONTENT_TEXT_HTML);
+	mBrowser->navigateTo(media_url, HTTP_CONTENT_TEXT_HTML);
 	setCurrentURL(media_url);
 }
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
old mode 100644
new mode 100755
index f61359f87a52e4f0e5bd5ca4bd91881cad6588cc..7852a1f7b3f6d69c755d53d777d7a0644579c098
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -1181,16 +1181,17 @@ BOOL LLFloaterIMSession::isInviteAllowed() const
 
 class LLSessionInviteResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLSessionInviteResponder);
 public:
 	LLSessionInviteResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	void httpFailure()
 	{
-		LL_WARNS() << "Error inviting all agents to session [status:" 
-				<< statusNum << "]: " << content << LL_ENDL;
+		LL_WARNS() << "Error inviting all agents to session " << dumpResponse() << LL_ENDL;
 		//throw something back to the viewer here?
 	}
 
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 12c1a68ccde5faad7d2b685f05f9a58953c9601c..b17ce97a2e694099532670b4042a22e3e596d2ba 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -5861,7 +5861,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
 }
 
-void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason)
+void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason)
 {
 	LL_WARNS() << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << LL_ENDL;
 	doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
@@ -5937,7 +5937,7 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
 	getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm);
 }
 
-void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason)
+void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::string& reason)
 {
 	LL_WARNS() << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << LL_ENDL;
 
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index e588418f7b1d7142fa07745040a176af93112f04..6c0c60b87fb648cf6322d4c806444971f0bb1aa1 100755
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -200,11 +200,11 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase
 	/*virtual*/ void onPermissionsReceived(const LLSD& result);
 
 	// called when error occurs during permissions request
-	/*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setPermissonsErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url);
 				void handleModelPhysicsFeeReceived();
-	/*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void onModelUploadSuccess();
 
diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp
index 2ad2d32652a271d95dd1c699ce1844b9fa8cb54d..22a8ac47057b636530235ff15322ec57116757ff 100755
--- a/indra/newview/llfloatermodeluploadbase.cpp
+++ b/indra/newview/llfloatermodeluploadbase.cpp
@@ -44,8 +44,10 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions()
 
 	if (!url.empty())
 	{
-		LL_INFOS()<< typeid(*this).name() <<"::requestAgentUploadPermissions() requesting for upload model permissions from: "<< url <<LL_ENDL;
-		LLHTTPClient::get(url, new LLUploadModelPremissionsResponder(getPermObserverHandle()));
+		LL_INFOS()<< typeid(*this).name()
+				  << "::requestAgentUploadPermissions() requesting for upload model permissions from: "
+				  << url << LL_ENDL;
+		LLHTTPClient::get(url, new LLUploadModelPermissionsResponder(getPermObserverHandle()));
 	}
 	else
 	{
diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h
index a52bc286874122d5dc64fe7473e8772f7e10f22d..d9a887968783f06749466660c6aa463e9ad562fc 100755
--- a/indra/newview/llfloatermodeluploadbase.h
+++ b/indra/newview/llfloatermodeluploadbase.h
@@ -37,13 +37,13 @@ class LLFloaterModelUploadBase : public LLFloater, public LLUploadPermissionsObs
 
 	virtual ~LLFloaterModelUploadBase(){};
 
-	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0;
 
 	virtual void onPermissionsReceived(const LLSD& result) = 0;
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
 
-	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
 
 	virtual void onModelUploadSuccess() {};
 
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
index 94bf8974bbb7cbd48812455b5414485890e78f4a..feaeef4ad0d35385cfae3a1cb535bb9e53ba5371 100755
--- a/indra/newview/llfloaterobjectweights.cpp
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -123,7 +123,7 @@ void LLFloaterObjectWeights::onWeightsUpdate(const SelectionCost& selection_cost
 }
 
 //virtual
-void LLFloaterObjectWeights::setErrorStatus(U32 status, const std::string& reason)
+void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reason)
 {
 	const std::string text = getString("nothing_selected");
 
diff --git a/indra/newview/llfloaterobjectweights.h b/indra/newview/llfloaterobjectweights.h
index 9a244573bef2ad3fded6d564765020a38a9f3a5e..1a2c317bad862171a9303d73b77a501534a60149 100755
--- a/indra/newview/llfloaterobjectweights.h
+++ b/indra/newview/llfloaterobjectweights.h
@@ -63,7 +63,7 @@ class LLFloaterObjectWeights : public LLFloater, LLAccountingCostObserver
 	/*virtual*/ void onOpen(const LLSD& key);
 
 	/*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost);
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 
 	void updateLandImpacts(const LLParcel* parcel);
 	void refresh();
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 4bfef8b45fae6ff58b26e57f116ade9b25dc6785..9986bdbd7f1169e0ae62a3e940dbcc45f4e6ec46 100755
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -162,21 +162,17 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 	{
 		parent_category_id = gInventory.getRootFolderID();
 	}
-	
-	LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear);
-	
+
+	inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear);
 	LLUUID category_id = gInventory.createNewCategory(parent_category_id, 
 													  LLFolderType::FT_NONE, 
 													  name,
-													  callbackCreateInventoryCategory,
-													  (void*)cat_data);
+													  func);
 
 	//If we get a null category ID, we are using a capability in createNewCategory and we will
 	//handle the following in the callbackCreateInventoryCategory routine.
 	if ( category_id.notNull() )
 	{
-		delete cat_data;
-		
 		LLCatAndWear* data = new LLCatAndWear;
 		data->mCatID = category_id;
 		data->mWear = wear;
@@ -198,20 +194,17 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 }
 
 // static
-void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data)
+void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear)
 {
-	LLCategoryCreate* cat_data = (LLCategoryCreate*)data;
-	
-	LLUUID category_id = result["folder_id"].asUUID();
 	LLCatAndWear* wear_data = new LLCatAndWear;
 
 	wear_data->mCatID = category_id;
-	wear_data->mWear = cat_data->mWear;
+	wear_data->mWear = wear;
 	wear_data->mFolderResponded = true;
 	
 	// Copy and/or move the items into the newly created folder.
 	// Ignore any "you're going to break this item" messages.
-	BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE,
+	BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
 													callbackMoveInventory, 
 													(void*)wear_data);
 	if (!success)
@@ -221,7 +214,6 @@ void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, vo
 		
 		LLNotificationsUtil::add("OpenObjectCannotCopy");
 	}
-	delete cat_data;	
 }
 
 // static
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index bf7fe69c656fbad1bb9e4b9d7f9a926a34aed5a3..8e472804a43e068bfe7407ca41f38fd9caca9da9 100755
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -45,15 +45,6 @@ class LLFloaterOpenObject
 	
 	void dirty();
 	
-	class LLCategoryCreate
-	{
-		public:
-			LLCategoryCreate(LLUUID object_id, bool wear) : mObjectID(object_id), mWear(wear) {}
-		public:
-			LLUUID mObjectID;
-			bool mWear;
-	};
-	
 	struct LLCatAndWear
 	{
 		LLUUID mCatID;
@@ -72,7 +63,7 @@ class LLFloaterOpenObject
 
 	void onClickMoveToInventory();
 	void onClickMoveAndWear();
-	static void callbackCreateInventoryCategory(const LLSD& result, void* data);
+	static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear);
 	static void callbackMoveInventory(S32 result, void* data);
 
 private:
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
index bed34abee8b0e4d7f958b6c28d9af09560420f0d..40757a4d049dcd1a59e3bdbbad6bcd5ad56e147c 100755
--- a/indra/newview/llfloaterregiondebugconsole.cpp
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -73,24 +73,29 @@ namespace
 	// called if this request times out.
 	class AsyncConsoleResponder : public LLHTTPClient::Responder
 	{
-	public:
+		LOG_CLASS(AsyncConsoleResponder);
+	protected:
 		/* virtual */
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+		void httpFailure()
 		{
+			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
 			sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
 		}
 	};
 
 	class ConsoleResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(ConsoleResponder);
 	public:
 		ConsoleResponder(LLTextEditor *output) : mOutput(output)
 		{
 		}
 
+	protected:
 		/*virtual*/
-		void error(U32 status, const std::string& reason)
+		void httpFailure()
 		{
+			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
 			if (mOutput)
 			{
 				mOutput->appendText(
@@ -100,8 +105,10 @@ namespace
 		}
 
 		/*virtual*/
-		void result(const LLSD& content)
+		void httpSuccess()
 		{
+			const LLSD& content = getContent();
+			LL_DEBUGS("Console") << content << LL_ENDL;
 			if (mOutput)
 			{
 				mOutput->appendText(
@@ -109,6 +116,7 @@ namespace
 			}
 		}
 
+	public:
 		LLTextEditor * mOutput;
 	};
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index d67089ff85e12fc8b29b22648fe079b3e7f5abe0..5e9b25b474877c04d4771e21501edb4d00d9e806 100755
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -759,12 +759,12 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
 
 class ConsoleRequestResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(ConsoleRequestResponder);
+protected:
 	/*virtual*/
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		LL_WARNS() << "ConsoleRequestResponder error requesting mesh_rez_enabled [status:"
-				<< status << "]: " << content << LL_ENDL;
+		LL_WARNS() << "error requesting mesh_rez_enabled " << dumpResponse() << LL_ENDL;
 	}
 };
 
@@ -772,12 +772,12 @@ class ConsoleRequestResponder : public LLHTTPClient::Responder
 // called if this request times out.
 class ConsoleUpdateResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(ConsoleUpdateResponder);
+protected:
 	/* virtual */
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		LL_WARNS() << "ConsoleRequestResponder error updating mesh enabled region setting [status:"
-				<< status << "]: " << content << LL_ENDL;
+		LL_WARNS() << "error updating mesh enabled region setting " << dumpResponse() << LL_ENDL;
 	}
 };
 
@@ -2244,14 +2244,16 @@ void LLPanelEstateInfo::getEstateOwner()
 
 class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLEstateChangeInfoResponder);
 public:
 	LLEstateChangeInfoResponder(LLPanelEstateInfo* panel)
 	{
 		mpPanel = panel->getHandle();
 	}
 	
+protected:
 	// if we get a normal response, handle it here
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
 		LL_INFOS("Windlight") << "Successfully committed estate info" << LL_ENDL;
 
@@ -2262,10 +2264,9 @@ class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 	}
 	
 	// if we get an error response
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	virtual void httpFailure()
 	{
-		LL_INFOS() << "LLEstateChangeInfoResponder::error [status:"
-			<< status << "]: " << content << LL_ENDL;
+		LL_WARNS("Windlight") << dumpResponse() << LL_ENDL;
 	}
 private:
 	LLHandle<LLPanel> mpPanel;
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 825159703cf4ff870d093b9f3df78fdc53dddb68..a3b9713e3ea382c3967e3c097b826a49f5ceb056 100755
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -707,16 +707,18 @@ class LLUserReportScreenshotResponder : public LLAssetUploadResponder
 
 class LLUserReportResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLUserReportResponder);
 public:
 	LLUserReportResponder(): LLHTTPClient::Responder()  {}
 
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-	{
-		// *TODO do some user messaging here
-		LLUploadDialog::modalUploadFinished();
-	}
-	void result(const LLSD& content)
+private:
+	void httpCompleted()
 	{
+		if (!isGoodStatus())
+		{
+			// *TODO do some user messaging here
+			LL_WARNS("UserReport") << dumpResponse() << LL_ENDL;
+		}
 		// we don't care about what the server returns
 		LLUploadDialog::modalUploadFinished();
 	}
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 2ed7bb842df5a397d92147ab331382d1350d5af9..5fbdd75e970a829db7ff67265b641bf37e33be9f 100755
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -183,8 +183,14 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
 // Responders
 ///----------------------------------------------------------------------------
 
-void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
+void fetchScriptLimitsRegionInfoResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	//we don't need to test with a fake respose here (shouldn't anyway)
 
 #ifdef DUMP_REPLIES_TO_LLINFOS
@@ -221,13 +227,14 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
 	}
 }
 
-void fetchScriptLimitsRegionInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionInfoResponder::httpFailure()
 {
-	LL_WARNS() << "fetchScriptLimitsRegionInfoResponder error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 }
 
-void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsRegionSummaryResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 #ifdef USE_FAKE_RESPONSES
 
 	LLSD fake_content;
@@ -268,6 +275,12 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
@@ -291,7 +304,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 		if(tab)
 		{
-		LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 			if(panel_memory)
 			{
 				panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
@@ -301,20 +314,21 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 				{
 					btn->setEnabled(true);
 				}
-				
-		panel_memory->setRegionSummary(content);
-	}
-}
+
+				panel_memory->setRegionSummary(content);
+			}
+		}
 	}
 }
 
-void fetchScriptLimitsRegionSummaryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionSummaryResponder::httpFailure()
 {
-	LL_WARNS() << "fetchScriptLimitsRegionSummaryResponder error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 }
 
-void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsRegionDetailsResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 #ifdef USE_FAKE_RESPONSES
 /*
 Updated detail service, ** denotes field added:
@@ -377,6 +391,12 @@ result (map)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
 	LLSDNotationStreamer notation_streamer(content);
@@ -417,13 +437,14 @@ result (map)
 	}
 }
 
-void fetchScriptLimitsRegionDetailsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionDetailsResponder::httpFailure()
 {
-	LL_WARNS() << "fetchScriptLimitsRegionDetailsResponder error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 }
 
-void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsAttachmentInfoResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 
 #ifdef USE_FAKE_RESPONSES
 
@@ -465,6 +486,12 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
 	LLSDNotationStreamer notation_streamer(content);
@@ -513,9 +540,9 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
 	}
 }
 
-void fetchScriptLimitsAttachmentInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsAttachmentInfoResponder::httpFailure()
 {
-	LL_WARNS() << "fetchScriptLimitsAttachmentInfoResponder error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 }
 
 ///----------------------------------------------------------------------------
@@ -586,7 +613,7 @@ void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
 }
 
 // virtual
-void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
+void LLPanelScriptLimitsRegionMemory::setErrorStatus(S32 status, const std::string& reason)
 {
 	LL_WARNS() << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<LL_ENDL;
 }
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index f8732ef94bb02f14db6c46cf0b2661e24953eb50..a5cb1b6184a571b4ad00f73ccf7b3a757c11ae3a 100755
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -85,49 +85,49 @@ class LLPanelScriptLimitsInfo : public LLPanel
 
 class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionInfoResponder);
+public:
+	fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionSummaryResponder);
+public:
+	fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionDetailsResponder);
+public:
+	fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsAttachmentInfoResponder() {};
+	LOG_CLASS(fetchScriptLimitsAttachmentInfoResponder);
+public:
+	fetchScriptLimitsAttachmentInfoResponder() {};
 
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 };
 
 /////////////////////////////////////////////////////////////////////////////
@@ -190,7 +190,7 @@ class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemote
 // LLRemoteParcelInfoObserver interface:
 /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 /*virtual*/ void setParcelID(const LLUUID& parcel_id);
-/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 	
 	static void onClickRefresh(void* userdata);
 	static void onClickHighlight(void* userdata);
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 2a946b1edfa06048dc610ae01cc7c940361149f5..a446b767acb0bef9daba63dd35e50f0004f41f7a 100755
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -30,6 +30,7 @@
 #include "llcommandhandler.h"
 #include "llfloaterreg.h"
 #include "llfloatersearch.h"
+#include "llhttpconstants.h"
 #include "llmediactrl.h"
 #include "llnotificationsutil.h"
 #include "lllogininstance.h"
@@ -200,5 +201,5 @@ void LLFloaterSearch::search(const SearchQuery &p)
 	url = LLWeb::expandURLSubstitutions(url, subs);
 
 	// and load the URL in the web view
-	mWebBrowser->navigateTo(url, "text/html");
+	mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 }
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index a242b224cd7fab1b538d4edad4bd287a8c1afc5b..0613ffc94d803f35e31e9d5a017c75d126cbe855 100755
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -36,7 +36,7 @@
 #include "llbutton.h"
 #include "llevents.h"
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"	// for HTTP_FOUND
+#include "llhttpconstants.h"
 #include "llnotificationsutil.h"
 #include "llradiogroup.h"
 #include "lltextbox.h"
@@ -62,42 +62,46 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& data)
 // on parent class indicating if the web server is working or not
 class LLIamHere : public LLHTTPClient::Responder
 {
-	private:
-		LLIamHere( LLFloaterTOS* parent ) :
-		   mParent( parent )
-		{}
+	LOG_CLASS(LLIamHere);
+private:
+	LLIamHere( LLFloaterTOS* parent ) :
+	   mParent( parent )
+	{}
 
-		LLFloaterTOS* mParent;
+	LLFloaterTOS* mParent;
 
-	public:
-
-		static LLIamHere* build( LLFloaterTOS* parent )
-		{
-			return new LLIamHere( parent );
-		};
-		
-		virtual void  setParent( LLFloaterTOS* parentIn )
-		{
-			mParent = parentIn;
-		};
-		
-		virtual void result( const LLSD& content )
+public:
+	static LLIamHere* build( LLFloaterTOS* parent )
+	{
+		return new LLIamHere( parent );
+	}
+	
+	virtual void  setParent( LLFloaterTOS* parentIn )
+	{
+		mParent = parentIn;
+	}
+	
+protected:
+	virtual void httpSuccess()
+	{
+		if ( mParent )
 		{
-			if ( mParent )
-				mParent->setSiteIsAlive( true );
-		};
+			mParent->setSiteIsAlive( true );
+		}
+	}
 
-		virtual void error( U32 status, const std::string& reason )
+	virtual void httpFailure()
+	{
+		LL_DEBUGS("LLIamHere") << dumpResponse() << LL_ENDL;
+		if ( mParent )
 		{
-			if ( mParent )
-			{
-				// *HACK: For purposes of this alive check, 302 Found
-				// (aka Moved Temporarily) is considered alive.  The web site
-				// redirects this link to a "cache busting" temporary URL. JC
-				bool alive = (status == HTTP_FOUND);
-				mParent->setSiteIsAlive( alive );
-			}
-		};
+			// *HACK: For purposes of this alive check, 302 Found
+			// (aka Moved Temporarily) is considered alive.  The web site
+			// redirects this link to a "cache busting" temporary URL. JC
+			bool alive = (getStatus() == HTTP_FOUND);
+			mParent->setSiteIsAlive( alive );
+		}
+	}
 };
 
 // this is global and not a class member to keep crud out of the header file
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index e85d849c9ad3b0ddca38532d739eafe3a467e29f..e26f1e9ea541d83d2345f53cfc804f2db3a173e6 100755
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -48,31 +48,30 @@ static LLFloaterURLEntry* sInstance = NULL;
 // on the Panel Land Media and to discover the MIME type
 class LLMediaTypeResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLMediaTypeResponder);
 public:
 	LLMediaTypeResponder( const LLHandle<LLFloater> parent ) :
-	  mParent( parent )
-	  {}
-
-	  LLHandle<LLFloater> mParent;
-
-
-	  virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	  {
-		  std::string media_type = content["content-type"].asString();
-		  std::string::size_type idx1 = media_type.find_first_of(";");
-		  std::string mime_type = media_type.substr(0, idx1);
-		  completeAny(status, mime_type);
-	  }
-
-	  void completeAny(U32 status, const std::string& mime_type)
-	  {
-		  // Set empty type to none/none.  Empty string is reserved for legacy parcels
-		  // which have no mime type set.
-		  std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
-		  LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
-		  if ( floater_url_entry )
-			  floater_url_entry->headerFetchComplete( status, resolved_mime_type );
-	  }
+		mParent( parent )
+	{}
+
+	LLHandle<LLFloater> mParent;
+
+private:
+	/* virtual */ void httpCompleted()
+	{
+		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
+		std::string::size_type idx1 = media_type.find_first_of(";");
+		std::string mime_type = media_type.substr(0, idx1);
+
+		// Set empty type to none/none.  Empty string is reserved for legacy parcels
+		// which have no mime type set.
+		std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
+		LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
+		if ( floater_url_entry )
+		{
+			floater_url_entry->headerFetchComplete( getStatus(), resolved_mime_type );
+		}
+	}
 };
 
 //-----------------------------------------------------------------------------
@@ -136,7 +135,7 @@ void LLFloaterURLEntry::buildURLHistory()
 	}
 }
 
-void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
+void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_type)
 {
 	LLPanelLandMedia* panel_media = dynamic_cast<LLPanelLandMedia*>(mPanelLandMediaHandle.get());
 	if (panel_media)
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index dfb49fe5ac97bdb8cd53d300a303aa6814971b14..bdd1ebe5921f5dbd01a48d694ab6c5a9e7c5ec57 100755
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -40,7 +40,7 @@ class LLFloaterURLEntry : public LLFloater
 	// that panel via the handle.
 	static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);
 	/*virtual*/	BOOL	postBuild();
-	void headerFetchComplete(U32 status, const std::string& mime_type);
+	void headerFetchComplete(S32 status, const std::string& mime_type);
 
 	bool addURLToCombobox(const std::string& media_url);
 
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 0f878f4eb3ec92617a6956e51c08cbd2aa3b3b50..bbfd855bc892bfb6477e46888c6a0b99a9675a3c 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -29,6 +29,7 @@
 #include "llcombobox.h"
 #include "lliconctrl.h"
 #include "llfloaterreg.h"
+#include "llhttpconstants.h"
 #include "llfacebookconnect.h"
 #include "llflickrconnect.h"
 #include "lltwitterconnect.h"
@@ -243,9 +244,9 @@ void LLFloaterWebContent::open_media(const Params& p)
 {
 	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
 	LLViewerMedia::proxyWindowOpened(p.target(), p.id());
-	mWebBrowser->setHomePageUrl(p.url, "text/html");
+	mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
 	mWebBrowser->setTarget(p.target);
-	mWebBrowser->navigateTo(p.url, "text/html", p.clean_browser);
+	mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser);
 	
 	set_current_url(p.url);
 
@@ -501,7 +502,7 @@ void LLFloaterWebContent::onEnterAddress()
     LLStringUtil::trim(url);
 	if ( url.length() > 0 )
 	{
-		mWebBrowser->navigateTo( url, "text/html");
+		mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	};
 }
 
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 6566ef5dca21732437d3f43d0721e2589b5871fe..307e2590062187f52bc4708b13ab36438103480e 100755
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -38,6 +38,7 @@
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llviewerinventory.h"
 #include "llinventorymodel.h"
+#include "llcallbacklist.h"
 
 // Constants;
 
@@ -86,7 +87,7 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect
 
 	if (cats_count > 1)
 	{
-		LL_WARNS("LLFriendCardsManager")
+		LL_WARNS_ONCE("LLFriendCardsManager")
 			<< "There is more than one Friend card folder."
 			<< "The first folder will be used."
 			<< LL_ENDL;
@@ -154,7 +155,7 @@ void LLInitialFriendCardsFetch::done()
 	// This observer is no longer needed.
 	gInventory.removeObserver(this);
 
-	mCheckFolderCallback();
+	doOnIdleOneTime(mCheckFolderCallback);
 
 	delete this;
 }
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index ffddeeb129e850fea5a77de769c9024581b74492..b15556d73d18a9bdcb251dbe7eab34d3759be22a 100755
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -299,6 +299,12 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,
 }
 
 
+void notify_update_label(const LLUUID& base_item_id)
+{
+	gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
+	LLGestureMgr::instance().notifyObservers();
+}
+
 void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 {
 	const LLUUID& base_item_id = get_linked_uuid(item_id);
@@ -322,7 +328,6 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 	}
 
 	mActive.erase(it);
-	gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
 
 	// Inform the database of this change
 	LLMessageSystem* msg = gMessageSystem;
@@ -338,9 +343,11 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 
 	gAgent.sendReliableMessage();
 
-	LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id);
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(notify_update_label,base_item_id));
 
-	notifyObservers();
+	LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, cb);
 }
 
 
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index b2ad737a1d70fcd4bdd8f1222f4287116f2cdb6b..d5b817ce765140615a7d4add736ace865c36fd59 100755
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -1851,23 +1851,31 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
 // Responder class for capability group management
 class GroupMemberDataResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(GroupMemberDataResponder);
 public:
-		GroupMemberDataResponder() {}
-		virtual ~GroupMemberDataResponder() {}
-		virtual void result(const LLSD& pContent);
-		virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
+	GroupMemberDataResponder() {}
+	virtual ~GroupMemberDataResponder() {}
+
 private:
-		LLSD mMemberData;
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mMemberData;
 };
 
-void GroupMemberDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void GroupMemberDataResponder::httpFailure()
 {
-	LL_WARNS("GrpMgr") << "Error receiving group member data [status:" 
-		<< pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS("GrpMgr") << "Error receiving group member data "
+		<< dumpResponse() << LL_ENDL;
 }
 
-void GroupMemberDataResponder::result(const LLSD& content)
+void GroupMemberDataResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLGroupMgr::processCapGroupMembersRequest(content);
 }
 
diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp
index eefa8bd42a18398df1ad11dfb2b2deff13213291..d0492bcdb438b0e190fcb982b07c9f9d7e1141ce 100755
--- a/indra/newview/llhomelocationresponder.cpp
+++ b/indra/newview/llhomelocationresponder.cpp
@@ -33,71 +33,76 @@
 #include "llagent.h"
 #include "llviewerregion.h"
 
-void LLHomeLocationResponder::result( const LLSD& content )
+void LLHomeLocationResponder::httpSuccess()
 {
+  const LLSD& content = getContent();
   LLVector3 agent_pos;
   bool      error = true;
-		
+
   do {
-	
+
     // was the call to /agent/<agent-id>/home-location successful?
     // If not, we keep error set to true
     if( ! content.has("success") )
     {
       break;
     }
-		
+
     if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) )
     {
       break;
     }
-		
+
     // did the simulator return a "justified" home location?
     // If no, we keep error set to true
     if( ! content.has( "HomeLocation" ) )
     {
       break;
     }
-		
+
     if( ! content["HomeLocation"].has("LocationPos") )
     {
       break;
     }
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("X") )
     {
       break;
     }
 
     agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger();
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("Y") )
     {
       break;
     }
 
     agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger();
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("Z") )
     {
       break;
     }
 
     agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger();
-		
+
     error = false;
   } while( 0 );
-	
-  if( ! error )
+
+  if( error )
+  {
+    failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content);
+  }
+  else
   {
     LL_INFOS() << "setting home position" << LL_ENDL;
-		
+
     LLViewerRegion *viewer_region = gAgent.getRegion();
     gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos );
   }
 }
 
-void LLHomeLocationResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content )
+void LLHomeLocationResponder::httpFailure()
 {
-	LL_WARNS() << "LLHomeLocationResponder error [status:" << status << "]: " << content << LL_ENDL;
+  LL_WARNS() << dumpResponse() << LL_ENDL;
 }
diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h
index 9bf4b12c4e9eef85c5e5cbd45de4b9fa220f2f35..adc6c8cb58109b11e5333c63b9dafbc0ae2ccb55 100755
--- a/indra/newview/llhomelocationresponder.h
+++ b/indra/newview/llhomelocationresponder.h
@@ -35,8 +35,10 @@
 /* Typedef, Enum, Class, Struct, etc. */
 class LLHomeLocationResponder : public LLHTTPClient::Responder
 {
-	virtual void result( const LLSD& content );
-	virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content );
+	LOG_CLASS(LLHomeLocationResponder);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 };
 
 #endif
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2d4ce6c883a2c6bec31265b2fd3420ddbdf2ead2
--- /dev/null
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -0,0 +1,142 @@
+/** 
+ * @file llhttpretrypolicy.h
+ * @brief Header for a retry policy class intended for use with http responders.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "llhttpretrypolicy.h"
+
+LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):
+	mMinDelay(min_delay),
+	mMaxDelay(max_delay),
+	mBackoffFactor(backoff_factor),
+	mMaxRetries(max_retries),
+	mRetryOn4xx(retry_on_4xx)
+{
+	init();
+}
+
+void LLAdaptiveRetryPolicy::init()
+{
+	mDelay = mMinDelay;
+	mRetryCount = 0;
+	mShouldRetry = true;
+}
+
+void LLAdaptiveRetryPolicy::reset()
+{
+	init();
+}
+
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time)
+{
+	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
+			&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time));
+}
+
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time)
+{
+	if (headers)
+	{
+		const std::string *retry_value = headers->find(HTTP_IN_HEADER_RETRY_AFTER.c_str()); 
+		if (retry_value && 
+			getSecondsUntilRetryAfter(*retry_value, retry_header_time))
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+void LLAdaptiveRetryPolicy::onSuccess()
+{
+	init();
+}
+
+void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
+{
+	F32 retry_header_time;
+	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
+	onFailureCommon(status, has_retry_header_time, retry_header_time);
+}
+  
+void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
+{
+	F32 retry_header_time;
+	const LLCore::HttpHeaders *headers = response->getHeaders();
+	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
+	onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time);
+}
+
+void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
+{
+	if (!mShouldRetry)
+	{
+		LL_INFOS() << "keep on failing" << LL_ENDL;
+		return;
+	}
+	if (mRetryCount > 0)
+	{
+		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+	}
+	// Honor server Retry-After header.
+	// Status 503 may ask us to wait for a certain amount of time before retrying.
+	F32 wait_time = mDelay;
+	if (has_retry_header_time)
+	{
+		wait_time = retry_header_time;
+	}
+
+	if (mRetryCount>=mMaxRetries)
+	{
+		LL_INFOS() << "Too many retries " << mRetryCount << ", will not retry" << LL_ENDL;
+		mShouldRetry = false;
+	}
+	if (!mRetryOn4xx && !isHttpServerErrorStatus(status))
+	{
+		LL_INFOS() << "Non-server error " << status << ", will not retry" << LL_ENDL;
+		mShouldRetry = false;
+	}
+	if (mShouldRetry)
+	{
+		LL_INFOS() << "Retry count " << mRetryCount << " should retry after " << wait_time << LL_ENDL;
+		mRetryTimer.reset();
+		mRetryTimer.setTimerExpirySec(wait_time);
+	}
+	mRetryCount++;
+}
+	
+
+bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
+{
+	if (mRetryCount == 0)
+	{
+		// Called shouldRetry before any failure.
+		seconds_to_wait = F32_MAX;
+		return false;
+	}
+	seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;
+	return mShouldRetry;
+}
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
new file mode 100755
index 0000000000000000000000000000000000000000..cf79e0b401b9948bcaf65480d33a3a82a51e6e78
--- /dev/null
+++ b/indra/newview/llhttpretrypolicy.h
@@ -0,0 +1,98 @@
+/** 
+ * @file file llhttpretrypolicy.h
+ * @brief declarations for http retry policy class.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+										
+#ifndef LL_RETRYPOLICY_H
+#define LL_RETRYPOLICY_H
+
+#include "lltimer.h"
+#include "llthread.h"
+
+#include "llhttpconstants.h"
+
+// For compatibility with new core http lib.
+#include "httpresponse.h"
+#include "httpheaders.h"
+
+// This is intended for use with HTTP Clients/Responders, but is not
+// specifically coupled with those classes.
+class LLHTTPRetryPolicy: public LLThreadSafeRefCount
+{
+public:
+	LLHTTPRetryPolicy() {}
+
+	virtual ~LLHTTPRetryPolicy() {}
+	// Call after a sucess to reset retry state.
+
+	virtual void onSuccess() = 0;
+	// Call once after an HTTP failure to update state.
+	virtual void onFailure(S32 status, const LLSD& headers) = 0;
+
+	virtual void onFailure(const LLCore::HttpResponse *response) = 0;
+
+	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
+
+	virtual void reset() = 0;
+};
+
+// Very general policy with geometric back-off after failures,
+// up to a maximum delay, and maximum number of retries.
+class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
+{
+public:
+	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx = false);
+
+	// virtual
+	void onSuccess();
+
+	void reset();
+	
+	// virtual
+	void onFailure(S32 status, const LLSD& headers);
+	// virtual
+	void onFailure(const LLCore::HttpResponse *response);
+	// virtual
+	bool shouldRetry(F32& seconds_to_wait) const;
+
+protected:
+	void init();
+	bool getRetryAfter(const LLSD& headers, F32& retry_header_time);
+	bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time);
+	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
+
+private:
+
+	const F32 mMinDelay; // delay never less than this value
+	const F32 mMaxDelay; // delay never exceeds this value
+	const F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
+	const U32 mMaxRetries; // maximum number of times shouldRetry will return true.
+	F32 mDelay; // current default delay.
+	U32 mRetryCount; // number of times shouldRetry has been called.
+	LLTimer mRetryTimer; // time until next retry.
+	bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
+	bool mRetryOn4xx; // Normally only retry on 5xx server errors.
+};
+
+#endif
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 34ccab0302f879ccca93b47a0e27f7f5aa0453c4..c194dc05b03b663ada9029fbf3b93663ddc3012f 100755
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -388,16 +388,17 @@ void LLFloaterIMPanel::draw()
 
 class LLSessionInviteResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLSessionInviteResponder);
 public:
 	LLSessionInviteResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	void httpFailure()
 	{
-		LL_WARNS() << "Error inviting all agents to session [status:" 
-				<< statusNum << "]: " << content << LL_ENDL;
+		LL_WARNS() << "Error inviting all agents to session " << dumpResponse() << LL_ENDL;
 		//throw something back to the viewer here?
 	}
 
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index af93778c102aca2a2a9488396ce6be78deb03b98..8917c0775969fdbecd5241dbabf4da16ede9145d 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -1460,6 +1460,7 @@ void start_deprecated_conference_chat(
 
 class LLStartConferenceChatResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLStartConferenceChatResponder);
 public:
 	LLStartConferenceChatResponder(
 		const LLUUID& temp_session_id,
@@ -1473,10 +1474,12 @@ class LLStartConferenceChatResponder : public LLHTTPClient::Responder
 		mAgents = agents_to_invite;
 	}
 
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	virtual void httpFailure()
 	{
 		//try an "old school" way.
-		if ( statusNum == 400 )
+		// *TODO: What about other error status codes?  4xx 5xx?
+		if ( getStatus() == HTTP_BAD_REQUEST )
 		{
 			start_deprecated_conference_chat(
 				mTempSessionID,
@@ -1485,8 +1488,7 @@ class LLStartConferenceChatResponder : public LLHTTPClient::Responder
 				mAgents);
 		}
 
-		LL_WARNS() << "LLStartConferenceChatResponder error [status:"
-				<< statusNum << "]: " << content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 
 		//else throw an error back to the client?
 		//in theory we should have just have these error strings
@@ -1578,6 +1580,7 @@ bool LLIMModel::sendStartSession(
 class LLViewerChatterBoxInvitationAcceptResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLViewerChatterBoxInvitationAcceptResponder);
 public:
 	LLViewerChatterBoxInvitationAcceptResponder(
 		const LLUUID& session_id,
@@ -1587,8 +1590,15 @@ class LLViewerChatterBoxInvitationAcceptResponder :
 		mInvitiationType = invitation_type;
 	}
 
-	void result(const LLSD& content)
+private:
+	void httpSuccess()
 	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		if ( gIMMgr)
 		{
 			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
@@ -1633,19 +1643,17 @@ class LLViewerChatterBoxInvitationAcceptResponder :
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		LL_WARNS() << "LLViewerChatterBoxInvitationAcceptResponder error [status:"
-				<< statusNum << "]: " << content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 		//throw something back to the viewer here?
 		if ( gIMMgr )
 		{
 			gIMMgr->clearPendingAgentListUpdates(mSessionID);
 			gIMMgr->clearPendingInvitation(mSessionID);
-			if ( 404 == statusNum )
+			if ( HTTP_NOT_FOUND == getStatus() )
 			{
-				std::string error_string;
-				error_string = "session_does_not_exist_error";
+				static const std::string error_string("session_does_not_exist_error");
 				gIMMgr->showSessionStartError(error_string, mSessionID);
 			}
 		}
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index b75140238edd3628d71b68b2e2ea06d04152b566..1e15dc832cd91f8a62c008baa4956252845715f9 100755
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -292,11 +292,6 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
 	delete mPropertiesRequest;
 	mPropertiesRequest = NULL;
 }
-/*
-prep#
-			virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-				LL_WARNS() << "MuteVoiceResponder error [status:" << status << "]: " << content << LL_ENDL;
-	*/
 
 void LLInspectAvatar::updateVolumeSlider()
 {
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c538fb6c6892565cdd9a4bfa23e4cbe13f79040e..5df28ccb7395c6310f9714a2166a99c8cc9191ce 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -202,6 +202,7 @@ const std::string& LLInvFVBridge::getDisplayName() const
 	{
 		buildDisplayName();
 	}
+
 	return mDisplayName;
 }
 
@@ -1161,17 +1162,10 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 
 void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
 {
-	LLInventoryCategory* cat = model->getCategory(uuid);
-	if (cat)
-	{
-		model->purgeDescendentsOf(uuid);
-		model->notifyObservers();
-	}
 	LLInventoryObject* obj = model->getObject(uuid);
 	if (obj)
 	{
-		model->purgeObject(uuid);
-		model->notifyObservers();
+		remove_inventory_object(uuid, NULL);
 	}
 }
 
@@ -1607,18 +1601,18 @@ void LLItemBridge::buildDisplayName() const
 	else
 	{
 		mDisplayName.assign(LLStringUtil::null);
-}
-
+	}
+	
 	mSearchableName.assign(mDisplayName);
 	mSearchableName.append(getLabelSuffix());
 	LLStringUtil::toUpper(mSearchableName);
-
+	
     //Name set, so trigger a sort
     if(mParent)
-{
-        mParent->requestSort();
-	}
+	{
+		mParent->requestSort();
 	}
+}
 
 LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
 {
@@ -1732,13 +1726,9 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
 	LLViewerInventoryItem* item = getItem();
 	if(item && (item->getName() != new_name))
 	{
-		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
-		new_item->rename(new_name);
-		new_item->updateServer(FALSE);
-		model->updateItem(new_item);
-
-		model->notifyObservers();
-		buildDisplayName();
+		LLSD updates;
+		updates["name"] = new_name;
+		update_inventory_item(item->getUUID(),updates, NULL);
 	}
 	// return FALSE because we either notified observers (& therefore
 	// rebuilt) or we didn't update.
@@ -1774,16 +1764,8 @@ BOOL LLItemBridge::removeItem()
 	{
 		if (!item->getIsLinkType())
 		{
-			LLInventoryModel::cat_array_t cat_array;
-			LLInventoryModel::item_array_t item_array;
-			LLLinkedItemIDMatches is_linked_item_match(mUUID);
-			gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
-											cat_array,
-											item_array,
-											LLInventoryModel::INCLUDE_TRASH,
-											is_linked_item_match);
-
-			const U32 num_links = cat_array.size() + item_array.size();
+			LLInventoryModel::item_array_t item_array = gInventory.collectLinksTo(mUUID);
+			const U32 num_links = item_array.size();
 			if (num_links > 0)
 			{
 				// Warn if the user is will break any links when deleting this item.
@@ -1935,49 +1917,19 @@ void LLFolderBridge::buildDisplayName() const
 
 void LLFolderBridge::update()
 {
-	bool possibly_has_children = false;
-	bool up_to_date = isUpToDate();
-	if(!up_to_date && hasChildren()) // we know we have children but  haven't  fetched them (doesn't obey filter)
-	{
-		possibly_has_children = true;
-	}
-
-	bool loading = (possibly_has_children
-		&& !up_to_date );
+	// we know we have children but  haven't  fetched them (doesn't obey filter)
+	bool loading = !isUpToDate() && hasChildren() && mFolderViewItem->isOpen();
 
 	if (loading != mIsLoading)
 	{
-		if ( loading && !mIsLoading )
+		if ( loading )
 		{
 			// Measure how long we've been in the loading state
 			mTimeSinceRequestStart.reset();
 		}
+		mIsLoading = loading;
 
-		const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID());
-		const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID());
-
-		bool root_is_loading = false;
-		if (in_inventory)
-		{
-			root_is_loading =   LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();
-		}
-		if (in_library)
-		{
-			root_is_loading =   LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
-		}
-		if ((mIsLoading
-				&&	mTimeSinceRequestStart.getElapsedTimeF32() >=   gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
-			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive()
-				&&	root_is_loading))
-		{
-			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) ";
-			mIsLoading = true;
-		}
-		else
-		{
-			mDisplayName = LLInvFVBridge::getDisplayName();
-			mIsLoading = false;
-		}
+		mFolderViewItem->refresh();
 	}
 }
 
@@ -2490,49 +2442,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 					}
 				}
 			}
-			// if target is an outfit or current outfit folder we use link
-			if (move_is_into_current_outfit || move_is_into_outfit)
+			// if target is current outfit folder we use link
+			if (move_is_into_current_outfit &&
+				inv_cat->getPreferredType() == LLFolderType::FT_NONE)
 			{
-				if (inv_cat->getPreferredType() == LLFolderType::FT_NONE)
-				{
-					if (move_is_into_current_outfit)
-					{
-						// traverse category and add all contents to currently worn.
-						BOOL append = true;
-						LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
-					}
-					else
-					{
-						// Recursively create links in target outfit.
-						LLInventoryModel::cat_array_t cats;
-						LLInventoryModel::item_array_t items;
-						model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
-						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
-					}
-				}
-				else
-				{
-#if SUPPORT_ENSEMBLES
-					// BAP - should skip if dup.
-					if (move_is_into_current_outfit)
-					{
-						LLAppearanceMgr::instance().addEnsembleLink(inv_cat);
-					}
-					else
-					{
-						LLPointer<LLInventoryCallback> cb = NULL;
-						const std::string empty_description = "";
-						link_inventory_item(
-							gAgent.getID(),
-							cat_id,
-							mUUID,
-							inv_cat->getName(),
-							empty_description,
-							LLAssetType::AT_LINK_FOLDER,
-							cb);
-					}
-#endif
-				}
+				// traverse category and add all contents to currently worn.
+				BOOL append = true;
+				LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
@@ -2924,17 +2840,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		modifyOutfit(FALSE);
 		return;
 	}
-#if SUPPORT_ENSEMBLES
-	else if ("wearasensemble" == action)
-	{
-		LLInventoryModel* model = getInventoryModel();
-		if(!model) return;
-		LLViewerInventoryCategory* cat = getCategory();
-		if(!cat) return;
-		LLAppearanceMgr::instance().addEnsembleLink(cat,true);
-		return;
-	}
-#endif
 	else if ("addtooutfit" == action)
 	{
 		modifyOutfit(TRUE);
@@ -3097,9 +3002,20 @@ LLUIImagePtr LLFolderBridge::getIconOverlay() const
 	return NULL;
 }
 
+std::string LLFolderBridge::getLabelSuffix() const
+{
+	static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f);
+	return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay() 
+		? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str())
+		: LLStringUtil::null;
+}
 
 BOOL LLFolderBridge::renameItem(const std::string& new_name)
 {
+
+	LLScrollOnRenameObserver *observer = new LLScrollOnRenameObserver(mUUID, mRoot);
+	gInventory.addObserver(observer);
+
 	rename_category(getInventoryModel(), mUUID, new_name);
 
 	// return FALSE because we either notified observers (& therefore
@@ -3337,28 +3253,9 @@ void LLFolderBridge::pasteLinkFromClipboard()
 					dropToOutfit(item, move_is_into_current_outfit);
 				}
 			}
-			else if (LLInventoryCategory *cat = model->getCategory(object_id))
+			else if (LLConstPointer<LLInventoryObject> obj = model->getObject(object_id))
 			{
-				const std::string empty_description = "";
-				link_inventory_item(
-					gAgent.getID(),
-					cat->getUUID(),
-					parent_id,
-					cat->getName(),
-					empty_description,
-					LLAssetType::AT_LINK_FOLDER,
-					LLPointer<LLInventoryCallback>(NULL));
-			}
-			else if (LLInventoryItem *item = model->getItem(object_id))
-			{
-				link_inventory_item(
-					gAgent.getID(),
-					item->getLinkedUUID(),
-					parent_id,
-					item->getName(),
-					item->getDescription(),
-					LLAssetType::AT_LINK,
-					LLPointer<LLInventoryCallback>(NULL));
+				link_inventory_object(parent_id, obj, LLPointer<LLInventoryCallback>(NULL));
 			}
 		}
 		// Change mode to paste for next paste
@@ -3449,16 +3346,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 				items.push_back(std::string("New Clothes"));
 				items.push_back(std::string("New Body Parts"));
 			}
-#if SUPPORT_ENSEMBLES
-			// Changing folder types is an unfinished unsupported feature
-			// and can lead to unexpected behavior if enabled.
-			items.push_back(std::string("Change Type"));
-			const LLViewerInventoryCategory *cat = getCategory();
-			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
-			{
-				disabled_items.push_back(std::string("Change Type"));
-			}
-#endif
 			getClipboardEntries(false, items, disabled_items, flags);
 		}
 		else
@@ -3620,6 +3507,10 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 		{
 			disabled_items.push_back(std::string("Replace Outfit"));
 		}
+		if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID))
+		{
+			disabled_items.push_back(std::string("Add To Outfit"));
+		}
 		items.push_back(std::string("Outfit Separator"));
 	}
 }
@@ -3950,14 +3841,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
 	else
 	{
 		LLPointer<LLInventoryCallback> cb = NULL;
-		link_inventory_item(
-			gAgent.getID(),
-			inv_item->getLinkedUUID(),
-			mUUID,
-			inv_item->getName(),
-			inv_item->getDescription(),
-			LLAssetType::AT_LINK,
-			cb);
+		link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
 	}
 }
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index bc875e8f3758af3d2f52e1dd4f42fbd554afc622..02134c7cc531355a33f02fbd09a264d43fc98b35 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -252,7 +252,7 @@ class LLFolderBridge : public LLInvFVBridge
 	LLFolderBridge(LLInventoryPanel* inventory, 
 				   LLFolderView* root,
 				   const LLUUID& uuid) 
-        :       LLInvFVBridge(inventory, root, uuid),
+	:	LLInvFVBridge(inventory, root, uuid),
 		mCallingCards(FALSE),
 		mWearables(FALSE),
 		mIsLoading(false)
@@ -276,6 +276,8 @@ class LLFolderBridge : public LLInvFVBridge
 	virtual LLUIImagePtr getIconOverlay() const;
 
 	static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
+	
+	virtual std::string getLabelSuffix() const;
 
 	virtual BOOL renameItem(const std::string& new_name);
 
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f16b9330be2150b3c9e165854543e5522ac59bb1..1e7825a13e3ac70a4a6980bdb571942d7319379f 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -123,12 +123,9 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 		return;
 	}
 
-	LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
-	new_cat->rename(new_name);
-	new_cat->updateServer(FALSE);
-	model->updateCategory(new_cat);
-
-	model->notifyObservers();
+	LLSD updates;
+	updates["name"] = new_name;
+	update_inventory_category(cat_id, updates, NULL);
 }
 
 void copy_inventory_category(LLInventoryModel* model,
@@ -741,6 +738,13 @@ bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item
 	return FALSE;
 }
 
+bool LLIsValidItemLink::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+	LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+	if (!vitem) return false;
+	return (vitem->getActualType() == LLAssetType::AT_LINK  && !vitem->getIsBrokenLink());
+}
+
 bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	if(mType == LLAssetType::AT_CATEGORY)
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index f1066a4dc96622575df5a3f80d4b9a13afb195ce..6b3861aa79f21984bc2a8f42bdd3f27ec1b5b3df 100755
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -186,6 +186,13 @@ class LLIsOfAssetType : public LLInventoryCollectFunctor
 	LLAssetType::EType mType;
 };
 
+class LLIsValidItemLink : public LLInventoryCollectFunctor
+{
+public:
+	virtual bool operator()(LLInventoryCategory* cat,
+							LLInventoryItem* item);
+};
+
 class LLIsTypeWithPermissions : public LLInventoryCollectFunctor
 {
 public:
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 7db1f29797f3da3838c414f4d339a4c7d8be1c4c..14ca0095ae596c3eef3d100d7e7af300fea43420 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "llinventorymodel.h"
 
+#include "llaisapi.h"
 #include "llagent.h"
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
@@ -48,6 +49,7 @@
 #include "llcallbacklist.h"
 #include "llvoavatarself.h"
 #include "llgesturemgr.h"
+#include "llsdutil.h"
 #include <typeinfo>
 
 //#define DIFF_INVENTORY_FILES
@@ -103,17 +105,7 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 		if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
 			S32 descendents_server = c->getDescendentCount();
-			LLInventoryModel::cat_array_t* cats;
-			LLInventoryModel::item_array_t* items;
-			mModel->getDirectDescendentsOf(
-				c->getUUID(),
-				cats,
-				items);
-			S32 descendents_actual = 0;
-			if(cats && items)
-			{
-				descendents_actual = cats->size() + items->size();
-			}
+			S32 descendents_actual = c->getViewerDescendentCount();
 			if(descendents_server == descendents_actual)
 			{
 				mCachedCatIDs.insert(c->getUUID());
@@ -135,6 +127,7 @@ LLInventoryModel gInventory;
 LLInventoryModel::LLInventoryModel()
 :	mModifyMask(LLInventoryObserver::ALL),
 	mChangedItemIDs(),
+	mBacklinkMMap(),
 	mCategoryMap(),
 	mItemMap(),
 	mCategoryLock(),
@@ -252,6 +245,23 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
 	return NULL;
 }
 
+bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+{
+	LLInventoryObject *object = getObject(object_id);
+	while (object && object->getParentUUID().notNull())
+	{
+		LLInventoryObject *parent_object = getObject(object->getParentUUID());
+		if (!parent_object)
+		{
+			LL_WARNS() << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL;
+			return false;
+		}
+		object = parent_object;
+	}
+	result = object->getUUID();
+	return true;
+}
+
 // Get the object by id. Returns NULL if not found.
 LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
 {
@@ -429,15 +439,12 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E
 	}
 }
 
-// findCategoryUUIDForType() returns the uuid of the category that
-// specifies 'type' as what it defaults to containing. The category is
-// not necessarily only for that type. *NOTE: This will create a new
-// inventory category on the fly if one does not exist.
-const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*,
-					  bool find_in_library*/)
+const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
+	LLFolderType::EType preferred_type,
+	bool create_folder,
+	const LLUUID& root_id)
 {
 	LLUUID rv = LLUUID::null;
-	const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID();
 	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
 	{
 		rv = root_id;
@@ -453,14 +460,17 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 			{
 				if(cats->at(i)->getPreferredType() == preferred_type)
 				{
-					rv = cats->at(i)->getUUID();
-					break;
+					const LLUUID& folder_id = cats->at(i)->getUUID();
+					if (rv.isNull() || folder_id < rv)
+					{
+						rv = folder_id;
+					}
 				}
 			}
 		}
 	}
 	
-	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))
+	if(rv.isNull() && isInventoryUsable() && create_folder)
 	{
 		if(root_id.notNull())
 		{
@@ -470,68 +480,49 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 	return rv;
 }
 
-const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
+// findCategoryUUIDForType() returns the uuid of the category that
+// specifies 'type' as what it defaults to containing. The category is
+// not necessarily only for that type. *NOTE: This will create a new
+// inventory category on the fly if one does not exist.
+const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
 {
-	LLUUID rv = LLUUID::null;
-
-	const LLUUID &root_id = gInventory.getLibraryRootFolderID();
-	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
-	{
-		rv = root_id;
-	}
-	else if (root_id.notNull())
-	{
-		cat_array_t* cats = NULL;
-		cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
-		if(cats)
-		{
-			S32 count = cats->size();
-			for(S32 i = 0; i < count; ++i)
-			{
-				if(cats->at(i)->getPreferredType() == preferred_type)
-				{
-					rv = cats->at(i)->getUUID();
-					break;
-				}
-			}
-		}
-	}
+	return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getRootFolderID());
+}
 
-	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))
-	{
-		if(root_id.notNull())
-		{
-			return createNewCategory(root_id, preferred_type, LLStringUtil::null);
-		}
-	}
-	return rv;
+const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
+{
+	return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID());
 }
 
 class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLCreateInventoryCategoryResponder);
 public:
 	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
-									   void (*callback)(const LLSD&, void*),
-									   void* user_data) :
-										mModel(model),
-										mCallback(callback), 
-										mData(user_data) 
+									   boost::optional<inventory_func_type> callback):
+		mModel(model),
+		mCallback(callback) 
 	{
 	}
 	
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+protected:
+	virtual void httpFailure()
 	{
-		LL_WARNS("InvAPI") << "CreateInventoryCategory failed [status:"
-				<< status << "]: " << content << LL_ENDL;
+		LL_WARNS("InvAPI") << dumpResponse() << LL_ENDL;
 	}
 	
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
 		//Server has created folder.
-		
+		const LLSD& content = getContent();
+		if (!content.isMap() || !content.has("folder_id"))
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLUUID category_id = content["folder_id"].asUUID();
 		
-		
+		LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << LL_ENDL;
 		// Add the category to the internal representation
 		LLPointer<LLViewerInventoryCategory> cat =
 		new LLViewerInventoryCategory( category_id, 
@@ -544,17 +535,15 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 		LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
 		mModel->accountForUpdate(update);
 		mModel->updateCategory(cat);
-		
-		if (mCallback && mData)
+
+		if (mCallback)
 		{
-			mCallback(content, mData);
+			mCallback.get()(category_id);
 		}
-		
 	}
 	
 private:
-	void (*mCallback)(const LLSD&, void*);
-	void* mData;
+	boost::optional<inventory_func_type> mCallback;
 	LLInventoryModel* mModel;
 };
 
@@ -565,8 +554,7 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 										   LLFolderType::EType preferred_type,
 										   const std::string& pname,
-										   void (*callback)(const LLSD&, void*),	//Default to NULL
-										   void* user_data)							//Default to NULL
+										   boost::optional<inventory_func_type> callback)
 {
 	
 	LLUUID id;
@@ -593,33 +581,32 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 		name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
 	}
 	
-	if ( callback && user_data )  //callback required for acked message.
+	LLViewerRegion* viewer_region = gAgent.getRegion();
+	std::string url;
+	if ( viewer_region )
+		url = viewer_region->getCapability("CreateInventoryCategory");
+	
+	if (!url.empty() && callback.get_ptr())
 	{
-		LLViewerRegion* viewer_region = gAgent.getRegion();
-		std::string url;
-		if ( viewer_region )
-			url = viewer_region->getCapability("CreateInventoryCategory");
+		//Let's use the new capability.
 		
-		if (!url.empty())
-		{
-			//Let's use the new capability.
-			
-			LLSD request, body;
-			body["folder_id"] = id;
-			body["parent_id"] = parent_id;
-			body["type"] = (LLSD::Integer) preferred_type;
-			body["name"] = name;
-			
-			request["message"] = "CreateInventoryCategory";
-			request["payload"] = body;
-			
-	//		viewer_region->getCapAPI().post(request);
-			LLHTTPClient::post(
-							   url,
-							   body,
-							   new LLCreateInventoryCategoryResponder(this, callback, user_data) );
-			return LLUUID::null;
-		}
+		LLSD request, body;
+		body["folder_id"] = id;
+		body["parent_id"] = parent_id;
+		body["type"] = (LLSD::Integer) preferred_type;
+		body["name"] = name;
+		
+		request["message"] = "CreateInventoryCategory";
+		request["payload"] = body;
+
+		LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL;
+		//		viewer_region->getCapAPI().post(request);
+		LLHTTPClient::post(
+			url,
+			body,
+			new LLCreateInventoryCategoryResponder(this, callback) );
+
+		return LLUUID::null;
 	}
 
 	// Add the category to the internal representation
@@ -646,6 +633,40 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 	return id;
 }
 
+// This is optimized for the case that we just want to know whether a
+// category has any immediate children meeting a condition, without
+// needing to recurse or build up any lists.
+bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id,
+												   LLInventoryCollectFunctor& filter)
+{
+	LLInventoryModel::cat_array_t *cats;
+	LLInventoryModel::item_array_t *items;
+	getDirectDescendentsOf(cat_id, cats, items);
+	if (cats)
+	{
+		for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin();
+			 it != cats->end(); ++it)
+		{
+			if (filter(*it,NULL))
+			{
+				return true;
+			}
+		}
+	}
+	if (items)
+	{
+		for (LLInventoryModel::item_array_t::const_iterator it = items->begin();
+			 it != items->end(); ++it)
+		{
+			if (filter(NULL,*it))
+			{
+				return true;
+			}
+		}
+	}
+	return false;
+}
+												  
 // Starting with the object specified, add its descendents to the
 // array provided, but do not add the inventory object specified by
 // id. There is no guaranteed order. Neither array will be erased
@@ -677,8 +698,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 											cat_array_t& cats,
 											item_array_t& items,
 											BOOL include_trash,
-											LLInventoryCollectFunctor& add,
-											BOOL follow_folder_links)
+											LLInventoryCollectFunctor& add)
 {
 	// Start with categories
 	if(!include_trash)
@@ -705,36 +725,6 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 	LLViewerInventoryItem* item = NULL;
 	item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
 
-	// Follow folder links recursively.  Currently never goes more
-	// than one level deep (for current outfit support)
-	// Note: if making it fully recursive, need more checking against infinite loops.
-	if (follow_folder_links && item_array)
-	{
-		S32 count = item_array->size();
-		for(S32 i = 0; i < count; ++i)
-		{
-			item = item_array->at(i);
-			if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER)
-			{
-				LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
-				if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
-					// BAP - was 
-					// LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType()))
-					// Change back once ensemble typing is in place.
-				{
-					if(add(linked_cat,NULL))
-					{
-						// BAP should this be added here?  May not
-						// matter if it's only being used in current
-						// outfit traversal.
-						cats.push_back(LLPointer<LLViewerInventoryCategory>(linked_cat));
-					}
-					collectDescendentsIf(linked_cat->getUUID(), cats, items, include_trash, add, FALSE);
-				}
-			}
-		}
-	}
-	
 	// Move onto items
 	if(item_array)
 	{
@@ -756,26 +746,7 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
 	if (!obj || obj->getIsLinkType())
 		return;
 
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t item_array;
-	LLLinkedItemIDMatches is_linked_item_match(object_id);
-	collectDescendentsIf(gInventory.getRootFolderID(),
-						 cat_array,
-						 item_array,
-						 LLInventoryModel::INCLUDE_TRASH,
-						 is_linked_item_match);
-	if (cat_array.empty() && item_array.empty())
-	{
-		return;
-	}
-	for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
-		 cat_iter != cat_array.end();
-		 cat_iter++)
-	{
-		LLViewerInventoryCategory *linked_cat = (*cat_iter);
-		addChangedMask(mask, linked_cat->getUUID());
-	};
-
+	LLInventoryModel::item_array_t item_array = collectLinksTo(object_id);
 	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
 		 iter != item_array.end();
 		 iter++)
@@ -803,17 +774,27 @@ LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id)
 	return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL;
 }
 
-LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID& id,
-																	const LLUUID& start_folder_id)
+LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id)
 {
+	// Get item list via collectDescendents (slow!)
 	item_array_t items;
-	LLInventoryModel::cat_array_t cat_array;
-	LLLinkedItemIDMatches is_linked_item_match(id);
-	collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id),
-						 cat_array,
-						 items,
-						 LLInventoryModel::INCLUDE_TRASH,
-						 is_linked_item_match);
+	const LLInventoryObject *obj = getObject(id);
+	// FIXME - should be as in next line, but this is causing a
+	// stack-smashing crash of cause TBD... check in the REBUILD code.
+	//if (obj && obj->getIsLinkType())
+	if (!obj || obj->getIsLinkType())
+		return items;
+	
+	std::pair<backlink_mmap_t::iterator, backlink_mmap_t::iterator> range = mBacklinkMMap.equal_range(id);
+	for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it)
+	{
+		LLViewerInventoryItem *item = getItem(it->second);
+		if (item)
+		{
+			items.push_back(item);
+		}
+	}
+
 	return items;
 }
 
@@ -830,9 +811,8 @@ bool LLInventoryModel::isInventoryUsable() const
 // Calling this method with an inventory item will either change an
 // existing item with a matching item_id, or will add the item to the
 // current inventory.
-U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
+U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
 {
-	U32 mask = LLInventoryObserver::NONE;
 	if(item->getUUID().isNull())
 	{
 		return mask;
@@ -1011,7 +991,7 @@ LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLU
 
 // Calling this method with an inventory category will either change
 // an existing item with the matching id, or it will add the category.
-void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat)
+void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask)
 {
 	if(cat->getUUID().isNull())
 	{
@@ -1028,7 +1008,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat)
 	if(old_cat)
 	{
 		// We already have an old category, modify it's values
-		U32 mask = LLInventoryObserver::NONE;
 		LLUUID old_parent_id = old_cat->getParentUUID();
 		LLUUID new_parent_id = cat->getParentUUID();
 		if(old_parent_id != new_parent_id)
@@ -1182,8 +1161,199 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 	notifyObservers();
 }
 
+void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
+{
+	LLTimer timer;
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
+	}
+
+	AISUpdate ais_update(update); // parse update llsd into stuff to do.
+	ais_update.doUpdate(); // execute the updates in the appropriate order.
+	LL_INFOS() << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL;
+}
+
+// Does not appear to be used currently.
+void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
+{
+	U32 mask = LLInventoryObserver::NONE;
+
+	LLPointer<LLViewerInventoryItem> item = gInventory.getItem(item_id);
+	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL;
+	if(item)
+	{
+		for (LLSD::map_const_iterator it = updates.beginMap();
+			 it != updates.endMap(); ++it)
+		{
+			if (it->first == "name")
+			{
+				LL_INFOS() << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL;
+				item->rename(it->second.asString());
+				mask |= LLInventoryObserver::LABEL;
+			}
+			else if (it->first == "desc")
+			{
+				LL_INFOS() << "Updating description from " << item->getActualDescription()
+						<< " to " << it->second.asString() << LL_ENDL;
+				item->setDescription(it->second.asString());
+			}
+			else
+			{
+				LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL;
+			}
+		}
+		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?
+	}
+}
+
+// Not used?
+void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates)
+{
+	U32 mask = LLInventoryObserver::NONE;
+
+	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(cat_id);
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL;
+	if(cat)
+	{
+		for (LLSD::map_const_iterator it = updates.beginMap();
+			 it != updates.endMap(); ++it)
+		{
+			if (it->first == "name")
+			{
+				LL_INFOS() << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL;
+				cat->rename(it->second.asString());
+				mask |= LLInventoryObserver::LABEL;
+			}
+			else
+			{
+				LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL;
+			}
+		}
+		mask |= LLInventoryObserver::INTERNAL;
+		addChangedMask(mask, cat->getUUID());
+		gInventory.notifyObservers(); // do we want to be able to make this optional?
+	}
+}
+
+// Update model after descendents have been purged.
+void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links)
+{
+	LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
+	if (cat.notNull())
+	{
+		// do the cache accounting
+		S32 descendents = cat->getDescendentCount();
+		if(descendents > 0)
+		{
+			LLInventoryModel::LLCategoryUpdate up(object_id, -descendents);
+			accountForUpdate(up);
+		}
+
+		// we know that descendent count is 0, however since the
+		// accounting may actually not do an update, we should force
+		// it here.
+		cat->setDescendentCount(0);
+
+		// unceremoniously remove anything we have locally stored.
+		LLInventoryModel::cat_array_t categories;
+		LLInventoryModel::item_array_t items;
+		collectDescendents(object_id,
+						   categories,
+						   items,
+						   LLInventoryModel::INCLUDE_TRASH);
+		S32 count = items.size();
+
+		LLUUID uu_id;
+		for(S32 i = 0; i < count; ++i)
+		{
+			uu_id = items.at(i)->getUUID();
+
+			// This check prevents the deletion of a previously deleted item.
+			// This is necessary because deletion is not done in a hierarchical
+			// order. The current item may have been already deleted as a child
+			// of its deleted parent.
+			if (getItem(uu_id))
+			{
+				deleteObject(uu_id, fix_broken_links);
+			}
+		}
+
+		count = categories.size();
+		// Slightly kludgy way to make sure categories are removed
+		// only after their child categories have gone away.
+
+		// FIXME: Would probably make more sense to have this whole
+		// descendent-clearing thing be a post-order recursive
+		// function to get the leaf-up behavior automatically.
+		S32 deleted_count;
+		S32 total_deleted_count = 0;
+		do
+		{
+			deleted_count = 0;
+			for(S32 i = 0; i < count; ++i)
+			{
+				uu_id = categories.at(i)->getUUID();
+				if (getCategory(uu_id))
+				{
+					cat_array_t* cat_list = getUnlockedCatArray(uu_id);
+					if (!cat_list || (cat_list->size() == 0))
+					{
+						deleteObject(uu_id, fix_broken_links);
+						deleted_count++;
+					}
+				}
+			}
+			total_deleted_count += deleted_count;
+		}
+		while (deleted_count > 0);
+		if (total_deleted_count != count)
+		{
+			LL_WARNS() << "Unexpected count of categories deleted, got "
+					<< total_deleted_count << " expected " << count << LL_ENDL;
+		}
+		//gInventory.validate();
+	}
+}
+
+// Update model after an item is confirmed as removed from
+// server. Works for categories or items.
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version, bool do_notify_observers)
+{
+	LLPointer<LLInventoryObject> obj = getObject(object_id);
+	if(obj)
+	{
+		if (getCategory(object_id))
+		{
+			// For category, need to delete/update all children first.
+			onDescendentsPurgedFromServer(object_id, fix_broken_links);
+		}
+
+
+		// From item/cat removeFromServer()
+		if (update_parent_version)
+		{
+			LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+			accountForUpdate(up);
+		}
+
+		// From purgeObject()
+		LLPreview::hide(object_id);
+		deleteObject(object_id, fix_broken_links, do_notify_observers);
+	}
+}
+
+
 // Delete a particular inventory object by ID.
-void LLInventoryModel::deleteObject(const LLUUID& id)
+void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, bool do_notify_observers)
 {
 	LL_DEBUGS() << "LLInventoryModel::deleteObject()" << LL_ENDL;
 	LLPointer<LLInventoryObject> obj = getObject(id);
@@ -1214,157 +1384,64 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 	item_list = getUnlockedItemArray(id);
 	if(item_list)
 	{
+		if (item_list->size())
+		{
+			LL_WARNS() << "Deleting cat " << id << " while it still has child items" << LL_ENDL;
+		}
 		delete item_list;
 		mParentChildItemTree.erase(id);
 	}
 	cat_list = getUnlockedCatArray(id);
 	if(cat_list)
 	{
+		if (cat_list->size())
+		{
+			LL_WARNS() << "Deleting cat " << id << " while it still has child cats" << LL_ENDL;
+		}
 		delete cat_list;
 		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
-	obj = NULL; // delete obj
-	updateLinkedObjectsFromPurge(id);
-	gInventory.notifyObservers();
-}
 
-// Delete a particular inventory item by ID, and remove it from the server.
-void LLInventoryModel::purgeObject(const LLUUID &id)
-{
-	LL_DEBUGS() << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << LL_ENDL;
-	LLPointer<LLInventoryObject> obj = getObject(id);
-	if(obj)
+	bool is_link_type = obj->getIsLinkType();
+	if (is_link_type)
+	{
+		removeBacklinkInfo(obj->getUUID(), obj->getLinkedUUID());
+	}
+
+	// Can't have links to links, so there's no need for this update
+	// if the item removed is a link. Can also skip if source of the
+	// update is getting broken link info separately.
+	obj = NULL; // delete obj
+	if (fix_broken_links && !is_link_type)
 	{
-		obj->removeFromServer();
-		LLPreview::hide(id);
-		deleteObject(id);
+		updateLinkedObjectsFromPurge(id);
+	}
+	if (do_notify_observers)
+	{
+		notifyObservers();
 	}
 }
 
 void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
 {
-	LLInventoryModel::item_array_t item_array = collectLinkedItems(baseobj_id);
+	LLInventoryModel::item_array_t item_array = collectLinksTo(baseobj_id);
 
 	// REBUILD is expensive, so clear the current change list first else
 	// everything else on the changelist will also get rebuilt.
-	gInventory.notifyObservers();
-	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
-		 iter != item_array.end();
-		 iter++)
+	if (item_array.size() > 0)
 	{
-		const LLViewerInventoryItem *linked_item = (*iter);
-		const LLUUID &item_id = linked_item->getUUID();
-		if (item_id == baseobj_id) continue;
-		addChangedMask(LLInventoryObserver::REBUILD, item_id);
-	}
-	gInventory.notifyObservers();
-}
-
-// 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 LLInventoryModel::purgeDescendentsOf(const LLUUID& id)
-{
-	LLPointer<LLViewerInventoryCategory> cat = getCategory(id);
-	if (cat.notNull())
-	{
-		if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode())
-		{
-			// Something on the clipboard is in "cut mode" and needs to be preserved
-			LL_INFOS() << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
-			<< " iterate and purge non hidden items" << LL_ENDL;
-			cat_array_t* categories;
-			item_array_t* items;
-			// Get the list of direct descendants in that category passed as argument
-			getDirectDescendentsOf(id, categories, items);
-			std::vector<LLUUID> list_uuids;
-			// Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently)
-			// Note: we need to do that shallow copy as purging things will invalidate the categories or items lists
-			for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it)
-			{
-				list_uuids.push_back((*it)->getUUID());
-			}
-			for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
-			{
-				list_uuids.push_back((*it)->getUUID());
-			}
-			// Iterate through the list and only purge the UUIDs that are not on the clipboard
-			for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
-			{
-				if (!LLClipboard::instance().isOnClipboard(*it))
-				{
-					purgeObject(*it);
-				}
-			}
-		}
-		else
+		gInventory.notifyObservers();
+		for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+			iter != item_array.end();
+			iter++)
 		{
-			// Fast purge
-			// do the cache accounting
-			LL_INFOS() << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
-				<< LL_ENDL;
-			S32 descendents = cat->getDescendentCount();
-			if(descendents > 0)
-			{
-				LLCategoryUpdate up(id, -descendents);
-				accountForUpdate(up);
-			}
-
-			// we know that descendent count is 0, however since the
-			// accounting may actually not do an update, we should force
-			// it here.
-			cat->setDescendentCount(0);
-
-			// send it upstream
-			LLMessageSystem* msg = gMessageSystem;
-			msg->newMessage("PurgeInventoryDescendents");
-			msg->nextBlock("AgentData");
-			msg->addUUID("AgentID", gAgent.getID());
-			msg->addUUID("SessionID", gAgent.getSessionID());
-			msg->nextBlock("InventoryData");
-			msg->addUUID("FolderID", id);
-			gAgent.sendReliableMessage();
-
-			// unceremoniously remove anything we have locally stored.
-			cat_array_t categories;
-			item_array_t items;
-			collectDescendents(id,
-							   categories,
-							   items,
-							   INCLUDE_TRASH);
-			S32 count = items.size();
-
-			item_map_t::iterator item_map_end = mItemMap.end();
-			cat_map_t::iterator cat_map_end = mCategoryMap.end();
-			LLUUID uu_id;
-
-			for(S32 i = 0; i < count; ++i)
-			{
-				uu_id = items.at(i)->getUUID();
-
-				// This check prevents the deletion of a previously deleted item.
-				// This is necessary because deletion is not done in a hierarchical
-				// order. The current item may have been already deleted as a child
-				// of its deleted parent.
-				if (mItemMap.find(uu_id) != item_map_end)
-				{
-					deleteObject(uu_id);
-				}
-			}
-
-			count = categories.size();
-			for(S32 i = 0; i < count; ++i)
-			{
-				uu_id = categories.at(i)->getUUID();
-				if (mCategoryMap.find(uu_id) != cat_map_end)
-				{
-					deleteObject(uu_id);
-				}
-			}
+			const LLViewerInventoryItem *linked_item = (*iter);
+			const LLUUID &item_id = linked_item->getUUID();
+			if (item_id == baseobj_id) continue;
+			addChangedMask(LLInventoryObserver::REBUILD, item_id);
 		}
+		gInventory.notifyObservers();
 	}
 }
 
@@ -1419,6 +1496,7 @@ void LLInventoryModel::notifyObservers()
 
 	mModifyMask = LLInventoryObserver::NONE;
 	mChangedItemIDs.clear();
+	mAddedItemIDs.clear();
 	mIsNotifyObservers = FALSE;
 }
 
@@ -1432,25 +1510,49 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
 		// (which is in the process of processing the list of items marked for change).
 		// This means the change may fail to be processed.
 		LL_WARNS() << "Adding changed mask within notify observers!  Change will likely be lost." << LL_ENDL;
+		LLViewerInventoryItem *item = getItem(referent);
+		if (item)
+		{
+			LL_WARNS() << "Item " << item->getName() << LL_ENDL;
+		}
+		else
+		{
+			LLViewerInventoryCategory *cat = getCategory(referent);
+			if (cat)
+			{
+				LL_WARNS() << "Category " << cat->getName() << LL_ENDL;
+			}
+		}
 	}
 	
 	mModifyMask |= mask; 
 	if (referent.notNull())
 	{
 		mChangedItemIDs.insert(referent);
-	}
+
+		if (mask & LLInventoryObserver::ADD)
+		{
+			mAddedItemIDs.insert(referent);
+		}
 	
-	// Update all linked items.  Starting with just LABEL because I'm
-	// not sure what else might need to be accounted for this.
-	if (mModifyMask & LLInventoryObserver::LABEL)
-	{
-		addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+		// Update all linked items.  Starting with just LABEL because I'm
+		// not sure what else might need to be accounted for this.
+		if (mask & LLInventoryObserver::LABEL)
+		{
+			addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+		}
 	}
 }
 
 // If we get back a normal response, handle it here
-void  LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
-{	
+void LLInventoryModel::fetchInventoryResponder::httpSuccess()
+{
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	start_new_inventory_observer();
 
 	/*LLUUID agent_id;
@@ -1471,8 +1573,8 @@ void  LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
 		LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
 		titem->unpackMessage(content["items"][i]);
 		
-		LL_DEBUGS() << "LLInventoryModel::messageUpdateCore() item id:"
-				 << titem->getUUID() << LL_ENDL;
+		LL_DEBUGS() << "LLInventoryModel::fetchInventoryResponder item id: "
+					<< titem->getUUID() << LL_ENDL;
 		items.push_back(titem);
 		// examine update for changes.
 		LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
@@ -1509,9 +1611,9 @@ void  LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
 }
 
 //If we get back an error (not found, etc...), handle it here
-void LLInventoryModel::fetchInventoryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLInventoryModel::fetchInventoryResponder::httpFailure()
 {
-	LL_WARNS() << "fetchInventory error [status:" << status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	gInventory.notifyObservers();
 }
 
@@ -1603,6 +1705,47 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
 	}
 }
 
+bool LLInventoryModel::hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const
+{
+	std::pair <backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range;
+	range = mBacklinkMMap.equal_range(target_id);
+	for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+	{
+		if (it->second == link_id)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+void LLInventoryModel::addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
+{
+	if (!hasBacklinkInfo(link_id, target_id))
+	{
+		mBacklinkMMap.insert(std::make_pair(target_id, link_id));
+	}
+}
+
+void LLInventoryModel::removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
+{
+	std::pair <backlink_mmap_t::iterator, backlink_mmap_t::iterator> range;
+	range = mBacklinkMMap.equal_range(target_id);
+	for (backlink_mmap_t::iterator it = range.first; it != range.second; )
+	{
+		if (it->second == link_id)
+		{
+			backlink_mmap_t::iterator delete_it = it; // iterator will be invalidated by erase.
+			++it;
+			mBacklinkMMap.erase(delete_it);
+		}
+		else
+		{
+			++it;
+		}
+	}
+}
+
 void LLInventoryModel::addItem(LLViewerInventoryItem* item)
 {
 	llassert(item);
@@ -1624,7 +1767,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
 		{
 			LL_INFOS() << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " )  parent: " << item->getParentUUID() << LL_ENDL;
 		}
-
+		if (item->getIsLinkType())
+		{
+			// Add back-link from linked-to UUID.
+			const LLUUID& link_id = item->getUUID();
+			const LLUUID& target_id = item->getLinkedUUID();
+			addBacklinkInfo(link_id, target_id);
+		}
 		mItemMap[item->getUUID()] = item;
 	}
 }
@@ -1643,6 +1792,7 @@ void LLInventoryModel::empty()
 		mParentChildItemTree.end(),
 		DeletePairedPointer());
 	mParentChildItemTree.clear();
+	mBacklinkMMap.clear(); // forget all backlink information.
 	mCategoryMap.clear(); // remove all references (should delete entries)
 	mItemMap.clear(); // remove all references (should delete entries)
 	mLastItem = NULL;
@@ -1654,37 +1804,34 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
 	LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
 	if(cat)
 	{
-		bool accounted = false;
 		S32 version = cat->getVersion();
 		if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
 			S32 descendents_server = cat->getDescendentCount();
-			LLInventoryModel::cat_array_t* cats;
-			LLInventoryModel::item_array_t* items;
-			getDirectDescendentsOf(update.mCategoryID, cats, items);
-			S32 descendents_actual = 0;
-			if(cats && items)
-			{
-				descendents_actual = cats->size() + items->size();
-			}
+			S32 descendents_actual = cat->getViewerDescendentCount();
 			if(descendents_server == descendents_actual)
 			{
-				accounted = true;
 				descendents_actual += update.mDescendentDelta;
 				cat->setDescendentCount(descendents_actual);
 				cat->setVersion(++version);
-				LL_DEBUGS() << "accounted: '" << cat->getName() << "' "
-						 << version << " with " << descendents_actual
-						 << " descendents." << LL_ENDL;
+				LL_DEBUGS("Inventory") << "accounted: '" << cat->getName() << "' "
+									   << version << " with " << descendents_actual
+									   << " descendents." << LL_ENDL;
+			}
+			else
+			{
+				// Error condition, this means that the category did not register that
+				// it got new descendents (perhaps because it is still being loaded)
+				// which means its descendent count will be wrong.
+				LL_WARNS() << "Accounting failed for '" << cat->getName() << "' version:"
+						   << version << " due to mismatched descendent count:  server == "
+						   << descendents_server << ", viewer == " << descendents_actual << LL_ENDL;
 			}
 		}
-		if(!accounted)
+		else
 		{
-			// Error condition, this means that the category did not register that
-			// it got new descendents (perhaps because it is still being loaded)
-			// which means its descendent count will be wrong.
-			LL_WARNS() << "Accounting failed for '" << cat->getName() << "' version:"
-					 << version << LL_ENDL;
+			LL_WARNS() << "Accounting failed for '" << cat->getName() << "' version: unknown (" 
+					   << version << ")" << LL_ENDL;
 		}
 	}
 	else
@@ -1718,47 +1865,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);
-			LL_INFOS() << "IncrementVersion: " << cat->getName() << " "
-					<< cat->getVersion() << LL_ENDL;
-		}
-		else
-		{
-			LL_INFOS() << "Attempt to increment version when unknown: "
-					<< category_id << LL_ENDL;
-		}
-	}
-	else
-	{
-		LL_INFOS() << "Attempt to increment category: " << category_id << LL_ENDL;
-	}
-}
-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
 {
@@ -1799,14 +1905,7 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
 	if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN))
 	{
 		S32 descendents_server = cat->getDescendentCount();
-		LLInventoryModel::cat_array_t* cats;
-		LLInventoryModel::item_array_t* items;
-		getDirectDescendentsOf(cat_id, cats, items);
-		S32 descendents_actual = 0;
-		if(cats && items)
-		{
-			descendents_actual = cats->size() + items->size();
-		}
+		S32 descendents_actual = cat->getViewerDescendentCount();
 		if(descendents_server == descendents_actual)
 		{
 			return true;
@@ -2144,11 +2243,16 @@ void LLInventoryModel::buildParentChildMap()
 	S32 count = cats.size();
 	S32 i;
 	S32 lost = 0;
+	cat_array_t lost_cats;
 	for(i = 0; i < count; ++i)
 	{
 		LLViewerInventoryCategory* cat = cats.at(i);
 		catsp = getUnlockedCatArray(cat->getParentUUID());
-		if(catsp)
+		if(catsp &&
+		   // Only the two root folders should be children of null.
+		   // Others should go to lost & found.
+		   (cat->getParentUUID().notNull() || 
+			cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY ))
 		{
 			catsp->push_back(cat);
 		}
@@ -2160,35 +2264,10 @@ void LLInventoryModel::buildParentChildMap()
 			// implement it, we would need a set or map of uuid pairs
 			// which would be (folder_id, new_parent_id) to be sent up
 			// to the server.
-			LL_INFOS() << "Lost categroy: " << cat->getUUID() << " - "
-					<< cat->getName() << LL_ENDL;
+			LL_INFOS() << "Lost category: " << cat->getUUID() << " - "
+					   << cat->getName() << LL_ENDL;
 			++lost;
-			// plop it into the lost & found.
-			LLFolderType::EType pref = cat->getPreferredType();
-			if(LLFolderType::FT_NONE == pref)
-			{
-				cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
-			}
-			else if(LLFolderType::FT_ROOT_INVENTORY == pref)
-			{
-				// it's the root
-				cat->setParent(LLUUID::null);
-			}
-			else
-			{
-				// it's a protected folder.
-				cat->setParent(gInventory.getRootFolderID());
-			}
-			cat->updateServer(TRUE);
-			catsp = getUnlockedCatArray(cat->getParentUUID());
-			if(catsp)
-			{
-				catsp->push_back(cat);
-			}
-			else
-			{		
-				LL_WARNS() << "Lost and found Not there!!" << LL_ENDL;
-			}
+			lost_cats.push_back(cat);
 		}
 	}
 	if(lost)
@@ -2196,6 +2275,42 @@ void LLInventoryModel::buildParentChildMap()
 		LL_WARNS() << "Found  " << lost << " lost categories." << LL_ENDL;
 	}
 
+	// Do moves in a separate pass to make sure we've properly filed
+	// the FT_LOST_AND_FOUND category before we try to find its UUID.
+	for(i = 0; i<lost_cats.size(); ++i)
+	{
+		LLViewerInventoryCategory *cat = lost_cats.at(i);
+
+		// plop it into the lost & found.
+		LLFolderType::EType pref = cat->getPreferredType();
+		if(LLFolderType::FT_NONE == pref)
+		{
+			cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+		}
+		else if(LLFolderType::FT_ROOT_INVENTORY == pref)
+		{
+			// it's the root
+			cat->setParent(LLUUID::null);
+		}
+		else
+		{
+			// it's a protected folder.
+			cat->setParent(gInventory.getRootFolderID());
+		}
+		// FIXME note that updateServer() fails with protected
+		// types, so this will not work as intended in that case.
+		cat->updateServer(TRUE);
+		catsp = getUnlockedCatArray(cat->getParentUUID());
+		if(catsp)
+		{
+			catsp->push_back(cat);
+		}
+		else
+		{		
+			LL_WARNS() << "Lost and found Not there!!" << LL_ENDL;
+		}
+	}
+
 	const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
 	sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
 
@@ -2228,7 +2343,7 @@ void LLInventoryModel::buildParentChildMap()
 		else
 		{
 			LL_INFOS() << "Lost item: " << item->getUUID() << " - "
-					<< item->getName() << LL_ENDL;
+					   << item->getName() << LL_ENDL;
 			++lost;
 			// plop it into the lost & found.
 			//
@@ -2319,11 +2434,25 @@ void LLInventoryModel::buildParentChildMap()
 			// The inv tree is built.
 			mIsAgentInvUsable = true;
 
-			LL_INFOS() << "Inventory initialized, notifying observers" << LL_ENDL;
-			addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
-			notifyObservers();
+			// notifyObservers() has been moved to
+			// llstartup/idle_startup() after this func completes.
+			// Allows some system categories to be created before
+			// observers start firing.
 		}
 	}
+
+	if (!gInventory.validate())
+	{
+	 	LL_WARNS() << "model failed validity check!" << LL_ENDL;
+	}
+}
+
+void LLInventoryModel::createCommonSystemCategories()
+{
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true);
 }
 
 struct LLUUIDAndName
@@ -2547,7 +2676,7 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
 void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**)
 {
 	// do accounting and highlight new items if they arrive
-	if (gInventory.messageUpdateCore(msg, true))
+	if (gInventory.messageUpdateCore(msg, true, LLInventoryObserver::UPDATE_CREATE))
 	{
 		U32 callback_id;
 		LLUUID item_id;
@@ -2567,7 +2696,7 @@ void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**)
 }
 
 
-bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
+bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask)
 {
 	//make sure our added inventory observer is active
 	start_new_inventory_observer();
@@ -2621,10 +2750,14 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
 	}
 
 	U32 changes = 0x0;
+	if (account)
+	{
+		mask |= LLInventoryObserver::CREATE;
+	}
 	//as above, this loop never seems to loop more than once per call
 	for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
 	{
-		changes |= gInventory.updateItem(*it);
+		changes |= gInventory.updateItem(*it, mask);
 	}
 	gInventory.notifyObservers();
 	gViewerWindow->getWindow()->decBusyCount();
@@ -2862,7 +2995,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	LLUUID tid;
 	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	LL_INFOS() << "Bulk inventory: " << tid << LL_ENDL;
+	LL_DEBUGS("Inventory") << "Bulk inventory: " << tid << LL_ENDL;
 #endif
 
 	update_map_t update;
@@ -2874,9 +3007,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	{
 		LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
 		tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
-		LL_INFOS() << "unpacked folder '" << tfolder->getName() << "' ("
-				<< tfolder->getUUID() << ") in " << tfolder->getParentUUID()
-				<< LL_ENDL;
+		LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' ("
+							   << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
+							   << LL_ENDL;
 		if(tfolder->getUUID().notNull())
 		{
 			folders.push_back(tfolder);
@@ -2916,8 +3049,8 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	{
 		LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
 		titem->unpackMessage(msg, _PREHASH_ItemData, i);
-		LL_INFOS() << "unpacked item '" << titem->getName() << "' in "
-				<< titem->getParentUUID() << LL_ENDL;
+		LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in "
+							   << titem->getParentUUID() << LL_ENDL;
 		U32 callback_id;
 		msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
 		if(titem->getUUID().notNull() ) // && callback_id.notNull() )
@@ -2994,6 +3127,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 		InventoryCallbackInfo cbinfo = (*inv_it);
 		gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
 	}
+
+	//gInventory.validate();
+
 	// Don't show the inventory.  We used to call showAgentInventory here.
 	//LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
 	//if(view)
@@ -3052,7 +3188,8 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
 		// If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
 		if (gInventory.getItem(titem->getUUID()))
 		{
-			LL_DEBUGS() << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << LL_ENDL;
+			LL_DEBUGS("Inventory") << "Skipping prefetched item [ Name: " << titem->getName()
+								   << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << LL_ENDL;
 			continue;
 		}
 		gInventory.updateItem(titem);
@@ -3138,8 +3275,7 @@ bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const L
 	if (option == 0) // YES
 	{
 		const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
-		purgeDescendentsOf(folder_id);
-		notifyObservers();
+		purge_descendents_of(folder_id, NULL);
 	}
 	return false;
 }
@@ -3154,8 +3290,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT
 	else
 	{
 		const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
-		purgeDescendentsOf(folder_id);
-		notifyObservers();
+		purge_descendents_of(folder_id, NULL);
 	}
 }
 
@@ -3442,6 +3577,305 @@ void LLInventoryModel::dumpInventory() const
 	LL_INFOS() << "\n**********************\nEnd Inventory Dump" << LL_ENDL;
 }
 
+// Do various integrity checks on model, logging issues found and
+// returning an overall good/bad flag.
+bool LLInventoryModel::validate() const
+{
+	bool valid = true;
+
+	if (getRootFolderID().isNull())
+	{
+		LL_WARNS() << "no root folder id" << LL_ENDL;
+		valid = false;
+	}
+	if (getLibraryRootFolderID().isNull())
+	{
+		LL_WARNS() << "no root folder id" << LL_ENDL;
+		valid = false;
+	}
+
+	if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
+	{
+		// ParentChild should be one larger because of the special entry for null uuid.
+		LL_INFOS() << "unexpected sizes: cat map size " << mCategoryMap.size()
+				<< " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
+		valid = false;
+	}
+	S32 cat_lock = 0;
+	S32 item_lock = 0;
+	S32 desc_unknown_count = 0;
+	S32 version_unknown_count = 0;
+	for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+	{
+		const LLUUID& cat_id = cit->first;
+		const LLViewerInventoryCategory *cat = cit->second;
+		if (!cat)
+		{
+			LL_WARNS() << "invalid cat" << LL_ENDL;
+			valid = false;
+			continue;
+		}
+		if (cat_id != cat->getUUID())
+		{
+			LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
+			valid = false;
+		}
+
+		if (cat->getParentUUID().isNull())
+		{
+			if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
+			{
+				LL_WARNS() << "cat " << cat_id << " has no parent, but is not root ("
+						<< getRootFolderID() << ") or library root ("
+						<< getLibraryRootFolderID() << ")" << LL_ENDL;
+			}
+		}
+		cat_array_t* cats;
+		item_array_t* items;
+		getDirectDescendentsOf(cat_id,cats,items);
+		if (!cats || !items)
+		{
+			LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL;
+			valid = false;
+			continue;
+		}
+		if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
+		{
+			desc_unknown_count++;
+		}
+		else if (cats->size() + items->size() != cat->getDescendentCount())
+		{
+			LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName()
+					<< "] parent " << cat->getParentUUID()
+					<< " cached " << cat->getDescendentCount()
+					<< " expected " << cats->size() << "+" << items->size()
+					<< "=" << cats->size() +items->size() << LL_ENDL;
+			valid = false;
+		}
+		if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+		{
+			version_unknown_count++;
+		}
+		if (mCategoryLock.count(cat_id))
+		{
+			cat_lock++;
+		}
+		if (mItemLock.count(cat_id))
+		{
+			item_lock++;
+		}
+		for (S32 i = 0; i<items->size(); i++)
+		{
+			LLViewerInventoryItem *item = items->at(i);
+
+			if (!item)
+			{
+				LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
+				valid = false;
+				continue;
+			}
+
+			const LLUUID& item_id = item->getUUID();
+			
+			if (item->getParentUUID() != cat_id)
+			{
+				LL_WARNS() << "wrong parent for " << item_id << " found "
+						<< item->getParentUUID() << " expected " << cat_id
+						<< LL_ENDL;
+				valid = false;
+			}
+
+
+			// Entries in items and mItemMap should correspond.
+			item_map_t::const_iterator it = mItemMap.find(item_id);
+			if (it == mItemMap.end())
+			{
+				LL_WARNS() << "item " << item_id << " found as child of "
+						<< cat_id << " but not in top level mItemMap" << LL_ENDL;
+				valid = false;
+			}
+			else
+			{
+				LLViewerInventoryItem *top_item = it->second;
+				if (top_item != item)
+				{
+					LL_WARNS() << "item mismatch, item_id " << item_id
+							<< " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
+				}
+			}
+
+			// Topmost ancestor should be root or library.
+			LLUUID topmost_ancestor_id;
+			bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+			if (!found)
+			{
+				LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL;
+				valid = false;
+			}
+			else
+			{
+				if (topmost_ancestor_id != getRootFolderID() &&
+					topmost_ancestor_id != getLibraryRootFolderID())
+				{
+					LL_WARNS() << "unrecognized top level ancestor for " << item_id
+							<< " got " << topmost_ancestor_id
+							<< " expected " << getRootFolderID()
+							<< " or " << getLibraryRootFolderID() << LL_ENDL;
+					valid = false;
+				}
+			}
+		}
+
+		// Does this category appear as a child of its supposed parent?
+		const LLUUID& parent_id = cat->getParentUUID();
+		if (!parent_id.isNull())
+		{
+			cat_array_t* cats;
+			item_array_t* items;
+			getDirectDescendentsOf(parent_id,cats,items);
+			if (!cats)
+			{
+				LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+						<< "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
+				valid = false;
+			}
+			else
+			{
+				bool found = false;
+				for (S32 i = 0; i<cats->size(); i++)
+				{
+					LLViewerInventoryCategory *kid_cat = cats->at(i);
+					if (kid_cat == cat)
+					{
+						found = true;
+						break;
+					}
+				}
+				if (!found)
+				{
+					LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+							<< "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+				}
+			}
+		}
+	}
+
+	for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+	{
+		const LLUUID& item_id = iit->first;
+		LLViewerInventoryItem *item = iit->second;
+		if (item->getUUID() != item_id)
+		{
+			LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
+			valid = false;
+		}
+
+		const LLUUID& parent_id = item->getParentUUID();
+		if (parent_id.isNull())
+		{
+			LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+		}
+		else
+		{
+			cat_array_t* cats;
+			item_array_t* items;
+			getDirectDescendentsOf(parent_id,cats,items);
+			if (!items)
+			{
+				LL_WARNS() << "item " << item_id << " name [" << item->getName()
+						<< "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+			}
+			else
+			{
+				bool found = false;
+				for (S32 i=0; i<items->size(); ++i)
+				{
+					if (items->at(i) == item) 
+					{
+						found = true;
+						break;
+					}
+				}
+				if (!found)
+				{
+					LL_WARNS() << "item " << item_id << " name [" << item->getName()
+							<< "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+				}
+			}
+				
+		}
+		// Link checking
+		if (item->getIsLinkType())
+		{
+			const LLUUID& link_id = item->getUUID();
+			const LLUUID& target_id = item->getLinkedUUID();
+			LLViewerInventoryItem *target_item = getItem(target_id);
+			LLViewerInventoryCategory *target_cat = getCategory(target_id);
+			// Linked-to UUID should have back reference to this link.
+			if (!hasBacklinkInfo(link_id, target_id))
+			{
+				LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType()
+						<< " missing backlink info at target_id " << target_id
+						<< LL_ENDL;
+			}
+			// Links should have referents.
+			if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
+			{
+				LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+			}
+			else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
+			{
+				LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+			}
+			if (target_item && target_item->getIsLinkType())
+			{
+				LL_WARNS() << "link " << item->getName() << " references a link item "
+						<< target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
+			}
+
+			// Links should not have backlinks.
+			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
+			if (range.first != range.second)
+			{
+				LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
+			}
+		}
+		else
+		{
+			// Check the backlinks of a non-link item.
+			const LLUUID& target_id = item->getUUID();
+			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
+			for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+			{
+				const LLUUID& link_id = it->second;
+				LLViewerInventoryItem *link_item = getItem(link_id);
+				if (!link_item || !link_item->getIsLinkType())
+				{
+					LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
+				}
+			}
+		}
+	}
+	
+	if (cat_lock > 0 || item_lock > 0)
+	{
+		LL_INFOS() << "Found locks on some categories: sub-cat arrays "
+				<< cat_lock << ", item arrays " << item_lock << LL_ENDL;
+	}
+	if (desc_unknown_count != 0)
+	{
+		LL_INFOS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL; 
+	}
+	if (version_unknown_count != 0)
+	{
+		LL_INFOS() << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;
+	}
+
+	LL_INFOS() << "Validate done, valid = " << (U32) valid << LL_ENDL;
+
+	return valid;
+}
+
 ///----------------------------------------------------------------------------
 /// Local function definitions
 ///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 7dd7ac8e9af67520a4cb77bd347c17b692646fe6..2e957809bee2cdb6b6788b2468924a106ad4f56e 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -33,6 +33,7 @@
 #include "llcurl.h"
 #include "lluuid.h"
 #include "llpermissionsflags.h"
+#include "llviewerinventory.h"
 #include "llstring.h"
 #include "llmd5.h"
 #include <map>
@@ -44,14 +45,9 @@ class LLInventoryObserver;
 class LLInventoryObject;
 class LLInventoryItem;
 class LLInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
 class LLMessageSystem;
 class LLInventoryCollectFunctor;
 
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // LLInventoryModel
 //
@@ -80,11 +76,12 @@ class LLInventoryModel
 
 	class fetchInventoryResponder : public LLCurl::Responder
 	{
+		LOG_CLASS(fetchInventoryResponder);
 	public:
 		fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
-		void result(const LLSD& content);			
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
 	protected:
+		virtual void httpSuccess();
+		virtual void httpFailure();
 		LLSD mRequestSD;
 	};
 
@@ -137,6 +134,8 @@ class LLInventoryModel
 	// during authentication. Returns true if everything parsed.
 	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
 	void buildParentChildMap(); // brute force method to rebuild the entire parent-child relations
+	void createCommonSystemCategories();
+	
 	// Call on logout to save a terse representation.
 	void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
 private:
@@ -155,6 +154,15 @@ class LLInventoryModel
 	parent_cat_map_t mParentChildCategoryTree;
 	parent_item_map_t mParentChildItemTree;
 
+	// Track links to items and categories. We do not store item or
+	// category pointers here, because broken links are also supported.
+	typedef std::multimap<LLUUID, LLUUID> backlink_mmap_t;
+	backlink_mmap_t mBacklinkMMap; // key = target_id: ID of item, values = link_ids: IDs of item or folder links referencing it.
+	// For internal use only
+	bool hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const;
+	void addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
+	void removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
+	
 	//--------------------------------------------------------------------
 	// Login
 	//--------------------------------------------------------------------
@@ -203,6 +211,9 @@ class LLInventoryModel
 		EXCLUDE_TRASH = FALSE, 
 		INCLUDE_TRASH = TRUE 
 	};
+	// Simpler existence test if matches don't actually need to be collected.
+	bool hasMatchingDirectDescendent(const LLUUID& cat_id,
+									 LLInventoryCollectFunctor& filter);
 	void collectDescendents(const LLUUID& id,
 							cat_array_t& categories,
 							item_array_t& items,
@@ -211,22 +222,27 @@ class LLInventoryModel
 							  cat_array_t& categories,
 							  item_array_t& items,
 							  BOOL include_trash,
-							  LLInventoryCollectFunctor& add,
-							  BOOL follow_folder_links = FALSE);
+							  LLInventoryCollectFunctor& add);
 
 	// Collect all items in inventory that are linked to item_id.
 	// Assumes item_id is itself not a linked item.
-	item_array_t collectLinkedItems(const LLUUID& item_id,
-									const LLUUID& start_folder_id = LLUUID::null);
-	
+	item_array_t collectLinksTo(const LLUUID& item_id);
 
 	// Check if one object has a parent chain up to the category specified by UUID.
 	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
 
+	// Follow parent chain to the top.
+	bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+	
 	//--------------------------------------------------------------------
 	// Find
 	//--------------------------------------------------------------------
 public:
+	const LLUUID findCategoryUUIDForTypeInRoot(
+		LLFolderType::EType preferred_type,
+		bool create_folder,
+		const LLUUID& root_id);
+
 	// Returns the uuid of the category that specifies 'type' as what it 
 	// defaults to containing. The category is not necessarily only for that type. 
 	//    NOTE: If create_folder is true, this will create a new inventory category 
@@ -296,7 +312,7 @@ class LLInventoryModel
 	//    NOTE: In usage, you will want to perform cache accounting
 	//    operations in LLInventoryModel::accountForUpdate() or
 	//    LLViewerInventoryItem::updateServer() before calling this method.
-	U32 updateItem(const LLViewerInventoryItem* item);
+	U32 updateItem(const LLViewerInventoryItem* item, U32 mask = 0);
 
 	// Change an existing item with the matching id or add
 	// the category. No notifcation will be sent to observers. This
@@ -305,7 +321,7 @@ class LLInventoryModel
 	//    NOTE: In usage, you will want to perform cache accounting
 	//    operations in accountForUpdate() or LLViewerInventoryCategory::
 	//    updateServer() before calling this method.
-	void updateCategory(const LLViewerInventoryCategory* cat);
+	void updateCategory(const LLViewerInventoryCategory* cat, U32 mask = 0);
 
 	// Move the specified object id to the specified category and
 	// update the internal structures. No cache accounting,
@@ -326,11 +342,31 @@ class LLInventoryModel
 	// Delete
 	//--------------------------------------------------------------------
 public:
+
+	// Update model after an AISv3 update received for any operation.
+	void onAISUpdateReceived(const std::string& context, const LLSD& update);
+		
+	// Update model after an item is confirmed as removed from
+	// server. Works for categories or items.
+	void onObjectDeletedFromServer(const LLUUID& item_id,
+								   bool fix_broken_links = true,
+								   bool update_parent_version = true,
+								   bool do_notify_observers = true);
+
+	// Update model after all descendents removed from server.
+	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, bool update_parent_version);
+
+	// Update model after an existing category gets updated on server.
+	void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates);
+
 	// Delete a particular inventory object by ID. Will purge one
 	// object from the internal data structures, maintaining a
 	// consistent internal state. No cache accounting, observer
 	// notification, or server update is performed.
-	void deleteObject(const LLUUID& id);
+	void deleteObject(const LLUUID& id, bool fix_broken_links = true, bool do_notify_observers = true);
 	/// move Item item_id to Trash
 	void removeItem(const LLUUID& item_id);
 	/// move Category category_id to Trash
@@ -338,17 +374,6 @@ class LLInventoryModel
 	/// removeItem() or removeCategory(), whichever is appropriate
 	void removeObject(const LLUUID& object_id);
 
-	// Delete a particular inventory object by ID, and delete it from
-	// the server. Also updates linked items.
-	void purgeObject(const LLUUID& id);
-
-	// Collects and purges the descendants of the id
-	// provided. If the category is not found, no action is
-	// taken. This method goes through the long winded process of
-	// removing server representation of folders and items while doing
-	// cache accounting in a fairly efficient manner. This method does
-	// not notify observers (though maybe it should...)
-	void purgeDescendentsOf(const LLUUID& id);
 protected:
 	void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id);
 	
@@ -383,8 +408,7 @@ class LLInventoryModel
 	LLUUID createNewCategory(const LLUUID& parent_id,
 							 LLFolderType::EType preferred_type,
 							 const std::string& name,
-							 void (*callback)(const LLSD&, void*) = NULL,
-							 void* user_data = NULL );
+							 boost::optional<inventory_func_type> callback = boost::optional<inventory_func_type>());
 protected:
 	// Internal methods that add inventory and make sure that all of
 	// the internal data structures are consistent. These methods
@@ -461,7 +485,9 @@ class LLInventoryModel
 	// been changed 'under the hood', but outside the control of the
 	// inventory. The next notify will include that notification.
 	void addChangedMask(U32 mask, const LLUUID& referent);
+	
 	const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
+	const changed_items_t& getAddedIDs() const { return mAddedItemIDs; }
 protected:
 	// Updates all linked items pointing to this id.
 	void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
@@ -472,6 +498,8 @@ class LLInventoryModel
 	// Variables used to track what has changed since the last notify.
 	U32 mModifyMask;
 	changed_items_t mChangedItemIDs;
+	changed_items_t mAddedItemIDs;
+	
 	
 	//--------------------------------------------------------------------
 	// Observers
@@ -533,7 +561,7 @@ class LLInventoryModel
 	static void processMoveInventoryItem(LLMessageSystem* msg, void**);
 	static void processFetchInventoryReply(LLMessageSystem* msg, void**);
 protected:
-	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
+	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, U32 mask = 0x0);
 
 	//--------------------------------------------------------------------
 	// Locks
@@ -555,6 +583,7 @@ class LLInventoryModel
 	//--------------------------------------------------------------------
 public:
 	void dumpInventory() const;
+	bool validate() const;
 
 /**                    Miscellaneous
  **                                                                            **
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index a8fda4fcf84f4d1d9adaafb70b24169d0aece078..2de37b0790262d571839ff2b9cd25e1e86cece94 100755
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -1,6 +1,6 @@
 /** 
- * @file llinventorymodel.cpp
- * @brief Implementation of the inventory model used to track agent inventory.
+ * @file llinventorymodelbackgroundfetch.cpp
+ * @brief Implementation of background fetching of inventory.
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -172,8 +172,11 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
 		mRecursiveLibraryFetchStarted)
 	{
 		mAllFoldersFetched = TRUE;
+		//LL_INFOS() << "All folders fetched, validating" << LL_ENDL;
+		//gInventory.validate();
 	}
 	mFolderFetchActive = false;
+	mBackgroundFetchActive = false;
 }
 
 void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
@@ -363,35 +366,40 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)
 
 class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
 {
+	LOG_CLASS(LLInventoryModelFetchItemResponder);
 public:
-	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
-	void result(const LLSD& content);			
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	LLInventoryModelFetchItemResponder(const LLSD& request_sd) :
+		LLInventoryModel::fetchInventoryResponder(request_sd)
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
+	}
+private:
+	/* virtual */ void httpCompleted()
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+		LLInventoryModel::fetchInventoryResponder::httpCompleted();
+	}
 };
 
-void LLInventoryModelFetchItemResponder::result( const LLSD& content )
-{
-	LLInventoryModel::fetchInventoryResponder::result(content);
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
-void LLInventoryModelFetchItemResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content )
-{
-	LLInventoryModel::fetchInventoryResponder::errorWithContent(status, reason, content);
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
-
 class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLInventoryModelFetchDescendentsResponder);
 public:
 	LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : 
 		mRequestSD(request_sd),
 		mRecursiveCatUUIDs(recursive_cats)
-	{};
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
+	}
 	//LLInventoryModelFetchDescendentsResponder() {};
-	void result(const LLSD& content);
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+private:
+	/* virtual */ void httpCompleted()
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+		LLHTTPClient::Responder::httpCompleted();
+	}
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 protected:
 	BOOL getIsRecursive(const LLUUID& cat_id) const;
 private:
@@ -400,8 +408,14 @@ class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 };
 
 // If we get back a normal response, handle it here.
-void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
+void LLInventoryModelFetchDescendentsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 	if (content.has("folders"))	
 	{
@@ -508,16 +522,15 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 		for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
 			folder_it != content["bad_folders"].endArray();
 			++folder_it)
-		{	
+		{
+			// *TODO: Stop copying data
 			LLSD folder_sd = *folder_it;
 			
 			// These folders failed on the dataserver.  We probably don't want to retry them.
-			LL_INFOS() << "Folder " << folder_sd["folder_id"].asString() 
-					<< "Error: " << folder_sd["error"].asString() << LL_ENDL;
+			LL_WARNS() << "Folder " << folder_sd["folder_id"].asString() 
+					   << "Error: " << folder_sd["error"].asString() << LL_ENDL;
 		}
 	}
-
-	fetcher->incrFetchCount(-1);
 	
 	if (fetcher->isBulkFetchProcessingComplete())
 	{
@@ -529,21 +542,21 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 }
 
 // If we get back an error (not found, etc...), handle it here.
-void LLInventoryModelFetchDescendentsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLInventoryModelFetchDescendentsResponder::httpFailure()
 {
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 
-	LL_INFOS() << "LLInventoryModelFetchDescendentsResponder::error [status:"
-			<< status << "]: " << content << LL_ENDL;
+	LL_INFOS() << dumpResponse() << LL_ENDL;
 						
 	fetcher->incrFetchCount(-1);
 
-	if (status==499) // timed out
+	if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure
 	{
 		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
 			folder_it != mRequestSD["folders"].endArray();
 			++folder_it)
-		{	
+		{
 			LLSD folder_sd = *folder_it;
 			LLUUID folder_id = folder_sd["folder_id"];
 			const BOOL recursive = getIsRecursive(folder_id);
@@ -586,7 +599,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
 	{
 		return; // just bail if we are disconnected
-	}	
+	}
 
 	U32 item_count=0;
 	U32 folder_count=0;
@@ -686,63 +699,46 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 	{
 		if (folder_count)
 		{
-			std::string url = region->getCapability("FetchInventoryDescendents2");   
+			std::string url = region->getCapability("FetchInventoryDescendents2");   			
 			if ( !url.empty() )
 			{
-			mFetchCount++;
-			if (folder_request_body["folders"].size())
-			{
-				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
-				LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
-			}
-			if (folder_request_body_lib["folders"].size())
-			{
-				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
+				if (folder_request_body["folders"].size())
+				{
+					LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
+					LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
+				}
+				if (folder_request_body_lib["folders"].size())
+				{
+					std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
 
-				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
-				LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
+					LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
+					LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
+				}
 			}
 		}
-		}
 		if (item_count)
 		{
 			std::string url;
 
 			if (item_request_body.size())
 			{
-				mFetchCount++;
 				url = region->getCapability("FetchInventory2");
 				if (!url.empty())
 				{
 					LLSD body;
-					body["agent_id"]	= gAgent.getID();
 					body["items"] = item_request_body;
 
 					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
 				}
-				//else
-				//{
-				//	LLMessageSystem* msg = gMessageSystem;
-				//	msg->newMessage("FetchInventory");
-				//	msg->nextBlock("AgentData");
-				//	msg->addUUID("AgentID", gAgent.getID());
-				//	msg->addUUID("SessionID", gAgent.getSessionID());
-				//	msg->nextBlock("InventoryData");
-				//	msg->addUUID("OwnerID", mPermissions.getOwner());
-				//	msg->addUUID("ItemID", mUUID);
-				//	gAgent.sendReliableMessage();
-				//}
 			}
 
 			if (item_request_body_lib.size())
 			{
-				mFetchCount++;
 
 				url = region->getCapability("FetchLib2");
 				if (!url.empty())
 				{
 					LLSD body;
-					body["agent_id"]	= gAgent.getID();
 					body["items"] = item_request_body_lib;
 
 					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 2cbf9bb8b62b91f479c41724580f7e155993e123..2dd8dce42f24da22a592e6ebb78c80df616b3fd4 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -465,41 +465,13 @@ void LLInventoryFetchComboObserver::startFetch()
 	mFetchDescendents->startFetch();
 }
 
-void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
-{
-	if (id.notNull())
-	{
-		mMIA.push_back(id);
-	}
-}
-
-void LLInventoryExistenceObserver::changed(U32 mask)
-{
-	// scan through the incomplete items and move or erase them as
-	// appropriate.
-	if (!mMIA.empty())
-	{
-		for (uuid_vec_t::iterator it = mMIA.begin(); it < mMIA.end(); )
-		{
-			LLViewerInventoryItem* item = gInventory.getItem(*it);
-			if (!item)
-			{
-				++it;
-				continue;
-			}
-			mExist.push_back(*it);
-			it = mMIA.erase(it);
-		}
-		if (mMIA.empty())
-		{
-			done();
-		}
-	}
-}
-
+// See comment preceding LLInventoryAddedObserver::changed() for some
+// concerns that also apply to this observer.
 void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 {
-	if(!(mask & LLInventoryObserver::ADD))
+	if(!(mask & LLInventoryObserver::ADD) ||
+	   !(mask & LLInventoryObserver::CREATE) ||
+	   !(mask & LLInventoryObserver::UPDATE_CREATE))
 	{
 		return;
 	}
@@ -510,20 +482,12 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 		return;
 	}
 
-	LLMessageSystem* msg = gMessageSystem;
-	if (!(msg->getMessageName() && (0 == strcmp(msg->getMessageName(), "UpdateCreateInventoryItem"))))
+	const uuid_set_t& added = gInventory.getAddedIDs();
+	for (uuid_set_t::iterator it = added.begin(); it != added.end(); ++it)
 	{
-		// this is not our message
-		return; // to prevent a crash. EXT-7921;
-	}
-
-	LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
-	S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
-	for(S32 i = 0; i < num_blocks; ++i)
-	{
-		item->unpackMessage(msg, _PREHASH_InventoryData, i);
+		LLInventoryItem *item = gInventory.getItem(*it);
 		const LLUUID& asset_uuid = item->getAssetUUID();
-		if (item->getUUID().notNull() && asset_uuid.notNull())
+		if (item && item->getUUID().notNull() && asset_uuid.notNull())
 		{
 			if (isAssetWatched(asset_uuid))
 			{
@@ -532,11 +496,11 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 			}
 		}
 	}
-
+	
 	if (mAddedItems.size() == mWatchedAssets.size())
 	{
-		done();
 		LL_DEBUGS("Inventory_Move") << "All watched items are added & processed." << LL_ENDL;
+		done();
 		mAddedItems.clear();
 
 		// Unable to clean watched items here due to somebody can require to check them in current frame.
@@ -566,41 +530,28 @@ bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id )
 	return std::find(mWatchedAssets.begin(), mWatchedAssets.end(), asset_id) != mWatchedAssets.end();
 }
 
+// This observer used to explicitly check for whether it was being
+// called as a result of an UpdateCreateInventoryItem message. It has
+// now been decoupled enough that it's not actually checking the
+// message system, but now we have the special UPDATE_CREATE flag
+// being used for the same purpose. Fixing this, as we would need to
+// do to get rid of the message, is somewhat subtle because there's no
+// particular obvious criterion for when creating a new item should
+// trigger this observer and when it shouldn't. For example, creating
+// a new notecard with new->notecard causes a preview window to pop up
+// via the derived class LLOpenTaskOffer, but creating a new notecard
+// by copy and paste does not, solely because one goes through
+// UpdateCreateInventoryItem and the other doesn't.
 void LLInventoryAddedObserver::changed(U32 mask)
 {
-	if (!(mask & LLInventoryObserver::ADD))
+	if (!(mask & LLInventoryObserver::ADD) ||
+		!(mask & LLInventoryObserver::CREATE) ||
+		!(mask & LLInventoryObserver::UPDATE_CREATE))
 	{
 		return;
 	}
 
-	// *HACK: If this was in response to a packet off
-	// the network, figure out which item was updated.
-	LLMessageSystem* msg = gMessageSystem;
-
-	std::string msg_name = msg->getMessageName();
-	if (msg_name.empty())
-	{
-		return;
-	}
-	
-	// We only want newly created inventory items. JC
-	if ( msg_name != "UpdateCreateInventoryItem")
-	{
-		return;
-	}
-
-	LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
-	S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
-	for (S32 i = 0; i < num_blocks; ++i)
-	{
-		titem->unpackMessage(msg, _PREHASH_InventoryData, i);
-		if (!(titem->getUUID().isNull()))
-		{
-			//we don't do anything with null keys
-			mAdded.push_back(titem->getUUID());
-		}
-	}
-	if (!mAdded.empty())
+	if (!gInventory.getAddedIDs().empty())
 	{
 		done();
 	}
@@ -613,9 +564,9 @@ void LLInventoryCategoryAddedObserver::changed(U32 mask)
 		return;
 	}
 	
-	const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs();
+	const LLInventoryModel::changed_items_t& added_ids = gInventory.getAddedIDs();
 	
-	for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit)
+	for (LLInventoryModel::changed_items_t::const_iterator cit = added_ids.begin(); cit != added_ids.end(); ++cit)
 	{
 		LLViewerInventoryCategory* cat = gInventory.getCategory(*cit);
 		
@@ -633,58 +584,6 @@ void LLInventoryCategoryAddedObserver::changed(U32 mask)
 	}
 }
 
-
-LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
-	mTransactionID(transaction_id)
-{
-}
-
-void LLInventoryTransactionObserver::changed(U32 mask)
-{
-	if (mask & LLInventoryObserver::ADD)
-	{
-		// This could be it - see if we are processing a bulk update
-		LLMessageSystem* msg = gMessageSystem;
-		if (msg->getMessageName()
-		   && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
-		{
-			// we have a match for the message - now check the
-			// transaction id.
-			LLUUID id;
-			msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
-			if (id == mTransactionID)
-			{
-				// woo hoo, we found it
-				uuid_vec_t folders;
-				uuid_vec_t items;
-				S32 count;
-				count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
-				S32 i;
-				for (i = 0; i < count; ++i)
-				{
-					msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
-					if (id.notNull())
-					{
-						folders.push_back(id);
-					}
-				}
-				count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
-				for (i = 0; i < count; ++i)
-				{
-					msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
-					if (id.notNull())
-					{
-						items.push_back(id);
-					}
-				}
-
-				// call the derived class the implements this method.
-				done(folders, items);
-			}
-		}
-	}
-}
-
 void LLInventoryCategoriesObserver::changed(U32 mask)
 {
 	if (!mCategoryMap.size())
@@ -702,7 +601,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
 		LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
 		if (!category)
         {
-            llwarns << "Category : Category id = " << cat_id << " disappeared" << llendl;
+            LL_WARNS() << "Category : Category id = " << cat_id << " disappeared" << LL_ENDL;
 			cat_data.mCallback();
             // Keep track of those deleted categories so we can remove them
             deleted_categories_ids.push_back(cat_id);
@@ -833,3 +732,23 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
 {
 	mItemNameHash.finalize();
 }
+
+void LLScrollOnRenameObserver::changed(U32 mask)
+{
+	if (mask & LLInventoryObserver::LABEL)
+	{
+		const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
+		for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
+		{
+			const LLUUID& id = *it;
+			if (id == mUUID)
+			{
+				mView->scrollToShowSelection();
+					
+				gInventory.removeObserver(this);
+				delete this;
+				return;
+			}
+		}
+	}
+}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index aa1eae84d707cf32c1589b13799fc0fa19960f02..8cf6a6bdab8f821815d831f3c0c6ae9a9729974c 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -58,6 +58,9 @@ class LLInventoryObserver
 		GESTURE 		= 64,
 		REBUILD 		= 128, 	// Item UI changed (e.g. item type different)
 		SORT 			= 256, 	// Folder needs to be resorted.
+		CREATE			= 512,  // With ADD, item has just been created.
+		// unfortunately a particular message is still associated with some unique semantics.
+		UPDATE_CREATE	= 1024,  // With ADD, item added via UpdateCreateInventoryItem
 		ALL 			= 0xffffffff
 	};
 	LLInventoryObserver();
@@ -151,25 +154,6 @@ class LLInventoryFetchComboObserver : public LLInventoryObserver
 	LLInventoryFetchDescendentsObserver *mFetchDescendents;
 };
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryExistenceObserver
-//
-//   Used as a base class for doing something when all the
-//   observed item ids exist in the inventory somewhere.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryExistenceObserver : public LLInventoryObserver
-{
-public:
-	LLInventoryExistenceObserver() {}
-	/*virtual*/ void changed(U32 mask);
-
-	void watchItem(const LLUUID& id);
-protected:
-	virtual void done() = 0;
-	uuid_vec_t mExist;
-	uuid_vec_t mMIA;
-};
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryMovedObserver
 //
@@ -209,13 +193,11 @@ class LLInventoryAddItemByAssetObserver : public LLInventoryObserver
 class LLInventoryAddedObserver : public LLInventoryObserver
 {
 public:
-	LLInventoryAddedObserver() : mAdded() {}
+	LLInventoryAddedObserver() {}
 	/*virtual*/ void changed(U32 mask);
 
 protected:
 	virtual void done() = 0;
-
-	uuid_vec_t mAdded;
 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -240,25 +222,6 @@ class LLInventoryCategoryAddedObserver : public LLInventoryObserver
 	cat_vec_t	mAddedCategories;
 };
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryTransactionObserver
-//
-//   Base class for doing something when an inventory transaction completes.
-//   NOTE: This class is not quite complete. Avoid using unless you fix up its
-//   functionality gaps.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryTransactionObserver : public LLInventoryObserver
-{
-public:
-	LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
-	/*virtual*/ void changed(U32 mask);
-
-protected:
-	virtual void done(const uuid_vec_t& folders, const uuid_vec_t& items) = 0;
-
-	LLTransactionID mTransactionID;
-};
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryCompletionObserver
 //
@@ -326,4 +289,22 @@ class LLInventoryCategoriesObserver : public LLInventoryObserver
 	category_map_t				mCategoryMap;
 };
 
+class LLFolderView;
+
+// Force a FolderView to scroll after an item in the corresponding view has been renamed.
+class LLScrollOnRenameObserver: public LLInventoryObserver
+{
+public:
+	LLFolderView *mView;
+	LLUUID mUUID;
+	
+	LLScrollOnRenameObserver(const LLUUID& uuid, LLFolderView *view):
+		mUUID(uuid),
+		mView(view)
+	{
+	}
+	/* virtual */ void changed(U32 mask);
+};
+
+
 #endif // LL_LLINVENTORYOBSERVERS_H
diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp
index a624c9fb879506f218fb839225d1a00cb8748df0..6bda8b1d0d90a556ff30e3c1160a3c3688e5a4f8 100755
--- a/indra/newview/lllistcontextmenu.cpp
+++ b/indra/newview/lllistcontextmenu.cpp
@@ -110,6 +110,7 @@ void LLListContextMenu::handleMultiple(functor_t functor, const uuid_vec_t& ids)
 // static
 LLContextMenu* LLListContextMenu::createFromFile(const std::string& filename)
 {
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		filename, LLContextMenu::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 }
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 194847553021b561e811369af0ecb8eb3afe32bd..8e4950f5c2491216f36b6514b8876a14d98ccc24 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -541,7 +541,7 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp
 					{
 						U32 index = gAgentWearables.getWearableIndex(wearable);
 						gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
-						gAgentAvatarp->wearableUpdated(type, FALSE);
+						gAgentAvatarp->wearableUpdated(type);
 
 						/* telling the manager to rebake once update cycle is fully done */
 						LLLocalBitmapMgr::setNeedsRebake();
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index af194aaa1d3eb07a43cea58e6e8d21626c5de59e..8d21fda8f918ea694b0046aa890cc8039873223e 100755
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -107,8 +107,8 @@ class LLAddLandmarkObserver : public LLInventoryAddedObserver
 private:
 	/*virtual*/ void done()
 	{
-		uuid_vec_t::const_iterator it = mAdded.begin(), end = mAdded.end();
-		for(; it != end; ++it)
+		const uuid_set_t& added = gInventory.getAddedIDs();
+		for (uuid_set_t::const_iterator it = added.begin(); it != added.end(); ++it)
 		{
 			LLInventoryItem* item = gInventory.getItem(*it);
 			if (!item || item->getType() != LLAssetType::AT_LANDMARK)
@@ -124,8 +124,6 @@ class LLAddLandmarkObserver : public LLInventoryAddedObserver
 				mInput->onLandmarkLoaded(lm);
 			}
 		}
-
-		mAdded.clear();
 	}
 
 	LLLocationInputCtrl* mInput;
@@ -142,7 +140,11 @@ class LLRemoveLandmarkObserver : public LLInventoryObserver
 private:
 	/*virtual*/ void changed(U32 mask)
 	{
-		if (mask & (~(LLInventoryObserver::LABEL|LLInventoryObserver::INTERNAL|LLInventoryObserver::ADD)))
+		if (mask & (~(LLInventoryObserver::LABEL|
+					  LLInventoryObserver::INTERNAL|
+					  LLInventoryObserver::ADD|
+					  LLInventoryObserver::CREATE|
+					  LLInventoryObserver::UPDATE_CREATE)))
 		{
 			mInput->updateAddLandmarkButton();
 		}
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 7907e700c410176f40e12f5c03773d4de9b87c99..4a7a4e268d33cccff9d744e7c901cf2350b0339e 100755
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -100,7 +100,7 @@ namespace LLMarketplaceImport
 	bool hasSessionCookie();
 	bool inProgress();
 	bool resultPending();
-	U32 getResultStatus();
+	S32 getResultStatus();
 	const LLSD& getResults();
 
 	bool establishMarketplaceSessionCookie();
@@ -114,7 +114,7 @@ namespace LLMarketplaceImport
 	static bool sImportInProgress = false;
 	static bool sImportPostPending = false;
 	static bool sImportGetPending = false;
-	static U32 sImportResultStatus = 0;
+	static S32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
 
 	static LLTimer slmGetTimer;
@@ -124,23 +124,26 @@ namespace LLMarketplaceImport
 	
 	class LLImportPostResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLImportPostResponder);
 	public:
 		LLImportPostResponder() : LLCurl::Responder() {}
-		
-		void completed(U32 status, const std::string& reason, const LLSD& content)
+
+	protected:
+		/* virtual */ void httpCompleted()
 		{
 			slmPostTimer.stop();
 
 			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 			{
-				LL_INFOS() << " SLM POST status: " << status << LL_ENDL;
-				LL_INFOS() << " SLM POST reason: " << reason << LL_ENDL;
-				LL_INFOS() << " SLM POST content: " << content.asString() << LL_ENDL;
-				LL_INFOS() << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << LL_ENDL;
+				LL_INFOS() << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] "
+						   << dumpResponse() << LL_ENDL;
 			}
 
-			// MAINT-2301 : we determined we can safely ignore that error in that context
-			if (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)
+			S32 status = getStatus();
+			if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
+				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
+				// MAINT-2301 : we determined we can safely ignore that error in that context
+				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
 			{
 				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 				{
@@ -161,39 +164,37 @@ namespace LLMarketplaceImport
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
 			sImportPostPending = false;
 			sImportResultStatus = status;
-			sImportId = content;
+			sImportId = getContent();
 		}
 	};
 	
 	class LLImportGetResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLImportGetResponder);
 	public:
 		LLImportGetResponder() : LLCurl::Responder() {}
 		
-		void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	protected:
+		/* virtual */ void httpCompleted()
 		{
-			const std::string& set_cookie_string = content["set-cookie"].asString();
+			const std::string& set_cookie_string = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
 			
 			if (!set_cookie_string.empty())
 			{
 				sMarketplaceCookie = set_cookie_string;
 			}
-		}
-		
-		void completed(U32 status, const std::string& reason, const LLSD& content)
-		{
+
 			slmGetTimer.stop();
 
 			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 			{
-				LL_INFOS() << " SLM GET status: " << status << LL_ENDL;
-				LL_INFOS() << " SLM GET reason: " << reason << LL_ENDL;
-				LL_INFOS() << " SLM GET content: " << content.asString() << LL_ENDL;
-				LL_INFOS() << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << LL_ENDL;
+				LL_INFOS() << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] "
+						   << dumpResponse() << LL_ENDL;
 			}
 			
             // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions
             // ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initally empty
+			S32 status = getStatus();
 			if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) &&
                 (status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) &&
                 (status != MarketplaceErrorCodes::IMPORT_NOT_FOUND))
@@ -212,7 +213,7 @@ namespace LLMarketplaceImport
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
 			sImportGetPending = false;
 			sImportResultStatus = status;
-			sImportResults = content;
+			sImportResults = getContent();
 		}
 	};
 
@@ -233,7 +234,7 @@ namespace LLMarketplaceImport
 		return (sImportPostPending || sImportGetPending);
 	}
 	
-	U32 getResultStatus()
+	S32 getResultStatus()
 	{
 		return sImportResultStatus;
 	}
@@ -297,10 +298,11 @@ namespace LLMarketplaceImport
 
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Cookie"] = sMarketplaceCookie;
-		headers["Content-Type"] = "application/llsd+xml";
-		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
+		// *TODO: Why are we setting Content-Type for a GET request?
+		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
@@ -334,11 +336,11 @@ namespace LLMarketplaceImport
 		
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Connection"] = "Keep-Alive";
-		headers["Cookie"] = sMarketplaceCookie;
-		headers["Content-Type"] = "application/xml";
-		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_CONNECTION] = "Keep-Alive";
+		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
+		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
old mode 100644
new mode 100755
index df6a42db4d84ad032ea1e4b2fa8a444b1452ba84..a1f6a01aa0d279934c071d8a2059b31639b4c4aa
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -71,8 +71,8 @@ class LLMaterialsResponder : public LLHTTPClient::Responder
 	LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
 	virtual ~LLMaterialsResponder();
 
-	virtual void result(const LLSD& pContent);
-	virtual void error(U32 pStatus, const std::string& pReason);
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
 	std::string      mMethod;
@@ -92,14 +92,19 @@ LLMaterialsResponder::~LLMaterialsResponder()
 {
 }
 
-void LLMaterialsResponder::result(const LLSD& pContent)
+void LLMaterialsResponder::httpSuccess()
 {
+	const LLSD& pContent = getContent();
+
 	LL_DEBUGS("Materials") << LL_ENDL;
 	mCallback(true, pContent);
 }
 
-void LLMaterialsResponder::error(U32 pStatus, const std::string& pReason)
+void LLMaterialsResponder::httpFailure()
 {
+	U32 pStatus = (U32) getStatus();
+	const std::string& pReason = getReason();
+	
 	LL_WARNS("Materials")
 		<< "\n--------------------------------------------------------------------------\n"
 		<< mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 53351ccca74e3aeac18646da42cd058abeb4a38c..086bc1c1860348ce04c26b6933ef4974ab8bd596 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -52,6 +52,7 @@
 #include "llsdutil.h"
 #include "lllayoutstack.h"
 #include "lliconctrl.h"
+#include "llhttpconstants.h"
 #include "lltextbox.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
@@ -390,8 +391,12 @@ BOOL LLMediaCtrl::postBuild ()
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
 	registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
 
+	// stinson 05/05/2014 : use this as the parent of the context menu if the static menu
+	// container has yet to be created
+	LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this);
+	llassert(menuParent != NULL);
 	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
-		"menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+		"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
 	setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
 
 	return TRUE;
@@ -576,7 +581,7 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str
 	{
 		mCurrentNavUrl = expanded_filename;
 		mMediaSource->setSize(mTextureWidth, mTextureHeight);
-		mMediaSource->navigateTo(expanded_filename, "text/html", false);
+		mMediaSource->navigateTo(expanded_filename, HTTP_CONTENT_TEXT_HTML, false);
 	}
 }
 
@@ -948,7 +953,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
 			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
 			if ( mErrorPageURL.length() > 0 )
 			{
-				navigateTo(mErrorPageURL, "text/html");
+				navigateTo(mErrorPageURL, HTTP_CONTENT_TEXT_HTML);
 			};
 		};
 		break;
@@ -1117,3 +1122,8 @@ void LLMediaCtrl::setTrustedContent(bool trusted)
 		mMediaSource->setTrustedBrowser(trusted);
 	}
 }
+
+void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
+{
+	mContextMenu->updateParent(pNewParent);
+}
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 11ba615cb8e6017c3aa6878f855f5976d6bd18c9..b6ed0f3fabd09367e27497dd0ba5c0c3558e81d8 100755
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -168,6 +168,8 @@ class LLMediaCtrl :
 
 		LLUUID getTextureID() {return mMediaTextureID;}
 
+		void updateContextMenuParent(LLView* pNewParent);
+
 	protected:
 		void convertInputCoords(S32& x, S32& y);
 
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index e3b46d5d2f3fd7727d844cf69d51e1c3e94b330f..691be13610e4b5e7908a53d71546631ab0968159 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -35,7 +35,7 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llsdutil.h"
 #include "llmediaentry.h"
 #include "lltextureentry.h"
@@ -564,7 +564,7 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
 }
 
 /*virtual*/
-void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLMediaDataClient::Responder::httpFailure()
 {
 	mRequest->stopTracking();
 
@@ -574,9 +574,17 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin
 		return;
 	}
 	
-	if (status == HTTP_SERVICE_UNAVAILABLE)
+	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
 	{
-		F32 retry_timeout = mRequest->getRetryTimerDelay();
+		F32 retry_timeout;
+#if 0
+		// *TODO: Honor server Retry-After header.
+		if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER)
+			|| !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout))
+#endif
+		{
+			retry_timeout = mRequest->getRetryTimerDelay();
+		}
 		
 		mRequest->incRetryCount();
 		
@@ -594,15 +602,16 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin
 				<< mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
 		}
 	}
+	// *TODO: Redirect on 3xx status codes.
 	else 
 	{
-		LL_WARNS("LLMediaDataClient") << *mRequest << " http error [status:" 
-				<< status << "]:" << content << ")" << LL_ENDL;
+		LL_WARNS("LLMediaDataClient") << *mRequest << " http failure "
+				<< dumpResponse() << LL_ENDL;
 	}
 }
 
 /*virtual*/
-void LLMediaDataClient::Responder::result(const LLSD& content)
+void LLMediaDataClient::Responder::httpSuccess()
 {
 	mRequest->stopTracking();
 
@@ -612,7 +621,7 @@ void LLMediaDataClient::Responder::result(const LLSD& content)
 		return;
 	}
 
-	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
+	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -876,7 +885,7 @@ LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResp
 
 
 /*virtual*/
-void LLObjectMediaDataClient::Responder::result(const LLSD& content)
+void LLObjectMediaDataClient::Responder::httpSuccess()
 {
 	getRequest()->stopTracking();
 
@@ -886,10 +895,16 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 		return;
 	}
 
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 	// This responder is only used for GET requests, not UPDATE.
+	LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
 
-	LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
-	
 	// Look for an error
 	if (content.has("error"))
 	{
@@ -1003,7 +1018,7 @@ LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::crea
 }
 
 /*virtual*/
-void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLObjectMediaNavigateClient::Responder::httpFailure()
 {
 	getRequest()->stopTracking();
 
@@ -1015,14 +1030,14 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const
 
 	// Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base
 	// class
-	if (status == HTTP_SERVICE_UNAVAILABLE)
+	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
 	{
-		LLMediaDataClient::Responder::errorWithContent(status, reason, content);
+		LLMediaDataClient::Responder::httpFailure();
 	}
 	else
 	{
 		// bounce the face back
-		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL;
+		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL;
 		const LLSD &payload = getRequest()->getPayload();
 		// bounce the face back
 		getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
@@ -1030,7 +1045,7 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const
 }
 
 /*virtual*/
-void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
+void LLObjectMediaNavigateClient::Responder::httpSuccess()
 {
 	getRequest()->stopTracking();
 
@@ -1040,8 +1055,9 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 		return;
 	}
 
-	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL;
+	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL;
 	
+	const LLSD& content = getContent();
 	if (content.has("error"))
 	{
 		const LLSD &error = content["error"];
@@ -1065,6 +1081,6 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 	else 
 	{
 		// No action required.
-		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " result : " << ll_print_sd(content) << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
 	}
 }
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 89e20a28d097e95c732b206fb509a9ec7498ea61..231b883c32c6f9d157839a2911622a2604eda2a2 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -74,8 +74,9 @@ class LLMediaDataClientObject : public LLRefCount
 // Abstracts the Cap URL, the request, and the responder
 class LLMediaDataClient : public LLRefCount
 {
-public:
+protected:
     LOG_CLASS(LLMediaDataClient);
+public:
     
     const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
 	const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
@@ -192,14 +193,16 @@ class LLMediaDataClient : public LLRefCount
 	// Responder
 	class Responder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(Responder);
 	public:
 		Responder(const request_ptr_t &request);
+		request_ptr_t &getRequest() { return mRequest; }
+
+	protected:
 		//If we get back an error (not found, etc...), handle it here
-		virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+		virtual void httpFailure();
 		//If we get back a normal response, handle it here.	 Default just logs it.
-		virtual void result(const LLSD& content);
-
-		request_ptr_t &getRequest() { return mRequest; }
+		virtual void httpSuccess();
 
 	private:
 		request_ptr_t mRequest;
@@ -287,8 +290,9 @@ class LLMediaDataClient : public LLRefCount
 // MediaDataClient specific for the ObjectMedia cap
 class LLObjectMediaDataClient : public LLMediaDataClient
 {
-public:
+protected:
     LOG_CLASS(LLObjectMediaDataClient);
+public:
     LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
 							F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
 							U32 max_retries = MAX_RETRIES,
@@ -341,10 +345,12 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 		    
     class Responder : public LLMediaDataClient::Responder
     {
+        LOG_CLASS(Responder);
     public:
         Responder(const request_ptr_t &request)
             : LLMediaDataClient::Responder(request) {}
-        virtual void result(const LLSD &content);
+    protected:
+        virtual void httpSuccess();
     };
 private:
 	// The Get/Update data client needs a second queue to avoid object updates starving load-ins.
@@ -362,8 +368,9 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 // MediaDataClient specific for the ObjectMediaNavigate cap
 class LLObjectMediaNavigateClient : public LLMediaDataClient
 {
-public:
+protected:
     LOG_CLASS(LLObjectMediaNavigateClient);
+public:
 	// NOTE: from llmediaservice.h
 	static const int ERROR_PERMISSION_DENIED_CODE = 8002;
 	
@@ -397,11 +404,13 @@ class LLObjectMediaNavigateClient : public LLMediaDataClient
 
     class Responder : public LLMediaDataClient::Responder
     {
+        LOG_CLASS(Responder);
     public:
         Responder(const request_ptr_t &request)
             : LLMediaDataClient::Responder(request) {}
-		virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-        virtual void result(const LLSD &content);
+    protected:
+        virtual void httpFailure();
+        virtual void httpSuccess();
     private:
         void mediaNavigateBounceBack();
     };
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 08d2d03b9bdeae1ae9e1d467bb225e68a2ef8ae2..80a427c0b817d13cb2fe4202744e44763ea685b3 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -27,8 +27,10 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "llhttpconstants.h"
 #include "llapr.h"
-#include "llhttpstatuscodes.h"
 #include "llmeshrepository.h"
 
 #include "llagent.h"
@@ -515,6 +517,7 @@ S32 LLMeshRepoThread::sRequestWaterLevel = 0;
 class LLMeshHandlerBase : public LLCore::HttpHandler
 {
 public:
+	LOG_CLASS(LLMeshHandlerBase);
 	LLMeshHandlerBase()
 		: LLCore::HttpHandler(),
 		  mMeshParams(),
@@ -547,6 +550,7 @@ class LLMeshHandlerBase : public LLCore::HttpHandler
 class LLMeshHeaderHandler : public LLMeshHandlerBase
 {
 public:
+	LOG_CLASS(LLMeshHeaderHandler);
 	LLMeshHeaderHandler(const LLVolumeParams & mesh_params)
 		: LLMeshHandlerBase()
 	{
@@ -603,6 +607,7 @@ class LLMeshLODHandler : public LLMeshHandlerBase
 class LLMeshSkinInfoHandler : public LLMeshHandlerBase
 	{
 public:
+	LOG_CLASS(LLMeshSkinInfoHandler);
 	LLMeshSkinInfoHandler(const LLUUID& id, U32 offset, U32 size)
 		: LLMeshHandlerBase(),
 		  mMeshID(id),
@@ -632,6 +637,7 @@ class LLMeshSkinInfoHandler : public LLMeshHandlerBase
 class LLMeshDecompositionHandler : public LLMeshHandlerBase
 	{
 public:
+	LOG_CLASS(LLMeshDecompositionHandler);
 	LLMeshDecompositionHandler(const LLUUID& id, U32 offset, U32 size)
 		: LLMeshHandlerBase(),
 		  mMeshID(id),
@@ -661,6 +667,7 @@ class LLMeshDecompositionHandler : public LLMeshHandlerBase
 class LLMeshPhysicsShapeHandler : public LLMeshHandlerBase
 	{
 public:
+	LOG_CLASS(LLMeshPhysicsShapeHandler);
 	LLMeshPhysicsShapeHandler(const LLUUID& id, U32 offset, U32 size)
 		: LLMeshHandlerBase(),
 		  mMeshID(id),
@@ -736,7 +743,6 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
 	}
 }
 
-
 LLMeshRepoThread::LLMeshRepoThread()
 : LLThread("mesh repo"),
   mHttpRequest(NULL),
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 62966e3a4ec1159168fdf40ff83ed9217179c77f..3cd39d7c7e34463a15f563dba9f67f314d994ade 100755
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -96,15 +96,11 @@ class LLClassifiedClickMessageResponder : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLClassifiedClickMessageResponder);
 
-public:
+protected:
 	// If we get back an error (not found, etc...), handle it here
-	virtual void errorWithContent(
-		U32 status,
-		const std::string& reason,
-		const LLSD& content)
+	virtual void httpFailure()
 	{
-		LL_WARNS() << "Sending click message failed (" << status << "): [" << reason << "]" << LL_ENDL;
-		LL_WARNS() << "Content: [" << content << "]" << LL_ENDL;
+		LL_WARNS() << "Sending click message failed " << dumpResponse() << LL_ENDL;
 	}
 };
 
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index daa7df682b699a9c58eb447aed6e542ccd5fdfa3..ac00c5d986e28640ec24134acebdd049231c7889 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -944,11 +944,11 @@ void LLPanelEditWearable::onCommitSexChange()
         LLViewerWearable*     wearable = gAgentWearables.getViewerWearable(type, index);
         if (wearable)
         {
-                wearable->setVisualParamWeight(param->getID(), is_new_sex_male, FALSE);
+                wearable->setVisualParamWeight(param->getID(), is_new_sex_male);
         }
-        param->setWeight( is_new_sex_male, FALSE );
+        param->setWeight( is_new_sex_male);
 
-        gAgentAvatarp->updateSexDependentLayerSets( FALSE );
+        gAgentAvatarp->updateSexDependentLayerSets();
 
         gAgentAvatarp->updateVisualParams();
 
@@ -983,7 +983,7 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
                                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                                 gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
                                 LLVisualParamHint::requestHintUpdates();
-                                gAgentAvatarp->wearableUpdated(type, FALSE);
+                                gAgentAvatarp->wearableUpdated(type);
                         }
                 }
                 else
@@ -1007,9 +1007,9 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
                         const LLColor4& new_color = LLColor4(ctrl->getValue());
                         if( old_color != new_color )
                         {
-                                getWearable()->setClothesColor(entry->mTextureIndex, new_color, TRUE);
+                                getWearable()->setClothesColor(entry->mTextureIndex, new_color);
                                 LLVisualParamHint::requestHintUpdates();
-                                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                                gAgentAvatarp->wearableUpdated(getWearable()->getType());
                         }
                 }
                 else
@@ -1080,10 +1080,10 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 
         if (force_save_as)
         {
-                // the name of the wearable has changed, re-save wearable with new name
-                LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID());
+			// the name of the wearable has changed, re-save wearable with new name
+			LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),gAgentAvatarp->mEndCustomizeCallback);
 			gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
-                mNameEditor->setText(mWearableItem->getName());
+			mNameEditor->setText(mWearableItem->getName());
         }
         else
         {
@@ -1093,17 +1093,19 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 			if (link_item)
 			{
 				// Create new link
-				link_inventory_item( gAgent.getID(),
-									 link_item->getLinkedUUID(),
-									 LLAppearanceMgr::instance().getCOF(),
-									 link_item->getName(),
-									 description,
-									 LLAssetType::AT_LINK,
-									 NULL);
+				LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
+									<< " removing old link at " << link_item->getUUID()
+									<< " wearable item id " << mWearablePtr->getItemID() << LL_ENDL;
+
+				LLInventoryObject::const_object_list_t obj_array;
+				obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
+				link_inventory_array(LLAppearanceMgr::instance().getCOF(),
+									 obj_array, 
+									 gAgentAvatarp->mEndCustomizeCallback);
 				// Remove old link
-				gInventory.purgeObject(link_item->getUUID());
+				remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
 			}
-                gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
+			gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name);
         }
 
 	
@@ -1121,7 +1123,7 @@ void LLPanelEditWearable::revertChanges()
         mNameEditor->setText(mWearableItem->getName());
         updatePanelPickerControls(mWearablePtr->getType());
         updateTypeSpecificControls(mWearablePtr->getType());
-        gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE);
+        gAgentAvatarp->wearableUpdated(mWearablePtr->getType());
 }
 
 void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch)
@@ -1583,7 +1585,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
                 LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                 gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
-                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
         else
         {
@@ -1600,7 +1602,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
 
                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                 gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
-                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
 
         updatePanelPickerControls(getWearable()->getType());
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 343f2b413f79e1d04d2d67cfdd788413b928f04c..67cbc913327e7131045f7035a54cf1cbc879d471 100755
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -527,7 +527,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
 }
 
 // virtual
-void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
+void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason)
 {
 	LL_WARNS() << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<LL_ENDL;
 }
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 80310d15242f8fcb026b0319b13effac24e14ace..c11cbe05ae655a9599a7157603fbeb85da2a5823 100755
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -108,7 +108,7 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	//LLRemoteParcelInfoObserver interface
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void setParcelID(const LLUUID& parcel_id);
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 	
 private:
 	void initFavoritesInventoryPanel();
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index e2b4d098e9fd0b092a9ac86c12362d23cc51c697..088eaa8e0d26cd4f02e4ea01ca6a16d8f1b41673 100755
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -421,7 +421,7 @@ void LLPanelLogin::showLoginWidgets()
 		sInstance->reshapeBrowser();
 		// *TODO: Append all the usual login parameters, like first_login=Y etc.
 		std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
-		web_browser->navigateTo( splash_screen_url, "text/html" );
+		web_browser->navigateTo( splash_screen_url, HTTP_CONTENT_TEXT_HTML );
 		LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
 		username_combo->setFocus(TRUE);
 	}
@@ -785,7 +785,7 @@ void LLPanelLogin::loadLoginPage()
 	if (web_browser->getCurrentNavUrl() != login_uri.asString())
 	{
 		LL_DEBUGS("AppInit") << "loading:    " << login_uri << LL_ENDL;
-		web_browser->navigateTo( login_uri.asString(), "text/html" );
+		web_browser->navigateTo( login_uri.asString(), HTTP_CONTENT_TEXT_HTML );
 	}
 }
 
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
index 2f65bedc2bde8b9c557aed5928441d90a6c81c81..f7c2f629ec1a8a4299f8bf6be4fcc2e5b8c6827b 100755
--- a/indra/newview/llpanelmarketplaceinboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -129,11 +129,11 @@ void LLInboxFolderViewFolder::addItem(LLFolderViewItem* item)
 // virtual
 void LLInboxFolderViewFolder::draw()
 {
-	if (!badgeHasParent())
+	if (!hasBadgeHolderParent())
 	{
-		addBadgeToParentPanel();
+		addBadgeToParentHolder();
 	}
-	
+
 	setBadgeVisibility(mFresh);
 
 	LLFolderViewFolder::draw();
@@ -214,9 +214,9 @@ BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)
 // virtual
 void LLInboxFolderViewItem::draw()
 {
-	if (!badgeHasParent())
+	if (!hasBadgeHolderParent())
 	{
-		addBadgeToParentPanel();
+		addBadgeToParentHolder();
 	}
 
 	setBadgeVisibility(mFresh);
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index e48aa889378b96bf51092dbcb9d6e73fd0cf4392..496168229daf117ef60bce300413a9a083b87ee4 100755
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -159,6 +159,7 @@ class LLPanelOutfitEditGearMenu
 
 		registrar.add("Wearable.Create", boost::bind(onCreate, _2));
 
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 			"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 		llassert(menu);
@@ -228,6 +229,7 @@ class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu>
 		enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2));
 		enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2));
 
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 			"menu_add_wearable_gear.xml",
 			LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
@@ -1184,12 +1186,12 @@ BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 			 * second argument is used to delay the appearance update until all dragged items
 			 * are added to optimize user experience.
 			 */
-			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false);
+			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID());
 		}
 		else
 		{
 			// if asset id is not available for the item we must wear it immediately (attachments only)
-			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true);
+			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID()));
 		}
 	}
 
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 3c72607678dce44b389f8fd307e0413ef30da5d8..1e1f59055f3b5c5404a4a214787fab27073c104a 100755
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -76,7 +76,8 @@ BOOL LLPanelOutfitsInventory::postBuild()
 	// Fetch your outfits folder so that the links are in memory.
 	// ( This is only necessary if we want to show a warning if a user deletes an item that has a
 	// a link in an outfit, see "ConfirmItemDeleteHasLinks". )
-	const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTFIT, false);
+
+	const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
 	if (outfits_cat.notNull())
 	{
 		LLInventoryModelBackgroundFetch::instance().start(outfits_cat);
@@ -183,7 +184,7 @@ bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD&
 		LLStringUtil::trim(outfit_name);
 		if( !outfit_name.empty() )
 		{
-			LLUUID outfit_folder = LLAppearanceMgr::getInstance()->makeNewOutfitLinks(outfit_name);
+			LLAppearanceMgr::getInstance()->makeNewOutfitLinks(outfit_name);
 
 			LLSidepanelAppearance* panel_appearance = getAppearanceSP();
 			if (panel_appearance)
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
index 3c1f14759c82b23974db4f85da22c5019748b15b..7a8bd66fcfe2420a503b3be2b8a107339ed9a62e 100755
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -86,7 +86,7 @@ class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRem
 	//This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; }
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {};
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {};
 
 protected:
 
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 4ae0c0eb1252c7c595b47333f3f75c89d61bb335..4e7c5f6ed2912e64bce73898d280bd8475f76d67 100755
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -169,15 +169,15 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
 }
 
 // virtual
-void LLPanelPlaceInfo::setErrorStatus(U32 status, const std::string& reason)
+void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason)
 {
 	// We only really handle 404 and 499 errors
 	std::string error_text;
-	if(status == 404)
+	if(status == HTTP_NOT_FOUND)
 	{
 		error_text = getString("server_error_text");
 	}
-	else if(status == 499)
+	else if(status == HTTP_INTERNAL_ERROR)
 	{
 		error_text = getString("server_forbidden_text");
 	}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 64f0b6b5503898e84746a10d35b5cfc406af52a2..30327378eff8c09a9d382e83ff3f7ca0881878e3 100755
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -86,7 +86,7 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 	void displayParcelInfo(const LLUUID& region_id,
 						   const LLVector3d& pos_global);
 
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index c05b379fd8bd1cfcf6ca0fefb9db4c77d784a2d6..2be96b9b78c59e2150cb73b731359079ec4adcb5 100755
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -168,8 +168,7 @@ class LLPlacesInventoryObserver : public LLInventoryAddedObserver
 protected:
 	/*virtual*/ void done()
 	{
-		mPlaces->showAddedLandmarkInfo(mAdded);
-		mAdded.clear();
+		mPlaces->showAddedLandmarkInfo(gInventory.getAddedIDs());
 	}
 
 private:
@@ -217,7 +216,7 @@ class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver
 			LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
 		}
 	}
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason)
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason)
 	{
 		LL_ERRS() << "Can't complete remote parcel request. Http Status: "
 			   << status << ". Reason : " << reason << LL_ENDL;
@@ -1100,9 +1099,9 @@ void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos)
 	updateVerbs();
 }
 
-void LLPanelPlaces::showAddedLandmarkInfo(const uuid_vec_t& items)
+void LLPanelPlaces::showAddedLandmarkInfo(const uuid_set_t& items)
 {
-	for (uuid_vec_t::const_iterator item_iter = items.begin();
+	for (uuid_set_t::const_iterator item_iter = items.begin();
 		 item_iter != items.end();
 		 ++item_iter)
 	{
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index b6019ca32ee0cffcee1d64caa17dc4976ce97c98..c3d1b9bc534bb05e6acb16dfb3fd930d13363e98 100755
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -69,7 +69,7 @@ class LLPanelPlaces : public LLPanel
 	void changedGlobalPos(const LLVector3d &global_pos);
 
 	// Opens landmark info panel when agent creates or receives landmark.
-	void showAddedLandmarkInfo(const uuid_vec_t& items);
+	void showAddedLandmarkInfo(const uuid_set_t& items);
 
 	void setItem(LLInventoryItem* item);
 
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 8fddd9523f8b12e794e46021637f09d52044168c..652d2be6f6104973e07777422f870b7e4fb214d0 100755
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -341,6 +341,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
 	registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
 
 	// create the context menu from the XUI
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 }
@@ -935,6 +936,7 @@ void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y
 	registrar.add("TeleportHistory.TabClose",	boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
 
 	// create the context menu from the XUI
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index ae5b3b4e7680669239f2f836d16d4bf25b9b8b54..4977a72dc692afcf655e1ebd74fa24af59ab34ba 100755
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -103,17 +103,16 @@ LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode
 
 class NavMeshStatusResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(NavMeshStatusResponder);
 public:
-	NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly);
+	NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly);
 	virtual ~NavMeshStatusResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string    mCapabilityURL;
 	LLViewerRegion *mRegion;
 	LLUUID         mRegionUUID;
 	bool           mIsGetStatusOnly;
@@ -125,17 +124,16 @@ class NavMeshStatusResponder : public LLHTTPClient::Responder
 
 class NavMeshResponder : public LLHTTPClient::Responder
 {
+    LOG_CLASS(NavMeshResponder);
 public:
-	NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
+	NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
 	virtual ~NavMeshResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string             mCapabilityURL;
 	U32                     mNavMeshVersion;
 	LLPathfindingNavMeshPtr mNavMeshPtr;
 };
@@ -146,17 +144,14 @@ class NavMeshResponder : public LLHTTPClient::Responder
 
 class AgentStateResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(AgentStateResponder);
 public:
-	AgentStateResponder(const std::string &pCapabilityURL);
+	AgentStateResponder();
 	virtual ~AgentStateResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
-
-private:
-	std::string mCapabilityURL;
+	virtual void httpSuccess();
+	virtual void httpFailure();
 };
 
 
@@ -165,17 +160,16 @@ class AgentStateResponder : public LLHTTPClient::Responder
 //---------------------------------------------------------------------------
 class NavMeshRebakeResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(NavMeshRebakeResponder);
 public:
-	NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback);
+	NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback);
 	virtual ~NavMeshRebakeResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string                                     mCapabilityURL;
 	LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback;
 };
 
@@ -190,11 +184,9 @@ class LinksetsResponder
 	virtual ~LinksetsResponder();
 
 	void handleObjectLinksetsResult(const LLSD &pContent);
-	void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, 
-								   const LLSD& pContent, const std::string &pURL);
+	void handleObjectLinksetsError();
 	void handleTerrainLinksetsResult(const LLSD &pContent);
-	void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason,
-									const LLSD& pContent, const std::string &pURL);
+	void handleTerrainLinksetsError();
 
 protected:
 
@@ -227,17 +219,16 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
 
 class ObjectLinksetsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ObjectLinksetsResponder);
 public:
-	ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr);
+	ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
 	virtual ~ObjectLinksetsResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string          mCapabilityURL;
 	LinksetsResponderPtr mLinksetsResponsderPtr;
 };
 
@@ -247,17 +238,16 @@ class ObjectLinksetsResponder : public LLHTTPClient::Responder
 
 class TerrainLinksetsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(TerrainLinksetsResponder);
 public:
-	TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr);
+	TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
 	virtual ~TerrainLinksetsResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string          mCapabilityURL;
 	LinksetsResponderPtr mLinksetsResponsderPtr;
 };
 
@@ -267,17 +257,16 @@ class TerrainLinksetsResponder : public LLHTTPClient::Responder
 
 class CharactersResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(TerrainLinksetsResponder);
 public:
-	CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback);
+	CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback);
 	virtual ~CharactersResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string                                     mCapabilityURL;
 	LLPathfindingManager::request_id_t              mRequestId;
 	LLPathfindingManager::object_request_callback_t mCharactersCallback;
 };
@@ -364,7 +353,7 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, b
 		std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion);
 		llassert(!navMeshStatusURL.empty());
 		navMeshPtr->handleNavMeshCheckVersion();
-		LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(navMeshStatusURL, pRegion, pIsGetStatusOnly);
+		LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(pRegion, pIsGetStatusOnly);
 		LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder);
 	}
 }
@@ -398,12 +387,12 @@ void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_re
 			bool doRequestTerrain = isAllowViewTerrainProperties();
 			LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain));
 
-			LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr);
+			LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
 			LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder);
 
 			if (doRequestTerrain)
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder);
 			}
 		}
@@ -447,13 +436,13 @@ void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLP
 
 			if (!objectPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder);
 			}
 
 			if (!terrainPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder);
 			}
 		}
@@ -486,7 +475,7 @@ void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_
 		{
 			pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr);
 
-			LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(charactersURL, pRequestId, pCharactersCallback);
+			LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(pRequestId, pCharactersCallback);
 			LLHTTPClient::get(charactersURL, charactersResponder);
 		}
 	}
@@ -519,7 +508,7 @@ void LLPathfindingManager::requestGetAgentState()
 		{
 			std::string agentStateURL = getAgentStateURLForRegion(currentRegion);
 			llassert(!agentStateURL.empty());
-			LLHTTPClient::ResponderPtr responder = new AgentStateResponder(agentStateURL);
+			LLHTTPClient::ResponderPtr responder = new AgentStateResponder();
 			LLHTTPClient::get(agentStateURL, responder);
 		}
 	}
@@ -543,7 +532,7 @@ void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebak
 		llassert(!navMeshStatusURL.empty());
 		LLSD postData;			
 		postData["command"] = "rebuild";
-		LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(navMeshStatusURL, pRebakeNavMeshCallback);
+		LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(pRebakeNavMeshCallback);
 		LLHTTPClient::post(navMeshStatusURL, postData, responder);
 	}
 }
@@ -565,7 +554,7 @@ void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPt
 		else
 		{
 			navMeshPtr->handleNavMeshStart(pNavMeshStatus);
-			LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, pNavMeshStatus.getVersion(), navMeshPtr);
+			LLHTTPClient::ResponderPtr responder = new NavMeshResponder(pNavMeshStatus.getVersion(), navMeshPtr);
 
 			LLSD postData;
 			LLHTTPClient::post(navMeshURL, postData, responder);
@@ -779,9 +768,8 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c
 // NavMeshStatusResponder
 //---------------------------------------------------------------------------
 
-NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly)
+NavMeshStatusResponder::NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRegion(pRegion),
 	mRegionUUID(),
 	mIsGetStatusOnly(pIsGetStatusOnly)
@@ -796,15 +784,15 @@ NavMeshStatusResponder::~NavMeshStatusResponder()
 {
 }
 
-void NavMeshStatusResponder::result(const LLSD &pContent)
+void NavMeshStatusResponder::httpSuccess()
 {
-	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, pContent);
+	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, getContent());
 	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
 }
 
-void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void NavMeshStatusResponder::httpFailure()
 {
-	LL_WARNS() << "NavMeshStatusResponder error [status:" << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID);
 	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
 }
@@ -813,9 +801,8 @@ void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pR
 // NavMeshResponder
 //---------------------------------------------------------------------------
 
-NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
+NavMeshResponder::NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mNavMeshVersion(pNavMeshVersion),
 	mNavMeshPtr(pNavMeshPtr)
 {
@@ -825,23 +812,23 @@ NavMeshResponder::~NavMeshResponder()
 {
 }
 
-void NavMeshResponder::result(const LLSD &pContent)
+void NavMeshResponder::httpSuccess()
 {
-	mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion);
+	mNavMeshPtr->handleNavMeshResult(getContent(), mNavMeshVersion);
 }
 
-void NavMeshResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void NavMeshResponder::httpFailure()
 {
-	mNavMeshPtr->handleNavMeshError(pStatus, pReason, pContent, mCapabilityURL, mNavMeshVersion);
+	LL_WARNS() << dumpResponse() << LL_ENDL;
+	mNavMeshPtr->handleNavMeshError(mNavMeshVersion);
 }
 
 //---------------------------------------------------------------------------
 // AgentStateResponder
 //---------------------------------------------------------------------------
 
-AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL)
+AgentStateResponder::AgentStateResponder()
 : LLHTTPClient::Responder()
-, mCapabilityURL(pCapabilityURL)
 {
 }
 
@@ -849,17 +836,18 @@ AgentStateResponder::~AgentStateResponder()
 {
 }
 
-void AgentStateResponder::result(const LLSD &pContent)
+void AgentStateResponder::httpSuccess()
 {
+	const LLSD& pContent = getContent();
 	llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
 	llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
 	BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
 	LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion);
 }
 
-void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void AgentStateResponder::httpFailure()
 {
-	LL_WARNS() << "AgentStateResponder error [status:" << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	LLPathfindingManager::getInstance()->handleAgentState(FALSE);
 }
 
@@ -867,9 +855,8 @@ void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReas
 //---------------------------------------------------------------------------
 // navmesh rebake responder
 //---------------------------------------------------------------------------
-NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback)
+NavMeshRebakeResponder::NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRebakeNavMeshCallback(pRebakeNavMeshCallback)
 {
 }
@@ -878,14 +865,14 @@ NavMeshRebakeResponder::~NavMeshRebakeResponder()
 {
 }
 
-void NavMeshRebakeResponder::result(const LLSD &pContent)
+void NavMeshRebakeResponder::httpSuccess()
 {
 	mRebakeNavMeshCallback(true);
 }
 
-void NavMeshRebakeResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void NavMeshRebakeResponder::httpFailure()
 {
-	LL_WARNS() << "NavMeshRebakeResponder error [status:" << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	mRebakeNavMeshCallback(false);
 }
 
@@ -918,11 +905,9 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent)
 	}
 }
 
-void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason,
-												 const LLSD& pContent, const std::string &pURL)
+void LinksetsResponder::handleObjectLinksetsError()
 {
-	LL_WARNS() << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << "LinksetsResponder object linksets error" << LL_ENDL;
 	mObjectMessagingState = kReceivedError;
 	if (mTerrainMessagingState != kWaiting)
 	{
@@ -941,11 +926,9 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent)
 	}
 }
 
-void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason,
-												   const LLSD& pContent, const std::string &pURL)
+void LinksetsResponder::handleTerrainLinksetsError()
 {
-	LL_WARNS() << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << "LinksetsResponder terrain linksets error" << LL_ENDL;
 	mTerrainMessagingState = kReceivedError;
 	if (mObjectMessagingState != kWaiting)
 	{
@@ -979,9 +962,8 @@ void LinksetsResponder::sendCallback()
 // ObjectLinksetsResponder
 //---------------------------------------------------------------------------
 
-ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr)
+ObjectLinksetsResponder::ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
 {
 }
@@ -990,23 +972,23 @@ ObjectLinksetsResponder::~ObjectLinksetsResponder()
 {
 }
 
-void ObjectLinksetsResponder::result(const LLSD &pContent)
+void ObjectLinksetsResponder::httpSuccess()
 {
-	mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent);
+	mLinksetsResponsderPtr->handleObjectLinksetsResult(getContent());
 }
 
-void ObjectLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void ObjectLinksetsResponder::httpFailure()
 {
-	mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, pContent, mCapabilityURL);
+	LL_WARNS() << dumpResponse() << LL_ENDL;
+	mLinksetsResponsderPtr->handleObjectLinksetsError();
 }
 
 //---------------------------------------------------------------------------
 // TerrainLinksetsResponder
 //---------------------------------------------------------------------------
 
-TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr)
+TerrainLinksetsResponder::TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
 {
 }
@@ -1015,23 +997,23 @@ TerrainLinksetsResponder::~TerrainLinksetsResponder()
 {
 }
 
-void TerrainLinksetsResponder::result(const LLSD &pContent)
+void TerrainLinksetsResponder::httpSuccess()
 {
-	mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent);
+	mLinksetsResponsderPtr->handleTerrainLinksetsResult(getContent());
 }
 
-void TerrainLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void TerrainLinksetsResponder::httpFailure()
 {
-	mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, pContent, mCapabilityURL);
+	LL_WARNS() << dumpResponse() << LL_ENDL;
+	mLinksetsResponsderPtr->handleTerrainLinksetsError();
 }
 
 //---------------------------------------------------------------------------
 // CharactersResponder
 //---------------------------------------------------------------------------
 
-CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback)
+CharactersResponder::CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRequestId(pRequestId),
 	mCharactersCallback(pCharactersCallback)
 {
@@ -1041,15 +1023,15 @@ CharactersResponder::~CharactersResponder()
 {
 }
 
-void CharactersResponder::result(const LLSD &pContent)
+void CharactersResponder::httpSuccess()
 {
-	LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(pContent));
+	LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(getContent()));
 	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr);
 }
 
-void CharactersResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void CharactersResponder::httpFailure()
 {
-	LL_WARNS() << "CharactersResponder error [status:" << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 
 	LLPathfindingObjectListPtr characterListPtr =  LLPathfindingObjectListPtr(new LLPathfindingCharacterList());
 	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr);
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp
index 40f5d8c23e10b578097f5f31cd697d75b8fc48bf..0287c07f962c0573f930c3bc9994efa44d178446 100755
--- a/indra/newview/llpathfindingnavmesh.cpp
+++ b/indra/newview/llpathfindingnavmesh.cpp
@@ -184,10 +184,8 @@ void LLPathfindingNavMesh::handleNavMeshError()
 	setRequestStatus(kNavMeshRequestError);
 }
 
-void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion)
+void LLPathfindingNavMesh::handleNavMeshError(U32 pNavMeshVersion)
 {
-	LL_WARNS() << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << LL_ENDL;
 	if (mNavMeshStatus.getVersion() == pNavMeshVersion)
 	{
 		handleNavMeshError();
diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h
index b872ccad7cbd24235889a427beb36b512cd2c292..87f32b8d56487245b7ff0ba0d890845b483cfb4a 100755
--- a/indra/newview/llpathfindingnavmesh.h
+++ b/indra/newview/llpathfindingnavmesh.h
@@ -74,7 +74,7 @@ class LLPathfindingNavMesh
 	void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion);
 	void handleNavMeshNotEnabled();
 	void handleNavMeshError();
-	void handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion);
+	void handleNavMeshError(U32 pNavMeshVersion);
 
 protected:
 
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
index 05ef436bd976180ab0816cf394e1cff09e10434e..ea10d03264f3d37f9f334bb03fea1d7994e096d9 100755
--- a/indra/newview/llphysicsmotion.cpp
+++ b/indra/newview/llphysicsmotion.cpp
@@ -668,9 +668,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time)
 			if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) &&
 			    (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT))
 			{
-				mCharacter->setVisualParamWeight(driver_param,
-								 0,
-								 FALSE);
+				mCharacter->setVisualParamWeight(driver_param, 0);
 			}
 			S32 num_driven = driver_param->getDrivenParamsCount();
 			for (S32 i = 0; i < num_driven; ++i)
@@ -770,7 +768,5 @@ void LLPhysicsMotion::setParamValue(const LLViewerVisualParam *param,
 	// Scale from [0,1] to [value_min_local,value_max_local]
         const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_rescaled;
 
-        mCharacter->setVisualParamWeight(param,
-                                         new_value_local,
-                                         FALSE);
+        mCharacter->setVisualParamWeight(param, new_value_local);
 }
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index b379ef7bdbfccc04e0633e971ad44f5e1707fed0..6d032ad3d399ecc7e7b4cf6eb8af3a69808103ed 100755
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -400,13 +400,6 @@ void LLPreview::onDiscardBtn(void* data)
 	self->mForceClose = TRUE;
 	self->closeFloater();
 
-	// Delete the item entirely
-	/*
-	item->removeFromServer();
-	gInventory.deleteObject(item->getUUID());
-	gInventory.notifyObservers();
-	*/
-
 	// Move the item to the trash
 	const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
 	if (item->getParentUUID() != trash_id)
diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp
index e85194d173f45112db92015cbd76ccab1b293647..e92bf4590d1096d2a2ce2de4805f5da54169ff18 100755
--- a/indra/newview/llproductinforequest.cpp
+++ b/indra/newview/llproductinforequest.cpp
@@ -35,18 +35,24 @@
 
 class LLProductInfoRequestResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(LLProductInfoRequestResponder);
+private:
 	//If we get back a normal response, handle it here
-	virtual void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		LLProductInfoRequestManager::instance().setSkuDescriptions(content);
+		const LLSD& content = getContent();
+		if (!content.isArray())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		LLProductInfoRequestManager::instance().setSkuDescriptions(getContent());
 	}
 
 	//If we get back an error (not found, etc...), handle it here
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpFailure()
 	{
-		LL_WARNS() << "LLProductInfoRequest error [status:"
-				<< status << ":] " << content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 	}
 };
 
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 13120fdf45c888eaa551fe4d9cc1f97ecbb5710d..29dcc12f9e315f3e96fd70c5fc3ab36773731595 100755
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -47,9 +47,15 @@ LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLRemote
 
 //If we get back a normal response, handle it here
 //virtual
-void LLRemoteParcelRequestResponder::result(const LLSD& content)
+void LLRemoteParcelRequestResponder::httpSuccess()
 {
-	LLUUID parcel_id = content["parcel_id"];
+	const LLSD& content = getContent();
+	if (!content.isMap() || !content.has("parcel_id"))
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	LLUUID parcel_id = getContent()["parcel_id"];
 
 	// Panel inspecting the information may be closed and destroyed
 	// before this response is received.
@@ -62,17 +68,16 @@ void LLRemoteParcelRequestResponder::result(const LLSD& content)
 
 //If we get back an error (not found, etc...), handle it here
 //virtual
-void LLRemoteParcelRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLRemoteParcelRequestResponder::httpFailure()
 {
-	LL_WARNS() << "LLRemoteParcelRequest error [status:"
-			<< status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 
 	// Panel inspecting the information may be closed and destroyed
 	// before this response is received.
 	LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
 	if (observer)
 	{
-		observer->setErrorStatus(status, reason);
+		observer->setErrorStatus(getStatus(), getReason());
 	}
 }
 
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index e4b8791f7c7d8b331e33fdd3e0177c701ed4e355..35348b69ffabb6de663366d2e0f62248928fb36e 100755
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -38,16 +38,17 @@ class LLRemoteParcelInfoObserver;
 
 class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLRemoteParcelRequestResponder);
 public:
 	LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle);
 
+private:
 	//If we get back a normal response, handle it here
-	/*virtual*/ void result(const LLSD& content);
+	/*virtual*/ void httpSuccess();
 
 	//If we get back an error (not found, etc...), handle it here
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	/*virtual*/ void httpFailure();
 
-protected:
 	LLHandle<LLRemoteParcelInfoObserver> mObserverHandle;
 };
 
@@ -79,7 +80,7 @@ class LLRemoteParcelInfoObserver
 	virtual ~LLRemoteParcelInfoObserver() {}
 	virtual void processParcelInfo(const LLParcelData& parcel_data) = 0;
 	virtual void setParcelID(const LLUUID& parcel_id) = 0;
-	virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setErrorStatus(S32 status, const std::string& reason) = 0;
 	LLHandle<LLRemoteParcelInfoObserver>	getObserverHandle() const { return mObserverHandle; }
 
 protected:
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 6a840f3f4004bc6b5f18c73131ccb03a987b4051..8708fb87ee31870d022c3e6ee2685634f2b3f642 100755
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -273,6 +273,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
 			// only cancel notification if it isn't being used in IM session
 			LLNotifications::instance().cancel(notification);
 		}
+
+		// It was assumed that the toast would take ownership of the panel pointer.
+		// But since we have decided not to display the toast, kill the panel to
+		// prevent the memory leak.
+		if (p.panel != NULL)
+		{
+			p.panel()->die();
+		}
 		return;
 	}
 
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
index a7e24b86b13e765fb727e29e766ee0044cb1b759..bfa453a0ae1862f72286ef4be3453f13e7e2a734 100755
--- a/indra/newview/llscrollingpanelparam.cpp
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -266,7 +266,7 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
 			if (slider->getMinValue() < new_percent
 				&& new_percent < slider->getMaxValue())
 			{
-				mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE);
+				mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight);
 				mWearable->writeToAvatar(gAgentAvatarp);
 				gAgentAvatarp->updateVisualParams();
 
@@ -299,7 +299,7 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
 			if (slider->getMinValue() < new_percent
 				&& new_percent < slider->getMaxValue())
 			{
-				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
 				self->mWearable->writeToAvatar(gAgentAvatarp);
 				slider->setValue( self->weightToPercent( new_weight ) );
 			}
@@ -333,7 +333,7 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
 				if (slider->getMinValue() < new_percent
 					&& new_percent < slider->getMaxValue())
 				{
-					self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+					self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
 					self->mWearable->writeToAvatar(gAgentAvatarp);
 					slider->setValue( self->weightToPercent( new_weight ) );
 				}
diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp
index 8e083ddb6c8ff60d466f01d8e72f2d3ee1c96f0f..fe7a3627235560c7cd38b126d7417477c928aece 100755
--- a/indra/newview/llscrollingpanelparambase.cpp
+++ b/indra/newview/llscrollingpanelparambase.cpp
@@ -93,7 +93,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
 	F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
 	if (current_weight != new_weight )
 	{
-		self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
+		self->mWearable->setVisualParamWeight( param->getID(), new_weight);
 		self->mWearable->writeToAvatar(gAgentAvatarp);
 		gAgentAvatarp->updateVisualParams();
 	}
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index c938a478f7268e0af0cdaa7adfa77ec76eeb2214..64f24cd2912af125215791284db4265b5a04b0ad 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -452,7 +452,7 @@ void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *dat
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD());
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
 	if (panel)
-	{
+	{	
 		panel->showWearableEditPanel(wearable, disable_camera_switch);
 	}
 }
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index a7b99a0f6bafdcc05fde8343f341d1345c4a594a..08a4d00d0f543bb5cecdd169ecde687fa9355547 100755
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -640,12 +640,26 @@ class LLVolumeGeometryManager: public LLGeometryManager
 		DISTANCE_SORT
 	} eSortType;
 
-	virtual ~LLVolumeGeometryManager() { }
+	LLVolumeGeometryManager();
+	virtual ~LLVolumeGeometryManager();
 	virtual void rebuildGeom(LLSpatialGroup* group);
 	virtual void rebuildMesh(LLSpatialGroup* group);
 	virtual void getGeometry(LLSpatialGroup* group);
 	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
 	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
+
+private:
+	void allocateFaces(U32 pMaxFaceCount);
+	void freeFaces();
+
+	static int32_t sInstanceCount;
+	static LLFace** sFullbrightFaces;
+	static LLFace** sBumpFaces;
+	static LLFace** sSimpleFaces;
+	static LLFace** sNormFaces;
+	static LLFace** sSpecFaces;
+	static LLFace** sNormSpecFaces;
+	static LLFace** sAlphaFaces;
 };
 
 //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index f25076d47ee59c3b3388c4f06fa58474e3fd8935..89302c3c647354522f26aea91371d4d8341f560d 100755
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -270,21 +270,23 @@ bool LLSpeakersDelayActionsStorage::isTimerStarted(const LLUUID& speaker_id)
 
 class ModerationResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ModerationResponder);
 public:
 	ModerationResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 	
-	virtual void error(U32 status, const std::string& reason)
+protected:
+	virtual void httpFailure()
 	{
-		LL_WARNS() << status << ": " << reason << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 		
 		if ( gIMMgr )
 		{
 			//403 == you're not a mod
 			//should be disabled if you're not a moderator
-			if ( 403 == status )
+			if ( HTTP_FORBIDDEN == getStatus() )
 			{
 				gIMMgr->showSessionEventError(
 											  "mute",
@@ -855,10 +857,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
 		}
 	}
 }
-/*prep#
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-		LL_WARNS() << "ModerationResponder error [status:" << status << "]: " << content << LL_ENDL;
-		*/
+
 void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
 {
 	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index a76b4bbe0946cb196d24de32bbd4c2341ac1cf04..56fac3b092b341b1a028317d99de9c8f6eefe851 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -311,6 +311,12 @@ void update_texture_fetch()
 	gTextureList.updateImages(0.10f);
 }
 
+void set_flags_and_update_appearance()
+{
+	LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
+	LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
+}
+
 // Returns false to skip other idle processing. Should only return
 // true when all initialization done.
 bool idle_startup()
@@ -1287,6 +1293,8 @@ bool idle_startup()
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
 		LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
 		
+		LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == "
+		<< gFirstSimSeedCap << LL_ENDL;
 		regionp->setSeedCapability(gFirstSimSeedCap);
 		LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
 		display_startup();
@@ -1771,6 +1779,15 @@ bool idle_startup()
 		// This method MUST be called before gInventory.findCategoryUUIDForType because of 
 		// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
 		gInventory.buildParentChildMap();
+		gInventory.createCommonSystemCategories();
+
+		// It's debatable whether this flag is a good idea - sets all
+		// bits, and in general it isn't true that inventory
+		// initialization generates all types of changes. Maybe add an
+		// INITIALIZE mask bit instead?
+		gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+		gInventory.notifyObservers();
+		
 		display_startup();
 
 		//all categories loaded. lets create "My Favorites" category
@@ -2018,7 +2035,7 @@ bool idle_startup()
 	{
 		display_startup();
 		F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
-
+		
 		// We now have an inventory skeleton, so if this is a user's first
 		// login, we can start setting up their clothing and avatar 
 		// appearance.  This helps to avoid the generic "Ruth" avatar in
@@ -2027,18 +2044,38 @@ bool idle_startup()
 			&& !sInitialOutfit.empty()    // registration set up an outfit
 			&& !sInitialOutfitGender.empty() // and a gender
 			&& isAgentAvatarValid()	  // can't wear clothes without object
-			&& !gAgent.isGenderChosen() ) // nothing already loading
+			&& !gAgent.isOutfitChosen()) // nothing already loading
 		{
 			// Start loading the wearables, textures, gestures
 			LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
 		}
+		// If not first login, we need to fetch COF contents and
+		// compute appearance from that.
+		if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen())
+		{
+			gAgentWearables.notifyLoadingStarted();
+			gAgent.setOutfitChosen(TRUE);
+			gAgentWearables.sendDummyAgentWearablesUpdate();
+			callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance);
+		}
 
 		display_startup();
 
 		// wait precache-delay and for agent's avatar or a lot longer.
-		if(((timeout_frac > 1.f) && isAgentAvatarValid())
-		   || (timeout_frac > 3.f))
+		if ((timeout_frac > 1.f) && isAgentAvatarValid())
+		{
+			LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
+		}
+		else if (timeout_frac > 10.f) 
 		{
+			// If we exceed the wait above while isAgentAvatarValid is
+			// not true yet, we will change startup state and
+			// eventually (once avatar does get created) wind up at
+			// the gender chooser. This should occur only in very
+			// unusual circumstances, so set the timeout fairly high
+			// to minimize mistaken hits here.
+			LL_WARNS() << "Wait for valid avatar state exceeded " 
+					<< timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; 
 			LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
 		}
 		else
@@ -2060,12 +2097,11 @@ bool idle_startup()
 		const F32 wearables_time = wearables_timer.getElapsedTimeF32();
 		static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay");
 
-		display_startup();
-		if (!gAgent.isGenderChosen() && isAgentAvatarValid())
+		if (!gAgent.isOutfitChosen() && isAgentAvatarValid())
 		{
-			// No point in waiting for clothing, we don't even
-			// know what gender we are.  Pop a dialog to ask and
-			// proceed to draw the world. JC
+			// No point in waiting for clothing, we don't even know
+			// what outfit we want.  Pop up a gender chooser dialog to
+			// ask and proceed to draw the world. JC
 			//
 			// *NOTE: We might hit this case even if we have an
 			// initial outfit, but if the load hasn't started
@@ -2075,7 +2111,10 @@ bool idle_startup()
 				callback_choose_gender);
 			LLStartUp::setStartupState( STATE_CLEANUP );
 		}
-		else if (wearables_time >= max_wearables_time())
+		
+		display_startup();
+
+		if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time))
 		{
 			LLNotificationsUtil::add("ClothingLoading");
 			record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time);
@@ -2086,25 +2125,24 @@ bool idle_startup()
 				&& gAgentAvatarp->isFullyLoaded())
 		{
 			// wait for avatar to be completely loaded
-			//LL_INFOS() << "avatar fully loaded" << LL_ENDL;
-			LLStartUp::setStartupState( STATE_CLEANUP );
-		}
-		// OK to just get the wearables
-		else if (!gAgent.isFirstLogin() && gAgentWearables.areWearablesLoaded() )
-		{
-			// We have our clothing, proceed.
-			//LL_INFOS() << "wearables loaded" << LL_ENDL;
-			LLStartUp::setStartupState( STATE_CLEANUP );
+			if (isAgentAvatarValid()
+				&& gAgentAvatarp->isFullyLoaded())
+			{
+				LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL;
+				LLStartUp::setStartupState( STATE_CLEANUP );
+				return TRUE;
+			}
 		}
 		else
 		{
-			display_startup();
-			update_texture_fetch();
-			display_startup();
-			set_startup_status(0.9f + 0.1f * wearables_time / max_wearables_time(),
-				LLTrans::getString("LoginDownloadingClothing").c_str(),
-				gAgent.mMOTD.c_str());
-			display_startup();
+			// OK to just get the wearables
+			if ( gAgentWearables.areWearablesLoaded() )
+			{
+				// We have our clothing, proceed.
+				LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL;
+				LLStartUp::setStartupState( STATE_CLEANUP );
+				return TRUE;
+			}
 		}
 		//fall through this frame to STATE_CLEANUP
 	}
@@ -2351,8 +2389,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair,	process_remove_name_value);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAnimation,		process_avatar_animation);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAppearance,		process_avatar_appearance);
-	msg->setHandlerFunc("AgentCachedTextureResponse",	LLAgent::processAgentCachedTextureResponse);
-	msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatarSelf::processRebakeAvatarTextures);
 	msg->setHandlerFuncFast(_PREHASH_CameraConstraint,		process_camera_constraint);
 	msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse,		process_avatar_sit_response);
 	msg->setHandlerFunc("SetFollowCamProperties",			process_set_follow_cam_properties);
@@ -2426,9 +2462,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	// msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
 	//					LLFloaterRate::processReputationIndividualReply);
 
-	msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
-						LLAgentWearables::processAgentInitialWearablesUpdate );
-
 	msg->setHandlerFunc("ScriptControlChange",
 						LLAgent::processScriptControlChange );
 
@@ -2585,9 +2618,8 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 		LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL;
 	}
 
-	// This is really misnamed -- it means we have started loading
-	// an outfit/shape that will give the avatar a gender eventually. JC
-	gAgent.setGenderChosen(TRUE);
+	gAgent.setOutfitChosen(TRUE);
+	gAgentWearables.sendDummyAgentWearablesUpdate();
 }
 
 //static
@@ -2600,10 +2632,10 @@ void LLStartUp::saveInitialOutfit()
 	
 	if (sWearablesLoadedCon.connected())
 	{
-		LL_DEBUGS() << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL;
+		LL_DEBUGS("Avatar") << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL;
 		sWearablesLoadedCon.disconnect();
 	}
-	LL_DEBUGS() << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL;
+	LL_DEBUGS("Avatar") << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL;
 	LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false);
 }
 
@@ -3348,7 +3380,11 @@ bool process_login_success_response()
 		flag = login_flags["gendered"].asString();
 		if(flag == "Y")
 		{
-			gAgent.setGenderChosen(TRUE);
+			// We don't care about this flag anymore; now base whether
+			// outfit is chosen on COF contents, initial outfit
+			// requested and available, etc.
+
+			//gAgent.setGenderChosen(TRUE);
 		}
 		
 		bool pacific_daylight_time = false;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 2acd38b75351ea00cdaf4b9131b56f3d1e4139c3..14a42dd8dc260dda6978f8e91d4eae61242ef134 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -36,7 +36,7 @@
 
 #include "lldir.h"
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llimage.h"
 #include "llimagej2c.h"
 #include "llimageworker.h"
@@ -64,6 +64,8 @@
 #include "bufferarray.h"
 #include "bufferstream.h"
 
+#include "llhttpretrypolicy.h"
+
 bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
 LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheHitRate("texture_cache_hits");
 LLTrace::EventStatHandle<F64Milliseconds > LLTextureFetch::sCacheReadLatency("texture_cache_read_latency");
@@ -245,6 +247,25 @@ static const S32 HTTP_REQUESTS_IN_QUEUE_LOW_WATER = 20;			// Active level at whi
 
 //////////////////////////////////////////////////////////////////////////////
 
+static const char* e_state_name[] =
+{
+	"INVALID",
+	"INIT",
+	"LOAD_FROM_TEXTURE_CACHE",
+	"CACHE_POST",
+	"LOAD_FROM_NETWORK",
+	"LOAD_FROM_SIMULATOR",
+	"WAIT_HTTP_RESOURCE",
+	"WAIT_HTTP_RESOURCE2",
+	"SEND_HTTP_REQ",
+	"WAIT_HTTP_REQ",
+	"DECODE_IMAGE",
+	"DECODE_IMAGE_UPDATE",
+	"WRITE_TO_CACHE",
+	"WAIT_ON_WRITE",
+	"DONE"
+};
+
 class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 
 {
@@ -383,12 +404,14 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; }
 	bool getCanUseHTTP() const { return mCanUseHTTP; }
 
+	void setUrl(const std::string& url) { mUrl = url; }
+
 	LLTextureFetch & getFetcher() { return *mFetcher; }
 
 	// Inherited from LLCore::HttpHandler
 	// Threads:  Ttf
 	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
-	
+
 protected:
 	LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type,
 						 const std::string& url, const LLUUID& id, const LLHost& host,
@@ -549,6 +572,8 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	S32 mActiveCount;
 	LLCore::HttpStatus mGetStatus;
 	std::string mGetReason;
+	LLAdaptiveRetryPolicy mFetchRetryPolicy;
+
 	
 	// Work Data
 	LLMutex mWorkMutex;
@@ -894,7 +919,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mHttpHasResource(false),
 	  mCacheReadCount(0U),
 	  mCacheWriteCount(0U),
-	  mResourceWaitCount(0U)
+	  mResourceWaitCount(0U),
+	  mFetchRetryPolicy(10.0,3600.0,2.0,10)
 {
 	mCanUseNET = mUrl.empty() ;
 	
@@ -1153,6 +1179,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE
 		LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)
 							 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
+
 		// fall through
 	}
 
@@ -1183,9 +1210,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 																		  offset, size, responder);
 				mCacheReadTimer.reset();
 			}
-/* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */
-/*			else if ((mUrl.empty()||mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache()) */
-			else if (mUrl.empty() && mFetcher->canLoadFromCache())
+			else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache())
 			{
 				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
 
@@ -1275,6 +1300,21 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 	if (mState == LOAD_FROM_NETWORK)
 	{
+		// Check for retries to previous server failures.
+		F32 wait_seconds;
+		if (mFetchRetryPolicy.shouldRetry(wait_seconds))
+		{
+			if (wait_seconds <= 0.0)
+			{
+				LL_INFOS() << mID << " retrying now" << LL_ENDL;
+			}
+			else
+			{
+				//LL_INFOS() << mID << " waiting to retry for " << wait_seconds << " seconds" << LL_ENDL;
+				return false;
+			}
+		}
+
 		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP", true);
 
 // 		if (mHost != LLHost::invalid) get_url = false;
@@ -1291,7 +1331,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				std::string http_url = region->getHttpUrl() ;
 				if (!http_url.empty())
 				{
-					mUrl = http_url + "/?texture_id=" + mID.asString().c_str();
+					if (mFTType != FTT_DEFAULT)
+					{
+						LL_WARNS() << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL;
+					}
+					setUrl(http_url + "/?texture_id=" + mID.asString().c_str());
 					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
 				}
 				else
@@ -1306,12 +1350,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				mCanUseHTTP = false;
 			}
 		}
-#if 0 /* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */
-		if (mFTType == FTT_SERVER_BAKE)
+		else if (mFTType == FTT_SERVER_BAKE)
 		{
 			mWriteToCacheState = CAN_WRITE;
 		}
-#endif
+
 		if (mCanUseHTTP && !mUrl.empty())
 		{
 			setState(WAIT_HTTP_RESOURCE);
@@ -1345,7 +1388,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			//recordTextureStart(false);
 			//setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 
-			LL_DEBUGS("Texture") << mID << " does this happen?" << LL_ENDL;
 			return false;
 		}
 	}
@@ -1487,12 +1529,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 								 << LL_ENDL;
 
 			// Will call callbackHttpGet when curl request completes
+			// Only server bake images use the returned headers currently, for getting retry-after field.
+			LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
 			mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass,
 																	  mWorkPriority,
 																	  mUrl,
 																	  mRequestedOffset,
 																	  mRequestedSize,
-																	  mFetcher->mHttpOptions,
+																	  options,
 																	  mFetcher->mHttpHeaders,
 																	  this);
 		}
@@ -1524,16 +1568,22 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			{
 				if (http_not_found == mGetStatus)
 				{
-					if(mWriteToCacheState == NOT_WRITE) //map tiles
+					if (mFTType != FTT_MAP_TILE)
+					{
+						LL_WARNS() << "Texture missing from server (404): " << mUrl << LL_ENDL;
+					}
+
+					if(mWriteToCacheState == NOT_WRITE) //map tiles or server bakes
 					{
 						setState(DONE);
 						releaseHttpSemaphore();
-						LL_DEBUGS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL;
-						return true; // failed, means no map tile on the empty region.
+						if (mFTType != FTT_MAP_TILE)
+						{
+							LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL;
+						}
+						return true; 
 					}
 
-					LL_WARNS() << "Texture missing from server (404): " << mUrl << LL_ENDL;
-
 					// roll back to try UDP
 					if (mCanUseNET)
 					{
@@ -1548,6 +1598,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				else if (http_service_unavail == mGetStatus)
 				{
 					LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
+					LL_INFOS() << "503: HTTP GET failed for: " << mUrl
+							<< " Status: " << mGetStatus.toHex()
+							<< " Reason: '" << mGetReason << "'"
+							<< LL_ENDL;
 				}
 				else if (http_not_sat == mGetStatus)
 				{
@@ -1562,7 +1616,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 							<< LL_ENDL;
 				}
 
-				mUrl.clear();
+				if (mFTType != FTT_SERVER_BAKE)
+				{
+					mUrl.clear();
+				}
 				if (cur_size > 0)
 				{
 					// Use available data
@@ -1589,7 +1646,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			// Clear the url since we're done with the fetch
 			// Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch
 			// next time the texture is requested, even if the data have already been fetched.
-			if(mWriteToCacheState != NOT_WRITE)
+			if(mWriteToCacheState != NOT_WRITE && mFTType != FTT_SERVER_BAKE)
 			{
 				// Why do we want to keep url if NOT_WRITE - is this a proxy for map tiles?
 				mUrl.clear();
@@ -1768,7 +1825,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0)
 				{
 					// Cache file should be deleted, try again
-// 					LL_WARNS() << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL;
+ 					LL_WARNS() << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL;
 					llassert_always(mDecodeHandle == 0);
 					mFormattedImage = NULL;
 					++mRetryAttempt;
@@ -1895,14 +1952,48 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, LLTimer::getTotalTime());
 	}
 
+	static LLCachedControl<F32> fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate", 0.0f);
+	F32 rand_val = ll_frand();
+	F32 rate = fake_failure_rate;
+	if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate))
+	{
+		LL_WARNS() << mID << " for debugging, setting fake failure status for texture " << mID
+				<< " (rand was " << rand_val << "/" << rate << ")" << LL_ENDL;
+		response->setStatus(LLCore::HttpStatus(503));
+	}
 	bool success = true;
 	bool partial = false;
 	LLCore::HttpStatus status(response->getStatus());
+	if (!status && (mFTType == FTT_SERVER_BAKE))
+	{
+		LL_INFOS() << mID << " state " << e_state_name[mState] << LL_ENDL;
+		mFetchRetryPolicy.onFailure(response);
+		F32 retry_after;
+		if (mFetchRetryPolicy.shouldRetry(retry_after))
+		{
+			LL_INFOS() << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << LL_ENDL;
+			mFetcher->removeFromHTTPQueue(mID, S32Bytes(0));
+			std::string reason(status.toString());
+			setGetStatus(status, reason);
+			releaseHttpSemaphore();
+			setState(LOAD_FROM_NETWORK);
+			return;
+		}
+		else
+		{
+			LL_INFOS() << mID << " will not retry" << LL_ENDL;
+		}
+	}
+	else
+	{
+		mFetchRetryPolicy.onSuccess();
+	}
 	
 	LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID
-			 << " status: " << status.toTerseString()
-			 << " '" << status.toString() << "'"
+						 << " status: " << status.toTerseString()
+						 << " '" << status.toString() << "'"
 						 << LL_ENDL;
+
 //	unsigned int offset(0), length(0), full_length(0);
 //	response->getRange(&offset, &length, &full_length);
 // 	LL_WARNS() << "HTTP COMPLETE: " << mID << " handle: " << handle
@@ -1911,13 +2002,18 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 // 			<< " offset: " << offset << " length: " << length
 // 			<< LL_ENDL;
 
+	std::string reason(status.toString());
+	setGetStatus(status, reason);
 	if (! status)
 	{
 		success = false;
-		std::string reason(status.toString());
-		setGetStatus(status, reason);
-		LL_WARNS() << "CURL GET FAILED, status: " << status.toTerseString()
-				<< " reason: " << reason << LL_ENDL;
+		if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them.
+		{
+			std::string reason(status.toString());
+			setGetStatus(status, reason);
+			LL_WARNS() << "CURL GET FAILED, status: " << status.toTerseString()
+					<< " reason: " << reason << LL_ENDL;
+		}
 	}
 	else
 	{
@@ -2477,7 +2573,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 	{
 		return false;
 	}
-	
+
+	if (f_type == FTT_SERVER_BAKE)
+	{
+		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << LL_ENDL;
+	}
 	LLTextureFetchWorker* worker = getWorker(id) ;
 	if (worker)
 	{
@@ -2493,7 +2593,18 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	S32 desired_size;
 	std::string exten = gDirUtilp->getExtension(url);
-	if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
+	if (f_type == FTT_SERVER_BAKE)
+	{
+		// SH-4030: This case should be redundant with the following one, just
+		// breaking it out here to clarify that it's intended behavior.
+		llassert(!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C));
+
+		// Do full requests for baked textures to reduce interim blurring.
+		LL_DEBUGS("Texture") << "full request for " << id << " texture is FTT_SERVER_BAKE" << LL_ENDL;
+		desired_size = MAX_IMAGE_DATA_SIZE;
+		desired_discard = 0;
+	}
+	else if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
 	{
 		LL_DEBUGS("Texture") << "full request for " << id << " exten is not J2C: " << exten << LL_ENDL;
 		// Only do partial requests for J2C at the moment
@@ -2535,7 +2646,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->mNeedsAux = needs_aux;
 		worker->setImagePriority(priority);
 		worker->setDesiredDiscard(desired_discard, desired_size);
-		worker->setCanUseHTTP(can_use_http) ;
+		worker->setCanUseHTTP(can_use_http);
+		worker->setUrl(url);
 		if (!worker->haveWork())
 		{
 			worker->setState(LLTextureFetchWorker::INIT);
@@ -2562,7 +2674,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->unlockWorkMutex();										// -Mw
 	}
 	
- 	LL_DEBUGS("Texture") << "REQUESTED: " << id << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL;
+ 	LL_DEBUGS("Texture") << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type)
+						 << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL;
 	return true;
 }
 
@@ -2741,7 +2854,8 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
 
 // Threads:  T*
 bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
-										LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
+										LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
+										LLCore::HttpStatus& last_http_get_status)
 {
 	bool res = false;
 	LLTextureFetchWorker* worker = getWorker(id);
@@ -2763,6 +2877,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
 		else if (worker->checkWork())
 		{
 			worker->lockWorkMutex();									// +Mw
+			last_http_get_status = worker->mGetStatus;
 			discard_level = worker->mDecodedDiscard;
 			raw = worker->mRawImage;
 			aux = worker->mAuxImage;
@@ -3233,25 +3348,14 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 
 void LLTextureFetchWorker::setState(e_state new_state)
 {
-	static const char* e_state_name[] =
-	{
-		"INVALID",
-		"INIT",
-		"LOAD_FROM_TEXTURE_CACHE",
-		"CACHE_POST",
-		"LOAD_FROM_NETWORK",
-		"LOAD_FROM_SIMULATOR",
-		"WAIT_HTTP_RESOURCE",
-		"WAIT_HTTP_RESOURCE2",
-		"SEND_HTTP_REQ",
-		"WAIT_HTTP_REQ",
-		"DECODE_IMAGE",
-		"DECODE_IMAGE_UPDATE",
-		"WRITE_TO_CACHE",
-		"WAIT_ON_WRITE",
-		"DONE"
-	};
-	LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << LL_ENDL;
+	if (mFTType == FTT_SERVER_BAKE)
+	{
+	// NOTE: turning on these log statements is a reliable way to get
+	// blurry images fairly frequently. Presumably this is an
+	// indication of some subtle timing or locking issue.
+
+//		LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << LL_ENDL;
+	}
 	mState = new_state;
 }
 
@@ -4016,7 +4120,7 @@ LLTextureFetchDebugger::~LLTextureFetchDebugger()
 
 void LLTextureFetchDebugger::init()
 {
-	mState = IDLE;
+	setDebuggerState(IDLE);
 	
 	mCacheReadTime = -1.f;
 	mCacheWriteTime = -1.f;
@@ -4113,7 +4217,7 @@ void LLTextureFetchDebugger::startDebug()
 	//clear the current fetching queue
 	gTextureList.clearFetchingRequests();
 
-	mState = START_DEBUG;
+	setDebuggerState(START_DEBUG);
 }
 
 bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
@@ -4188,7 +4292,7 @@ void LLTextureFetchDebugger::tryToStopDebug()
 
 	//clear the current debug work
 	S32 size = mFetchingHistory.size();
-	switch(mState)
+	switch(mDebuggerState)
 	{
 	case READ_CACHE:		
 		for(S32 i = 0 ; i < size; i++)
@@ -4261,7 +4365,7 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 
 	if(mFreezeHistory)
 	{
-		if(mState == REFETCH_VIS_CACHE || mState == REFETCH_VIS_HTTP)
+		if(mDebuggerState == REFETCH_VIS_CACHE || mDebuggerState == REFETCH_VIS_HTTP)
 		{
 			mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
 			mRefetchedVisData += worker->mFormattedImage->getDataSize();
@@ -4306,9 +4410,9 @@ void LLTextureFetchDebugger::unlockCache()
 void LLTextureFetchDebugger::debugCacheRead()
 {
 	lockCache();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = READ_CACHE;
+	setDebuggerState(READ_CACHE);
 	mCacheReadTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4342,9 +4446,9 @@ void LLTextureFetchDebugger::debugCacheWrite()
 	clearCache();
 
 	lockCache();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = WRITE_CACHE;
+	setDebuggerState(WRITE_CACHE);
 	mCacheWriteTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4371,9 +4475,9 @@ void LLTextureFetchDebugger::unlockDecoder()
 void LLTextureFetchDebugger::debugDecoder()
 {
 	lockDecoder();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = DECODING;
+	setDebuggerState(DECODING);
 	mDecodingTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4392,7 +4496,7 @@ void LLTextureFetchDebugger::debugDecoder()
 
 void LLTextureFetchDebugger::debugHTTP()
 {
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 
 	LLViewerRegion* region = gAgent.getRegion();
 	if (!region)
@@ -4409,7 +4513,7 @@ void LLTextureFetchDebugger::debugHTTP()
 	}
 	
 	mTimer.reset();
-	mState = HTTP_FETCHING;
+	setDebuggerState(HTTP_FETCHING);
 	mHTTPTime = -1.f;
 	
 	S32 size = mFetchingHistory.size();
@@ -4489,8 +4593,8 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
 
 void LLTextureFetchDebugger::debugGLTextureCreation()
 {
-	llassert_always(mState == IDLE);
-	mState = GL_TEX;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(GL_TEX);
 	mTempTexList.clear();
 
 	S32 size = mFetchingHistory.size();
@@ -4611,8 +4715,8 @@ void LLTextureFetchDebugger::scanRefetchList()
 
 void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_VIS_CACHE;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_VIS_CACHE);
 
 	clearTextures();
 	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
@@ -4626,8 +4730,8 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
 
 void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_VIS_HTTP;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_VIS_HTTP);
 
 	clearTextures();
 	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
@@ -4641,8 +4745,8 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
 
 void LLTextureFetchDebugger::debugRefetchAllFromCache()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_ALL_CACHE;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_ALL_CACHE);
 
 	clearTextures();
 	makeRefetchList();
@@ -4658,8 +4762,8 @@ void LLTextureFetchDebugger::debugRefetchAllFromCache()
 
 void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_ALL_HTTP;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_ALL_HTTP);
 
 	clearTextures();
 	makeRefetchList();
@@ -4675,19 +4779,19 @@ void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
 
 bool LLTextureFetchDebugger::update(F32 max_time)
 {
-	switch(mState)
+	switch(mDebuggerState)
 	{
 	case START_DEBUG:
 		if(processStartDebug(max_time))
 		{
-			mState = IDLE;
+			setDebuggerState(IDLE);
 		}
 		break;
 	case READ_CACHE:
 		if(!mTextureCache->update(1))
 		{
 			mCacheReadTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockCache();
 		}
 		break;
@@ -4695,7 +4799,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if(!mTextureCache->update(1))
 		{
 			mCacheWriteTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockCache();
 		}
 		break;
@@ -4703,7 +4807,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if(!mImageDecodeThread->update(1))
 		{
 			mDecodingTime =  mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockDecoder();
 		}
 		break;
@@ -4713,13 +4817,13 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
 		{
 			mHTTPTime =  mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 		}
 		break;
 	case GL_TEX:
 		if(processGLCreation(max_time))
 		{
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mTempTexList.clear();
 		}
 		break;
@@ -4727,7 +4831,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 		}
@@ -4736,7 +4840,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 		}
@@ -4753,7 +4857,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 			}
 
 			mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE; 
+			setDebuggerState(IDLE); 
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 			mRefetchList.clear();
@@ -4765,7 +4869,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 			mRefetchList.clear();
@@ -4773,11 +4877,11 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		}
 		break;
 	default:
-		mState = IDLE;
+		setDebuggerState(IDLE);
 		break;
 	}
 
-	return mState == IDLE;
+	return mDebuggerState == IDLE;
 }
 
 void LLTextureFetchDebugger::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index d7fb2b4356cb1c2f10a4342c45d4df0e50e28546..c4da2e868535e5ca81ff0dfb4f1f4579cd73f580 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -95,7 +95,8 @@ class LLTextureFetch : public LLWorkerThread
 
 	// Threads:  T*
 	bool getRequestFinished(const LLUUID& id, S32& discard_level,
-							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
+							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
+							LLCore::HttpStatus& last_http_get_status);
 
 	// Threads:  T*
 	bool updateRequestPriority(const LLUUID& id, F32 priority);
@@ -396,6 +397,9 @@ class LLTextureFetch : public LLWorkerThread
 	e_tex_source mFetchSource;
 	e_tex_source mOriginFetchSource;
 
+	// Retry logic
+	//LLAdaptiveRetryPolicy mFetchRetryPolicy;
+	
 public:
 	//debug use
 	LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
@@ -475,8 +479,9 @@ class LLTextureFetchDebugger : public LLCore::HttpHandler
 
 	typedef std::map<LLCore::HttpHandle, S32> handle_fetch_map_t;
 	handle_fetch_map_t mHandleToFetchIndex;
-	
-	e_debug_state mState;
+
+	void setDebuggerState(e_debug_state new_state) { mDebuggerState = new_state; }
+	e_debug_state mDebuggerState;
 	
 	F32 mCacheReadTime;
 	F32 mCacheWriteTime;
@@ -549,7 +554,7 @@ class LLTextureFetchDebugger : public LLCore::HttpHandler
 	void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux);
 	void callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response);
 
-	e_debug_state getState()             {return mState;}
+	e_debug_state getState()             {return mDebuggerState;}
 	S32  getNumFetchedTextures()         {return mNumFetchedTextures;}
 	S32  getNumFetchingRequests()        {return mFetchingHistory.size();}
 	S32  getNumCacheHits()               {return mNumCacheHits;}
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 8ee83b5df01ba8de96345add10661822370f1467..aa1f680a1e9bbcb47f12d07e07fdaaf8f5faa3db 100755
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -434,15 +434,7 @@ void LLAvatarTexBar::draw()
 		if (!layerset_buffer) continue;
 
 		LLColor4 text_color = LLColor4::white;
-		
-		if (layerset_buffer->uploadNeeded())
-		{
-			text_color = LLColor4::red;
-		}
- 		if (layerset_buffer->uploadInProgress())
-		{
-			text_color = LLColor4::magenta;
-		}
+
 		std::string text = layerset_buffer->dumpTextureInfo();
 		LLFontGL::getFontMonospace()->renderUTF8(text, 0, l_offset, v_offset + line_height*line_num,
 												 text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index a27105e22d8dcdbb4610775f12b8278c6a7fabbb..39adfb3431252c9a9425fdbffa0f64da9401b173 100755
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -54,6 +54,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif
 	mAvatarName = getChild<LLTextBox>("user_name");
 	mTime = getChild<LLTextBox>("time_box");
 	mMessage = getChild<LLTextBox>("message");
+	mMessage->setContentTrusted(false);
 
 	LLStyle::Params style_params;
 	LLFontGL* fontp = LLViewerChat::getChatFont();
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 51935dc03be8e63ce3ac14377dbe44592e2b7e23..907baf0661901f785d7b393b8354ee7672ea025d 100755
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -270,8 +270,12 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
     // customize panel's attributes
     // is it intended for displaying a tip?
     mIsTip = mNotification->getType() == "notifytip";
+
+    std::string notif_name = mNotification->getName();
     // is it a script dialog?
-    mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup");
+    mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup");
+
+    bool is_content_trusted = (notif_name != "LoadWebPage");
     // is it a caution?
     //
     // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
@@ -314,6 +318,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
     mTextBox->setMaxTextLength(MAX_LENGTH);
     mTextBox->setVisible(TRUE);
     mTextBox->setPlainText(!show_images);
+    mTextBox->setContentTrusted(is_content_trusted);
     mTextBox->setValue(mNotification->getMessage());
 	mTextBox->setIsFriendCallback(LLAvatarActions::isFriend);
 
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 148e5a015b199b4397c567cf7f36a6b4b2b3e4b5..2d458db36bb782d86be08b836c4e65380c2b6a1d 100755
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -54,6 +54,7 @@
 #include "llviewercamera.h"
 #include "llviewertexturelist.h"
 #include "llviewerobject.h"
+#include "llviewerwearable.h"
 #include "llviewerwindow.h"
 #include "llvoavatarself.h"
 #include "pipeline.h"
@@ -147,13 +148,20 @@ BOOL LLVisualParamHint::needsRender()
 
 void LLVisualParamHint::preRender(BOOL clear_depth)
 {
+	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
+	if (wearable)
+	{
+		wearable->setVolatile(TRUE);
+	}
 	mLastParamWeight = mVisualParam->getWeight();
-	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
-	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
+	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight);
+	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight);
 	gAgentAvatarp->setVisualParamWeight("Blink_Left", 0.f);
 	gAgentAvatarp->setVisualParamWeight("Blink_Right", 0.f);
 	gAgentAvatarp->updateComposites();
-	gAgentAvatarp->updateVisualParams();
+	// Calling LLCharacter version, as we don't want position/height changes to cause the avatar to jump
+	// up and down when we're doing preview renders. -Nyx
+	gAgentAvatarp->LLCharacter::updateVisualParams();
 	gAgentAvatarp->updateGeometry(gAgentAvatarp->mDrawable);
 	gAgentAvatarp->updateLOD();
 
@@ -238,7 +246,13 @@ BOOL LLVisualParamHint::render()
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
-	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight, FALSE);
+	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
+	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
+	if (wearable)
+	{
+		wearable->setVolatile(FALSE);
+	}
+
 	gAgentAvatarp->updateVisualParams();
 	gGL.color4f(1,1,1,1);
 	mGLTexturep->setGLTextureCreated(true);
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 7e80d72dec61596d782099e911e61c886aaf9e91..c0ba0a1f39d9911d84433850614616f7b461574b 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -84,7 +84,7 @@ bool LLGoogleTranslationHandler::parseResponse(
 		return false;
 	}
 
-	if (status != STATUS_OK)
+	if (status != HTTP_OK)
 	{
 		// Request failed. Extract error message from the response.
 		parseErrorResponse(root, status, err_msg);
@@ -186,7 +186,7 @@ bool LLBingTranslationHandler::parseResponse(
 	std::string& detected_lang,
 	std::string& err_msg) const
 {
-	if (status != STATUS_OK)
+	if (status != HTTP_OK)
 	{
 		static const std::string MSG_BEGIN_MARKER = "Message: ";
 		size_t begin = body.find(MSG_BEGIN_MARKER);
@@ -251,8 +251,6 @@ LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_la
 
 // virtual
 void LLTranslate::TranslationReceiver::completedRaw(
-	U32 http_status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
@@ -262,8 +260,8 @@ void LLTranslate::TranslationReceiver::completedRaw(
 
 	const std::string body = strstrm.str();
 	std::string translation, detected_lang, err_msg;
-	int status = http_status;
-	LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
+	int status = getStatus();
+	LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL;
 	LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
 	if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
 	{
@@ -301,12 +299,10 @@ LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
 
 // virtual
 void LLTranslate::KeyVerificationReceiver::completedRaw(
-	U32 http_status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
-	bool ok = (http_status == 200);
+	bool ok = (getStatus() == HTTP_OK);
 	setVerificationStatus(ok);
 }
 
@@ -398,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr
 			LLVersionInfo::getPatch(),
 			LLVersionInfo::getBuild());
 
-		sHeader.insert("Accept", "text/plain");
-		sHeader.insert("User-Agent", user_agent);
+		sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+		sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent);
 	}
 
 	LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index db5ad9479c13c5bb2f9b42a45ebb8e72b696babb..972274714a073607d8b498bbdaba01475ac51ac6 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -95,9 +95,6 @@ class LLTranslationAPIHandler
 	virtual bool isConfigured() const = 0;
 
 	virtual ~LLTranslationAPIHandler() {}
-
-protected:
-	static const int STATUS_OK = 200;
 };
 
 /// Google Translate v2 API handler.
@@ -201,8 +198,6 @@ public :
 		 * @see mHandler
 		 */
 		/*virtual*/ void completedRaw(
-			U32 http_status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 
@@ -250,8 +245,6 @@ public :
 		 * @see setVerificationStatus()
 		 */
 		/*virtual*/ void completedRaw(
-			U32 http_status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 
diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp
index 248f1bf1d55e8b25c63684aa9116290b6510fa5e..69b9b1f9f1aba978cb185f1a40da55ff86c8a1fd 100755
--- a/indra/newview/lluploadfloaterobservers.cpp
+++ b/indra/newview/lluploadfloaterobservers.cpp
@@ -1,6 +1,6 @@
 /**
  * @file lluploadfloaterobservers.cpp
- * @brief LLUploadModelPremissionsResponder definition
+ * @brief LLUploadModelPermissionsResponder definition
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -28,26 +28,31 @@
 
 #include "lluploadfloaterobservers.h"
 
-LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer)
+LLUploadModelPermissionsResponder::LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer)
 :mObserverHandle(observer)
 {
 }
 
-void LLUploadModelPremissionsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLUploadModelPermissionsResponder::httpFailure()
 {
-	LL_WARNS() << "LLUploadModelPremissionsResponder error [status:"
-			<< status << "]: " << content << LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 
 	LLUploadPermissionsObserver* observer = mObserverHandle.get();
 
 	if (observer)
 	{
-		observer->setPermissonsErrorStatus(status, reason);
+		observer->setPermissonsErrorStatus(getStatus(), getReason());
 	}
 }
 
-void LLUploadModelPremissionsResponder::result(const LLSD& content)
+void LLUploadModelPermissionsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLUploadPermissionsObserver* observer = mObserverHandle.get();
 
 	if (observer)
@@ -55,3 +60,4 @@ void LLUploadModelPremissionsResponder::result(const LLSD& content)
 		observer->onPermissionsReceived(content);
 	}
 }
+
diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h
index b43ddb44d95456e57c9e952a51153c4409675d39..4ff4a827a5ee5f9a409e5f4052909a9d064add6d 100755
--- a/indra/newview/lluploadfloaterobservers.h
+++ b/indra/newview/lluploadfloaterobservers.h
@@ -1,6 +1,6 @@
 /**
  * @file lluploadfloaterobservers.h
- * @brief LLUploadModelPremissionsResponder declaration
+ * @brief LLUploadModelPermissionsResponder declaration
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -39,7 +39,7 @@ class LLUploadPermissionsObserver
 	virtual ~LLUploadPermissionsObserver() {}
 
 	virtual void onPermissionsReceived(const LLSD& result) = 0;
-	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0;
 
 	LLHandle<LLUploadPermissionsObserver> getPermObserverHandle() const {return mUploadPermObserverHandle;}
 
@@ -54,7 +54,7 @@ class LLWholeModelFeeObserver
 	virtual ~LLWholeModelFeeObserver() {}
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
-	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
 
 	LLHandle<LLWholeModelFeeObserver> getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; }
 
@@ -80,17 +80,16 @@ class LLWholeModelUploadObserver
 };
 
 
-class LLUploadModelPremissionsResponder : public LLHTTPClient::Responder
+class LLUploadModelPermissionsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLUploadModelPermissionsResponder);
 public:
-
-	LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer);
-
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-
-	void result(const LLSD& content);
+	LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer);
 
 private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+
 	LLHandle<LLUploadPermissionsObserver> mObserverHandle;
 };
 
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
index 3d794f0d91db0c9f0995b3ab96a20d8383e2a32c..e390e8776db446a2c67d0ca5c1cb20500642c8e4 100755
--- a/indra/newview/llviewerdisplayname.cpp
+++ b/indra/newview/llviewerdisplayname.cpp
@@ -58,12 +58,12 @@ namespace LLViewerDisplayName
 
 class LLSetDisplayNameResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(LLSetDisplayNameResponder);
+private:
 	// only care about errors
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void httpFailure()
 	{
-		LL_WARNS() << "LLSetDisplayNameResponder error [status:"
-				<< status << "]: " << content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 		LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
 		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
 	}
@@ -86,7 +86,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl
 	// People API can return localized error messages.  Indicate our
 	// language preference via header.
 	LLSD headers;
-	headers["Accept-Language"] = LLUI::getLanguage();
+	headers[HTTP_OUT_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage();
 
 	// People API requires both the old and new value to change a variable.
 	// Our display name will be in cache before the viewer's UI is available
@@ -128,7 +128,7 @@ class LLSetDisplayNameReply : public LLHTTPNode
 		LLSD body = input["body"];
 
 		S32 status = body["status"].asInteger();
-		bool success = (status == 200);
+		bool success = (status == HTTP_OK);
 		std::string reason = body["reason"].asString();
 		LLSD content = body["content"];
 
@@ -137,7 +137,7 @@ class LLSetDisplayNameReply : public LLHTTPNode
 		// If viewer's concept of display name is out-of-date, the set request
 		// will fail with 409 Conflict.  If that happens, fetch up-to-date
 		// name information.
-		if (status == 409)
+		if (status == HTTP_CONFLICT)
 		{
 			LLUUID agent_id = gAgent.getID();
 			// Flush stale data
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 4237ffd2953488402f8f683770d21ec24bf43659..2c196ece5173707336ccbf2d2157b68a394ce137 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -143,14 +143,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 		 
 	addEntry(LLFolderType::FT_NONE, 				new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false, "default"));
 
-#if SUPPORT_ENSEMBLES
-	initEnsemblesFromFile();
-#else
 	for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type)
 	{
 		addEntry((LLFolderType::EType)type, 		new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false));
-	}	
-#endif
+	}
 }
 
 bool LLViewerFolderDictionary::initEnsemblesFromFile()
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index a4773646ef35d4c6e7ad193ba0a70ed7f161ff0f..b236bba3b713242f8cda4da8f550263b49009899 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -31,6 +31,7 @@
 #include "llsdserialize.h"
 #include "message.h"
 
+#include "llaisapi.h"
 #include "llagent.h"
 #include "llagentcamera.h"
 #include "llagentwearables.h"
@@ -65,9 +66,12 @@
 #include "llavataractions.h"
 #include "lllogininstance.h"
 #include "llfavoritesbar.h"
+#include "llclipboard.h"
+#include "llhttpretrypolicy.h"
 
-// Two do-nothing ops for use in callbacks.
+// do-nothing ops for use in callbacks.
 void no_op_inventory_func(const LLUUID&) {} 
+void no_op_llsd_func(const LLSD&) {}
 void no_op() {}
 
 ///----------------------------------------------------------------------------
@@ -256,7 +260,6 @@ class LLInventoryHandler : public LLCommandHandler
 };
 LLInventoryHandler gInventoryHandler;
 
-
 ///----------------------------------------------------------------------------
 /// Class LLViewerInventoryItem
 ///----------------------------------------------------------------------------
@@ -345,24 +348,6 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne
 	}
 }
 
-void LLViewerInventoryItem::removeFromServer()
-{
-	LL_DEBUGS() << "Removing inventory item " << mUUID << " from server."
-			 << LL_ENDL;
-
-	LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
-	gInventory.accountForUpdate(up);
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_RemoveInventoryItem);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 
-	msg->nextBlockFast(_PREHASH_InventoryData);
-	msg->addUUIDFast(_PREHASH_ItemID, mUUID);
-	gAgent.sendReliableMessage();
-}
-
 void LLViewerInventoryItem::updateServer(BOOL is_new) const
 {
 	if(!mIsComplete)
@@ -376,8 +361,9 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const
 	if(gAgent.getID() != mPermissions.getOwner())
 	{
 		// *FIX: deal with this better.
-		LL_WARNS() << "LLViewerInventoryItem::updateServer() - for unowned item"
-				<< LL_ENDL;
+		LL_WARNS() << "LLViewerInventoryItem::updateServer() - for unowned item "
+				   << ll_pretty_print_sd(this->asLLSD())
+				   << LL_ENDL;
 		return;
 	}
 	LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
@@ -444,7 +430,7 @@ void LLViewerInventoryItem::fetchFromServer(void) const
 }
 
 // virtual
-BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
+BOOL LLViewerInventoryItem::unpackMessage(const LLSD& item)
 {
 	BOOL rv = LLInventoryItem::fromLLSD(item);
 
@@ -469,7 +455,7 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_
 {
 	mTransactionID = transaction_id;
 }
-// virtual
+
 void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
 {
 	msg->addUUIDFast(_PREHASH_ItemID, mUUID);
@@ -488,6 +474,7 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
 	U32 crc = getCRC32();
 	msg->addU32Fast(_PREHASH_CRC, crc);
 }
+
 // virtual
 BOOL LLViewerInventoryItem::importFile(LLFILE* fp)
 {
@@ -599,6 +586,15 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego
 }
 
 
+void LLViewerInventoryCategory::packMessage(LLMessageSystem* msg) const
+{
+	msg->addUUIDFast(_PREHASH_FolderID, mUUID);
+	msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
+	S8 type = static_cast<S8>(mPreferredType);
+	msg->addS8Fast(_PREHASH_Type, type);
+	msg->addStringFast(_PREHASH_Name, mName);
+}
+
 void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
 {
 	LLMessageSystem* msg = gMessageSystem;
@@ -637,30 +633,6 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
 	gAgent.sendReliableMessage();
 }
 
-void LLViewerInventoryCategory::removeFromServer( void )
-{
-	LL_INFOS() << "Removing inventory category " << mUUID << " from server."
-			<< LL_ENDL;
-	// communicate that change with the server.
-	if(LLFolderType::lookupIsProtectedType(mPreferredType))
-	{
-		LLNotificationsUtil::add("CannotRemoveProtectedCategories");
-		return;
-	}
-
-	LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
-	gInventory.accountForUpdate(up);
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->nextBlockFast(_PREHASH_FolderData);
-	msg->addUUIDFast(_PREHASH_FolderID, mUUID);
-	gAgent.sendReliableMessage();
-}
-
 S32 LLViewerInventoryCategory::getVersion() const
 {
 	return mVersion;
@@ -729,6 +701,19 @@ bool LLViewerInventoryCategory::fetch()
 	return false;
 }
 
+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;
+}
+
 bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp)
 {
 	// *NOTE: This buffer size is hard coded into scanf() below.
@@ -894,6 +879,21 @@ 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
 ///----------------------------------------------------------------------------
@@ -1087,75 +1087,148 @@ void copy_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
-void link_inventory_item(
-	const LLUUID& agent_id,
-	const LLUUID& item_id,
-	const LLUUID& parent_id,
-	const std::string& new_name,
-	const std::string& new_description,
-	const LLAssetType::EType asset_type,
-	LLPointer<LLInventoryCallback> cb)
+// Create link to single inventory object.
+void link_inventory_object(const LLUUID& category,
+			 LLConstPointer<LLInventoryObject> baseobj,
+			 LLPointer<LLInventoryCallback> cb)
 {
-	const LLInventoryObject *baseobj = gInventory.getObject(item_id);
 	if (!baseobj)
 	{
-		LL_WARNS() << "attempt to link to unknown item, linked-to-item's itemID " << item_id << LL_ENDL;
-		return;
-	}
-	if (baseobj && baseobj->getIsLinkType())
-	{
-		LL_WARNS() << "attempt to create a link to a link, linked-to-item's itemID " << item_id << LL_ENDL;
+		LL_WARNS() << "Attempt to link to non-existent object" << LL_ENDL;
 		return;
 	}
 
-	if (baseobj && !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() << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << LL_ENDL;
-		return;
-	}
-	
-	LLUUID transaction_id;
-	LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
-	if (dynamic_cast<const LLInventoryCategory *>(baseobj))
-	{
-		inv_type = LLInventoryType::IT_CATEGORY;
-	}
-	else
+	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<LLInventoryCallback> cb)
+{
+	LLConstPointer<LLInventoryObject> 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<LLInventoryCallback> 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 LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
-		if (baseitem)
+		const LLInventoryObject* baseobj = *it;
+		if (!baseobj)
 		{
-			inv_type = baseitem->getInventoryType();
+			LL_WARNS() << "attempt to link to unknown object" << LL_ENDL;
+			continue;
 		}
-	}
 
-#if 1 // debugging stuff
-	LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
-	LL_DEBUGS() << "cat: " << cat << LL_ENDL;
-	
+		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() << "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<const LLInventoryCategory *>(baseobj))
+		{
+			inv_type = LLInventoryType::IT_CATEGORY;
+			asset_type = LLAssetType::AT_LINK_FOLDER;
+			linkee_id = baseobj->getUUID();
+		}
+		else
+		{
+			const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(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() << "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("Inventory") << "Linking Object [ name:" << baseobj->getName() 
+							   << " UUID:" << baseobj->getUUID() 
+							   << " ] into Category [ name:" << cat_name 
+							   << " UUID:" << category << " ] " << LL_ENDL;
 #endif
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_LinkInventoryItem);
-	msg->nextBlock(_PREHASH_AgentData);
+	}
+
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
 	{
-		msg->addUUIDFast(_PREHASH_AgentID, agent_id);
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		LLSD new_inventory = LLSD::emptyMap();
+		new_inventory["links"] = links;
+		LLPointer<AISCommand> cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb);
+		ais_ran = cmd_ptr->run_command();
 	}
-	msg->nextBlock(_PREHASH_InventoryBlock);
+
+	if (!ais_ran)
 	{
-		msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
-		msg->addUUIDFast(_PREHASH_FolderID, parent_id);
-		msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
-		msg->addUUIDFast(_PREHASH_OldItemID, item_id);
-		msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
-		msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
-		msg->addStringFast(_PREHASH_Name, new_name);
-		msg->addStringFast(_PREHASH_Description, new_description);
+		LLMessageSystem* msg = gMessageSystem;
+		for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter )
+		{
+			msg->newMessageFast(_PREHASH_LinkInventoryItem);
+			msg->nextBlock(_PREHASH_AgentData);
+			{
+				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			}
+			msg->nextBlock(_PREHASH_InventoryBlock);
+			{
+				LLSD link = (*iter);
+				msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+				msg->addUUIDFast(_PREHASH_FolderID, category);
+				msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
+				msg->addUUIDFast(_PREHASH_OldItemID, link["linked_id"].asUUID());
+				msg->addS8Fast(_PREHASH_Type, link["type"].asInteger());
+				msg->addS8Fast(_PREHASH_InvType, link["inv_type"].asInteger());
+				msg->addStringFast(_PREHASH_Name, link["name"].asString());
+				msg->addStringFast(_PREHASH_Description, link["desc"].asString());
+			}
+			gAgent.sendReliableMessage();
+		}
 	}
-	gAgent.sendReliableMessage();
 }
 
 void move_inventory_item(
@@ -1179,6 +1252,392 @@ void move_inventory_item(
 	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<LLInventoryCallback> cb)
+{
+	const LLUUID& item_id = update_item->getUUID();
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
+	{
+		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");
+			updates["hash_id"] = update_item->getTransactionID();
+		}
+		if (updates.has("shadow_id"))
+		{
+			updates.erase("shadow_id");
+			updates["hash_id"] = update_item->getTransactionID();
+		}
+		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+		ais_ran = cmd_ptr->run_command();
+	}
+	if (!ais_ran)
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
+		if(obj)
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, update_item->getTransactionID());
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addU32Fast(_PREHASH_CallbackID, 0);
+			update_item->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(update_item->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateItem(update_item);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
+}
+
+// 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<LLInventoryCallback> cb)
+{
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
+	{
+		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+		ais_ran = cmd_ptr->run_command();
+	}
+	if (!ais_ran)
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
+		if(obj)
+		{
+			LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+			new_item->copyViewerItem(obj);
+			new_item->fromLLSD(updates,false);
+
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, new_item->getTransactionID());
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addU32Fast(_PREHASH_CallbackID, 0);
+			new_item->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateItem(new_item);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
+}
+
+void update_inventory_category(
+	const LLUUID& cat_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb)
+{
+	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
+	if(obj)
+	{
+		if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
+		{
+			LLNotificationsUtil::add("CannotModifyProtectedCategories");
+			return;
+		}
+
+		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
+		new_cat->fromLLSD(updates);
+		// FIXME - restore this once the back-end work has been done.
+		if (AISCommand::isAPIAvailable())
+		{
+			LLSD new_llsd = new_cat->asLLSD();
+			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
+			cmd_ptr->run_command();
+		}
+		else // no cap
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_FolderData);
+			new_cat->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(new_cat->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateCategory(new_cat);
+			if (cb)
+			{
+				cb->fire(cat_id);
+			}
+		}
+	}
+}
+
+void remove_inventory_items(
+	LLInventoryObject::object_list_t& items_to_kill,
+	LLPointer<LLInventoryCallback> 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<LLInventoryCallback> cb)
+{
+	LLPointer<LLInventoryObject> obj = gInventory.getItem(item_id);
+	if (obj)
+	{
+		remove_inventory_item(obj, cb);
+	}
+	else
+	{
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL;
+	}
+}
+
+void remove_inventory_item(
+	LLPointer<LLInventoryObject> obj,
+	LLPointer<LLInventoryCallback> cb)
+{
+	if(obj)
+	{
+		const LLUUID item_id(obj->getUUID());
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL;
+		if (AISCommand::isAPIAvailable())
+		{
+			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
+			cmd_ptr->run_command();
+		}
+		else // no cap
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_RemoveInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addUUIDFast(_PREHASH_ItemID, item_id);
+			gAgent.sendReliableMessage();
+
+			// Update inventory and call callback immediately since
+			// message-based system has no callback mechanism (!)
+			gInventory.onObjectDeletedFromServer(item_id);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
+	else
+	{
+		// *TODO: Clean up callback?
+		LL_WARNS() << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL;
+	}
+}
+
+class LLRemoveCategoryOnDestroy: public LLInventoryCallback
+{
+public:
+	LLRemoveCategoryOnDestroy(const LLUUID& cat_id, LLPointer<LLInventoryCallback> 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() << "remove descendents failed, cannot remove category " << LL_ENDL;
+		}
+		else
+		{
+			remove_inventory_category(mID, mCB);
+		}
+	}
+private:
+	LLUUID mID;
+	LLPointer<LLInventoryCallback> mCB;
+};
+
+void remove_inventory_category(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb)
+{
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << LL_ENDL;
+	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
+	if(obj)
+	{
+		if(LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
+		{
+			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
+			return;
+		}
+		if (AISCommand::isAPIAvailable())
+		{
+			LLPointer<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
+			cmd_ptr->run_command();
+		}
+		else // no cap
+		{
+			// RemoveInventoryFolder does not remove children, so must
+			// clear descendents first.
+			LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
+			if(children != LLInventoryModel::CHILDREN_NO)
+			{
+				LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << LL_ENDL;
+				LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); 
+				purge_descendents_of(cat_id, wrap_cb);
+				return;
+			}
+
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_FolderData);
+			msg->addUUIDFast(_PREHASH_FolderID, cat_id);
+			gAgent.sendReliableMessage();
+
+			// Update inventory and call callback immediately since
+			// message-based system has no callback mechanism (!)
+			gInventory.onObjectDeletedFromServer(cat_id);
+			if (cb)
+			{
+				cb->fire(cat_id);
+			}
+		}
+	}
+	else
+	{
+		LL_WARNS() << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL;
+	}
+}
+
+void remove_inventory_object(
+	const LLUUID& object_id,
+	LLPointer<LLInventoryCallback> 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<LLInventoryCallback> cb)
+{
+	LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id);
+	if(children == LLInventoryModel::CHILDREN_NO)
+	{
+		LL_DEBUGS("Inventory") << "No descendents to purge for " << id << LL_ENDL;
+		return;
+	}
+	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
+	if (cat.notNull())
+	{
+		if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode())
+		{
+			// Something on the clipboard is in "cut mode" and needs to be preserved
+			LL_DEBUGS("Inventory") << "purge_descendents_of clipboard case " << cat->getName()
+								   << " iterate and purge non hidden items" << LL_ENDL;
+			LLInventoryModel::cat_array_t* categories;
+			LLInventoryModel::item_array_t* items;
+			// Get the list of direct descendants in tha categoy passed as argument
+			gInventory.getDirectDescendentsOf(id, categories, items);
+			std::vector<LLUUID> list_uuids;
+			// Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently)
+			// Note: we need to do that shallow copy as purging things will invalidate the categories or items lists
+			for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it)
+			{
+				list_uuids.push_back((*it)->getUUID());
+			}
+			for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
+			{
+				list_uuids.push_back((*it)->getUUID());
+			}
+			// Iterate through the list and only purge the UUIDs that are not on the clipboard
+			for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
+			{
+				if (!LLClipboard::instance().isOnClipboard(*it))
+				{
+					remove_inventory_object(*it, NULL);
+				}
+			}
+		}
+		else
+		{
+			if (AISCommand::isAPIAvailable())
+			{
+				LLPointer<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
+				cmd_ptr->run_command();
+			}
+			else // no cap
+			{
+				// Fast purge
+				LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << LL_ENDL;
+
+				// send it upstream
+				LLMessageSystem* msg = gMessageSystem;
+				msg->newMessage("PurgeInventoryDescendents");
+				msg->nextBlock("AgentData");
+				msg->addUUID("AgentID", gAgent.getID());
+				msg->addUUID("SessionID", gAgent.getSessionID());
+				msg->nextBlock("InventoryData");
+				msg->addUUID("FolderID", id);
+				gAgent.sendReliableMessage();
+
+				// Update model immediately because there is no callback mechanism.
+				gInventory.onDescendentsPurgedFromServer(id);
+				if (cb)
+				{
+					cb->fire(id);
+				}
+			}
+		}
+	}
+}
+
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src)
 {
 	LLUUID retval = LLUUID::null;
@@ -1278,6 +1737,53 @@ void create_new_item(const std::string& name,
 	
 }	
 
+void slam_inventory_folder(const LLUUID& folder_id,
+						   const LLSD& contents,
+						   LLPointer<LLInventoryCallback> cb)
+{
+	if (AISCommand::isAPIAvailable())
+	{
+		LL_DEBUGS("Avatar") << "using AISv3 to slam folder, id " << folder_id
+							<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
+		LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
+		cmd_ptr->run_command();
+	}
+	else // no cap
+	{
+		LL_DEBUGS("Avatar") << "using item-by-item calls to slam folder, id " << folder_id
+							<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
+		for (LLSD::array_const_iterator it = contents.beginArray();
+			 it != contents.endArray();
+			 ++it)
+		{
+			const LLSD& item_contents = *it;
+			LLViewerInventoryItem *item = new LLViewerInventoryItem;
+			item->fromLLSD(item_contents);
+			link_inventory_object(folder_id, item, cb);
+		}
+		remove_folder_contents(folder_id,false,cb);
+	}
+}
+
+void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
+							LLPointer<LLInventoryCallback> 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)
@@ -1713,3 +2219,5 @@ BOOL LLViewerInventoryItem::regenerateLink()
 	gInventory.notifyObservers();
 	return TRUE;
 }
+
+
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index a10eda947d823e55199db451e16859bf31012329..c284c703d4d18d413c646249f8b8105a87545817 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -118,14 +118,13 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	void cloneViewerItem(LLPointer<LLViewerInventoryItem>& newitem) const;
 
 	// virtual methods
-	virtual void removeFromServer( void );
 	virtual void updateParentOnServer(BOOL restamp) const;
 	virtual void updateServer(BOOL is_new) const;
 	void fetchFromServer(void) const;
 
-	//virtual void packMessage(LLMessageSystem* msg) const;
+	virtual void packMessage(LLMessageSystem* msg) const;
 	virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
-	virtual BOOL unpackMessage(LLSD item);
+	virtual BOOL unpackMessage(const LLSD& item);
 	virtual BOOL importFile(LLFILE* fp);
 	virtual BOOL importLegacyStream(std::istream& input_stream);
 
@@ -139,7 +138,6 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	void setComplete(BOOL complete) { mIsComplete = complete; }
 	//void updateAssetOnServer() const;
 
-	virtual void packMessage(LLMessageSystem* msg) const;
 	virtual void setTransactionID(const LLTransactionID& transaction_id);
 	struct comparePointers
 	{
@@ -198,10 +196,11 @@ class LLViewerInventoryCategory  : public LLInventoryCategory
 	LLViewerInventoryCategory(const LLViewerInventoryCategory* other);
 	void copyViewerCategory(const LLViewerInventoryCategory* other);
 
-	virtual void removeFromServer();
 	virtual void updateParentOnServer(BOOL restamp_children) const;
 	virtual void updateServer(BOOL is_new) const;
 
+	virtual void packMessage(LLMessageSystem* msg) const;
+
 	const LLUUID& getOwnerID() const { return mOwnerID; }
 
 	// Version handling
@@ -218,6 +217,8 @@ class LLViewerInventoryCategory  : public LLInventoryCategory
 	enum { DESCENDENT_COUNT_UNKNOWN = -1 };
 	S32 getDescendentCount() const { return mDescendentCount; }
 	void setDescendentCount(S32 descendents) { mDescendentCount = descendents; }
+	// How many descendents do we currently have information for in the InventoryModel?
+	S32 getViewerDescendentCount() const;
 
 	// file handling on the viewer. These are not meant for anything
 	// other than caching.
@@ -225,6 +226,8 @@ class LLViewerInventoryCategory  : public LLInventoryCategory
 	bool importFileLocal(LLFILE* fp);
 	void determineFolderType();
 	void changeType(LLFolderType::EType new_folder_type);
+	virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
+	virtual BOOL unpackMessage(const LLSD& category);
 
 private:
 	friend class LLInventoryModel;
@@ -264,9 +267,11 @@ class AddFavoriteLandmarkCallback : public LLInventoryCallback
 };
 
 typedef boost::function<void(const LLUUID&)> inventory_func_type;
-void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
-
+typedef boost::function<void(const LLSD&)> llsd_func_type;
 typedef boost::function<void()> nullary_func_type;
+
+void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
+void no_op_llsd_func(const LLSD&); // likewise for LLSD
 void no_op(); // A do-nothing nullary func.
 
 // Shim between inventory callback and boost function/callable
@@ -274,7 +279,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback
 {
 public:
 
-	LLBoostFuncInventoryCallback(inventory_func_type fire_func,
+	LLBoostFuncInventoryCallback(inventory_func_type fire_func = no_op_inventory_func,
 								 nullary_func_type destroy_func = no_op):
 		mFireFunc(fire_func),
 		mDestroyFunc(destroy_func)
@@ -348,14 +353,16 @@ void copy_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
-void link_inventory_item(
-	const LLUUID& agent_id,
-	const LLUUID& item_id,
-	const LLUUID& parent_id,
-	const std::string& new_name,
-	const std::string& new_description,
-	const LLAssetType::EType asset_type,
-	LLPointer<LLInventoryCallback> cb);
+// utility functions for inventory linking.
+void link_inventory_object(const LLUUID& category,
+			 LLConstPointer<LLInventoryObject> baseobj,
+			 LLPointer<LLInventoryCallback> cb);
+void link_inventory_object(const LLUUID& category,
+			 const LLUUID& id,
+			 LLPointer<LLInventoryCallback> cb);
+void link_inventory_array(const LLUUID& category,
+						  LLInventoryObject::const_object_list_t& baseobj_array,
+						  LLPointer<LLInventoryCallback> cb);
 
 void move_inventory_item(
 	const LLUUID& agent_id,
@@ -365,6 +372,44 @@ void move_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
+void update_inventory_item(
+	LLViewerInventoryItem *update_item,
+	LLPointer<LLInventoryCallback> cb);
+
+void update_inventory_item(
+	const LLUUID& item_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb);
+
+void update_inventory_category(
+	const LLUUID& cat_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb);
+
+void remove_inventory_items(
+	LLInventoryObject::object_list_t& items,
+	LLPointer<LLInventoryCallback> cb);
+
+void remove_inventory_item(
+	LLPointer<LLInventoryObject> obj,
+	LLPointer<LLInventoryCallback> cb);
+
+void remove_inventory_item(
+	const LLUUID& item_id,
+	LLPointer<LLInventoryCallback> cb);
+	
+void remove_inventory_category(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb);
+	
+void remove_inventory_object(
+	const LLUUID& object_id,
+	LLPointer<LLInventoryCallback> cb);
+
+void purge_descendents_of(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb);
+
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src);
 
 void copy_inventory_from_notecard(const LLUUID& destination_id,
@@ -379,4 +424,11 @@ void menu_create_inventory_item(LLInventoryPanel* root,
 								const LLSD& userdata,
 								const LLUUID& default_parent_uuid = LLUUID::null);
 
+void slam_inventory_folder(const LLUUID& folder_id,
+						   const LLSD& contents,
+						   LLPointer<LLInventoryCallback> cb);
+
+void remove_folder_contents(const LLUUID& folder_id, bool keep_outfit_links,
+							  LLPointer<LLInventoryCallback> cb);
+
 #endif // LL_LLVIEWERINVENTORY_H
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 7a1b25e194663062dcbb97f7cfd86a8b7f63a4ad..bdda37cc5ff2c054677ca781e5dcfbc2922c2180 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -157,7 +157,7 @@ LLViewerMediaObserver::~LLViewerMediaObserver()
 // on the Panel Land Media and to discover the MIME type
 class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
 {
-LOG_CLASS(LLMimeDiscoveryResponder);
+	LOG_CLASS(LLMimeDiscoveryResponder);
 public:
 	LLMimeDiscoveryResponder( viewer_media_t media_impl)
 		: mMediaImpl(media_impl),
@@ -176,13 +176,19 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 		disconnectOwner();
 	}
 
-	virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpCompleted()
 	{
-		std::string media_type = content["content-type"].asString();
+		if (!isGoodStatus())
+		{
+			LL_WARNS() << dumpResponse()
+					<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
+		}
+		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
 		std::string::size_type idx1 = media_type.find_first_of(";");
 		std::string mime_type = media_type.substr(0, idx1);
 
-		LL_DEBUGS() << "status is " << status << ", media type \"" << media_type << "\"" << LL_ENDL;
+		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL;
 		
 		// 2xx status codes indicate success.
 		// Most 4xx status codes are successful enough for our purposes.
@@ -199,32 +205,27 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 //			)
 		// We now no longer check the error code returned from the probe.
 		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
-		if(1)
+		//if(1)
 		{
 			// The probe was successful.
 			if(mime_type.empty())
 			{
 				// Some sites don't return any content-type header at all.
 				// Treat an empty mime type as text/html.
-				mime_type = "text/html";
-			}
-			
-			completeAny(status, mime_type);
-		}
-		else
-		{
-			LL_WARNS() << "responder failed with status " << status << ", reason " << reason << LL_ENDL;
-		
-			if(mMediaImpl)
-			{
-				mMediaImpl->mMediaSourceFailed = true;
+				mime_type = HTTP_CONTENT_TEXT_HTML;
 			}
 		}
+		//else
+		//{
+		//	LL_WARNS() << "responder failed with status " << dumpResponse() << LL_ENDL;
+		//
+		//	if(mMediaImpl)
+		//	{
+		//		mMediaImpl->mMediaSourceFailed = true;
+		//	}
+		//	return;
+		//}
 
-	}
-
-	void completeAny(U32 status, const std::string& mime_type)
-	{
 		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
 		// Make a local copy so we can call loadURI() afterwards.
 		LLViewerMediaImpl *impl = mMediaImpl;
@@ -240,6 +241,7 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 		}
 	}
 	
+public:
 	void cancelRequest()
 	{
 		disconnectOwner();
@@ -268,7 +270,7 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 
 class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
 {
-LOG_CLASS(LLViewerMediaOpenIDResponder);
+	LOG_CLASS(LLViewerMediaOpenIDResponder);
 public:
 	LLViewerMediaOpenIDResponder( )
 	{
@@ -278,23 +280,17 @@ LOG_CLASS(LLViewerMediaOpenIDResponder);
 	{
 	}
 
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
-		LL_DEBUGS("MediaAuth") << content << LL_ENDL;
-		std::string cookie = content["set-cookie"].asString();
-		
-		LLViewerMedia::openIDCookieResponse(cookie);
-	}
-
 	/* virtual */ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
+		// We don't care about the content of the response, only the Set-Cookie header.
+		LL_DEBUGS("MediaAuth") << dumpResponse() 
+				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
+		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
+		
+		// *TODO: What about bad status codes?  Does this destroy previous cookies?
+		LLViewerMedia::openIDCookieResponse(cookie);
 	}
 
 };
@@ -312,17 +308,23 @@ LOG_CLASS(LLViewerMediaWebProfileResponder);
 	{
 	}
 
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	 void completedRaw(
+		const LLChannelDescriptors& channels,
+		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+		// We don't care about the content of the response, only the set-cookie header.
+		LL_WARNS("MediaAuth") << dumpResponse() 
+				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
 
-		LLSD stripped_content = content;
-		stripped_content.erase("set-cookie");
+		LLSD stripped_content = getResponseHeaders();
+		// *TODO: Check that this works.
+		stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE);
 		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL;
 
-		std::string cookie = content["set-cookie"].asString();
+		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
 		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
 
+		// *TODO: What about bad status codes?  Does this destroy previous cookies?
 		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
 
 		// Set cookie for snapshot publishing.
@@ -330,16 +332,6 @@ LOG_CLASS(LLViewerMediaWebProfileResponder);
 		LLWebProfile::setAuthCookie(auth_cookie);
 	}
 
-	 void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
-	}
-
 	std::string mHost;
 };
 
@@ -1386,10 +1378,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 LLSD LLViewerMedia::getHeaders()
 {
 	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "*/*";
-	headers["Content-Type"] = "application/xml";
-	headers["Cookie"] = sOpenIDCookie;
-	headers["User-Agent"] = getCurrentUserAgent();
+	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+	// *TODO: Should this be 'application/llsd+xml' ?
+	// *TODO: Should this even be set at all?   This header is only not overridden in 'GET' methods.
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+	headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
+	headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 	return headers;
 }
@@ -1427,9 +1421,9 @@ void LLViewerMedia::setOpenIDCookie()
 
 		// Do a web profile get so we can store the cookie 
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Cookie"] = sOpenIDCookie;
-		headers["User-Agent"] = getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 		std::string profile_url = getProfileURL("");
 		LLURL raw_profile_url( profile_url.c_str() );
@@ -1459,9 +1453,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string
 
 	LLSD headers = LLSD::emptyMap();
 	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers["Accept"] = "*/*";
+	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers["Content-Type"] = "application/x-www-form-urlencoded";
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
 
 	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
 	size_t size = openid_token.size();
@@ -1533,7 +1527,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 		// The null owner will keep the browser plugin from fully initializing
 		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
 		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
-		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
+		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0);
 	}
 }
 
@@ -1599,6 +1593,17 @@ void LLViewerMedia::cleanupClass()
 {
 	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection.disconnect();
+	if (sSpareBrowserMediaSource != NULL)
+	{
+		delete sSpareBrowserMediaSource;
+		sSpareBrowserMediaSource = NULL;
+	}
+
+	if (sCookieStore != NULL)
+	{
+		delete sCookieStore;
+		sCookieStore = NULL;
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2647,16 +2652,16 @@ void LLViewerMediaImpl::navigateInternal()
 			//    Accept: application/llsd+xml
 			// which is really not what we want.
 			LLSD headers = LLSD::emptyMap();
-			headers["Accept"] = "*/*";
+			headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers["Cookie"] = "";
+			headers[HTTP_OUT_HEADER_COOKIE] = "";
 			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
 		}
 		else if("data" == scheme || "file" == scheme || "about" == scheme)
 		{
 			// FIXME: figure out how to really discover the type for these schemes
 			// We use "data" internally for a text/html url for loading the login screen
-			if(initializeMedia("text/html"))
+			if(initializeMedia(HTTP_CONTENT_TEXT_HTML))
 			{
 				loadURI();
 			}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9c08ec7e77d0945d95185a449235babf2db91374..b23e23f32e4d49945502d0fc0ddc1a344997860e 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7839,6 +7839,7 @@ void handle_buy_currency_test(void*)
 	LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
 }
 
+// SUNSHINE CLEANUP - is only the request update at the end needed now?
 void handle_rebake_textures(void*)
 {
 	if (!isAgentAvatarValid()) return;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 00d28a43074141639ecba06a7df7baeba863329d..0d1ffd2b51608eaf641acea58e0ed4ffe3bb21ae 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1010,7 +1010,12 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
 protected:
 	/*virtual*/ void done()
 	{
-		for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();)
+		uuid_vec_t added;
+		for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
+		{
+			added.push_back(*it);
+		}
+		for (uuid_vec_t::iterator it = added.begin(); it != added.end();)
 		{
 			const LLUUID& item_uuid = *it;
 			bool was_moved = false;
@@ -1032,13 +1037,12 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
 
 			if (was_moved)
 			{
-				it = mAdded.erase(it);
+				it = added.erase(it);
 			}
 			else ++it;
 		}
 
-		open_inventory_offer(mAdded, "");
-		mAdded.clear();
+		open_inventory_offer(added, "");
 	}
  };
 
@@ -1047,8 +1051,12 @@ class LLOpenTaskGroupOffer : public LLInventoryAddedObserver
 protected:
 	/*virtual*/ void done()
 	{
-		open_inventory_offer(mAdded, "group_offer");
-		mAdded.clear();
+		uuid_vec_t added;
+		for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
+		{
+			added.push_back(*it);
+		}
+		open_inventory_offer(added, "group_offer");
 		gInventory.removeObserver(this);
 		delete this;
 	}
@@ -4001,6 +4009,8 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
 	gAgent.setTeleportState( LLAgent::TELEPORT_MOVING );
 	gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]);
 
+	LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_teleport_finish(). Seed cap == "
+			<< seedCap << LL_ENDL;
 	regionp->setSeedCapability(seedCap);
 
 	// Don't send camera updates to the new region until we're
@@ -4116,10 +4126,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
 
 		gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL );
 
-		// set the appearance on teleport since the new sim does not
-		// know what you look like.
-		gAgent.sendAgentSetAppearance();
-
 		if (isAgentAvatarValid())
 		{
 			// Set the new position
@@ -4243,6 +4249,9 @@ void process_crossed_region(LLMessageSystem* msg, void**)
 	send_complete_agent_movement(sim_host);
 
 	LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host);
+
+	LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_crossed_region(). Seed cap == "
+			<< seedCap << LL_ENDL;
 	regionp->setSeedCapability(seedCap);
 }
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1dabe0794272753096e80202da46b30e6c849d98..7c60be7046267f049f31f484837d2a8cd389c0e9 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -56,6 +56,7 @@
 #include "llaudiosourcevo.h"
 #include "llagent.h"
 #include "llagentcamera.h"
+#include "llagentwearables.h"
 #include "llbbox.h"
 #include "llbox.h"
 #include "llcylinder.h"
@@ -152,6 +153,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
 			{
 				gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp);
 				gAgentAvatarp->initInstance();
+				gAgentWearables.setAvatarObject(gAgentAvatarp);
 			}
 			else 
 			{
@@ -5502,6 +5504,28 @@ void LLViewerObject::clearDrawableState(U32 state, BOOL recursive)
 	}
 }
 
+BOOL LLViewerObject::isDrawableState(U32 state, BOOL recursive) const
+{
+	BOOL matches = FALSE;
+	if (mDrawable)
+	{
+		matches = mDrawable->isState(state);
+	}
+	if (recursive)
+	{
+		for (child_list_t::const_iterator iter = mChildList.begin();
+			 (iter != mChildList.end()) && matches; iter++)
+		{
+			LLViewerObject* child = *iter;
+			matches &= child->isDrawableState(state, recursive);
+		}
+	}
+
+	return matches;
+}
+
+
+
 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 // RN: these functions assume a 2-level hierarchy 
 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index d92c00a6b21fb9ee532b19b67df0f0fe0d98e25c..bab107cc5709b67b62d9233b829d6adec0074833 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -415,6 +415,7 @@ class LLViewerObject
 
 	void setDrawableState(U32 state, BOOL recursive = TRUE);
 	void clearDrawableState(U32 state, BOOL recursive = TRUE);
+	BOOL isDrawableState(U32 state, BOOL recursive = TRUE) const;
 
 	// Called when the drawable shifts
 	virtual void onShift(const LLVector4a &shift_vector)	{ }
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 0e40db8504d2294516cc3c256fdc6b072256dc34..7f5d2ac125cf314fecbd9119b44b88aad999eb97 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -796,6 +796,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 
 class LLObjectCostResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLObjectCostResponder);
 public:
 	LLObjectCostResponder(const LLSD& object_ids)
 		: mObjectIDs(object_ids)
@@ -816,20 +817,19 @@ class LLObjectCostResponder : public LLCurl::Responder
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
-		LL_WARNS()
-			<< "Transport error requesting object cost "
-			<< "[status: " << statusNum << "]: "
-			<< content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 
 		// TODO*: Error message to user
 		// For now just clear the request from the pending list
 		clear_object_list_pending_requests();
 	}
 
-	void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if ( !content.isMap() || content.has("error") )
 		{
 			// Improper response or the request had an error,
@@ -885,6 +885,7 @@ class LLObjectCostResponder : public LLCurl::Responder
 
 class LLPhysicsFlagsResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLPhysicsFlagsResponder);
 public:
 	LLPhysicsFlagsResponder(const LLSD& object_ids)
 		: mObjectIDs(object_ids)
@@ -905,20 +906,19 @@ class LLPhysicsFlagsResponder : public LLCurl::Responder
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
-		LL_WARNS()
-			<< "Transport error requesting object physics flags "
-			<< "[status: " << statusNum << "]: "
-			<< content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 
 		// TODO*: Error message to user
 		// For now just clear the request from the pending list
 		clear_object_list_pending_requests();
 	}
 
-	void result(const LLSD& content)
+	/* virtual void */ void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if ( !content.isMap() || content.has("error") )
 		{
 			// Improper response or the request had an error,
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index b55154f889d325e14f38f8a04465ce8aeed78494..37b249dddd14c2cbdb8ac373b8be136981d3bcde 100755
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -99,7 +99,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
 			std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL());
 
 			// if we have a current (link sharing) url, use it instead
-			if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html")
+			if (mediaCurrentUrl != "" && parcel->getMediaType() == HTTP_CONTENT_TEXT_HTML)
 			{
 				mediaUrl = mediaCurrentUrl;
 			}
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 9f80c84703d1fd9ec3cb3ad5971824b82917565e..be0f28df44ed03e714ee9bbdd6fa90d0e8ae4ea6 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -30,6 +30,7 @@
 
 // linden libraries
 #include "indra_constants.h"
+#include "llaisapi.h"
 #include "llavatarnamecache.h"		// name lookup cap url
 #include "llfloaterreg.h"
 #include "llmath.h"
@@ -80,6 +81,11 @@
 	#pragma warning(disable:4355)
 #endif
 
+// When we receive a base grant of capabilities that has a different number of 
+// capabilities than the original base grant received for the region, print 
+// out the two lists of capabilities for analysis.
+//#define DEBUG_CAPS_GRANTS
+
 const F32 WATER_TEXTURE_SCALE = 8.f;			//  Number of times to repeat the water texture across a region
 const S16 MAX_MAP_DIST = 10;
 // The server only keeps our pending agent info for 60 seconds.
@@ -97,6 +103,8 @@ S32  LLViewerRegion::sNewObjectCreationThrottle = -1;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
+static void log_capabilities(const CapabilityMap &capmap);
+
 class LLViewerRegionImpl {
 public:
 	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
@@ -164,7 +172,7 @@ class LLViewerRegionImpl {
 
 	CapabilityMap mCapabilities;
 	CapabilityMap mSecondCapabilitiesTracker; 
-	
+
 	LLEventPoll* mEventPoll;
 
 	S32 mSeedCapMaxAttempts;
@@ -228,24 +236,30 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 {
 	LOG_CLASS(BaseCapabilitiesComplete);
 public:
-    BaseCapabilitiesComplete(U64 region_handle, S32 id)
+	BaseCapabilitiesComplete(U64 region_handle, S32 id)
 		: mRegionHandle(region_handle), mID(id)
-    { }
+	{ }
 	virtual ~BaseCapabilitiesComplete()
 	{ }
 
-    void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-    {
-		LL_WARNS("AppInit", "Capabilities") << "[status:" << statusNum << ":] " << content << LL_ENDL;
+	static BaseCapabilitiesComplete* build( U64 region_handle, S32 id )
+	{
+		return new BaseCapabilitiesComplete(region_handle, id);
+	}
+
+private:
+	/* virtual */void httpFailure()
+	{
+		LL_WARNS("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if (regionp)
 		{
 			regionp->failedSeedCapability();
 		}
-    }
+	}
 
-    void result(const LLSD& content)
-    {
+	/* virtual */ void httpSuccess()
+	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if(!regionp) //region was removed
 		{
@@ -259,12 +273,19 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 			return ;
 		}
 
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
 			regionp->setCapability(iter->first, iter->second);
-			
-			LL_DEBUGS("AppInit", "Capabilities") << "got capability for " << iter->first << LL_ENDL;
+
+			LL_DEBUGS("AppInit", "Capabilities") << "got capability for " 
+				<< iter->first << LL_ENDL;
 
 			/* HACK we're waiting for the ServerReleaseNotes */
 			if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())
@@ -281,11 +302,6 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 		}
 	}
 
-    static BaseCapabilitiesComplete* build( U64 region_handle, S32 id )
-    {
-		return new BaseCapabilitiesComplete(region_handle, id);
-    }
-
 private:
 	U64 mRegionHandle;
 	S32 mID;
@@ -302,19 +318,32 @@ class BaseCapabilitiesCompleteTracker :  public LLHTTPClient::Responder
 	virtual ~BaseCapabilitiesCompleteTracker()
 	{ }
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+	static BaseCapabilitiesCompleteTracker* build( U64 region_handle )
+	{
+		return new BaseCapabilitiesCompleteTracker( region_handle );
+	}
+
+private:
+	/* virtual */ void httpFailure()
 	{
-		LL_WARNS() << "BaseCapabilitiesCompleteTracker error [status:"
-				<< statusNum << "]: " << content << LL_ENDL;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 	}
 
-	void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if( !regionp ) 
 		{
+			LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
 			return ;
-		}		
+		}
+
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
@@ -324,32 +353,46 @@ class BaseCapabilitiesCompleteTracker :  public LLHTTPClient::Responder
 		
 		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
 		{
-			LL_INFOS() << "BaseCapabilitiesCompleteTracker " << "sim " << regionp->getName()
-				<< " sent duplicate seed caps that differs in size - most likely content. " 
-				<< (S32) regionp->getRegionImpl()->mCapabilities.size() << " vs " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
-				<< LL_ENDL;			
-			
-			//todo#add cap debug versus original check?
-			/*
-			CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();
-			while (iter!=regionp->getRegionImpl()->mCapabilities.end() )
+			LL_WARNS("AppInit", "Capabilities") 
+				<< "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
+				<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
+				<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
+				<< LL_ENDL;
+#ifdef DEBUG_CAPS_GRANTS
+			LL_WARNS("AppInit", "Capabilities")
+				<< "Initial Base capabilities: " << LL_ENDL;
+
+			log_capabilities(regionp->getRegionImpl()->mCapabilities);
+
+			LL_WARNS("AppInit", "Capabilities")
+							<< "Latest base capabilities: " << LL_ENDL;
+
+			log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
+
+#endif
+
+			if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() )
 			{
-				LL_INFOS() << "BaseCapabilitiesCompleteTracker Original " << iter->first << " " << iter->second<<LL_ENDL;
-				++iter;
+				// *HACK Since we were granted more base capabilities in this grant request than the initial, replace
+				// the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a
+				// sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the
+				// inventory api capability grants.
+
+				// Need to clear a std::map before copying into it because old keys take precedence.
+				regionp->getRegionImplNC()->mCapabilities.clear();
+				regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker;
 			}
-			*/
-			regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
 		}
-
+		else
+		{
+			LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
+		}
+		regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
 	}
 
-	static BaseCapabilitiesCompleteTracker* build( U64 region_handle )
-	{
-		return new BaseCapabilitiesCompleteTracker( region_handle );
-	}
 
 private:
-	U64 mRegionHandle;	
+	U64 mRegionHandle;
 };
 
 
@@ -369,7 +412,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mSimAccess( SIM_ACCESS_MIN ),
 	mBillableFactor(1.0),
 	mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
-	mCentralBakeVersion(0),
+	mCentralBakeVersion(1),
 	mClassID(0),
 	mCPURatio(0),
 	mColoName("unknown"),
@@ -2584,6 +2627,8 @@ void LLViewerRegion::unpackRegionHandshake()
 	msg->nextBlock("RegionInfo");
 
 	U32 flags = 0;
+	flags |= REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE;
+
 	if(sVOCacheCullingEnabled)
 	{
 		flags |= 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects.		
@@ -2617,12 +2662,13 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("TwitterConnect");
 
 	if (gSavedSettings.getBOOL("UseHTTPInventory"))
-	{
+	{	
 		capabilityNames.append("FetchLib2");
 		capabilityNames.append("FetchLibDescendents2");
 		capabilityNames.append("FetchInventory2");
 		capabilityNames.append("FetchInventoryDescendents2");
 		capabilityNames.append("IncrementCOFVersion");
+		AISCommand::getCapabilityNames(capabilityNames);
 	}
 
 	capabilityNames.append("GetDisplayNames");
@@ -2637,7 +2683,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("LandResources");
 	capabilityNames.append("MapLayer");
 	capabilityNames.append("MapLayerGod");
-	capabilityNames.append("MeshUploadFlag");
+	capabilityNames.append("MeshUploadFlag");	
 	capabilityNames.append("NavMeshGenerationStatus");
 	capabilityNames.append("NewFileAgentInventory");
 	capabilityNames.append("ObjectMedia");
@@ -2678,7 +2724,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("ViewerMetrics");
 	capabilityNames.append("ViewerStartAuction");
 	capabilityNames.append("ViewerStats");
-	
+
 	// Please add new capabilities alphabetically to reduce
 	// merge conflicts.
 }
@@ -2686,8 +2732,11 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 void LLViewerRegion::setSeedCapability(const std::string& url)
 {
 	if (getCapability("Seed") == url)
-    {
-		//LL_WARNS() << "Ignoring duplicate seed capability" << LL_ENDL;
+    {	
+		setCapabilityDebug("Seed", url);
+		LL_DEBUGS("CrossingCaps") <<  "Received duplicate seed capability, posting to seed " <<
+				url	<< LL_ENDL;
+
 		//Instead of just returning we build up a second set of seed caps and compare them 
 		//to the "original" seed cap received and determine why there is problem!
 		LLSD capabilityNames = LLSD::emptyArray();
@@ -2760,31 +2809,36 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder
 {
 	LOG_CLASS(SimulatorFeaturesReceived);
 public:
-    SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
-			S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
-	: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
-    { }
-	
-	
-    void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-    {
-		LL_WARNS("AppInit", "SimulatorFeatures") << "[status:" << statusNum << "]: " << content << LL_ENDL;
+	SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
+							  S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
+		: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
+	{ }
+
+	/* virtual */ void httpFailure()
+	{
+		LL_WARNS("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL;
 		retry();
-    }
+	}
 
-    void result(const LLSD& content)
-    {
+	/* virtual */ void httpSuccess()
+	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if(!regionp) //region is removed or responder is not created.
 		{
-			LL_WARNS("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;
+			LL_WARNS("AppInit", "SimulatorFeatures") 
+				<< "Received results for region that no longer exists!" << LL_ENDL;
 			return ;
 		}
-		
+
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		regionp->setSimulatorFeatures(content);
 	}
 
-private:
 	void retry()
 	{
 		if (mAttempt < mMaxAttempts)
@@ -2794,7 +2848,7 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder
 			LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT);
 		}
 	}
-	
+
 	std::string mRetryURL;
 	U64 mRegionHandle;
 	S32 mAttempt;
@@ -2831,7 +2885,16 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
 
 void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url)
 {
-	mImpl->mSecondCapabilitiesTracker[name] = url;
+	// Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later.
+	if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) )
+	{
+		mImpl->mSecondCapabilitiesTracker[name] = url;
+		if(name == "GetTexture")
+		{
+			mHttpUrl = url ;
+		}
+	}
+
 }
 
 bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
@@ -2843,7 +2906,7 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
 {
 	if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
 	{
-		LL_WARNS() << "getCapability called before caps received" << LL_ENDL;
+		LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL;
 	}
 	
 	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
@@ -2855,6 +2918,22 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
 	return iter->second;
 }
 
+bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const
+{
+	if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
+	{
+		LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL;
+	}
+	
+	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
+	if(iter == mImpl->mCapabilities.end())
+	{
+		return false;
+	}
+
+	return true;
+}
+
 bool LLViewerRegion::capabilitiesReceived() const
 {
 	return mCapabilitiesReceived;
@@ -2882,16 +2961,7 @@ boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(cons
 
 void LLViewerRegion::logActiveCapabilities() const
 {
-	int count = 0;
-	CapabilityMap::const_iterator iter;
-	for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count)
-	{
-		if (!iter->second.empty())
-		{
-			LL_INFOS() << iter->first << " URL is " << iter->second << LL_ENDL;
-		}
-	}
-	LL_INFOS() << "Dumped " << count << " entries." << LL_ENDL;
+	log_capabilities(mImpl->mCapabilities);
 }
 
 LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
@@ -2983,7 +3053,21 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const
 	return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") &&
 			 mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean());
 }
+/* Static Functions */
 
+void log_capabilities(const CapabilityMap &capmap)
+{
+	S32 count = 0;
+	CapabilityMap::const_iterator iter;
+	for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count)
+	{
+		if (!iter->second.empty())
+		{
+			LL_INFOS() << "log_capabilities: " << iter->first << " URL is " << iter->second << LL_ENDL;
+		}
+	}
+	LL_INFOS() << "log_capabilities: Dumped " << count << " entries." << LL_ENDL;
+}
 void LLViewerRegion::resetMaterialsCapThrottle()
 {
 	F32 requests_per_sec = 	1.0f; // original default;
@@ -3028,3 +3112,4 @@ U32 LLViewerRegion::getMaxMaterialsPerTransaction() const
 }
 
 
+
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 00d3900a88c1fe79e1d51ff1787b30a09d944322..1e225553b8191ed3819607357dc6bcc47dc00caa 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -48,6 +48,8 @@
 #define WATER 2
 const U32	MAX_OBJECT_CACHE_ENTRIES = 50000;
 
+// Region handshake flags
+const U32 REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE = 1U << 2;
 
 class LLEventPoll;
 class LLVLComposition;
@@ -255,6 +257,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	S32 getNumSeedCapRetries();
 	void setCapability(const std::string& name, const std::string& url);
 	void setCapabilityDebug(const std::string& name, const std::string& url);
+	bool isCapabilityAvailable(const std::string& name) const;
 	// implements LLCapabilityProvider
     virtual std::string getCapability(const std::string& name) const;
 
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 9d2a4a50e120ad406d6f24dd19e41e2798c940ec..dafe2cafec02676632892c7871201e6be3f52432 100755
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -355,6 +355,16 @@ LLViewerShaderMgr * LLViewerShaderMgr::instance()
 	return static_cast<LLViewerShaderMgr*>(sInstance);
 }
 
+// static
+void LLViewerShaderMgr::releaseInstance()
+{
+	if (sInstance != NULL)
+	{
+		delete sInstance;
+		sInstance = NULL;
+	}
+}
+
 void LLViewerShaderMgr::initAttribsAndUniforms(void)
 {
 	if (mReservedAttribs.empty())
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 42147fdd2999f3bdc351e373fc1a543e4a0bcd56..923aa522ad2ebe85e74bb108eae0c6bafd577a5e 100755
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -43,6 +43,7 @@ class LLViewerShaderMgr: public LLShaderMgr
 
 	// singleton pattern implementation
 	static LLViewerShaderMgr * instance();
+	static void releaseInstance();
 
 	void initAttribsAndUniforms(void);
 	void setShaders();
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index d5ae2d1030837f995096da39cf7a5cde3adc8bae..f60829e9e8def1169f7e95c9b47219c7a9383ce5 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -412,18 +412,19 @@ void update_statistics()
 
 class ViewerStatsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ViewerStatsResponder);
 public:
-    ViewerStatsResponder() { }
+	ViewerStatsResponder() { }
 
-    void error(U32 statusNum, const std::string& reason)
-    {
-		LL_INFOS() << "ViewerStatsResponder::error " << statusNum << " "
-				<< reason << LL_ENDL;
-    }
+private:
+	/* virtual */ void httpFailure()
+	{
+		LL_WARNS() << dumpResponse() << LL_ENDL;
+	}
 
-    void result(const LLSD& content)
-    {
-		LL_INFOS() << "ViewerStatsResponder::result" << LL_ENDL;
+	/* virtual */ void httpSuccess()
+	{
+		LL_INFOS() << "OK" << LL_ENDL;
 	}
 };
 
@@ -622,44 +623,28 @@ void send_stats()
 	LLViewerStats::instance().getRecording().resume();
 }
 
-LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
+LLTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
 	if (iter == mPhaseMap.end())
 	{
-		LLFrameTimer timer;
+		LLTimer timer;
 		mPhaseMap[phase_name] = timer;
 	}
-	LLFrameTimer& timer = mPhaseMap[phase_name];
+	LLTimer& timer = mPhaseMap[phase_name];
 	return timer;
 }
 
 void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
 {
-	LLFrameTimer& timer = getPhaseTimer(phase_name);
-	LL_DEBUGS() << "startPhase " << phase_name << LL_ENDL;
-	timer.unpause();
-}
-
-void LLViewerStats::PhaseMap::stopAllPhases()
-{
-	for (phase_map_t::iterator iter = mPhaseMap.begin();
-		 iter != mPhaseMap.end(); ++iter)
-	{
-		const std::string& phase_name = iter->first;
-		if (iter->second.getStarted())
-		{
-			// Going from started to paused state - record stats.
-			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
-		}
-		LL_DEBUGS() << "stopPhase (all) " << phase_name << LL_ENDL;
-		iter->second.pause();
-	}
+	LLTimer& timer = getPhaseTimer(phase_name);
+	timer.start();
+	//LL_DEBUGS("Avatar") << "startPhase " << phase_name << LL_ENDL;
 }
 
 void LLViewerStats::PhaseMap::clearPhases()
 {
-	LL_DEBUGS() << "clearPhases" << LL_ENDL;
+	//LL_DEBUGS("Avatar") << "clearPhases" << LL_ENDL;
 
 	mPhaseMap.clear();
 }
@@ -684,7 +669,6 @@ LLViewerStats::PhaseMap::PhaseMap()
 {
 }
 
-
 void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
@@ -697,6 +681,7 @@ void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
 		}
 	}
 }
+
 // static
 LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
 {
@@ -720,14 +705,18 @@ void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32
 bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
+	bool found = false;
 	if (iter != mPhaseMap.end())
 	{
+		found = true;
 		elapsed =  iter->second.getElapsedTimeF32();
 		completed = !iter->second.getStarted();
-		return true;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << LL_ENDL;
 	}
 	else
 	{
-		return false;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << LL_ENDL;
 	}
+
+	return found;
 }
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 0d959ed034640b10d7f0c28d416cb2db62e38a10..7843652589f7621b60fa7db3696dcbb3d3ecbabe 100755
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -342,7 +342,7 @@ class LLViewerStats : public LLSingleton<LLViewerStats>
 
 	// Phase tracking (originally put in for avatar rezzing), tracking
 	// progress of active/completed phases for activities like outfit changing.
-	typedef std::map<std::string,LLFrameTimer>	phase_map_t;
+	typedef std::map<std::string,LLTimer>	phase_map_t;
 	typedef std::map<std::string,StatsAccumulator>	phase_stats_t;
 	class PhaseMap
 	{
@@ -351,11 +351,10 @@ class LLViewerStats : public LLSingleton<LLViewerStats>
 		static phase_stats_t sStats;
 	public:
 		PhaseMap();
-		LLFrameTimer& 	getPhaseTimer(const std::string& phase_name);
+		LLTimer& 		getPhaseTimer(const std::string& phase_name);
 		bool 			getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed);
 		void			startPhase(const std::string& phase_name);
 		void			stopPhase(const std::string& phase_name);
-		void			stopAllPhases();
 		void			clearPhases();
 		LLSD			asLLSD();
 		static StatsAccumulator& getPhaseStats(const std::string& phase_name);
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index 62e8da81ec021a6433dd17cacfa98ed42b18c993..65ba3fb6e5017fe80b221d228ee3f770457b92cd 100755
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -37,7 +37,6 @@
 #include "llglslshader.h"
 #include "llvoavatarself.h"
 #include "pipeline.h"
-#include "llassetuploadresponders.h"
 #include "llviewercontrol.h"
 
 static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
@@ -46,22 +45,6 @@ static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power o
 // runway consolidate
 extern std::string self_av_string();
 
-
-//-----------------------------------------------------------------------------
-// LLBakedUploadData()
-//-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
-									 LLViewerTexLayerSet* layerset,
-									 const LLUUID& id,
-									 bool highest_res) :
-	mAvatar(avatar),
-	mTexLayerSet(layerset),
-	mID(id),
-	mStartTime(LLFrameTimer::getTotalTime()),		// Record starting time
-	mIsHighestRes(highest_res)
-{ 
-}
-
 //-----------------------------------------------------------------------------
 // LLViewerTexLayerSetBuffer
 // The composite image that a LLViewerTexLayerSet writes to.  Each LLViewerTexLayerSet has one.
@@ -75,15 +58,10 @@ LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner,
 	// ORDER_LAST => must render these after the hints are created.
 	LLTexLayerSetBuffer(owner),
 	LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), 
-	mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
-	mNeedsUpload(FALSE),
-	mNumLowresUploads(0),
-	mUploadFailCount(0),
 	mNeedsUpdate(TRUE),
 	mNumLowresUpdates(0)
 {
 	LLViewerTexLayerSetBuffer::sGLByteCount += getSize();
-	mNeedsUploadTimer.start();
 	mNeedsUpdateTimer.start();
 }
 
@@ -126,33 +104,6 @@ void LLViewerTexLayerSetBuffer::requestUpdate()
 	restartUpdateTimer();
 	mNeedsUpdate = TRUE;
 	mNumLowresUpdates = 0;
-	// If we're in the middle of uploading a baked texture, we don't care about it any more.
-	// When it's downloaded, ignore it.
-	mUploadID.setNull();
-}
-
-void LLViewerTexLayerSetBuffer::requestUpload()
-{
-	conditionalRestartUploadTimer();
-	mNeedsUpload = TRUE;
-	mNumLowresUploads = 0;
-	mUploadPending = TRUE;
-}
-
-void LLViewerTexLayerSetBuffer::conditionalRestartUploadTimer()
-{
-	// If we requested a new upload but haven't even uploaded
-	// a low res version of our last upload request, then
-	// keep the timer ticking instead of resetting it.
-	if (mNeedsUpload && (mNumLowresUploads == 0))
-	{
-		mNeedsUploadTimer.unpause();
-	}
-	else
-	{
-		mNeedsUploadTimer.reset();
-		mNeedsUploadTimer.start();
-	}
 }
 
 void LLViewerTexLayerSetBuffer::restartUpdateTimer()
@@ -161,25 +112,16 @@ void LLViewerTexLayerSetBuffer::restartUpdateTimer()
 	mNeedsUpdateTimer.start();
 }
 
-void LLViewerTexLayerSetBuffer::cancelUpload()
-{
-	mNeedsUpload = FALSE;
-	mUploadPending = FALSE;
-	mNeedsUploadTimer.pause();
-	mUploadRetryTimer.reset();
-}
-
 // virtual
 BOOL LLViewerTexLayerSetBuffer::needsRender()
 {
 	llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp);
 	if (!isAgentAvatarValid()) return FALSE;
 
-	const BOOL upload_now = mNeedsUpload && isReadyToUpload();
 	const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
 
-	// Don't render if we don't want to (or aren't ready to) upload or update.
-	if (!(update_now || upload_now))
+	// Don't render if we don't want to (or aren't ready to) update.
+	if (!update_now)
 	{
 		return FALSE;
 	}
@@ -190,11 +132,10 @@ BOOL LLViewerTexLayerSetBuffer::needsRender()
 		return FALSE;
 	}
 
-	// Don't render if we are trying to create a shirt texture but aren't wearing a skirt.
+	// Don't render if we are trying to create a skirt texture but aren't wearing a skirt.
 	if (gAgentAvatarp->getBakedTE(getViewerTexLayerSet()) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && 
 		!gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
 	{
-		cancelUpload();
 		return FALSE;
 	}
 
@@ -222,36 +163,7 @@ void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
 // virtual
 void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success)
 {
-	// do we need to upload, and do we have sufficient data to create an uploadable composite?
-	// TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
-	const BOOL upload_now = mNeedsUpload && isReadyToUpload();
 	const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
-
-	if(upload_now)
-	{
-		if (!success)
-		{
-			LL_INFOS() << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << LL_ENDL;
-			mUploadPending = FALSE;
-		}
-		else
-		{
-			LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
-			if (layer_set->isVisible())
-			{
-				layer_set->getAvatar()->debugBakedTextureUpload(layer_set->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish.
-				doUpload();
-			}
-			else
-			{
-				mUploadPending = FALSE;
-				mNeedsUpload = FALSE;
-				mNeedsUploadTimer.pause();
-				layer_set->getAvatar()->setNewBakedTexture(layer_set->getBakedTexIndex(),IMG_INVISIBLE);
-			}
-		}
-	}
-	
 	if (update_now)
 	{
 		doUpdate();
@@ -267,60 +179,6 @@ BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const
 	return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
 }
 
-BOOL LLViewerTexLayerSetBuffer::uploadPending() const
-{
-	return mUploadPending;
-}
-
-BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const
-{
-	return mNeedsUpload;
-}
-
-BOOL LLViewerTexLayerSetBuffer::uploadInProgress() const
-{
-	return !mUploadID.isNull();
-}
-
-BOOL LLViewerTexLayerSetBuffer::isReadyToUpload() const
-{
-	if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
-	if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) return FALSE; // Don't upload if avatar is being edited.
-
-	BOOL ready = FALSE;
-	if (getViewerTexLayerSet()->isLocalTextureDataFinal())
-	{
-		// If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry)
-		if (mUploadFailCount == 0)
-		{
-			ready = TRUE;
-		}
-		else
-		{
-			ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1));
-		}
-	}
-	else
-	{
-		// Upload if we've hit a timeout.  Upload is a pretty expensive process so we need to make sure
-		// we aren't doing uploads too frequently.
-		const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
-		if (texture_timeout != 0)
-		{
-			// The timeout period increases exponentially between every lowres upload in order to prevent
-			// spamming the server with frequent uploads.
-			const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
-
-			// If we hit our timeout and have textures available at even lower resolution, then upload.
-			const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
-			const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable();
-			ready = has_lower_lod && is_upload_textures_timeout;
-		}
-	}
-
-	return ready;
-}
-
 BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const
 {
 	// If we requested an update and have the final LOD ready, then update.
@@ -358,159 +216,6 @@ BOOL LLViewerTexLayerSetBuffer::requestUpdateImmediate()
 	return result;
 }
 
-// Create the baked texture, send it out to the server, then wait for it to come
-// back so we can switch to using it.
-void LLViewerTexLayerSetBuffer::doUpload()
-{
-	LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
-	LL_DEBUGS("Avatar") << "Uploading baked " << layer_set->getBodyRegionName() << LL_ENDL;
-	add(LLStatViewer::TEX_BAKES, 1);
-
-	// Don't need caches since we're baked now.  (note: we won't *really* be baked 
-	// until this image is sent to the server and the Avatar Appearance message is received.)
-	layer_set->deleteCaches();
-
-	// Get the COLOR information from our texture
-	U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
-	glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
-	stop_glerror();
-
-	// Get the MASK information from our texture
-	LLGLSUIDefault gls_ui;
-	LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 );
-	U8* baked_mask_data = baked_mask_image->getData(); 
-	layer_set->gatherMorphMaskAlpha(baked_mask_data,
-									mOrigin.mX, mOrigin.mY,
-									mFullWidth, mFullHeight);
-
-
-	// Create the baked image from our color and mask information
-	const S32 baked_image_components = 5; // red green blue [bump] clothing
-	LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components );
-	U8* baked_image_data = baked_image->getData();
-	S32 i = 0;
-	for (S32 u=0; u < mFullWidth; u++)
-	{
-		for (S32 v=0; v < mFullHeight; v++)
-		{
-			baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
-			baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
-			baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
-			baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
-			baked_image_data[5*i + 4] = baked_mask_data[i];
-			i++;
-		}
-	}
-	
-	LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
-	const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask)
-	if (compressedImage->encode(baked_image, comment_text))
-	{
-		LLTransactionID tid;
-		tid.generate();
-		const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-		if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
-							   gVFS, asset_id, LLAssetType::AT_TEXTURE))
-		{
-			// Read back the file and validate.
-			BOOL valid = FALSE;
-			LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
-			S32 file_size = 0;
-			LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE);
-			file_size = file.getSize();
-			U8* data = integrity_test->allocateData(file_size);
-			file.read(data, file_size);
-			if (data)
-			{
-				valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data'
-			}
-			else
-			{
-				integrity_test->setLastError("Unable to read entire file");
-			}
-			
-			if (valid)
-			{
-				const bool highest_lod = layer_set->isLocalTextureDataFinal();
-				// Baked_upload_data is owned by the responder and deleted after the request completes.
-				LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, 
-																			 layer_set, 
-																			 asset_id,
-																			 highest_lod);
-				// upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
-				mUploadID = asset_id;
-
-				// Upload the image
-				const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
-				if(!url.empty()
-					&& !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
-					&& (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.
-				{
-					LLSD body = LLSD::emptyMap();
-					// The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete()
-					LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data));
-					LL_INFOS() << "Baked texture upload via capability of " << mUploadID << " to " << url << LL_ENDL;
-				} 
-				else
-				{
-					gAssetStorage->storeAssetData(tid,
-												  LLAssetType::AT_TEXTURE,
-												  LLViewerTexLayerSetBuffer::onTextureUploadComplete,
-												  baked_upload_data,
-												  TRUE,		// temp_file
-												  TRUE,		// is_priority
-												  TRUE);	// store_local
-					LL_INFOS() << "Baked texture upload via Asset Store." <<  LL_ENDL;
-				}
-
-				if (highest_lod)
-				{
-					// Sending the final LOD for the baked texture.  All done, pause 
-					// the upload timer so we know how long it took.
-					mNeedsUpload = FALSE;
-					mNeedsUploadTimer.pause();
-				}
-				else
-				{
-					// Sending a lower level LOD for the baked texture.  Restart the upload timer.
-					mNumLowresUploads++;
-					mNeedsUploadTimer.unpause();
-					mNeedsUploadTimer.reset();
-				}
-
-				// Print out notification that we uploaded this texture.
-				if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
-				{
-					const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
-					LLSD args;
-					args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32());
-					args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32());
-					args["BODYREGION"] = layer_set->getBodyRegionName();
-					args["RESOLUTION"] = lod_str;
-					LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args);
-					LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
-				}
-			}
-			else
-			{
-				// The read back and validate operation failed.  Remove the uploaded file.
-				mUploadPending = FALSE;
-				LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
-				file.remove();
-				LL_INFOS() << "Unable to create baked upload file (reason: corrupted)." << LL_ENDL;
-			}
-		}
-	}
-	else
-	{
-		// The VFS write file operation failed.
-		mUploadPending = FALSE;
-		LL_INFOS() << "Unable to create baked upload file (reason: failed to write file)" << LL_ENDL;
-	}
-
-	delete [] baked_color_data;
-}
-
 // Mostly bookkeeping; don't need to actually "do" anything since
 // render() will actually do the update.
 void LLViewerTexLayerSetBuffer::doUpdate()
@@ -547,82 +252,6 @@ void LLViewerTexLayerSetBuffer::doUpdate()
 	}
 }
 
-// static
-void LLViewerTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
-												  void* userdata,
-												  S32 result,
-												  LLExtStat ext_status) // StoreAssetData callback (not fixed)
-{
-	LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
-
-	if (isAgentAvatarValid() &&
-		!gAgentAvatarp->isDead() &&
-		(baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.
-		(baked_upload_data->mTexLayerSet->hasComposite()))
-	{
-		LLViewerTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getViewerComposite();
-		S32 failures = layerset_buffer->mUploadFailCount;
-		layerset_buffer->mUploadFailCount = 0;
-
-		if (layerset_buffer->mUploadID.isNull())
-		{
-			// The upload got canceled, we should be in the
-			// process of baking a new texture so request an
-			// upload with the new data
-
-			// BAP: does this really belong in this callback, as
-			// opposed to where the cancellation takes place?
-			// suspect this does nothing.
-			layerset_buffer->requestUpload();
-		}
-		else if (baked_upload_data->mID == layerset_buffer->mUploadID)
-		{
-			// This is the upload we're currently waiting for.
-			layerset_buffer->mUploadID.setNull();
-			const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName());
-			const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";
-			if (result >= 0)
-			{
-				layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later
-				LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->getViewerTexLayerSet());
-				// Update baked texture info with the new UUID
-				U64 now = LLFrameTimer::getTotalTime();		// Record starting time
-				LL_INFOS() << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << LL_ENDL;
-				gAgentAvatarp->setNewBakedTexture(baked_te, uuid);
-			}
-			else
-			{	
-				++failures;
-				S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes
-				LL_WARNS() << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << LL_ENDL;
-				if (failures < max_attempts)
-				{
-					layerset_buffer->mUploadFailCount = failures;
-					layerset_buffer->mUploadRetryTimer.start();
-					layerset_buffer->requestUpload();
-				}
-			}
-		}
-		else
-		{
-			LL_INFOS() << "Received baked texture out of date, ignored." << LL_ENDL;
-		}
-
-		gAgentAvatarp->dirtyMesh();
-	}
-	else
-	{
-		// Baked texture failed to upload (in which case since we
-		// didn't set the new baked texture, it means that they'll try
-		// and rebake it at some point in the future (after login?)),
-		// or this response to upload is out of date, in which case a
-		// current response should be on the way or already processed.
-		LL_WARNS() << "Baked upload failed" << LL_ENDL;
-	}
-
-	delete baked_upload_data;
-}
-
 //-----------------------------------------------------------------------------
 // LLViewerTexLayerSet
 // An ordered set of texture layers that get composited into a single texture.
@@ -664,20 +293,6 @@ void LLViewerTexLayerSet::requestUpdate()
 	}
 }
 
-void LLViewerTexLayerSet::requestUpload()
-{
-	createComposite();
-	getViewerComposite()->requestUpload();
-}
-
-void LLViewerTexLayerSet::cancelUpload()
-{
-	if(mComposite)
-	{
-		getViewerComposite()->cancelUpload();
-	}
-}
-
 void LLViewerTexLayerSet::updateComposite()
 {
 	createComposite();
@@ -730,19 +345,12 @@ const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
 {
 	if (!isAgentAvatarValid()) return "";
 
-	const BOOL is_high_res = !mNeedsUpload;
-	const U32 num_low_res = mNumLowresUploads;
-	const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
+	const BOOL is_high_res = TRUE; 
+	const U32 num_low_res = 0;
 	const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet());
 
-	std::string status 				= "CREATING ";
-	if (!uploadNeeded()) status 	= "DONE     ";
-	if (uploadInProgress()) status 	= "UPLOADING";
-
-	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
-								status.c_str(),
+	std::string text = llformat("[HiRes:%d LoRes:%d] %s",
 								is_high_res, num_low_res,
-								upload_time, 
 								local_texture_info.c_str());
 	return text;
 }
diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h
old mode 100644
new mode 100755
index 959c883da86d9789427e18b89e6d3e5068545749..027ae255ec3b53fef615dd18eec97b96ee6613d0
--- a/indra/newview/llviewertexlayer.h
+++ b/indra/newview/llviewertexlayer.h
@@ -47,8 +47,6 @@ class LLViewerTexLayerSet : public LLTexLayerSet
 	virtual ~LLViewerTexLayerSet();
 
 	/*virtual*/void				requestUpdate();
-	void						requestUpload();
-	void						cancelUpload();
 	BOOL						isLocalTextureDataAvailable() const;
 	BOOL						isLocalTextureDataFinal() const;
 	void						updateComposite();
@@ -115,31 +113,6 @@ class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDyn
 	virtual void			postRender(BOOL success) { postRenderTexLayerSet(success); }
 	virtual BOOL			render() { return renderTexLayerSet(); }
 	
-	//--------------------------------------------------------------------
-	// Uploads
-	//--------------------------------------------------------------------
-public:
-	void					requestUpload();
-	void					cancelUpload();
-	BOOL					uploadNeeded() const; 			// We need to upload a new texture
-	BOOL					uploadInProgress() const; 		// We have started uploading a new texture and are awaiting the result
-	BOOL					uploadPending() const; 			// We are expecting a new texture to be uploaded at some point
-	static void				onTextureUploadComplete(const LLUUID& uuid,
-													void* userdata,
-													S32 result, LLExtStat ext_status);
-protected:
-	BOOL					isReadyToUpload() const;
-	void					doUpload(); 					// Does a read back and upload.
-	void					conditionalRestartUploadTimer();
-private:
-	BOOL					mNeedsUpload; 					// Whether we need to send our baked textures to the server
-	U32						mNumLowresUploads; 				// Number of times we've sent a lowres version of our baked textures to the server
-	BOOL					mUploadPending; 				// Whether we have received back the new baked textures
-	LLUUID					mUploadID; 						// The current upload process (null if none).
-	LLFrameTimer    		mNeedsUploadTimer; 				// Tracks time since upload was requested and performed.
-	S32						mUploadFailCount;				// Number of consecutive upload failures
-	LLFrameTimer    		mUploadRetryTimer; 				// Tracks time since last upload failure.
-
 	//--------------------------------------------------------------------
 	// Updates
 	//--------------------------------------------------------------------
@@ -156,25 +129,5 @@ class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDyn
 	LLFrameTimer    		mNeedsUpdateTimer; 				// Tracks time since update was requested and performed.
 };
 
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LLBakedUploadData
-//
-// Used by LLTexLayerSetBuffer for a callback.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-struct LLBakedUploadData
-{
-	LLBakedUploadData(const LLVOAvatarSelf* avatar,
-					  LLViewerTexLayerSet* layerset, 
-					  const LLUUID& id,
-					  bool highest_res);
-	~LLBakedUploadData() {}
-	const LLUUID				mID;
-	const LLVOAvatarSelf*		mAvatar; // note: backlink only; don't LLPointer 
-	LLViewerTexLayerSet*		mTexLayerSet;
-   	const U64					mStartTime;	// for measuring baked texture upload time
-   	const bool					mIsHighestRes; // whether this is a "final" bake, or intermediate low res
-};
-
 #endif  // LL_VIEWER_TEXLAYER_H
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 3be82a55314e6b66387f00715613e1de1bc7003a..ba89aafc84bacb7416f6ca46eb8b3e36a20cd904 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -961,6 +961,27 @@ void LLViewerTexture::updateBindStatsForTester()
 //end of LLViewerTexture
 //----------------------------------------------------------------------------------------------
 
+const std::string& fttype_to_string(const FTType& fttype)
+{
+	static const std::string ftt_unknown("FTT_UNKNOWN");
+	static const std::string ftt_default("FTT_DEFAULT");
+	static const std::string ftt_server_bake("FTT_SERVER_BAKE");
+	static const std::string ftt_host_bake("FTT_HOST_BAKE");
+	static const std::string ftt_map_tile("FTT_MAP_TILE");
+	static const std::string ftt_local_file("FTT_LOCAL_FILE");
+	static const std::string ftt_error("FTT_ERROR");
+	switch(fttype)
+	{
+		case FTT_UNKNOWN: return ftt_unknown; break;
+		case FTT_DEFAULT: return ftt_default; break;
+		case FTT_SERVER_BAKE: return ftt_server_bake; break;
+		case FTT_HOST_BAKE: return ftt_host_bake; break;
+		case FTT_MAP_TILE: return ftt_map_tile; break;
+		case FTT_LOCAL_FILE: return ftt_local_file; break;
+	}
+	return ftt_error;
+}
+
 //----------------------------------------------------------------------------------------------
 //start of LLViewerFetchedTexture
 //----------------------------------------------------------------------------------------------
@@ -973,7 +994,7 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type,
 	mFTType = f_type;
 	if (mFTType == FTT_HOST_BAKE)
 	{
-		mCanUseHTTP = false;
+		LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL;
 	}
 	generateGLTexture();
 }
@@ -998,6 +1019,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 {
 	mOrigWidth = 0;
 	mOrigHeight = 0;
+	mHasAux = FALSE;
 	mNeedsAux = FALSE;
 	mRequestedDiscardLevel = -1;
 	mRequestedDownloadPriority = 0.f;
@@ -1054,7 +1076,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mLastReferencedSavedRawImageTime = 0.0f;
 	mKeptSavedRawImageTime = 0.f;
 	mLastCallBackActiveTime = 0.f;
-
+	mForceCallbackFetch = FALSE;
 	mInDebug = FALSE;
 
 	mFTType = FTT_UNKNOWN;
@@ -1836,9 +1858,14 @@ bool LLViewerFetchedTexture::updateFetch()
 		
 		if (mRawImage.notNull()) sRawCount--;
 		if (mAuxRawImage.notNull()) sAuxCount--;
-		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
+		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage,
+																		   mLastHttpGetStatus);
 		if (mRawImage.notNull()) sRawCount++;
-		if (mAuxRawImage.notNull()) sAuxCount++;
+		if (mAuxRawImage.notNull())
+		{
+			mHasAux = TRUE;
+			sAuxCount++;
+		}
 		if (finished)
 		{
 			mIsFetching = FALSE;
@@ -1899,20 +1926,34 @@ bool LLViewerFetchedTexture::updateFetch()
 			if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
 			{
 				// We finished but received no data
-				if (current_discard < 0)
+				if (getDiscardLevel() < 0)
 				{
-					LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority
-							<< " mRawDiscardLevel " << mRawDiscardLevel
-							<< " current_discard " << current_discard
-							<< LL_ENDL;
+					if (getFTType() != FTT_MAP_TILE)
+					{
+						LL_WARNS() << mID
+								<< " Fetch failure, setting as missing, decode_priority " << decode_priority
+								<< " mRawDiscardLevel " << mRawDiscardLevel
+								<< " current_discard " << current_discard
+								<< " stats " << mLastHttpGetStatus.toHex()
+								<< LL_ENDL;
+					}
 					setIsMissingAsset();
 					desired_discard = -1;
 				}
 				else
 				{
 					//LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
-					mMinDiscardLevel = current_discard;
-					desired_discard = current_discard;
+					if(current_discard >= 0)
+					{
+						mMinDiscardLevel = current_discard;
+						desired_discard = current_discard;
+					}
+					else
+					{
+						S32 dis_level = getDiscardLevel();
+						mMinDiscardLevel = dis_level;
+						desired_discard = dis_level;
+					}
 				}
 				destroyRawImage();
 			}
@@ -2083,29 +2124,43 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
 	mDesiredDiscardLevel = getMaxDiscardLevel() + 1;
 }
 
-void LLViewerFetchedTexture::setIsMissingAsset()
+void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 {
-	if (mUrl.empty())
+	if (is_missing == mIsMissingAsset)
 	{
-		LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
+		return;
 	}
-	else
+	if (is_missing)
 	{
-		// This may or may not be an error - it is normal to have no
-		// map tile on an empty region, but bad if we're failing on a
-		// server bake texture.
-		LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
+		if (mUrl.empty())
+		{
+			LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
+		}
+		else
+		{
+			// This may or may not be an error - it is normal to have no
+			// map tile on an empty region, but bad if we're failing on a
+			// server bake texture.
+			if (getFTType() != FTT_MAP_TILE)
+			{
+				LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
+			}
+		}
+		if (mHasFetcher)
+		{
+			LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+			mHasFetcher = FALSE;
+			mIsFetching = FALSE;
+			mLastPacketTimer.reset();
+			mFetchState = 0;
+			mFetchPriority = 0;
+		}
 	}
-	if (mHasFetcher)
+	else
 	{
-		LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
-		mHasFetcher = FALSE;
-		mIsFetching = FALSE;
-		mLastPacketTimer.reset();
-		mFetchState = 0;
-		mFetchPriority = 0;
+		LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL;
 	}
-	mIsMissingAsset = TRUE;
+	mIsMissingAsset = is_missing;
 }
 
 void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
@@ -2148,10 +2203,19 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 	}
 	if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
 	{
-		// We need aux data, but we've already loaded the image, and it didn't have any
-		LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
+		if(mHasAux)
+		{
+			//trigger a refetch
+			forceToRefetchTexture();
+		}
+		else
+		{
+			// We need aux data, but we've already loaded the image, and it didn't have any
+			LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
+		}
 	}
-	mLastCallBackActiveTime = sCurrentTime;
+	mLastCallBackActiveTime = sCurrentTime ;
+        mLastReferencedSavedRawImageTime = sCurrentTime;
 }
 
 void LLViewerFetchedTexture::clearCallbackEntryList()
@@ -2262,8 +2326,9 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
 			}
 		}
 	}
-	mPauseLoadedCallBacks = FALSE;
-	mLastCallBackActiveTime = sCurrentTime;
+	mPauseLoadedCallBacks = FALSE ;
+	mLastCallBackActiveTime = sCurrentTime ;
+	mForceCallbackFetch = TRUE;
 	if(need_raw)
 	{
 		mSaveRawImage = TRUE;
@@ -2303,7 +2368,8 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
 
 bool LLViewerFetchedTexture::doLoadedCallbacks()
 {
-	static const F32 MAX_INACTIVE_TIME = 900.f; //seconds
+	static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds
+	static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds
 
 	if (mNeedsCreateTexture)
 	{
@@ -2316,14 +2382,30 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 	}	
 	if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching)
 	{
-		clearCallbackEntryList(); //remove all callbacks.
-		return false;
+		if (mFTType == FTT_SERVER_BAKE)
+		{
+			//output some debug info
+			LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL;
+			LL_INFOS() << mUrl << LL_ENDL;
+			LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() <<
+				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL;
+		}
+
+		clearCallbackEntryList() ; //remove all callbacks.
+		return false ;
 	}
 
 	bool res = false;
 	
 	if (isMissingAsset())
 	{
+		if (mFTType == FTT_SERVER_BAKE)
+		{
+			//output some debug info
+			LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL;
+			LL_INFOS() << mUrl << LL_ENDL;
+		}
+
 		for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
 			iter != mLoadedCallbackList.end(); )
 		{
@@ -2508,6 +2590,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 		}
 	}
 
+	// Done with any raw image data at this point (will be re-created if we still have callbacks)
+	destroyRawImage();
+
 	//
 	// If we have no callbacks, take us off of the image callback list.
 	//
@@ -2515,10 +2600,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 	{
 		gTextureList.mCallbackList.erase(this);
 	}
+	else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching)
+	{
+		//wait for long enough but no fetching request issued, force one.
+		forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f);
+		mForceCallbackFetch = FALSE; //fire once.
+	}
 
-	// Done with any raw image data at this point (will be re-created if we still have callbacks)
-	destroyRawImage();
-	
 	return res;
 }
 
@@ -2600,7 +2688,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
 
 void LLViewerFetchedTexture::destroyRawImage()
 {	
-	if (mAuxRawImage.notNull())
+	if (mAuxRawImage.notNull() && !needsToSaveRawImage())
 	{
 		sAuxCount--;
 		mAuxRawImage = NULL;
@@ -2756,6 +2844,24 @@ void LLViewerFetchedTexture::saveRawImage()
 	mLastReferencedSavedRawImageTime = sCurrentTime;
 }
 
+//force to refetch the texture to the discard level 
+void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time)
+{
+	if(mForceToSaveRawImage)
+	{
+		desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel);
+		kept_time = llmax(kept_time, mKeptSavedRawImageTime);
+	}
+
+	//trigger a new fetch.
+	mForceToSaveRawImage = TRUE ;
+	mDesiredSavedRawDiscardLevel = desired_discard ;
+	mKeptSavedRawImageTime = kept_time ;
+	mLastReferencedSavedRawImageTime = sCurrentTime ;
+	mSavedRawImage = NULL ;
+	mSavedRawDiscardLevel = -1 ;
+}
+
 void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) 
 { 
 	mKeptSavedRawImageTime = kept_time;
@@ -2796,13 +2902,19 @@ void LLViewerFetchedTexture::destroySavedRawImage()
 
 	clearCallbackEntryList();
 	
-	mSavedRawImage = NULL;
-	mForceToSaveRawImage  = FALSE;
-	mSaveRawImage = FALSE;
-	mSavedRawDiscardLevel = -1;
-	mDesiredSavedRawDiscardLevel = -1;
-	mLastReferencedSavedRawImageTime = 0.0f;
-	mKeptSavedRawImageTime = 0.f;
+	mSavedRawImage = NULL ;
+	mForceToSaveRawImage  = FALSE ;
+	mSaveRawImage = FALSE ;
+	mSavedRawDiscardLevel = -1 ;
+	mDesiredSavedRawDiscardLevel = -1 ;
+	mLastReferencedSavedRawImageTime = 0.0f ;
+	mKeptSavedRawImageTime = 0.f ;
+	
+	if(mAuxRawImage.notNull())
+	{
+		sAuxCount--;
+		mAuxRawImage = NULL;
+	}
 }
 
 LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index b12b988513c34d4c3117d22a7e3782ae3edf0a82..307204da60f362084d20434ebf5e75ec339b658c 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -34,6 +34,7 @@
 #include "llgltypes.h"
 #include "llrender.h"
 #include "llmetricperformancetester.h"
+#include "httpcommon.h"
 
 #include <map>
 #include <list>
@@ -41,6 +42,7 @@
 extern const S32Megabytes gMinVideoRam;
 extern const S32Megabytes gMaxVideoRam;
 
+class LLFace;
 class LLImageGL ;
 class LLImageRaw;
 class LLViewerObject;
@@ -97,6 +99,7 @@ class LLViewerTexture : public LLGLTexture
 		DYNAMIC_TEXTURE,
 		FETCHED_TEXTURE,
 		LOD_TEXTURE,
+		ATLAS_TEXTURE,
 		INVALID_TEXTURE_TYPE
 	};
 
@@ -118,7 +121,7 @@ class LLViewerTexture : public LLGLTexture
 	LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
 
 	virtual S8 getType() const;
-	virtual BOOL isMissingAsset()const ;
+	virtual BOOL isMissingAsset() const ;
 	virtual void dump();	// debug info to LL_INFOS()
 	
 	/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
@@ -244,6 +247,8 @@ enum FTType
 	FTT_LOCAL_FILE // fetch directly from a local file.
 };
 
+const std::string& fttype_to_string(const FTType& fttype);
+
 //
 //textures are managed in gTextureList.
 //raw image data is fetched from remote or local cache
@@ -340,8 +345,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	// more data.
 	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
-	void setIsMissingAsset();
-	/*virtual*/ BOOL isMissingAsset()	const		{ return mIsMissingAsset; }
+	void setIsMissingAsset(BOOL is_missing = true);
+	/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
 
 	// returns dimensions of original image for local files (before power of two scaling)
 	// and returns 0 for all asset system images
@@ -383,6 +388,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
 	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	
 	void        forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
+	void        forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
 	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 	void        destroySavedRawImage() ;
 	LLImageRaw* getSavedRawImage() ;
@@ -411,10 +417,16 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	void saveRawImage() ;
 	void setCachedRawImage() ;
 
+	//for atlas
+	void resetFaceAtlas() ;
+	void invalidateAtlas(BOOL rebuild_geom) ;
+	BOOL insertToAtlas() ;
+
 private:
 	BOOL  mFullyLoaded;
 	BOOL  mInDebug;
 	BOOL  mInFastCacheList;
+	BOOL  mForceCallbackFetch;
 
 protected:		
 	std::string mLocalFileName;
@@ -442,11 +454,13 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	S8  mMinDesiredDiscardLevel;	// The minimum discard level we'd like to have
 
 	S8  mNeedsAux;					// We need to decode the auxiliary channels
+	S8  mHasAux;                    // We have aux channels
 	S8  mDecodingAux;				// Are we decoding high components
 	S8  mIsRawImageValid;
 	S8  mHasFetcher;				// We've made a fecth request
 	S8  mIsFetching;				// Fetch request is active
-	bool mCanUseHTTP ;              //This texture can be fetched through http if true.
+	bool mCanUseHTTP;              //This texture can be fetched through http if true.
+	LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture.
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
 	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
old mode 100644
new mode 100755
index a544cc81dacd91e9f3c3c8d478a6abbfdd5bf1fc..7de82a4710856ffa096304595d5e881054526130
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -73,14 +73,16 @@ class LLOverrideBakedTextureUpdate
 static std::string asset_id_to_filename(const LLUUID &asset_id);
 
 LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id) :
-	LLWearable()
+	LLWearable(),
+	mVolatile(FALSE)
 {
 	mTransactionID = transaction_id;
 	mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
 }
 
 LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id) :
-	LLWearable()
+	LLWearable(),
+	mVolatile(FALSE)
 {
 	mAssetID = asset_id;
 	mTransactionID.setNull();
@@ -265,7 +267,7 @@ void LLViewerWearable::setParamsToDefaults()
 	{
 		if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) )
 		{
-			setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE);
+			setVisualParamWeight(param->getID(),param->getDefaultWeight());
 		}
 	}
 }
@@ -321,16 +323,6 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 
 	if (!viewer_avatar->isValid()) return;
 
-#if 0
-	// FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables.
-	// Ideally would avoid calling this func in the first place.
-	if (viewer_avatar->isUsingServerBakes() &&
-		!viewer_avatar->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
-
 	ESex old_sex = avatarp->getSex();
 
 	LLWearable::writeToAvatar(avatarp);
@@ -360,19 +352,14 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 	ESex new_sex = avatarp->getSex();
 	if( old_sex != new_sex )
 	{
-		viewer_avatar->updateSexDependentLayerSets( FALSE );
+		viewer_avatar->updateSexDependentLayerSets();
 	}	
-	
-//	if( upload_bake )
-//	{
-//		gAgent.sendAgentSetAppearance();
-//	}
 }
 
 
 // Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
 // static 
-void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake )
+void LLViewerWearable::removeFromAvatar( LLWearableType::EType type)
 {
 	if (!isAgentAvatarValid()) return;
 
@@ -391,7 +378,7 @@ void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload
 		if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) )
 		{
 			S32 param_id = param->getID();
-			gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake );
+			gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight());
 		}
 	}
 
@@ -401,12 +388,7 @@ void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload
 	}
 
 	gAgentAvatarp->updateVisualParams();
-	gAgentAvatarp->wearableUpdated(type, FALSE);
-
-//	if( upload_bake )
-//	{
-//		gAgent.sendAgentSetAppearance();
-//	}
+	gAgentAvatarp->wearableUpdated(type);
 }
 
 // Does not copy mAssetID.
@@ -479,13 +461,6 @@ void LLViewerWearable::setItemID(const LLUUID& item_id)
 
 void LLViewerWearable::revertValues()
 {
-#if 0
-	// DRANO avoid overwrite when not in local appearance
-	if (isAgentAvatarValid() && gAgentAvatarp->isUsingServerBakes() && !gAgentAvatarp->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
 	LLWearable::revertValues();
 
 
@@ -523,13 +498,6 @@ void LLViewerWearable::refreshName()
 	}
 }
 
-// virtual
-void LLViewerWearable::addToBakedTextureHash(LLMD5& hash) const
-{
-	LLUUID asset_id = getAssetID();
-	hash.update((const unsigned char*)asset_id.mData, UUID_BYTES);
-}
-
 struct LLWearableSaveData
 {
 	LLWearableType::EType mType;
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
old mode 100644
new mode 100755
index 8f49e3c4e23872b1839747a9f8e132920e20d345..62cd5e21add899551997d32ba06a1b773e315f4a
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -62,13 +62,15 @@ class LLViewerWearable : public LLWearable
 	BOOL				isOldVersion() const;
 
 	/*virtual*/ void	writeToAvatar(LLAvatarAppearance *avatarp);
-	void				removeFromAvatar( BOOL upload_bake )	{ LLViewerWearable::removeFromAvatar( mType, upload_bake ); }
-	static void			removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); 
+	void				removeFromAvatar()	{ LLViewerWearable::removeFromAvatar( mType); }
+	static void			removeFromAvatar( LLWearableType::EType type); 
 
 	/*virtual*/ EImportResult	importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
 	
 	void				setParamsToDefaults();
 	void				setTexturesToDefaults();
+	void				setVolatile(BOOL is_volatile) { mVolatile = is_volatile; } // TRUE when doing preview renders, some updates will be suppressed.
+	BOOL				getVolatile() { return mVolatile; }
 
 	/*virtual*/ LLUUID	getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const;
 
@@ -89,14 +91,14 @@ class LLViewerWearable : public LLWearable
 	// the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem,
 	// not the wearable asset itself.
 	void				refreshName();
-
-	// Update the baked texture hash.
-	/*virtual*/void		addToBakedTextureHash(LLMD5& hash) const;
+	/*virtual*/void		addToBakedTextureHash(LLMD5& hash) const {}
 
 protected:
 	LLAssetID			mAssetID;
 	LLTransactionID		mTransactionID;
 
+	BOOL 				mVolatile; // True when rendering preview images. Can suppress some updates.
+
 	LLUUID				mItemID;  // ID of the inventory item in the agent's inventory	
 };
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ec794e527d71cf08cf078fafa6e56036a6d0c07f..d052906bee2e1eb8ac8e2030752179b625d8dd69 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -261,7 +261,7 @@ std::string	LLViewerWindow::sMovieBaseName;
 LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity");
 
 
-class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
+class RecordToChatConsoleRecorder : public LLError::Recorder
 {
 public:
 	virtual void recordMessage(LLError::ELevel level,
@@ -285,6 +285,22 @@ class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordT
 	}
 };
 
+class RecordToChatConsole : public LLSingleton<RecordToChatConsole>
+{
+public:
+	RecordToChatConsole()
+		: LLSingleton<RecordToChatConsole>(),
+		mRecorder(new RecordToChatConsoleRecorder())
+	{
+	}
+
+	void startRecorder() { LLError::addRecorder(mRecorder); }
+	void stopRecorder() { LLError::removeRecorder(mRecorder); }
+
+private:
+	LLError::RecorderPtr mRecorder;
+};
+
 ////////////////////////////////////////////////////////////////////////////
 //
 // LLDebugText
@@ -1886,11 +1902,11 @@ void LLViewerWindow::initBase()
 	// optionally forward warnings to chat console/chat floater
 	// for qa runs and dev builds
 #if  !LL_RELEASE_FOR_DOWNLOAD
-	LLError::addRecorder(RecordToChatConsole::getInstance());
+	RecordToChatConsole::getInstance()->startRecorder();
 #else
 	if(gSavedSettings.getBOOL("QAMode"))
 	{
-		LLError::addRecorder(RecordToChatConsole::getInstance());
+		RecordToChatConsole::getInstance()->startRecorder();
 	}
 #endif
 
@@ -1907,9 +1923,7 @@ void LLViewerWindow::initBase()
 	setProgressCancelButtonVisible(FALSE);
 
 	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
-
 	LLMenuGL::sMenuContainer = gMenuHolder;
-
 }
 
 void LLViewerWindow::initWorldUI()
@@ -2023,7 +2037,7 @@ void LLViewerWindow::initWorldUI()
 		destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
 		std::string url = gSavedSettings.getString("DestinationGuideURL");
 		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		destinations->navigateTo(url, "text/html");
+		destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	}
 	LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
 	if (avatar_picker)
@@ -2031,7 +2045,7 @@ void LLViewerWindow::initWorldUI()
 		avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
 		std::string url = gSavedSettings.getString("AvatarPickerURL");
 		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		avatar_picker->navigateTo(url, "text/html");
+		avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	}
 }
 
@@ -2039,8 +2053,7 @@ void LLViewerWindow::initWorldUI()
 void LLViewerWindow::shutdownViews()
 {
 	// clean up warning logger
-	LLError::removeRecorder(RecordToChatConsole::getInstance());
-
+	RecordToChatConsole::getInstance()->stopRecorder();
 	LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ;
 
 	delete mDebugText;
@@ -2075,6 +2088,9 @@ void LLViewerWindow::shutdownViews()
 	// access to gMenuHolder
 	cleanup_menus();
 	LL_INFOS() << "menus destroyed." << LL_ENDL ;
+
+	view_listener_t::cleanup();
+	LL_INFOS() << "view listeners destroyed." << LL_ENDL ;
 	
 	// Delete all child views.
 	delete mRootView;
@@ -2150,6 +2166,12 @@ LLViewerWindow::~LLViewerWindow()
 
 	delete mDebugText;
 	mDebugText = NULL;
+
+	if (LLViewerShaderMgr::sInitialized)
+	{
+		LLViewerShaderMgr::releaseInstance();
+		LLViewerShaderMgr::sInitialized = FALSE;
+	}
 }
 
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 04f64a499748ca704a22813e525705a4fa913b97..9f42776d78d92bc4a5f03659504c8631d691520a 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -109,7 +109,7 @@ extern F32 SPEED_ADJUST_MAX;
 extern F32 SPEED_ADJUST_MAX_SEC;
 extern F32 ANIM_SPEED_MAX;
 extern F32 ANIM_SPEED_MIN;
-
+extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
 
 // #define OUTPUT_BREAST_DATA
 
@@ -713,7 +713,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mLastRezzedStatus(-1),
 	mIsEditingAppearance(FALSE),
 	mUseLocalAppearance(FALSE),
-	mUseServerBakes(FALSE), // FIXME DRANO consider using boost::optional, defaulting to unknown.
 	mLastUpdateRequestCOFVersion(-1),
 	mLastUpdateReceivedCOFVersion(-1)
 {
@@ -723,7 +722,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
 	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
 
-	LL_DEBUGS() << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
+	LL_DEBUGS("Avatar") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
 
 	mPelvisp = NULL;
 
@@ -830,8 +829,8 @@ LLVOAvatar::~LLVOAvatar()
 		}
 
 	logPendingPhases();
-
-	LL_DEBUGS() << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL;
+	
+	LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL;
 
 	std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer());
 	mAttachmentPoints.clear();
@@ -1085,7 +1084,7 @@ void LLVOAvatar::restoreGL()
 	gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
 	for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++)
 	{
-		gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i), FALSE);
+		gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i));
 	}
 	gAgentAvatarp->updateMeshTextures();
 }
@@ -1252,6 +1251,7 @@ LLTexLayerSet* LLVOAvatar::createTexLayerSet()
 
 const LLVector3 LLVOAvatar::getRenderPosition() const
 {
+
 	if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
 	{
 		return getPositionAgent();
@@ -1274,6 +1274,8 @@ const LLVector3 LLVOAvatar::getRenderPosition() const
 	{
 		return getPosition() * mDrawable->getParent()->getRenderMatrix();
 	}
+	
+	
 }
 
 void LLVOAvatar::updateDrawable(BOOL force_damped)
@@ -1309,6 +1311,8 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
 		mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition();
 		mDrawable->setPositionGroup(pos_group);
 	}
+	
+	
 }
 
 void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
@@ -1986,24 +1990,23 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 		// Should already exist, don't need to find it on sim or baked-texture host.
 		result = gTextureList.findImage(uuid);
 	}
-
 	if (!result)
 {
 		const std::string url = getImageURL(te,uuid);
-		if (!url.empty())
-	{
-			LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL;
-			result = LLViewerTextureManager::getFetchedTextureFromUrl(
-				url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
-	}
-	else
-	{
-			LL_DEBUGS("Avatar") << avString() << "from host " << uuid << LL_ENDL;
-			LLHost host = getObjectHost();
-			result = LLViewerTextureManager::getFetchedTexture(
-				uuid, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
+
+		if (url.empty())
+		{
+			LL_WARNS() << "unable to determine URL for te " << te << " uuid " << uuid << LL_ENDL;
+			return NULL;
+		}
+		LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL;
+		result = LLViewerTextureManager::getFetchedTextureFromUrl(
+			url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
+		if (result->isMissingAsset())
+		{
+			result->setIsMissingAsset(false);
+		}
 	}
-}
 	return result;
 }
 
@@ -2231,8 +2234,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 				
 				if ( mLipSyncActive )
 				{
-					if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight(), FALSE);
-					if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight(), FALSE);
+					if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight());
+					if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight());
 					
 					mLipSyncActive = false;
 					LLCharacter::updateVisualParams();
@@ -2255,7 +2258,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 		{
 			LLVector3 tagPos = mRoot->getWorldPosition();
 			tagPos[VZ] -= mPelvisToFoot;
-			tagPos[VZ] += ( mBodySize[VZ] + 0.125f );
+			tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); // does not need mAvatarOffset -Nyx
 			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );
 		}
 	}//if ( voiceEnabled )
@@ -2395,14 +2398,10 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 			{
 				if (param->isTweakable())
 				{
-					param->stopAnimating(FALSE);
+					param->stopAnimating();
 				}
 			}
 			updateVisualParams();
-			if (isSelf())
-			{
-				gAgent.sendAgentSetAppearance();
-			}
 		}
 		else
 		{
@@ -2418,7 +2417,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 				{
 					if (param->isTweakable())
 					{
-						param->animate(morph_amt, FALSE);
+						param->animate(morph_amt);
 					}
 				}
 			}
@@ -2471,7 +2470,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 			F32 ooh_weight = mOohMorph->getMinWeight()
 				+ ooh_morph_amount * (mOohMorph->getMaxWeight() - mOohMorph->getMinWeight());
 
-			mOohMorph->setWeight( ooh_weight, FALSE );
+			mOohMorph->setWeight( ooh_weight);
 		}
 
 		if( mAahMorph )
@@ -2479,7 +2478,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 			F32 aah_weight = mAahMorph->getMinWeight()
 				+ aah_morph_amount * (mAahMorph->getMaxWeight() - mAahMorph->getMinWeight());
 
-			mAahMorph->setWeight( aah_weight, FALSE );
+			mAahMorph->setWeight( aah_weight);
 		}
 
 		mLipSyncActive = true;
@@ -2996,6 +2995,8 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
 	local_camera_up.normalize();
 	local_camera_up = local_camera_up * inv_root_rot;
 
+
+	// position is based on head position, does not require mAvatarOffset here. - Nyx
 	LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f,
 								mBodySize.mV[VY] * 0.4f,
 								mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT);
@@ -3175,7 +3176,10 @@ void	LLVOAvatar::forceUpdateVisualMuteSettings()
 // called on both your avatar and other avatars
 //------------------------------------------------------------------------
 BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
-{
+{	
+	// clear debug text
+	mDebugText.clear();
+
 	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 	{
 		S32 central_bake_version = -1;
@@ -3189,7 +3193,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 										  isSelf() ? (all_local_downloaded ? "L" : "l") : "-",
 										  all_baked_downloaded ? "B" : "b",
 										  mUseLocalAppearance, mIsEditingAppearance,
-										  mUseServerBakes, central_bake_version);
+										  1, central_bake_version);
 		std::string origin_string = bakedTextureOriginInfo();
 		debug_line += " [" + origin_string + "]";
 		S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion();
@@ -3689,6 +3693,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	//mesh vertices need to be reskinned
 	mNeedsSkin = TRUE;
 
+
+		
+	
 	return TRUE;
 }
 //-----------------------------------------------------------------------------
@@ -3722,9 +3729,9 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
 {
 	mHasPelvisOffset = hasOffset;
 	if ( mHasPelvisOffset )
-	{
+	{	
 		//Store off last pelvis to foot value
-		mLastPelvisToFoot = mPelvisToFoot;
+		mLastPelvisToFoot = mPelvisToFoot;		
 		mPelvisOffset	  = offsetAmount;
 		mLastPelvisFixup  = mPelvisFixup;
 		mPelvisFixup	  = pelvisFixup;
@@ -3734,18 +3741,16 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
 // postPelvisSetRecalc
 //------------------------------------------------------------------------
 void LLVOAvatar::postPelvisSetRecalc( void )
-{	
-	computeBodySize(); 
-	mRoot->touch();
-	mRoot->updateWorldMatrixChildren();	
-	dirtyMesh();
-	updateHeadOffset();
+{		
+	mRoot->updateWorldMatrixChildren();			
+	computeBodySize();
+	dirtyMesh(2);
 }
 //------------------------------------------------------------------------
-// pelisPoke
+// setPelvisOffset
 //------------------------------------------------------------------------
 void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
-{	
+{		
 	mHasPelvisOffset  = true;
 	mLastPelvisFixup  = mPelvisFixup;	
 	mPelvisFixup	  = pelvisFixupAmount;	
@@ -4285,34 +4290,6 @@ bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const
 	return allTexturesCompletelyDownloaded(baked_ids);
 }
 
-void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has origin URL.
-										  S32 &host_count, // host-based bake, has host.
-										  S32 &both_count, // error - both host and URL set.
-										  S32 &neither_count) // error - neither set.
-{
-	sb_count = host_count = both_count = neither_count = 0;
-	
-	std::set<LLUUID> baked_ids;
-	collectBakedTextureUUIDs(baked_ids);
-	for (std::set<LLUUID>::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it)
-	{
-		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
-		bool has_url = false, has_host = false;
-		if (!imagep->getUrl().empty())
-		{
-			has_url = true;
-		}
-		if (imagep->getTargetHost().isOk())
-		{
-			has_host = true;
-		}
-		if (has_url && !has_host) sb_count++;
-		else if (has_host && !has_url) host_count++;
-		else if (has_host && has_url) both_count++;
-		else if (!has_host && !has_url) neither_count++;
-	}
-}
-
 std::string LLVOAvatar::bakedTextureOriginInfo()
 {
 	std::string result;
@@ -4553,19 +4530,6 @@ void LLVOAvatar::updateTextures()
 		{
 			const S32 boost_level = getAvatarBakedBoostLevel();
 			imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE);
-			// Spam if this is a baked texture, not set to default image, without valid host info
-			if (isIndexBakedTexture((ETextureIndex)texture_index)
-				&& imagep->getID() != IMG_DEFAULT_AVATAR
-				&& imagep->getID() != IMG_INVISIBLE
-				&& !isUsingServerBakes() 
-				&& !imagep->getTargetHost().isOk())
-			{
-				LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
-										 << imagep->getID() << " for avatar "
-										 << (isSelf() ? "<myself>" : getID().asString()) 
-										 << " on host " << getRegion()->getHost() << LL_ENDL;
-			}
-
 			addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );			
 		}
 	}
@@ -4585,7 +4549,7 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture
 }
 
 const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames.	
-const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = S32_MAX ; //frames
+const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = S32_MAX ; //frames
 void LLVOAvatar::checkTextureLoading()
 {
 	static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds
@@ -4648,11 +4612,11 @@ const F32  ADDITIONAL_PRI = 0.5f;
 void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
 {
 	//Note:
-	//if this function is not called for the last MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL frames, 
+	//if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, 
 	//the texture pipeline will stop fetching this texture.
 
 	imagep->resetTextureStats();
-	imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL);
+	imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
 	imagep->resetMaxVirtualSizeResetCounter() ;
 
 	mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
@@ -4697,22 +4661,19 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid)
 {
 	llassert(isIndexBakedTexture(ETextureIndex(te)));
 	std::string url = "";
-	if (isUsingServerBakes())
+	const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL();
+	if (appearance_service_url.empty())
 	{
-		const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL();
-		if (appearance_service_url.empty())
-		{
-			// Probably a server-side issue if we get here:
-			LL_WARNS() << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << LL_ENDL;
-			return url;
-		}
+		// Probably a server-side issue if we get here:
+		LL_WARNS() << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << LL_ENDL;
+		return url;
+	}
 	
-		const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
-		if (texture_entry != NULL)
-		{
-			url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString();
-			//LL_INFOS() << "baked texture url: " << url << LL_ENDL;
-		}
+	const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
+	if (texture_entry != NULL)
+	{
+		url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString();
+		//LL_INFOS() << "baked texture url: " << url << LL_ENDL;
 	}
 	return url;
 }
@@ -5096,70 +5057,39 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
 
 	return jointp;
 }
-
-//-----------------------------------------------------------------------------
-// resetJointPositions
-//-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointPositions( void )
-{
-	avatar_joint_list_t::iterator iter = mSkeleton.begin();
-	avatar_joint_list_t::iterator end  = mSkeleton.end();
-	for (; iter != end; ++iter)
-	{
-		(*iter)->restoreOldXform();
-		(*iter)->setId( LLUUID::null );
-	}
-	mHasPelvisOffset = false;
-	mPelvisFixup	 = mLastPelvisFixup;
-}
-//-----------------------------------------------------------------------------
-// resetSpecificJointPosition
-//-----------------------------------------------------------------------------
-void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
-{
-	LLJoint* pJoint = mRoot->findJoint( name );
-	
-	if ( pJoint  && pJoint->doesJointNeedToBeReset() )
-	{
-		pJoint->restoreOldXform();
-		pJoint->setId( LLUUID::null );
-		//If we're reseting the pelvis position make sure not to apply offset
-		if ( name == "mPelvis" )
-		{
-			mHasPelvisOffset = false;
-		}
-	}
-	else
-	{
-		LL_INFOS()<<"Did not find "<< name.c_str()<<LL_ENDL;
-	}
-}
 //-----------------------------------------------------------------------------
 // resetJointPositionsToDefault
 //-----------------------------------------------------------------------------
 void LLVOAvatar::resetJointPositionsToDefault( void )
-{
+{	
 	//Subsequent joints are relative to pelvis
 	avatar_joint_list_t::iterator iter = mSkeleton.begin();
 	avatar_joint_list_t::iterator end  = mSkeleton.end();
+
+	LLJoint* pJointPelvis = getJoint("mPelvis");
+	
 	for (; iter != end; ++iter)
 	{
 		LLJoint* pJoint = (*iter);
-		if ( pJoint->doesJointNeedToBeReset() )
+		//Reset joints except for pelvis
+		if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() )
+		{			
+			pJoint->setId( LLUUID::null );
+			pJoint->restoreOldXform();
+		}		
+		else
+		if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() )
 		{
 			pJoint->setId( LLUUID::null );
-			//restore joints to default positions, however skip over the pelvis
-			// *TODO: How does this pointer check skip over pelvis?
-			if ( pJoint )
-			{
-				pJoint->restoreOldXform();
-			}
-		}
-	}
+			pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
+			pJoint->setJointResetFlag( false );
+		}		
+	}	
+		
 	//make sure we don't apply the joint offset
 	mHasPelvisOffset = false;
 	mPelvisFixup	 = mLastPelvisFixup;
-	postPelvisSetRecalc();
+	postPelvisSetRecalc();	
 }
 //-----------------------------------------------------------------------------
 // getCharacterPosition()
@@ -5314,7 +5244,7 @@ BOOL LLVOAvatar::loadSkeletonNode ()
 			{
 				attachment->setOriginalPosition(info->mPosition);
 			}
-
+			
 			if (info->mHasRotation)
 			{
 				LLQuaternion rotation;
@@ -5384,7 +5314,6 @@ void LLVOAvatar::updateVisualParams()
 	dirtyMesh();
 	updateHeadOffset();
 }
-
 //-----------------------------------------------------------------------------
 // isActive()
 //-----------------------------------------------------------------------------
@@ -5541,11 +5470,11 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
 //-----------------------------------------------------------------------------
 // updateSexDependentLayerSets()
 //-----------------------------------------------------------------------------
-void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
+void LLVOAvatar::updateSexDependentLayerSets()
 {
-	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-	invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
-	invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
+	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+	invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet);
+	invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet);
 }
 
 //-----------------------------------------------------------------------------
@@ -5761,6 +5690,7 @@ void LLVOAvatar::lazyAttach()
 
 void LLVOAvatar::resetHUDAttachments()
 {
+
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end();
 		 ++iter)
@@ -5813,10 +5743,10 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 		{
 			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
 			if (pSkinData 
-				&& pSkinData->mJointNames.size() > 20				// full rig
-				&& pSkinData->mAlternateBindMatrix.size() > 0)
-					{
-						LLVOAvatar::resetJointPositionsToDefault();
+				&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG	// full rig
+				&& pSkinData->mAlternateBindMatrix.size() > 0 )
+					{				
+						LLVOAvatar::resetJointPositionsToDefault();							
 						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing 
 						//This handles the case where we detach a replacement rig.
 						if ( gAgentCamera.cameraCustomizeAvatar() )
@@ -5835,6 +5765,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
 {
+
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end();
 		 ++iter)
@@ -5845,6 +5776,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
 		{
 			mVisualComplexityStale = TRUE;
 			cleanupAttachedMesh( viewer_object );
+		
 			attachment->removeObject(viewer_object);
 			LL_DEBUGS() << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << LL_ENDL;
 			return TRUE;
@@ -6058,8 +5990,6 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const
 	return FALSE;
 }
 
-
-
 LLViewerObject *	LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const
 {
 	for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin();
@@ -6083,9 +6013,8 @@ LLViewerObject *	LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) cons
 	return NULL;
 }
 
-
 // virtual
-void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
+void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset)
 {
 }
 
@@ -6094,18 +6023,18 @@ void LLVOAvatar::invalidateAll()
 }
 
 // virtual
-void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
+void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
 {
 	if (global_color == mTexSkinColor)
 	{
-		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet);
 	}
 	else if (global_color == mTexHairColor)
 	{
-		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet);
 		
 		// ! BACKWARDS COMPATIBILITY !
 		// Fix for dealing with avatars from viewers that don't bake hair.
@@ -6127,7 +6056,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL
 	else if (global_color == mTexEyeColor)
 	{
 //		LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; 
-		invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet,  upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet);
 	}
 	updateMeshTextures();
 }
@@ -6218,9 +6147,12 @@ void LLVOAvatar::clearPhases()
 
 void LLVOAvatar::startPhase(const std::string& phase_name)
 {
-	F32 elapsed;
-	bool completed;
-	if (getPhases().getPhaseValues(phase_name, elapsed, completed))
+	F32 elapsed = 0.0;
+	bool completed = false;
+	bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
+	//LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
+	//					<< " found " << found << " elapsed " << elapsed << " completed " << completed << LL_ENDL;
+	if (found)
 	{
 		if (!completed)
 		{
@@ -6233,9 +6165,9 @@ void LLVOAvatar::startPhase(const std::string& phase_name)
 }
 
 void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check)
-		{
-	F32 elapsed;
-	bool completed;
+{
+	F32 elapsed = 0.0;
+	bool completed = false;
 	if (getPhases().getPhaseValues(phase_name, elapsed, completed))
 	{
 		if (!completed)
@@ -6321,7 +6253,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
 		}
 	record["grid_x"] = LLSD::Integer(grid_x);
 	record["grid_y"] = LLSD::Integer(grid_y);
-	record["is_using_server_bakes"] = ((bool) isUsingServerBakes());
+	record["is_using_server_bakes"] = true;
 	record["is_self"] = isSelf();
 		
 	if (isAgentAvatarValid())
@@ -6566,6 +6498,8 @@ void LLVOAvatar::updateMeshTextures()
 				// we'll consider it loaded and use it (rather than
 				// doing compositing).
 				useBakedTexture( baked_img->getID() );
+                                mLoadedCallbacksPaused |= !isVisible();
+                                checkTextureLoading();
 			}
 			else
 			{
@@ -6578,6 +6512,10 @@ void LLVOAvatar::updateMeshTextures()
 				}
 				baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), 
 					src_callback_list, paused );
+
+                               // this could add paused texture callbacks
+                               mLoadedCallbacksPaused |= paused; 
+                               checkTextureLoading();
 			}
 		}
 		else if (layerset && isUsingLocalAppearance())
@@ -6724,8 +6662,6 @@ void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com
 	}
 }
 
-
-
 // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise
 BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index)
 {
@@ -6936,6 +6872,9 @@ void LLVOAvatar::onFirstTEMessageReceived()
 				LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL;
 				image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), 
 					src_callback_list, paused );
+
+                               // this could add paused texture callbacks
+                               mLoadedCallbacksPaused |= paused; 
 			}
 		}
 
@@ -7008,7 +6947,7 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value)
 
 void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
 	const LLAppearanceMessageContents& contents)
-	{
+{
 	std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml");
 	const std::vector<F32>& params_for_dump = contents.mParamWeights;
 	const LLTEContents& tec = contents.mTEContents;
@@ -7035,7 +6974,8 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
 	LLVisualParam* param = getFirstVisualParam();
 	for (S32 i = 0; i < params_for_dump.size(); i++)
 	{
-		while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && 
+						 (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		{
 			param = getNextVisualParam();
 		}
@@ -7089,7 +7029,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 		{
 			for( S32 i = 0; i < num_blocks; i++ )
 			{
-				while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+				while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && 
+								 (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 				{
 					param = getNextVisualParam();
 				}
@@ -7110,7 +7051,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 			}
 		}
 
-		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
+											 getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		if (num_blocks != expected_tweakable_count)
 		{
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << LL_ENDL;
@@ -7157,13 +7099,13 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 	{
 		appearance_version = contents.mParamAppearanceVersion;
 	}
-	if (contents.mAppearanceVersion >= 0)
+	else if (contents.mAppearanceVersion > 0)
 	{
 		appearance_version = contents.mAppearanceVersion;
 	}
-	if (appearance_version < 0) // still not set, go with 0.
+	else // still not set, go with 1.
 	{
-		appearance_version = 0;
+		appearance_version = 1;
 	}
 	LL_DEBUGS("Avatar") << "appearance version info - field " << contents.mAppearanceVersion
 						<< " param: " << contents.mParamAppearanceVersion
@@ -7201,24 +7143,21 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		LL_WARNS() << "bad appearance version info, discarding" << LL_ENDL;
 		return;
 	}
+	llassert(appearance_version > 0);
+	if (appearance_version > 1)
+	{
+		LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL;
+		return;
+	}
+
 	S32 this_update_cof_version = contents.mCOFVersion;
 	S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion;
 
-	// Only now that we have result of appearance_version can we decide whether to bail out.
 	if( isSelf() )
 	{
 		LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version
 				<< " last_update_request_cof_version " << last_update_request_cof_version
 				<<  " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL;
-
-		if (getRegion() && (getRegion()->getCentralBakeVersion()==0))
-		{
-			LL_WARNS() << avString() << "Received AvatarAppearance message for self in non-server-bake region" << LL_ENDL;
-		}
-		if( mFirstTEMessageReceived && (appearance_version == 0))
-		{
-			return;
-		}
 	}
 	else
 	{
@@ -7227,7 +7166,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 
 	// Check for stale update.
 	if (isSelf()
-		&& (appearance_version>0)
 		&& (this_update_cof_version < last_update_request_cof_version))
 	{
 		LL_WARNS() << "Stale appearance update, wanted version " << last_update_request_cof_version
@@ -7241,6 +7179,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	// SUNSHINE CLEANUP - is this case OK now?
 	S32 num_params = contents.mParamWeights.size();
 	if (num_params <= 1)
 	{
@@ -7252,10 +7191,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	// No backsies zone - if we get here, the message should be valid and usable, will be processed.
+
+	// Note:
+	// RequestAgentUpdateAppearanceResponder::onRequestRequested()
+	// assumes that cof version is only updated with server-bake
+	// appearance messages.
 	mLastUpdateReceivedCOFVersion = this_update_cof_version;
 		
-	setIsUsingServerBakes(appearance_version > 0);
-
 	applyParsedTEMessage(contents.mTEContents);
 
 	// prevent the overwriting of valid baked textures with invalid baked textures
@@ -7265,9 +7208,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			&& mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT
 			&& baked_index != BAKED_SKIRT)
 		{
+			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL;
 			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, 
 				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
 		}
+		else
+		{
+			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using texture id "
+								<< getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << LL_ENDL;
+		}
 	}
 
 	// runway - was
@@ -7293,32 +7242,38 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		LL_DEBUGS("Avatar") << avString() << " handle visual params, num_params " << num_params << LL_ENDL;
 		BOOL params_changed = FALSE;
 		BOOL interp_params = FALSE;
+		S32 params_changed_count = 0;
 		
 		for( S32 i = 0; i < num_params; i++ )
 		{
 			LLVisualParam* param = contents.mParams[i];
 			F32 newWeight = contents.mParamWeights[i];
 
-				if (is_first_appearance_message || (param->getWeight() != newWeight))
+			if (is_first_appearance_message || (param->getWeight() != newWeight))
+			{
+				params_changed = TRUE;
+				params_changed_count++;
+
+				if(is_first_appearance_message)
 				{
-					params_changed = TRUE;
-					if(is_first_appearance_message)
-					{
-						param->setWeight(newWeight, FALSE);
-					}
-					else
-					{
-						interp_params = TRUE;
-						param->setAnimationTarget(newWeight, FALSE);
-					}
+					//LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL;
+					param->setWeight(newWeight);
 				}
+				else
+				{
+					interp_params = TRUE;
+					param->setAnimationTarget(newWeight);
+				}
+			}
 		}
-		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
+											 getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		if (num_params != expected_tweakable_count)
 		{
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << LL_ENDL;
 		}
 
+		LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << LL_ENDL;
 		if (params_changed)
 		{
 			if (interp_params)
@@ -7330,7 +7285,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			ESex new_sex = getSex();
 			if( old_sex != new_sex )
 			{
-				updateSexDependentLayerSets( FALSE );
+				updateSexDependentLayerSets();
 			}	
 		}
 
@@ -7368,7 +7323,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	}
 
 	updateMeshTextures();
-
 	//if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end");
 }
 
@@ -7553,7 +7507,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
 		LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
 		if (id == image_baked->getID())
 		{
-			LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL;
+			//LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL;
 			mBakedTextureDatas[i].mIsLoaded = true;
 			mBakedTextureDatas[i].mLastTextureID = id;
 			mBakedTextureDatas[i].mIsUsed = true;
@@ -7626,6 +7580,15 @@ std::string get_sequential_numbered_file_name(const std::string& prefix,
 	return outfilename;
 }
 
+void dump_sequential_xml(const std::string outprefix, const LLSD& content)
+{
+	std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
+	std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
+	std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
+	ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
+	LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
+}
+
 void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables )
 {
 	std::string outprefix(prefix);
@@ -7634,10 +7597,6 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
 		outprefix = getFullname() + (isSelf()?"_s":"_o");
 	}
 	if (outprefix.empty())
-{
-		outprefix = getFullname() + (isSelf()?"_s":"_o");
-	}
-	if (outprefix.empty())
 	{
 		outprefix = std::string("new_archetype");
 	}
@@ -7704,6 +7663,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
 
 		for (U8 te = 0; te < TEX_NUM_INDICES; te++)
 		{
+			{
 				// MULTIPLE_WEARABLES: extend to multiple wearables?
 				LLViewerTexture* te_image = getImage((ETextureIndex)te, 0);
 				if( te_image )
@@ -7715,6 +7675,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
 			}
 		}
 
+	}
 	apr_file_printf( file, "\t</archetype>\n" );
 	apr_file_printf( file, "\n</linden_genepool>\n" );
 
@@ -7836,41 +7797,6 @@ void LLVOAvatar::startAppearanceAnimation()
 	}
 }
 
-// virtual
-void LLVOAvatar::bodySizeChanged()
-{	
-	if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
-	{	// notify simulator of change in size
-		// but not if we are in the middle of updating appearance
-		gAgent.sendAgentSetAppearance();
-}
-}
-
-BOOL LLVOAvatar::isUsingServerBakes() const
-{
-#if 1
-	// Sanity check - visual param for appearance version should match mUseServerBakes
-	LLVisualParam* appearance_version_param = getVisualParam(11000);
-	llassert(appearance_version_param);
-	F32 wt = appearance_version_param->getWeight();
-	F32 expect_wt = mUseServerBakes ? 1.0 : 0.0;
-	if (!is_approx_equal(wt,expect_wt))
-{
-		LL_WARNS() << "wt " << wt << " differs from expected " << expect_wt << LL_ENDL;
-	}
-#endif
-
-	return mUseServerBakes;
-		}
-		
-void LLVOAvatar::setIsUsingServerBakes(BOOL newval)
-		{
-	mUseServerBakes = newval;
-	LLVisualParam* appearance_version_param = getVisualParam(11000);
-	llassert(appearance_version_param);
-	appearance_version_param->setWeight(newval ? 1.0 : 0.0, false);
-		}
-
 // virtual
 void LLVOAvatar::removeMissingBakedTextures()
 			{
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 9d0391b42c7a838a3dc417de6349972afd1c7371..42ff7bff92fb72a468602a7ec1cc0dfea5fee8d4 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -199,9 +199,7 @@ class LLVOAvatar :
 
 	virtual LLJoint*		getJoint(const std::string &name);
 	
-	void					resetJointPositions( void );
 	void					resetJointPositionsToDefault( void );
-	void					resetSpecificJointPosition( const std::string& name );
 	
 	/*virtual*/ const LLUUID&	getID() const;
 	/*virtual*/ void			addDebugText(const std::string& text);
@@ -210,7 +208,7 @@ class LLVOAvatar :
 	/*virtual*/ F32				getPixelArea() const;
 	/*virtual*/ LLVector3d		getPosGlobalFromAgent(const LLVector3 &position);
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
-	virtual void			updateVisualParams();
+	virtual void				updateVisualParams();
 
 
 /**                    Inherited
@@ -442,7 +440,7 @@ class LLVOAvatar :
 	// Global colors
 	//--------------------------------------------------------------------
 public:
-	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake);
+	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color);
 
 	//--------------------------------------------------------------------
 	// Visibility
@@ -602,7 +600,7 @@ class LLVOAvatar :
 	// Composites
 	//--------------------------------------------------------------------
 public:
-	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+	virtual void	invalidateComposite(LLTexLayerSet* layerset);
 	virtual void	invalidateAll();
 	virtual void	setCompositeUpdatesEnabled(bool b) {}
 	virtual void 	setCompositeUpdatesEnabled(U32 index, bool b) {}
@@ -639,7 +637,7 @@ class LLVOAvatar :
 public:
 	void			debugColorizeSubMeshes(U32 i, const LLColor4& color);
 	virtual void 	updateMeshTextures();
-	void 			updateSexDependentLayerSets(BOOL upload_bake);
+	void 			updateSexDependentLayerSets();
 	virtual void	dirtyMesh(); // Dirty the avatar mesh
 	void 			updateMeshData();
 protected:
@@ -672,7 +670,6 @@ class LLVOAvatar :
 	void 			processAvatarAppearance(LLMessageSystem* mesgsys);
 	void 			hideSkirt();
 	void			startAppearanceAnimation();
-	/*virtual*/ void bodySizeChanged();
 	
 	//--------------------------------------------------------------------
 	// Appearance morphing
@@ -685,12 +682,6 @@ class LLVOAvatar :
 	// editing or when waiting for a subsequent server rebake.
 	/*virtual*/ BOOL	isUsingLocalAppearance() const { return mUseLocalAppearance; }
 
-	// True if this avatar should fetch its baked textures via the new
-	// appearance mechanism.
-	BOOL				isUsingServerBakes() const;
-	void 				setIsUsingServerBakes(BOOL newval);
-
-
 	// True if we are currently in appearance editing mode. Often but
 	// not always the same as isUsingLocalAppearance().
 	/*virtual*/ BOOL	isEditingAppearance() const { return mIsEditingAppearance; }
@@ -703,7 +694,6 @@ class LLVOAvatar :
 	F32				mLastAppearanceBlendTime;
 	BOOL			mIsEditingAppearance; // flag for if we're actively in appearance editing mode
 	BOOL			mUseLocalAppearance; // flag for if we're using a local composite
-	BOOL			mUseServerBakes; // flag for if baked textures should be fetched from baking service (false if they're temporary uploads)
 
 	//--------------------------------------------------------------------
 	// Visibility
@@ -1031,10 +1021,11 @@ class LLVOAvatar :
 
 }; // LLVOAvatar
 extern const F32 SELF_ADDITIONAL_PRI;
-extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL;
+extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
 
 std::string get_sequential_numbered_file_name(const std::string& prefix,
 											  const std::string& suffix);
+void dump_sequential_xml(const std::string outprefix, const LLSD& content);
 void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value);
 
 #endif // LL_VOAVATAR_H
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 319da1abb5913fd7d8741d6020286a74b99238d2..42a7c2e576c92189668dffb32994711fb36b0741 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -161,8 +161,6 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 	mRegionCrossingCount(0),
 	mInitialBakesLoaded(false)
 {
-	gAgentWearables.setAvatarObject(this);
-
 	mMotionController.mIsSelf = TRUE;
 
 	LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL;
@@ -188,15 +186,6 @@ bool update_avatar_rez_metrics()
 	return false;
 }
 
-bool check_for_unsupported_baked_appearance()
-{
-	if (!isAgentAvatarValid())
-		return true;
-
-	gAgentAvatarp->checkForUnsupportedServerBakeAppearance();
-	return false;
-}
-
 void LLVOAvatarSelf::initInstance()
 {
 	BOOL status = TRUE;
@@ -233,7 +222,33 @@ void LLVOAvatarSelf::initInstance()
 
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
-	doPeriodically(check_for_unsupported_baked_appearance, 120.0);
+	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
+}
+
+bool LLVOAvatarSelf::checkStuckAppearance()
+{
+	const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
+	const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0;
+	
+	if (gAgentWearables.isCOFChangeInProgress())
+	{
+		LL_DEBUGS("Avatar") << "checking for stuck appearance" << LL_ENDL;
+		F32 change_time = gAgentWearables.getCOFChangeTime();
+		LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << LL_ENDL;
+		S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
+		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << LL_ENDL;
+		S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
+		LL_DEBUGS("Avatar") << "active copy operations " << active_copies << LL_ENDL;
+
+		if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) ||
+			(change_time > UNCONDITIONAL_UNSTICK_INTERVAL))
+		{
+			gAgentWearables.notifyLoadingFinished();
+		}
+	}
+
+	// Return false to continue running check periodically.
+	return LLApp::isExiting();
 }
 
 // virtual
@@ -644,55 +659,42 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
 	}
 	return LLVOAvatar::getJoint(name);
 }
-//virtual
-void LLVOAvatarSelf::resetJointPositions( void )
-{
-	return LLVOAvatar::resetJointPositions();
-}
 // virtual
-BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight)
 {
 	if (!which_param)
 	{
 		return FALSE;
 	}
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID());
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
 // virtual
-BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight)
 {
 	if (!param_name)
 	{
 		return FALSE;
 	}
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name);
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
 // virtual
-BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight)
 {
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
-BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight)
 {
 	if (!param)
 	{
 		return FALSE;
 	}
 
-#if 0
-	// FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables.
-	if (isUsingServerBakes() && !isUsingLocalAppearance())
-	{
-		return FALSE;
-	}
-#endif
-
 	if (param->getCrossWearable())
 	{
 		LLWearableType::EType type = (LLWearableType::EType)param->getWearableType();
@@ -702,12 +704,12 @@ BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight
 			LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count);
 			if (wearable)
 			{
-				wearable->setVisualParamWeight(param->getID(), weight, upload_bake);
+				wearable->setVisualParamWeight(param->getID(), weight);
 			}
 		}
 	}
 
-	return LLCharacter::setVisualParamWeight(param,weight,upload_bake);
+	return LLCharacter::setVisualParamWeight(param,weight);
 }
 
 /*virtual*/ 
@@ -720,7 +722,7 @@ void LLVOAvatarSelf::updateVisualParams()
 void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
 {
 	// Animate all top-level wearable visual parameters
-	gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE);
+	gAgentWearables.animateAllWearableParams(calcMorphAmount());
 
 	// apply wearable visual params to avatar
 	for (U32 type = 0; type < LLWearableType::WT_COUNT; type++)
@@ -762,57 +764,6 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
 	}
 }
 
-//virtual
-U32  LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
-													 void **user_data,
-													 U32 block_num,
-													 const EObjectUpdateType update_type,
-													 LLDataPacker *dp)
-{
-	U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
-
-#if 0
-	// DRANO - it's not clear this does anything useful. If we wait
-	// until an appearance message has been received, we already have
-	// the texture ids. If we don't wait, we don't yet know where to
-	// look for baked textures, because we haven't received the
-	// appearance version data from the appearance message. This looks
-	// like an old optimization that's incompatible with server-side
-	// texture baking.
-	
-	// FIXME DRANO - skipping in the case of !mFirstAppearanceMessageReceived prevents us from trying to
-	// load textures before we know where they come from (ie, from baking service or not);
-	// unknown impact on performance.
-	if (mInitialBakesLoaded == false && retval == 0x0 && mFirstAppearanceMessageReceived)
-	{
-		// call update textures to force the images to be created
-		updateMeshTextures();
-
-		// unpack the texture UUIDs to the texture slots
-		if(mesgsys != NULL)
-		{
-		retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num);
-		}
-
-		// need to trigger a few operations to get the avatar to use the new bakes
-		for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-		{
-			const LLAvatarAppearanceDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex;
-			LLUUID texture_id = getTEImage(te)->getID();
-			setNewBakedTexture(te, texture_id);
-			mInitialBakeIDs[i] = texture_id;
-		}
-
-		onFirstTEMessageReceived();
-
-		mInitialBakesLoaded = true;
-	}
-#endif
-
-	return retval;
-}
-
-
 void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
 {
 	if (te >= TEX_NUM_INDICES)
@@ -864,13 +815,9 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
 		{
 			LLViewerTexLayerSet *layerset = getTexLayerSet(i);
 			layerset->setUpdatesEnabled(TRUE);
-			invalidateComposite(layerset, FALSE);
-		}
-		updateMeshTextures();	// may call back into this function
-		if (getRegion() && !getRegion()->getCentralBakeVersion())
-		{
-			requestLayerSetUploads();
+			invalidateComposite(layerset);
 		}
+		updateMeshTextures();
 	}
 }
 
@@ -1039,7 +986,7 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
 // forces an update to any baked textures relevant to type.
 // will force an upload of the resulting bake if the second parameter is TRUE
 //-----------------------------------------------------------------------------
-void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result )
+void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type)
 {
 	for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin();
 		 baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end();
@@ -1061,20 +1008,13 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re
 					if (layerset)
 					{
 						layerset->setUpdatesEnabled(true);
-						invalidateComposite(layerset, upload_result);
+						invalidateComposite(layerset);
 					}
 					break;
 				}
 			}
 		}
 	}
-	
-	// Physics type has no associated baked textures, but change of params needs to be sent to
-	// other avatars.
-	if (type == LLWearableType::WT_PHYSICS)
-	  {
-	    gAgent.sendAgentSetAppearance();
-	  }
 }
 
 //-----------------------------------------------------------------------------
@@ -1486,15 +1426,6 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const
 	return TRUE;
 }
 
-BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const
-{
-	const LLViewerTexLayerSet *layerset = getLayerSet(index);
-	if (!layerset) return FALSE;
-	const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite();
-	if (!layerset_buffer) return FALSE;
-	return !layerset_buffer->uploadNeeded();
-}
-
 BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const
 {
 	LLUUID id;
@@ -1552,49 +1483,12 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t
 	return isTextureVisible(type,index);
 }
 
-
-//-----------------------------------------------------------------------------
-// requestLayerSetUploads()
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::requestLayerSetUploads()
-{
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		requestLayerSetUpload((EBakedTextureIndex)i);
-	}
-}
-
-void LLVOAvatarSelf::requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i)
-{
-	ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
-	const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
-	LLViewerTexLayerSet *layerset = getLayerSet(i);
-	if (!layer_baked && layerset)
-	{
-		layerset->requestUpload();
-	}
-}
-
 bool LLVOAvatarSelf::areTexturesCurrent() const
 {
-	return !hasPendingBakedUploads() && gAgentWearables.areWearablesLoaded();
+	return gAgentWearables.areWearablesLoaded();
 }
 
-// virtual
-bool LLVOAvatarSelf::hasPendingBakedUploads() const
-{
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		LLViewerTexLayerSet* layerset = getTexLayerSet(i);
-		if (layerset && layerset->getViewerComposite() && layerset->getViewerComposite()->uploadPending())
-		{
-			return true;
-		}
-	}
-	return false;
-}
-
-void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
+void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset)
 {
 	LLViewerTexLayerSet *layer_set = dynamic_cast<LLViewerTexLayerSet*>(layerset);
 	if( !layer_set || !layer_set->getUpdatesEnabled() )
@@ -1605,16 +1499,6 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_r
 
 	layer_set->requestUpdate();
 	layer_set->invalidateMorphMasks();
-
-	if( upload_result  && (getRegion() && !getRegion()->getCentralBakeVersion()))
-	{
-		llassert(isSelf());
-
-		ETextureIndex baked_te = getBakedTE( layer_set );
-		setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR) );
-		layer_set->requestUpload();
-		updateMeshTextures();
-	}
 }
 
 void LLVOAvatarSelf::invalidateAll()
@@ -1622,7 +1506,7 @@ void LLVOAvatarSelf::invalidateAll()
 	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
 	{
 		LLViewerTexLayerSet *layerset = getTexLayerSet(i);
-		invalidateComposite(layerset, TRUE);
+		invalidateComposite(layerset);
 	}
 	//mDebugSelfLoadTimer.reset();
 }
@@ -2033,7 +1917,10 @@ BOOL LLVOAvatarSelf::getIsCloud() const
 /*static*/
 void LLVOAvatarSelf::debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
 {
-	gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata);
+	if (gAgentAvatarp.notNull())
+	{
+		gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata);
+	}
 }
 
 void LLVOAvatarSelf::debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
@@ -2217,27 +2104,9 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const
 	return text;
 }
 
-
-#if 0
-// Dump avatar metrics data.
-LLSD LLVOAvatarSelf::metricsData()
-{
-	// runway - add region info
-	LLSD result;
-	result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-	result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32();
-	result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32();
-	result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
-	result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32();
-	result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32();
-	result["startup"] = LLStartUp::getPhases().asLLSD();
-	
-	return result;
-}
-#endif
-
 class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 {
+	LOG_CLASS(ViewerAppearanceChangeMetricsResponder);
 public:
 	ViewerAppearanceChangeMetricsResponder( S32 expected_sequence,
 											volatile const S32 & live_sequence,
@@ -2248,32 +2117,25 @@ class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 	{
 	}
 
-	virtual void completed(U32 status,
-						   const std::string& reason,
-						   const LLSD& content)
+private:
+	/* virtual */ void httpSuccess()
 	{
-		gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case.
-		if (isGoodStatus(status))
-		{
-			LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
-			result(content);
-		}
-		else
-		{
-			LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL;
-			errorWithContent(status,reason,content);
-		}
-	}
+		LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
 
-	// virtual
-	void result(const LLSD & content)
-	{
+		gPendingMetricsUploads--;
 		if (mLiveSequence == mExpectedSequence)
 		{
 			mReportingStarted = true;
 		}
 	}
 
+	/* virtual */ void httpFailure()
+	{
+		// if we add retry, this should be removed from the httpFailure case
+		LL_WARNS("Avatar") << dumpResponse() << LL_ENDL;
+		gPendingMetricsUploads--;
+	}
+
 private:
 	S32 mExpectedSequence;
 	volatile const S32 & mLiveSequence;
@@ -2356,11 +2218,10 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
 
 void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 {
-	// gAgentAvatarp->stopAllPhases();
 	static volatile bool reporting_started(false);
 	static volatile S32 report_sequence(0);
 
-	LLSD msg; // = metricsData();
+	LLSD msg;
 	msg["message"] = "ViewerAppearanceChangeMetrics";
 	msg["session_id"] = gAgentSessionID;
 	msg["agent_id"] = gAgentID;
@@ -2420,63 +2281,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	}
 }
 
-class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder
-{
-public:
-	CheckAgentAppearanceServiceResponder()
-	{
-	}
-	
-	virtual ~CheckAgentAppearanceServiceResponder()
-	{
-	}
-
-	/* virtual */ void result(const LLSD& content)
-	{
-		LL_DEBUGS("Avatar") << "status OK" << LL_ENDL;
-	}
-
-	// Error
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-	{
-		if (isAgentAvatarValid())
-		{
-			LL_DEBUGS("Avatar") << "failed, will rebake [status:"
-					<< status << "]: " << content << LL_ENDL;
-			forceAppearanceUpdate();
-		}
-	}	
-
-	static void forceAppearanceUpdate()
-	{
-		// Trying to rebake immediately after crossing region boundary
-		// seems to be failure prone; adding a delay factor. Yes, this
-		// fix is ad-hoc and not guaranteed to work in all cases.
-		doAfterInterval(boost::bind(&LLVOAvatarSelf::forceBakeAllTextures,
-									gAgentAvatarp.get(), true), 5.0);
-	}
-};
-
-void LLVOAvatarSelf::checkForUnsupportedServerBakeAppearance()
-{
-	// Need to check only if we have a server baked appearance and are
-	// in a non-baking region.
-	if (!gAgentAvatarp->isUsingServerBakes())
-		return;
-	if (!gAgent.getRegion() || gAgent.getRegion()->getCentralBakeVersion()!=0)
-		return;
-
-	// if baked image service is unknown, need to refresh.
-	if (LLAppearanceMgr::instance().getAppearanceServiceURL().empty())
-	{
-		CheckAgentAppearanceServiceResponder::forceAppearanceUpdate();
-	}
-	// query baked image service to check status.
-	std::string image_url = gAgentAvatarp->getImageURL(TEX_HEAD_BAKED,
-													   getTE(TEX_HEAD_BAKED)->getID());
-	LLHTTPClient::head(image_url, new CheckAgentAppearanceServiceResponder);
-}
-
 const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const
 {
 	if (canGrabBakedTexture(baked_index))
@@ -2587,7 +2391,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
 				imagep->setBoostLevel(getAvatarBoostLevel());
 				imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
 				imagep->resetTextureStats();
-				imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL);
+				imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
 				imagep->addTextureStats( desired_pixels / texel_area_ratio );
 				imagep->forceUpdateBindStats() ;
 				if (imagep->getDiscardLevel() < 0)
@@ -2633,82 +2437,6 @@ ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset )
 	return TEX_HEAD_BAKED;
 }
 
-
-void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid)
-{
-	ETextureIndex index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(i);
-	setNewBakedTexture(index, uuid);
-}
-
-
-//-----------------------------------------------------------------------------
-// setNewBakedTexture()
-// A new baked texture has been successfully uploaded and we can start using it now.
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
-{
-	// Baked textures live on other sims.
-	LLHost target_host = getObjectHost();	
-	setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) );
-	updateMeshTextures();
-	dirtyMesh();
-
-	LLVOAvatar::cullAvatarsByPixelArea();
-
-	/* switch(te)
-		case TEX_HEAD_BAKED:
-			LL_INFOS() << "New baked texture: HEAD" << LL_ENDL; */
-	const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(te);
-	if (texture_dict->mIsBakedTexture)
-	{
-		debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish.
-		LL_INFOS() << "New baked texture: " << texture_dict->mName << " UUID: " << uuid <<LL_ENDL;
-	}
-	else
-	{
-		LL_WARNS() << "New baked texture: unknown te " << te << LL_ENDL;
-	}
-	
-	//	dumpAvatarTEs( "setNewBakedTexture() send" );
-	// RN: throttle uploads
-	if (!hasPendingBakedUploads())
-	{
-		gAgent.sendAgentSetAppearance();
-
-		if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
-		{
-			LLSD args;
-			args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
-			args["TIME"] = llformat("%d",(U32)mDebugSelfLoadTimer.getElapsedTimeF32());
-			if (isAllLocalTextureDataFinal())
-			{
-				LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args);
-				LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-						<< "sec ]"
-						<< avString() 
-						<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-						<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-						<< " Notification " << "AvatarRezSelfBakedDoneNotification"
-						<< LL_ENDL;
-			}
-			else
-			{
-				args["STATUS"] = debugDumpAllLocalTextureDataInfo();
-				LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args);
-				LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-						<< "sec ]"
-						<< avString() 
-						<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-						<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-						<< " Notification " << "AvatarRezSelfBakedUpdateNotification"
-						<< LL_ENDL;
-			}
-		}
-
-		outputRezDiagnostics();
-	}
-}
-
 // FIXME: This is not called consistently. Something may be broken.
 void LLVOAvatarSelf::outputRezDiagnostics() const
 {
@@ -2784,89 +2512,7 @@ void LLVOAvatarSelf::reportAvatarRezTime() const
 	// TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow.
 }
 
-//-----------------------------------------------------------------------------
-// setCachedBakedTexture()
-// A baked texture id was received from a cache query, make it active
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
-{
-	setTETexture( te, uuid );
-
-	/* switch(te)
-		case TEX_HEAD_BAKED:
-			if( mHeadLayerSet )
-				mHeadLayerSet->cancelUpload(); */
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		LLViewerTexLayerSet *layerset = getTexLayerSet(i);
-		if ( mBakedTextureDatas[i].mTextureIndex == te && layerset)
-		{
-			if (mInitialBakeIDs[i] != LLUUID::null)
-			{
-				if (mInitialBakeIDs[i] == uuid)
-				{
-					LL_INFOS() << "baked texture correctly loaded at login! " << i << LL_ENDL;
-				}
-				else
-				{
-					LL_WARNS() << "baked texture does not match id loaded at login!" << i << LL_ENDL;
-				}
-				mInitialBakeIDs[i] = LLUUID::null;
-			}
-			layerset->cancelUpload();
-		}
-	}
-}
-
-// static
-void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
-{
-	LLUUID texture_id;
-	msg->getUUID("TextureData", "TextureID", texture_id);
-	if (!isAgentAvatarValid()) return;
-
-	// If this is a texture corresponding to one of our baked entries, 
-	// just rebake that layer set.
-	BOOL found = FALSE;
-
-	/* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] =
-			TEX_HEAD_BAKED,
-			TEX_UPPER_BAKED, */
-	for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
-		 iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
-		 ++iter)
-	{
-		const ETextureIndex index = iter->first;
-		const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
-		if (texture_dict->mIsBakedTexture)
-		{
-			if (texture_id == gAgentAvatarp->getTEImage(index)->getID())
-			{
-				LLViewerTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index);
-				if (layer_set)
-				{
-					LL_INFOS() << "TAT: rebake - matched entry " << (S32)index << LL_ENDL;
-					gAgentAvatarp->invalidateComposite(layer_set, TRUE);
-					found = TRUE;
-					add(LLStatViewer::TEX_REBAKES, 1);
-				}
-			}
-		}
-	}
-
-	// If texture not found, rebake all entries.
-	if (!found)
-	{
-		gAgentAvatarp->forceBakeAllTextures();
-	}
-	else
-	{
-		// Not sure if this is necessary, but forceBakeAllTextures() does it.
-		gAgentAvatarp->updateMeshTextures();
-	}
-}
-
-
+// SUNSHINE CLEANUP - not clear we need any of this, may be sufficient to request server appearance in llviewermenu.cpp:handle_rebake_textures()
 void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 {
 	LL_INFOS() << "TAT: forced full rebake. " << LL_ENDL;
@@ -2880,10 +2526,9 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 			if (slam_for_debug)
 			{
 				layer_set->setUpdatesEnabled(TRUE);
-				layer_set->cancelUpload();
 			}
 
-			invalidateComposite(layer_set, TRUE);
+			invalidateComposite(layer_set);
 			add(LLStatViewer::TEX_REBAKES, 1);
 		}
 		else
@@ -2952,6 +2597,11 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch)
 {
 	if (isAgentAvatarValid())
 	{
+		if (!gAgentAvatarp->mEndCustomizeCallback.get())
+		{
+			gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy;
+		}
+		
 		gAgentAvatarp->mIsEditingAppearance = true;
 		gAgentAvatarp->mUseLocalAppearance = true;
 
@@ -2978,12 +2628,6 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
 	if (isAgentAvatarValid())
 	{
 		gAgentAvatarp->mIsEditingAppearance = false;
-		if (gAgentAvatarp->getRegion() && !gAgentAvatarp->getRegion()->getCentralBakeVersion())
-		{
-			// FIXME DRANO - move to sendAgentSetAppearance, make conditional on upload complete.
-			gAgentAvatarp->mUseLocalAppearance = false;
-		}
-
 		gAgentAvatarp->invalidateAll();
 
 		if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch)
@@ -2991,8 +2635,11 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
 			gAgentCamera.changeCameraToDefault();
 			gAgentCamera.resetView();
 		}
-	
-		LLAppearanceMgr::instance().updateAppearanceFromCOF();	
+
+		// Dereferencing the previous callback will cause
+		// updateAppearanceFromCOF to be called, whenever all refs
+		// have resolved.
+		gAgentAvatarp->mEndCustomizeCallback = NULL;
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 444175b62e99f458f1c8c6fe682c96e0e08e7fcd..e03de9fa0bfc9794c0e5cf3409063663275832cc 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -33,6 +33,7 @@
 #include <map>
 
 struct LocalTextureData;
+class LLInventoryCallback;
 
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -87,21 +88,15 @@ class LLVOAvatarSelf :
 	
 				void		resetJointPositions( void );
 	
-	/*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
-	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
-	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+	/*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
+	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight);
+	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight);
 	/*virtual*/ void updateVisualParams();
 	/*virtual*/ void idleUpdateAppearanceAnimation();
 
-	/*virtual*/ U32  processUpdateMessage(LLMessageSystem *mesgsys,
-													 void **user_data,
-													 U32 block_num,
-													 const EObjectUpdateType update_type,
-													 LLDataPacker *dp);
-
 private:
 	// helper function. Passed in param is assumed to be in avatar's parameter list.
-	BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE );
+	BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight);
 
 
 
@@ -129,6 +124,7 @@ class LLVOAvatarSelf :
 public:
 	/*virtual*/ BOOL 	updateCharacter(LLAgent &agent);
 	/*virtual*/ void 	idleUpdateTractorBeam();
+	bool				checkStuckAppearance();
 
 	//--------------------------------------------------------------------
 	// Loading state
@@ -185,12 +181,10 @@ class LLVOAvatarSelf :
 	// Loading status
 	//--------------------------------------------------------------------
 public:
-	/*virtual*/ bool	hasPendingBakedUploads() const;
 	S32					getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	bool				areTexturesCurrent() const;
 	BOOL				isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const;
 	BOOL				isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const;
-	BOOL				isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const;
 	// If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index
 	/*virtual*/ BOOL    isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	/*virtual*/ BOOL	isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const;
@@ -225,11 +219,8 @@ class LLVOAvatarSelf :
 	//--------------------------------------------------------------------
 public:
 	LLAvatarAppearanceDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const;
-	void				setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid);
-	void				setNewBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid);
-	void				setCachedBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid);
+	// SUNSHINE CLEANUP - dead? or update to just call request appearance update?
 	void				forceBakeAllTextures(bool slam_for_debug = false);
-	static void			processRebakeAvatarTextures(LLMessageSystem* msg, void**);
 protected:
 	/*virtual*/ void	removeMissingBakedTextures();
 
@@ -237,8 +228,6 @@ class LLVOAvatarSelf :
 	// Layers
 	//--------------------------------------------------------------------
 public:
-	void 				requestLayerSetUploads();
-	void				requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i);
 	void				requestLayerSetUpdate(LLAvatarAppearanceDefines::ETextureIndex i);
 	LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
 	LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::ETextureIndex index) const;
@@ -248,7 +237,7 @@ class LLVOAvatarSelf :
 	// Composites
 	//--------------------------------------------------------------------
 public:
-	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset);
 	/* virtual */ void	invalidateAll();
 	/* virtual */ void	setCompositeUpdatesEnabled(bool b); // only works for self
 	/* virtual */ void  setCompositeUpdatesEnabled(U32 index, bool b);
@@ -290,7 +279,7 @@ class LLVOAvatarSelf :
  **/
 
 public:
-	void				wearableUpdated(LLWearableType::EType type, BOOL upload_result);
+	void				wearableUpdated(LLWearableType::EType type);
 protected:
 	U32 getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const;
 
@@ -331,6 +320,7 @@ class LLVOAvatarSelf :
 public:
 	static void		onCustomizeStart(bool disable_camera_switch = false);
 	static void		onCustomizeEnd(bool disable_camera_switch = false);
+	LLPointer<LLInventoryCallback> mEndCustomizeCallback;
 
 	//--------------------------------------------------------------------
 	// Visibility
@@ -392,7 +382,6 @@ class LLVOAvatarSelf :
 	const std::string		debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer
 	const std::string		debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD
 	void					sendViewerAppearanceChangeMetrics(); // send data associated with completing a change.
-	void 					checkForUnsupportedServerBakeAppearance();
 private:
 	LLFrameTimer    		mDebugSelfLoadTimer;
 	F32						mDebugTimeWearablesLoaded;
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 312842a70ffd86921a16a654ddf803ef4468b95f..3c3dc3377221b53b444945e7077543361bd25300 100755
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -55,26 +55,27 @@ const U32 DEFAULT_RETRIES_COUNT = 3;
 
 class LLVoiceCallCapResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVoiceCallCapResponder);
 public:
 	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
 
+protected:
 	// called with bad status codes
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+	virtual void httpFailure();
+	virtual void httpSuccess();
 
 private:
 	LLUUID mSessionID;
 };
 
 
-void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLVoiceCallCapResponder::httpFailure()
 {
-	LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
 	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
 	if ( channelp )
 	{
-		if ( 403 == status )
+		if ( HTTP_FORBIDDEN == getStatus() )
 		{
 			//403 == no ability
 			LLNotificationsUtil::add(
@@ -91,12 +92,18 @@ void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& re
 	}
 }
 
-void LLVoiceCallCapResponder::result(const LLSD& content)
+void LLVoiceCallCapResponder::httpSuccess()
 {
 	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
 	if (channelp)
 	{
 		//*TODO: DEBUG SPAM
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 09a2003ef871e0c62fd1358c5d94e97d13d57ebd..9937a1c42a20d18951720cc143acf148c4ae7e06 100755
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -124,17 +124,19 @@ static int scale_speaker_volume(float volume)
 class LLVivoxVoiceAccountProvisionResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVivoxVoiceAccountProvisionResponder);
 public:
 	LLVivoxVoiceAccountProvisionResponder(int retries)
 	{
 		mRetries = retries;
 	}
 
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
 		LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, "
 			<<  ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" )
-			<< status << "]: " << content << LL_ENDL;
+			<< " " << dumpResponse() << LL_ENDL;
 
 		if ( mRetries > 0 )
 		{
@@ -146,14 +148,19 @@ class LLVivoxVoiceAccountProvisionResponder :
 		}
 	}
 
-	virtual void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-
 		std::string voice_sip_uri_hostname;
 		std::string voice_account_server_uri;
 		
-		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL;
 		
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		if(content.has("voice_sip_uri_hostname"))
 			voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
 		
@@ -166,7 +173,6 @@ class LLVivoxVoiceAccountProvisionResponder :
 			content["password"].asString(),
 			voice_sip_uri_hostname,
 			voice_account_server_uri);
-
 	}
 
 private:
@@ -190,33 +196,34 @@ static bool sMuteListListener_listening = false;
 
 class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVivoxVoiceClientCapResponder);
 public:
 	LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {};
 
+private:
 	// called with bad status codes
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+	/* virtual */ void httpFailure();
+	/* virtual */ void httpSuccess();
 
-private:
 	LLVivoxVoiceClient::state mRequestingState;  // state 
 };
 
-void LLVivoxVoiceClientCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLVivoxVoiceClientCapResponder::httpFailure()
 {
-	LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder error [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
 	LLVivoxVoiceClient::getInstance()->sessionTerminate();
 }
 
-void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
+void LLVivoxVoiceClientCapResponder::httpSuccess()
 {
 	LLSD::map_const_iterator iter;
 	
-	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << dumpResponse() << LL_ENDL;
 
 	std::string uri;
 	std::string credentials;
 	
+	const LLSD& content = getContent();
 	if ( content.has("voice_credentials") )
 	{
 		LLSD voice_credentials = content["voice_credentials"];
@@ -2651,7 +2658,7 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString
 	
 	// Status code of 20200 means "bad password".  We may want to special-case that at some point.
 	
-	if ( statusCode == 401 )
+	if ( statusCode == HTTP_UNAUTHORIZED )
 	{
 		// Login failure which is probably caused by the delay after a user's password being updated.
 		LL_INFOS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
@@ -3153,7 +3160,7 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent(
 		switch(statusCode)
 		{
 			case 0:
-			case 200:
+			case HTTP_OK:
 				// generic success
 				// Don't change the saved error code (it may have been set elsewhere)
 			break;
@@ -3426,7 +3433,7 @@ void LLVivoxVoiceClient::messageEvent(
 	LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
 //	LL_DEBUGS("Voice") << "    header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
 	
-	if(messageHeader.find("text/html") != std::string::npos)
+	if(messageHeader.find(HTTP_CONTENT_TEXT_HTML) != std::string::npos)
 	{
 		std::string message;
 
@@ -5393,9 +5400,10 @@ void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESta
 		{
 			switch(mAudioSession->mErrorStatusCode)
 			{
-				case 404:	// NOT_FOUND
+				case HTTP_NOT_FOUND:	// NOT_FOUND
+				// *TODO: Should this be 503?
 				case 480:	// TEMPORARILY_UNAVAILABLE
-				case 408:	// REQUEST_TIMEOUT
+				case HTTP_REQUEST_TIME_OUT:	// REQUEST_TIMEOUT
 					// call failed because other user was not available
 					// treat this as an error case
 					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index d1108020ff0170af9902002141604a1ea7c142b3..945d3711f013148cf570d55dfb118d37f35a442a 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -82,7 +82,7 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
 const F32 FORCE_CULL_AREA = 8.f;
 const F32 MAX_LOD_DISTANCE = 24.f;
-
+U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
 
 BOOL gAnimateTextures = TRUE;
 //extern BOOL gHideSelectedObjects;
@@ -4059,7 +4059,8 @@ U32 LLVOVolume::getPartitionType() const
 }
 
 LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp)
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp),
+LLVolumeGeometryManager()
 {
 	mLODPeriod = 32;
 	mDepthMask = FALSE;
@@ -4070,7 +4071,8 @@ LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
 }
 
 LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
-: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp)
+: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp),
+LLVolumeGeometryManager()
 {
 	mDepthMask = FALSE;
 	mLODPeriod = 32;
@@ -4107,6 +4109,70 @@ bool can_batch_texture(LLFace* facep)
 	return true;
 }
 
+const static U32 MAX_FACE_COUNT = 4096U;
+int32_t LLVolumeGeometryManager::sInstanceCount = 0;
+LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL;
+LLFace** LLVolumeGeometryManager::sBumpFaces = NULL;
+LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL;
+LLFace** LLVolumeGeometryManager::sNormFaces = NULL;
+LLFace** LLVolumeGeometryManager::sSpecFaces = NULL;
+LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL;
+LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL;
+
+LLVolumeGeometryManager::LLVolumeGeometryManager()
+	: LLGeometryManager()
+{
+	llassert(sInstanceCount >= 0);
+	if (sInstanceCount == 0)
+	{
+		allocateFaces(MAX_FACE_COUNT);
+	}
+
+	++sInstanceCount;
+}
+
+LLVolumeGeometryManager::~LLVolumeGeometryManager()
+{
+	llassert(sInstanceCount > 0);
+	--sInstanceCount;
+
+	if (sInstanceCount <= 0)
+	{
+		freeFaces();
+		sInstanceCount = 0;
+	}
+}
+
+void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount)
+{
+	sFullbrightFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sBumpFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sSimpleFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sNormFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sNormSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sAlphaFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+}
+
+void LLVolumeGeometryManager::freeFaces()
+{
+	ll_aligned_free<64>(sFullbrightFaces);
+	ll_aligned_free<64>(sBumpFaces);
+	ll_aligned_free<64>(sSimpleFaces);
+	ll_aligned_free<64>(sNormFaces);
+	ll_aligned_free<64>(sSpecFaces);
+	ll_aligned_free<64>(sNormSpecFaces);
+	ll_aligned_free<64>(sAlphaFaces);
+
+	sFullbrightFaces = NULL;
+	sBumpFaces = NULL;
+	sSimpleFaces = NULL;
+	sNormFaces = NULL;
+	sSpecFaces = NULL;
+	sNormSpecFaces = NULL;
+	sAlphaFaces = NULL;
+}
+
 static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face");
 
 void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
@@ -4429,16 +4495,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	mFaceList.clear();
 
-	const U32 MAX_FACE_COUNT = 4096;
-	
-	static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** bump_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** simple_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** norm_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** spec_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	
 	U32 fullbright_count = 0;
 	U32 bump_count = 0;
 	U32 simple_count = 0;
@@ -4458,7 +4514,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	bool emissive = false;
 
-	
+	//Determine if we've received skininfo that contains an
+	//alternate bind matrix - if it does then apply the translational component
+	//to the joints of the avatar.
+	bool pelvisGotSet = false;
 
 	{
 		LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST);
@@ -4541,18 +4600,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					is_rigged = true;
 				
 					//get drawpool of avatar with rigged face
-					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
-				
-					//Determine if we've received skininfo that contains an
-					//alternate bind matrix - if it does then apply the translational component
-					//to the joints of the avatar.
-					bool pelvisGotSet = false;
-
+					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);				
+					
 					if ( pAvatarVO )
 					{
-						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
+						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						
 						const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
-					
 						if ( pSkinData )
 						{
 							const int bindCnt = pSkinData->mAlternateBindMatrix.size();								
@@ -4560,43 +4613,42 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{					
 								const int jointCnt = pSkinData->mJointNames.size();
 								const F32 pelvisZOffset = pSkinData->mPelvisOffset;
-								bool fullRig = (jointCnt>=20) ? true : false;
+								bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								
 								if ( fullRig )
-								{
+								{								
 									for ( int i=0; i<jointCnt; ++i )
 									{
 										std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
-										//LL_INFOS()<<"joint name "<<lookingForJoint.c_str()<<LL_ENDL;
 										LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint );
 										if ( pJoint && pJoint->getId() != currentId )
 										{   									
 											pJoint->setId( currentId );
 											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									
+											
 											//Set the joint position
-											pJoint->storeCurrentXform( jointPos );																																
+											pJoint->storeCurrentXform( jointPos );					
+									
 											//If joint is a pelvis then handle old/new pelvis to foot values
 											if ( lookingForJoint == "mPelvis" )
 											{	
-												pJoint->storeCurrentXform( jointPos );																																
 												if ( !pAvatarVO->hasPelvisOffset() )
 												{										
 													pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset );
-													//Trigger to rebuild viewer AV
 													pelvisGotSet = true;											
 												}										
 											}										
-										}
-									}
+										}										
+									}																
 								}							
 							}
 						}
 					}
-					//If we've set the pelvis to a new position we need to also rebuild some information that the
-					//viewer does at launch (e.g. body size etc.)
-					if ( pelvisGotSet )
+					
+					//Rebuild body data if we altered joints/pelvis
+					if ( pelvisGotSet && pAvatarVO ) 
 					{
 						pAvatarVO->postPelvisSetRecalc();
-					}
+					}		
 
 					if (pool)
 					{
@@ -4820,7 +4872,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						{ //can be treated as alpha mask
 							if (simple_count < MAX_FACE_COUNT)
 							{
-								simple_faces[simple_count++] = facep;
+								sSimpleFaces[simple_count++] = facep;
 							}
 						}
 						else
@@ -4831,7 +4883,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							}
 							if (alpha_count < MAX_FACE_COUNT)
 							{
-								alpha_faces[alpha_count++] = facep;
+								sAlphaFaces[alpha_count++] = facep;
 							}
 						}
 					}
@@ -4854,14 +4906,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 									{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
 										if (normspec_count < MAX_FACE_COUNT)
 										{
-											normspec_faces[normspec_count++] = facep;
+											sNormSpecFaces[normspec_count++] = facep;
 										}
 									}
 									else
 									{ //has normal map (needs texcoord1 and tangent)
 										if (norm_count < MAX_FACE_COUNT)
 										{
-											norm_faces[norm_count++] = facep;
+											sNormFaces[norm_count++] = facep;
 										}
 									}
 								}
@@ -4869,14 +4921,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								{ //has specular map but no normal map, needs texcoord2
 									if (spec_count < MAX_FACE_COUNT)
 									{
-										spec_faces[spec_count++] = facep;
+										sSpecFaces[spec_count++] = facep;
 									}
 								}
 								else
 								{ //has neither specular map nor normal map, only needs texcoord0
 									if (simple_count < MAX_FACE_COUNT)
 									{
-										simple_faces[simple_count++] = facep;
+										sSimpleFaces[simple_count++] = facep;
 									}
 								}									
 							}
@@ -4884,14 +4936,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal + tangent
 								if (bump_count < MAX_FACE_COUNT)
 								{
-									bump_faces[bump_count++] = facep;
+									sBumpFaces[bump_count++] = facep;
 								}
 							}
 							else if (te->getShiny() || !te->getFullbright())
 							{ //needs normal
 								if (simple_count < MAX_FACE_COUNT)
 								{
-									simple_faces[simple_count++] = facep;
+									sSimpleFaces[simple_count++] = facep;
 								}
 							}
 							else 
@@ -4899,7 +4951,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								facep->setState(LLFace::FULLBRIGHT);
 								if (fullbright_count < MAX_FACE_COUNT)
 								{
-									fullbright_faces[fullbright_count++] = facep;
+									sFullbrightFaces[fullbright_count++] = facep;
 								}
 							}
 						}
@@ -4909,7 +4961,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal + tangent
 								if (bump_count < MAX_FACE_COUNT)
 								{
-									bump_faces[bump_count++] = facep;
+									sBumpFaces[bump_count++] = facep;
 								}
 							}
 							else if ((te->getShiny() && LLPipeline::sRenderBump) ||
@@ -4917,7 +4969,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal
 								if (simple_count < MAX_FACE_COUNT)
 								{
-									simple_faces[simple_count++] = facep;
+									sSimpleFaces[simple_count++] = facep;
 								}
 							}
 							else 
@@ -4925,7 +4977,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								facep->setState(LLFace::FULLBRIGHT);
 								if (fullbright_count < MAX_FACE_COUNT)
 								{
-									fullbright_faces[fullbright_count++] = facep;
+									sFullbrightFaces[fullbright_count++] = facep;
 								}
 							}
 						}
@@ -4952,7 +5004,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			{
 				drawablep->clearState(LLDrawable::RIGGED);
 			}
+			
 		}
+
+		
+		
+			
+		
+					
+
+		
 	}
 
 	group->mBufferUsage = useage;
@@ -4988,13 +5049,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
 	}
 
-	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, batch_textures, FALSE);
-	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, batch_textures);
-	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, TRUE, batch_textures);
-	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, FALSE);
-	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, norm_faces, norm_count, FALSE, FALSE);
-	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, spec_faces, spec_count, FALSE, FALSE);
-	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, normspec_faces, normspec_count, FALSE, FALSE);
+	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
+	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
+	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
+	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
+	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
+	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
+	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
 
 	if (!LLPipeline::sDelayVBUpdate)
 	{
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 608589312908dd2c85707b7309d4606395f7e382..b61fbbd07304cad9739741cb24d7698389f5b0ef 100755
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -81,6 +81,7 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara
 	LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL );
 	if( instance )
 	{
+		LL_DEBUGS("Avatar") << "wearable " << assetID << " found in LLWearableList" << LL_ENDL;
 		asset_arrived_callback( instance, userdata );
 	}
 	else
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index 0cf0e7b9c07bdbe419b940a8c07e2ee1405af1b9..ddb7f7bfce147daf0036ada23bc88734e1ceeacc 100755
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -67,9 +67,8 @@ class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::Responder
 	{
 	}
 
+	// *TODO: Check for 'application/json' content type, and parse json at the base class.
 	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
@@ -78,9 +77,9 @@ class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::Responder
 		strstrm << istr.rdbuf();
 		const std::string body = strstrm.str();
 
-		if (status != 200)
+		if (getStatus() != HTTP_OK)
 		{
-			LL_WARNS() << "Failed to get upload config (" << status << ")" << LL_ENDL;
+			LL_WARNS() << "Failed to get upload config " << dumpResponse() << LL_ENDL;
 			LLWebProfile::reportImageUploadStatus(false);
 			return;
 		}
@@ -128,14 +127,12 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::
 
 public:
 	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (status != 200)
+		if (getStatus() != HTTP_OK)
 		{
-			LL_WARNS() << "Failed to upload image: " << status << " " << reason << LL_ENDL;
+			LL_WARNS() << "Failed to upload image " << dumpResponse() << LL_ENDL;
 			LLWebProfile::reportImageUploadStatus(false);
 			return;
 		}
@@ -158,33 +155,36 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde
 	LOG_CLASS(LLWebProfileResponders::PostImageResponder);
 
 public:
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void completedRaw(const LLChannelDescriptors& channels,
+								  const LLIOPipe::buffer_ptr_t& buffer)
 	{
 		// Viewer seems to fail to follow a 303 redirect on POST request
 		// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
 		// Handle it manually.
-		if (status == 303)
+		if (getStatus() == HTTP_SEE_OTHER)
 		{
 			LLSD headers = LLViewerMedia::getHeaders();
-			headers["Cookie"] = LLWebProfile::getAuthCookie();
-			const std::string& redir_url = content["location"];
-			LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
-			LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder(), headers);
+			headers[HTTP_OUT_HEADER_COOKIE] = LLWebProfile::getAuthCookie();
+			const std::string& redir_url = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (redir_url.empty())
+			{
+				LL_WARNS() << "Received empty redirection URL " << dumpResponse() << LL_ENDL;
+				LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+				LLWebProfile::reportImageUploadStatus(false);
+			}
+			else
+			{
+				LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
+				LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
+			}
 		}
 		else
 		{
-			LL_WARNS() << "Unexpected POST status: " << status << " " << reason << LL_ENDL;
-			LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << LL_ENDL;
+			LL_WARNS() << "Unexpected POST response " << dumpResponse() << LL_ENDL;
+			LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
 			LLWebProfile::reportImageUploadStatus(false);
 		}
 	}
-
-	// Override just to suppress warnings.
-	/*virtual*/ void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
-	{
-	}
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -203,7 +203,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
 
 	LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL;
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Cookie"] = getAuthCookie();
+	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
 	LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers);
 }
 
@@ -227,8 +227,8 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
 	const std::string boundary = "----------------------------0123abcdefab";
 
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Cookie"] = getAuthCookie();
-	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
+	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary;
 
 	std::ostringstream body;
 
diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp
index 551d0be8d760ff9ae031e5b8e0a33b3275d966a9..eff70ca0b2853bd3aab295aa6356cea3a0370aef 100755
--- a/indra/newview/llwindebug.cpp
+++ b/indra/newview/llwindebug.cpp
@@ -45,7 +45,7 @@ class LLMemoryReserve {
 	~LLMemoryReserve();
 	void reserve();
 	void release();
-protected:
+private:
 	unsigned char *mReserve;
 	static const size_t MEMORY_RESERVATION_SIZE;
 };
@@ -53,7 +53,7 @@ class LLMemoryReserve {
 LLMemoryReserve::LLMemoryReserve() :
 	mReserve(NULL)
 {
-};
+}
 
 LLMemoryReserve::~LLMemoryReserve()
 {
@@ -66,14 +66,19 @@ const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024;
 void LLMemoryReserve::reserve()
 {
 	if(NULL == mReserve)
+	{
 		mReserve = new unsigned char[MEMORY_RESERVATION_SIZE];
-};
+	}
+}
 
 void LLMemoryReserve::release()
 {
-	delete [] mReserve;
+	if (NULL != mReserve)
+	{
+		delete [] mReserve;
+	}
 	mReserve = NULL;
-};
+}
 
 static LLMemoryReserve gEmergencyMemoryReserve;
 
@@ -130,6 +135,11 @@ void  LLWinDebug::init()
 	}
 }
 
+void LLWinDebug::cleanup ()
+{
+	gEmergencyMemoryReserve.release();
+}
+
 void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename)
 {
 	// Temporary fix to switch out the code that writes the DMP file.
diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h
index 6f274c6f162d400339ce4f12573c07c3fa20425f..a3cbf6dc036cde80da35f5c19d5c20dffbec2f89 100755
--- a/indra/newview/llwindebug.h
+++ b/indra/newview/llwindebug.h
@@ -37,6 +37,7 @@ class LLWinDebug:
 public:
 	static void init();
 	static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL);
+	static void cleanup();
 private:
 	static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename);
 };
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index 93eba5b6048aeddcf4552df38f76c295fee5eef0..3bedfbe502af09f22717da6c035bf5e8e7c47c96 100755
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -95,8 +95,9 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
 {
 	mID = ++sCount;
 }
-/*virtual*/ void LLEnvironmentRequestResponder::result(const LLSD& unvalidated_content)
+/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess()
 {
+	const LLSD& unvalidated_content = getContent();
 	LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
 
 	if (mID != sCount)
@@ -122,10 +123,10 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
 	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content);
 }
 /*virtual*/
-void LLEnvironmentRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLEnvironmentRequestResponder::httpFailure()
 {
-	LL_INFOS("WindlightCaps") << "Got an error, not using region windlight... [status:" 
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... "
+			<< dumpResponse() << LL_ENDL;
 	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
 }
 
@@ -169,8 +170,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 /****
  * LLEnvironmentApplyResponder
  ****/
-/*virtual*/ void LLEnvironmentApplyResponder::result(const LLSD& content)
+/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap() || !content.has("regionID"))
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
 	{
 		LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
@@ -185,7 +192,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 	}
 	else
 	{
-		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  Reason from sim: " << content["fail_reason"].asString() << LL_ENDL;
+		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << dumpResponse() << LL_ENDL;
 		LLSD args(LLSD::emptyMap());
 		args["FAIL_REASON"] = content["fail_reason"].asString();
 		LLNotificationsUtil::add("WLRegionApplyFail", args);
@@ -193,14 +200,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 	}
 }
 /*virtual*/
-void LLEnvironmentApplyResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLEnvironmentApplyResponder::httpFailure()
 {
-	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region!  [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! "
+		<< dumpResponse() << LL_ENDL;
 
 	LLSD args(LLSD::emptyMap());
 	std::stringstream msg;
-	msg << reason << " (Code " << status << ")";
+	msg << getReason() << " (Code " << getStatus() << ")";
 	args["FAIL_REASON"] = msg.str();
 	LLNotificationsUtil::add("WLRegionApplyFail", args);
 }
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
index 598ce6d52ac52c6c54989ce6d5498237564b92b5..089c799da7cac21dd37228c41411fe0acd7854f4 100755
--- a/indra/newview/llwlhandlers.h
+++ b/indra/newview/llwlhandlers.h
@@ -45,9 +45,9 @@ class LLEnvironmentRequest
 class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLEnvironmentRequestResponder);
-public:
-	virtual void result(const LLSD& content);
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 
 private:
 	friend class LLEnvironmentRequest;
@@ -72,7 +72,7 @@ class LLEnvironmentApply
 class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLEnvironmentApplyResponder);
-public:
+private:
 	/*
 	 * Expecting reply from sim in form of:
 	 * {
@@ -87,10 +87,10 @@ class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
 	 *   fail_reason : string
 	 * }
 	 */
-	virtual void result(const LLSD& content);
+	/* virtual */ void httpSuccess();
 
-	// non-200 errors only
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	// non-2xx errors only
+	/* virtual */ void httpFailure();
 
 private:
 	friend class LLEnvironmentApply;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 1ef2cfff8a601a3d707e5698ad4b814b4c73bc9e..b4e8114a5f5385a508dfd9a9ec77909305ce0410 100755
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1149,6 +1149,8 @@ class LLEstablishAgentCommunication : public LLHTTPNode
 					<< sim << LL_ENDL;
 			return;
 		}
+		LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == "
+				<< input["body"]["seed-capability"] << LL_ENDL;
 		regionp->setSeedCapability(input["body"]["seed-capability"]);
 	}
 };
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 8e164337b657d76ae0b1c239dc09b91f9fb8f41b..c12c2cc24c3639c8e020d0e6ec788246e61677b5 100755
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -333,7 +333,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	   This might help with bug #503 */
 	mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
 
-    mCurlRequest->slist_append("Content-Type: text/xml");
+    mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 
 	if (useGzip)
 	{
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..25e6de46d9572b19246f599db643b5363a37d8ff
--- /dev/null
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -0,0 +1,328 @@
+/** 
+ * @file llhttpretrypolicy_test.cpp
+ * @brief Header tests to exercise the LLHTTPRetryPolicy classes.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "../llhttpretrypolicy.h"
+#include "lltut.h"
+
+namespace tut
+{
+struct TestData
+{
+};
+
+typedef test_group<TestData>	RetryPolicyTestGroup;
+typedef RetryPolicyTestGroup::object		RetryPolicyTestObject;
+RetryPolicyTestGroup retryPolicyTestGroup("retry_policy");
+
+template<> template<>
+void RetryPolicyTestObject::test<1>()
+{
+	LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0);
+	LLSD headers;
+	F32 wait_seconds;
+	
+	// No retry until we've failed a try.
+	ensure("never retry 0", !never_retry.shouldRetry(wait_seconds));
+
+	// 0 retries max.
+	never_retry.onFailure(500,headers);
+	ensure("never retry 1", !never_retry.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<2>()
+{
+	LLSD headers;
+	F32 wait_seconds;
+
+	// Normally only retry on server error (5xx)
+	LLAdaptiveRetryPolicy noRetry404(1.0,2.0,3.0,10);
+	noRetry404.onFailure(404,headers);
+	ensure("no retry on 404", !noRetry404.shouldRetry(wait_seconds)); 
+
+	// Can retry on 4xx errors if enabled by flag.
+	bool do_retry_4xx = true;
+	LLAdaptiveRetryPolicy doRetry404(1.0,2.0,3.0,10,do_retry_4xx);
+	doRetry404.onFailure(404,headers);
+	ensure("do retry on 404", doRetry404.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<3>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// No retry until we've failed a try.
+	ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds));
+
+	// Starting wait 1.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 1", should_retry);
+	ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 2", should_retry);
+	ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits);
+
+	// Hit max wait of 3.0 (4.0 clamped to max 3)
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 3", should_retry);
+	ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits);
+
+	// At max wait, should stay at 3.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 4", should_retry);
+	ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits);
+
+	// Max retries, should fail now.
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 5", !should_retry);
+
+	// Max retries, should fail now.
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 5", !should_retry);
+
+	// After a success, should reset to the starting state.
+	basic_retry.onSuccess();
+
+	// No retry until we've failed a try.
+	ensure("basic_retry 6", !basic_retry.shouldRetry(wait_seconds));
+
+	// Starting wait 1.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 7", should_retry);
+	ensure_approximately_equals("basic_retry 7", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 8", should_retry);
+	ensure_approximately_equals("basic_retry 8", wait_seconds, 2.0F, frac_bits);
+}
+
+// Retries should stop as soon as a non-5xx error is received.
+template<> template<>
+void RetryPolicyTestObject::test<4>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// Starting wait 1.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 1", should_retry);
+	ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 2", should_retry);
+	ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits);
+
+	// Should fail on non-5xx
+	killer404.onFailure(404,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 3", !should_retry);
+
+	// After a non-5xx, should keep failing.
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 4", !should_retry);
+}
+
+// Test handling of "retry-after" header. If present, this header
+// value overrides the computed delay, but does not affect the
+// progression of delay values.  For example, if the normal
+// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls
+// get a retry header of 33, the pattern would become 1,33,33,8...
+template<> template<>
+void RetryPolicyTestObject::test<5>()
+{
+	LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6);
+	LLSD headers_with_retry;
+	headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666";
+	LLSD headers_without_retry;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 1", should_retry);
+	ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 2", should_retry);
+	ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 3", should_retry);
+	// 4.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 4", should_retry);
+	// 8.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 5", should_retry);
+	ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 6", should_retry);
+	ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 7", !should_retry);
+}
+
+// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait),
+// used by header parsing of the retry policy.
+template<> template<>
+void RetryPolicyTestObject::test<6>()
+{
+	F32 seconds_to_wait;
+	bool success;
+
+	std::string str1("0");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
+	ensure("parse 1", success);
+	ensure_equals("parse 1", seconds_to_wait, 0.0);
+
+	std::string str2("999.9");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
+	ensure("parse 2", success);
+	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
+
+	time_t nowseconds;
+	time(&nowseconds);
+	std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123();
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+	std::cerr << " str3 [" << str3 << "]" << std::endl;
+	ensure("parse 3", success);
+	ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F);
+}
+
+// Test retry-after field in both llmessage and CoreHttp headers.
+template<> template<>
+void RetryPolicyTestObject::test<7>()
+{
+	std::cerr << "7 starts" << std::endl;
+	
+	LLSD sd_headers;
+	time_t nowseconds;
+	time(&nowseconds);
+	LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5);
+	F32 seconds_to_wait;
+	bool should_retry;
+
+	// No retry until we've failed a try.
+	ensure("header 0", !policy.shouldRetry(seconds_to_wait));
+	
+	// no retry header, use default.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 1", should_retry);
+	ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6);
+
+	// retry header should override, give delay of 0
+	std::string date_string = LLDate((F64)(nowseconds+7)).asRFC1123();
+	sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = date_string;
+	policy.onFailure(503,sd_headers);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 2", should_retry);
+	ensure_approximately_equals_range("header 2", seconds_to_wait, 7.0F, 2.0F);
+
+	LLCore::HttpResponse *response;
+	LLCore::HttpHeaders *headers;
+
+	response = new LLCore::HttpResponse();
+	headers = new LLCore::HttpHeaders();
+	response->setStatus(503);
+	response->setHeaders(headers);
+	headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600"));
+	policy.onFailure(response);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 3",should_retry);
+	ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6);
+	response->release();
+
+	response = new LLCore::HttpResponse();
+	headers = new LLCore::HttpHeaders();
+	response->setStatus(503);
+	response->setHeaders(headers);
+	time(&nowseconds);
+	date_string = LLDate((F64)(nowseconds+77)).asRFC1123();
+	std::cerr << "date_string [" << date_string << "]" << std::endl;
+	headers->append(HTTP_IN_HEADER_RETRY_AFTER,date_string);
+	policy.onFailure(response);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 4",should_retry);
+	ensure_approximately_equals_range("header 4", seconds_to_wait, 77.0F, 2.0F);
+	response->release();
+
+	// Timeout should be clamped at max.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 5", should_retry);
+	ensure_approximately_equals("header 5", seconds_to_wait, 644.0F, 6);
+
+	// No more retries.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 6", !should_retry);
+}
+
+}
+
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 3e55336f2de25e454488a1e37b190210bb273de3..6f57daf1519a096c00057ddf7b6020a174d9f952 100755
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -33,7 +33,7 @@
 #include "llsdserialize.h"
 #include "llsdutil.h"
 #include "llerrorcontrol.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 
 #include "../llmediadataclient.h"
 #include "../llvovolume.h"
@@ -129,7 +129,7 @@ void LLHTTPClient::post(
 	{
 		LLSD content;
 		content["reason"] = "fake reason";
-		responder->errorWithContent(HTTP_SERVICE_UNAVAILABLE, "fake reason", content);
+		responder->failureResult(HTTP_SERVICE_UNAVAILABLE, "fake reason", content);
 		return;
 	}
 	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) 
@@ -137,8 +137,8 @@ void LLHTTPClient::post(
 		LLSD error;
 		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
 		result["error"] = error;
-	}	
-	responder->result(result);
+	}
+	responder->successResult(result);
 }
 
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index ed66066b0ad840f97dc044d79c2b9396b0dac239..c49b0350e9b279925145c3674de7861cbd8a9297 100755
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -40,12 +40,14 @@ namespace {
 
 LLCurl::Responder::Responder() { }
 LLCurl::Responder::~Responder() { }
-void LLCurl::Responder::error(U32,std::string const &) { }
-void LLCurl::Responder::result(LLSD const &) { }
-void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
-void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
-void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
-void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
+void LLCurl::Responder::httpFailure() { }
+void LLCurl::Responder::httpSuccess() { }
+void LLCurl::Responder::httpCompleted() { }
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) { }
+void LLCurl::Responder::successResult(const LLSD& content) { }
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) { }
+std::string LLCurl::Responder::dumpResponse() const { return "(failure)"; }
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
 void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
 void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
 void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
@@ -85,7 +87,7 @@ namespace tut
 
 		virtual void setParcelID(const LLUUID& parcel_id) { }
 
-		virtual void setErrorStatus(U32 status, const std::string& reason) { }
+		virtual void setErrorStatus(S32 status, const std::string& reason) { }
 
 		bool mProcessed;
 	};
diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp
index 8ce56326d83c54d84419f97a738900e93bc5f8be..5e73dbb981dab970d337ea8c46403218079217ec 100755
--- a/indra/newview/tests/lltranslate_test.cpp
+++ b/indra/newview/tests/lltranslate_test.cpp
@@ -34,6 +34,8 @@
 #include "lltrans.h"
 #include "llui.h"
 
+#include "../../llmessage/llhttpconstants.cpp"
+
 static const std::string GOOGLE_VALID_RESPONSE1 =
 "{\
  \"data\": {\
@@ -300,12 +302,10 @@ std::string LLControlGroup::getString(const std::string& name) { return "dummy";
 LLControlGroup::~LLControlGroup() {}
 
 LLCurl::Responder::Responder() {}
-void LLCurl::Responder::completedHeader(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::completedRaw(U32, const std::string&, const LLChannelDescriptors&, const LLIOPipe::buffer_ptr_t& buffer) {}
-void LLCurl::Responder::completed(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::error(U32, std::string const&) {}
-void LLCurl::Responder::errorWithContent(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::result(LLSD const&) {}
+void LLCurl::Responder::httpFailure() { }
+void LLCurl::Responder::httpSuccess() { }
+void LLCurl::Responder::httpCompleted() { }
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
 LLCurl::Responder::~Responder() {}
 
 void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32, bool) {}
diff --git a/indra/test/llassetuploadqueue_tut.cpp b/indra/test/llassetuploadqueue_tut.cpp
index ec952e0058c47aa0224066f4f53913f408161f87..25efe63d3fa84d41f43be6a497b46b915958c4cc 100755
--- a/indra/test/llassetuploadqueue_tut.cpp
+++ b/indra/test/llassetuploadqueue_tut.cpp
@@ -45,11 +45,11 @@ LLAssetUploadResponder::~LLAssetUploadResponder()
 {
 }
 
-void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
+void LLAssetUploadResponder::httpFailure()
 {
 }
 
-void LLAssetUploadResponder::result(const LLSD& content)
+void LLAssetUploadResponder::httpSuccess()
 {
 }
 
diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp
index 96e30f4e1e8cfa509c16a2891fae12bfff67211e..18eb01363f16e1c1063a96541759c42bf4ebad2e 100755
--- a/indra/test/llblowfish_tut.cpp
+++ b/indra/test/llblowfish_tut.cpp
@@ -65,7 +65,7 @@ namespace tut
 			}
 			if (!fp)
 			{
-				LL_WARNS() << "unabled to open " << filename << LL_ENDL;
+				LL_WARNS() << "unable to open " << filename << LL_ENDL;
 				return false;
 			}
 
diff --git a/indra/test/llhttpnode_tut.cpp b/indra/test/llhttpnode_tut.cpp
index 216c59d766de0620f73e62c472c3beb02a16e2c7..c528a3412927ea9032eb839ef14bf18c4f42b32f 100755
--- a/indra/test/llhttpnode_tut.cpp
+++ b/indra/test/llhttpnode_tut.cpp
@@ -44,7 +44,7 @@ namespace tut
 			std::ostringstream pathOutput;
 			bool addSlash = false;
 			
-			LLSD& remainder = mContext["request"]["remainder"];
+			LLSD& remainder = mContext[CONTEXT_REQUEST]["remainder"];
 			for (LLSD::array_const_iterator i = remainder.beginArray();
 				i != remainder.endArray();
 				++i)
@@ -81,6 +81,7 @@ namespace tut
 			void result(const LLSD& result) { mResult = result; }
 			void status(S32 code, const std::string& message) { }
 			void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+			void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
 			
 		private:
 			Response() {;} // Must be accessed through LLPointer.
diff --git a/indra/test/llsd_new_tut.cpp b/indra/test/llsd_new_tut.cpp
index f928a1bad0e6176af82a175428298f3b4f637ad4..03df1d339bc4f1856e3decdb97847a845fc6530d 100755
--- a/indra/test/llsd_new_tut.cpp
+++ b/indra/test/llsd_new_tut.cpp
@@ -93,6 +93,18 @@ namespace tut
 			ensure(			s + " type",	traits.checkType(actual));
 			ensure_equals(	s + " value",	traits.get(actual), expectedValue);
 		}
+
+		template<class T>
+		static void ensureTypeAndRefValue(const char* msg, const LLSD& actual,
+			const T& expectedValue)
+		{
+			LLSDTraits<const T&> traits;
+			
+			std::string s(msg);
+			
+			ensure(			s + " type",	traits.checkType(actual));
+			ensure_equals(	s + " value",	traits.get(actual), expectedValue);
+		}
 	};
 	
 	typedef test_group<SDTestData>	SDTestGroup;
@@ -162,7 +174,7 @@ namespace tut
 		std::vector<U8> data;
 		copy(&source[0], &source[sizeof(source)], back_inserter(data));
 		
-		v = data;		ensureTypeAndValue("set to data", v, data);
+		v = data;		ensureTypeAndRefValue("set to data", v, data);
 		
 		v.clear();
 		ensure("reset to undefined", v.type() == LLSD::TypeUndefined);
@@ -213,8 +225,8 @@ namespace tut
 		const char source[] = "once in a blue moon";
 		std::vector<U8> data;
 		copy(&source[0], &source[sizeof(source)], back_inserter(data));
-		LLSD x1(data);	ensureTypeAndValue("construct vector<U8>", x1, data);
-		LLSD x2 = data;	ensureTypeAndValue("initialize vector<U8>", x2, data);
+		LLSD x1(data);	ensureTypeAndRefValue("construct vector<U8>", x1, data);
+		LLSD x2 = data;	ensureTypeAndRefValue("initialize vector<U8>", x2, data);
 	}
 	
 	void checkConversions(const char* msg, const LLSD& v,
@@ -754,42 +766,6 @@ namespace tut
 			w = "nice day";
 		}
 
-		{
-			SDAllocationCheck check("shared values test for threaded work", 9);
-
-			//U32 start_llsd_count = llsd::outstandingCount();
-
-			LLSD m = LLSD::emptyMap();
-
-			m["one"] = 1;
-			m["two"] = 2;
-			m["one_copy"] = m["one"];			// 3 (m, "one" and "two")
-
-			m["undef_one"] = LLSD();
-			m["undef_two"] = LLSD();
-			m["undef_one_copy"] = m["undef_one"];
-
-			{	// Ensure first_array gets freed to avoid counting it
-				LLSD first_array = LLSD::emptyArray();
-				first_array.append(1.0f);
-				first_array.append(2.0f);			
-				first_array.append(3.0f);			// 7
-
-				m["array"] = first_array;
-				m["array_clone"] = first_array;
-				m["array_copy"] = m["array"];		// 7
-			}
-
-			m["string_one"] = "string one value";
-			m["string_two"] = "string two value";
-			m["string_one_copy"] = m["string_one"];		// 9
-
-			//U32 llsd_object_count = llsd::outstandingCount();
-			//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
-
-			//m.dumpStats();
-		}
-
 		{
 			SDAllocationCheck check("shared values test for threaded work", 9);
 
@@ -852,3 +828,4 @@ namespace tut
 		test serializations
 	*/
 }
+
diff --git a/indra/test/llsdtraits.h b/indra/test/llsdtraits.h
index 8144aaee948924dde8ab43e659ec6f1e2cefd888..07f6193ce247fdd98ce797964dcc3c8eaa42702e 100755
--- a/indra/test/llsdtraits.h
+++ b/indra/test/llsdtraits.h
@@ -93,7 +93,7 @@ LLSDTraits<LLSD::URI>::LLSDTraits()
 { }
 
 template<> inline
-LLSDTraits<LLSD::Binary>::LLSDTraits()
+LLSDTraits<const LLSD::Binary&>::LLSDTraits()
 	: type(LLSD::TypeBinary), getter(&LLSD::asBinary)
 { }
 
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
index 55d84bcaca3d5199ee88ba95a6222f465ced845b..243e869be7f6c3a89eeb4a7c7d14e9c61864a6b4 100755
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -65,6 +65,16 @@ namespace tut
 		ensure_approximately_equals(NULL, actual, expected, frac_bits);
 	}
 
+	inline void ensure_approximately_equals_range(const char *msg, F32 actual, F32 expected, F32 delta)
+	{
+		if (fabs(actual-expected)>delta)
+		{
+			std::stringstream ss;
+			ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected << " tolerance: " << delta;
+			throw tut::failure(ss.str().c_str());
+		}
+	}
+
 	inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len)
 	{
 		if((expected_len != actual_len) || 
diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp
index 4c0463c65c438bd28c7e82273636713dd6429856..57e423e5500bce7f388f15d1cc4587f3a8556ba5 100755
--- a/indra/test/message_tut.cpp
+++ b/indra/test/message_tut.cpp
@@ -45,6 +45,7 @@ namespace
 			mStatus = code;
 		}
 		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+		virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
 		S32 mStatus;
 	};
 }
@@ -141,7 +142,7 @@ namespace tut
 		const LLSD message;
 		const LLPointer<Response> response = new Response();
 		gMessageSystem->dispatch(name, message, response);
-		ensure_equals(response->mStatus, 404);
+		ensure_equals(response->mStatus, HTTP_NOT_FOUND);
 	}
 }
 
diff --git a/indra/test/mock_http_client.cpp b/indra/test/mock_http_client.cpp
index d7ef407d52e450c79d5ed97a2734f75256ec2dfd..e72902bfc2bbeb931ac934dacfba1990b00543ec 100755
--- a/indra/test/mock_http_client.cpp
+++ b/indra/test/mock_http_client.cpp
@@ -25,8 +25,7 @@
  */
 
 #include "linden_common.h"
-#include "llsdhttpserver.h"
-#include "lliohttpserver.h"
+#include "llhttpnode.h"
 
 namespace tut
 {
diff --git a/indra/test/mock_http_client.h b/indra/test/mock_http_client.h
index 7668a43fdf94ebc58a9d51aac09910c9c450527b..a2b9b435fb1db995e0108cbc65bcb6c1923b2b86 100755
--- a/indra/test/mock_http_client.h
+++ b/indra/test/mock_http_client.h
@@ -98,7 +98,7 @@ namespace tut
 			if (mSawError)
 			{
 				std::string msg =
-					llformat("error() called when not expected, status %d",
+					llformat("httpFailure() called when not expected, status %d",
 						mStatus); 
 				fail(msg);
 			}
@@ -108,7 +108,7 @@ namespace tut
 		{
 			if (!mSawError)
 			{
-				fail("error() wasn't called");
+				fail("httpFailure() wasn't called");
 			}
 		}
 		
@@ -119,7 +119,7 @@ namespace tut
 	
 	protected:
 		bool mSawError;
-		U32 mStatus;
+		S32 mStatus;
 		std::string mReason;
 		bool mSawCompleted;
 		LLSD mResult;
@@ -144,23 +144,22 @@ namespace tut
 				mClient.mResultDeleted = true;
 			}
 			
-			virtual void error(U32 status, const std::string& reason)
+		protected:
+			virtual void httpFailure()
 			{
 				mClient.mSawError = true;
-				mClient.mStatus = status;
-				mClient.mReason = reason;
+				mClient.mStatus = getStatus();
+				mClient.mReason = getReason();
 			}
 
-			virtual void result(const LLSD& content)
+			virtual void httpSuccess()
 			{
-				mClient.mResult = content;
+				mClient.mResult = getContent();
 			}
 
-			virtual void completed(
-							U32 status, const std::string& reason,
-							const LLSD& content)
+			virtual void httpCompleted()
 			{
-				LLHTTPClient::Responder::completed(status, reason, content);
+				LLHTTPClient::Responder::httpCompleted();
 				
 				mClient.mSawCompleted = true;
 			}
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 10f71a2843ef69fa42bfcbaad6229beb9aefed96..e42374d56bb503ce20cd82871c356f729f92d237 100755
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -95,25 +95,20 @@ class LLReplayLog
 	virtual void replay(std::ostream&) {}
 };
 
-class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boost::noncopyable
+class RecordToTempFile : public LLError::Recorder, public boost::noncopyable
 {
 public:
-	LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool):
-		mOldSettings(LLError::saveAndResetSettings()),
-		mProxy(new RecorderProxy(this)),
-		mTempFile("log", "", pool),		// create file
-		mFile(mTempFile.getName().c_str()) // open it
+	RecordToTempFile(apr_pool_t* pPool)
+		: LLError::Recorder(),
+		boost::noncopyable(),
+		mTempFile("log", "", pPool),
+		mFile(mTempFile.getName().c_str())
 	{
-		LLError::setFatalFunction(wouldHaveCrashed);
-		LLError::setDefaultLevel(level);
-		LLError::addRecorder(mProxy);
 	}
 
-	virtual ~LLReplayLogReal()
+	virtual ~RecordToTempFile()
 	{
-		LLError::removeRecorder(mProxy);
-		delete mProxy;
-		LLError::restoreSettings(mOldSettings);
+		mFile.close();
 	}
 
 	virtual void recordMessage(LLError::ELevel level, const std::string& message)
@@ -121,13 +116,13 @@ class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boos
 		mFile << message << std::endl;
 	}
 
-	virtual void reset()
+	void reset()
 	{
 		mFile.close();
 		mFile.open(mTempFile.getName().c_str());
 	}
 
-	virtual void replay(std::ostream& out)
+	void replay(std::ostream& out)
 	{
 		mFile.close();
 		std::ifstream inf(mTempFile.getName().c_str());
@@ -139,12 +134,45 @@ class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boos
 	}
 
 private:
-	LLError::Settings* mOldSettings;
-	LLError::Recorder* mProxy;
 	NamedTempFile mTempFile;
 	std::ofstream mFile;
 };
 
+class LLReplayLogReal: public LLReplayLog, public boost::noncopyable
+{
+public:
+	LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool)
+		: LLReplayLog(),
+		boost::noncopyable(),
+		mOldSettings(LLError::saveAndResetSettings()),
+		mRecorder(new RecordToTempFile(pool))
+	{
+		LLError::setFatalFunction(wouldHaveCrashed);
+		LLError::setDefaultLevel(level);
+		LLError::addRecorder(mRecorder);
+	}
+
+	virtual ~LLReplayLogReal()
+	{
+		LLError::removeRecorder(mRecorder);
+		LLError::restoreSettings(mOldSettings);
+	}
+
+	virtual void reset()
+	{
+		boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->reset();
+	}
+
+	virtual void replay(std::ostream& out)
+	{
+		boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->replay(out);
+	}
+
+private:
+	LLError::SettingsStoragePtr mOldSettings;
+	LLError::RecorderPtr mRecorder;
+};
+
 class LLTestCallback : public tut::callback
 {
 public:
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index dc8ff2f64476517cbbb573556a1ff6141739cdb9..8da4f88905c51f9ad365c7e4007352480858268a 100755
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -130,12 +130,13 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,
 	}
 }
 
-void LLUpdateChecker::Implementation::completed(U32 status,
-												const std::string & reason,
-												const LLSD & content)
+void LLUpdateChecker::Implementation::httpCompleted()
 {
 	mInProgress = false;	
-	
+
+	S32 status = getStatus();
+	const LLSD& content = getContent();
+	const std::string& reason = getReason();
 	if(status != 200)
 	{
 		std::string server_error;
@@ -162,8 +163,9 @@ void LLUpdateChecker::Implementation::completed(U32 status,
 }
 
 
-void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
+void LLUpdateChecker::Implementation::httpFailure()
 {
+	const std::string& reason = getReason();
 	mInProgress = false;
 	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
 	mClient.error(reason);
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index 4244007340103b2274fa027377bdfa9bd821031b..3163a6d53c517801c5d4509bb25809686678f2a9 100755
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -52,11 +52,10 @@ class LLUpdateChecker {
 						  bool                willing_to_test
 						  );
 	
+    protected:
 		// Responder:
-		virtual void completed(U32 status,
-							   const std::string & reason,
-							   const LLSD& content);
-		virtual void error(U32 status, const std::string & reason);
+		virtual void httpCompleted();
+		virtual void httpFailure();
 	
 	private:	
 		static const char * sLegacyProtocolVersion;