diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 5726ff62d10fac718218e56686399dc9cc859c09..4f573356886af53a69483b207d7fb27013c8bff5 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -37,6 +37,7 @@
 
 class LLTexLayerSet;
 class LLTexGlobalColor;
+class LLTexGlobalColorInfo;
 class LLWearableData;
 class LLAvatarBoneInfo;
 class LLAvatarSkeletonInfo;
diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h
index e7c94104cc5c19ec6d496c8bf9b616f1ebed2d4c..0351f28429510a6d54bed83acd870ecf3b850787 100644
--- a/indra/llappearance/llavatarappearancedefines.h
+++ b/indra/llappearance/llavatarappearancedefines.h
@@ -29,9 +29,10 @@
 #define LL_AVATARAPPEARANCE_DEFINES_H
 
 #include <vector>
-#include "llwearable.h"
 #include "lljointpickname.h"
 #include "lldictionary.h"
+#include "llwearabletype.h"
+#include "lluuid.h"
 
 namespace LLAvatarAppearanceDefines
 {
diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h
index 6f14448cca40bc483ed248f757a46816292d15b5..9b9f41fd1961e0ca30b149a8a0a647734ad36f12 100644
--- a/indra/llappearance/lllocaltextureobject.h
+++ b/indra/llappearance/lllocaltextureobject.h
@@ -32,7 +32,6 @@
 #include "llpointer.h"
 #include "llgltexture.h"
 
-class LLUUID;
 class LLTexLayer;
 class LLTexLayerTemplate;
 class LLWearable;
diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h
index 0d7fad349cbb409c6bdd98293a4f035eb8cb26f8..692cfa1a38fc0bc0966ac1ef5525b45299a81b85 100644
--- a/indra/llappearance/lltexlayer.h
+++ b/indra/llappearance/lltexlayer.h
@@ -36,6 +36,7 @@
 class LLAvatarAppearance;
 class LLImageTGA;
 class LLImageRaw;
+class LLLocalTextureObject;
 class LLXmlTreeNode;
 class LLTexLayerSet;
 class LLTexLayerSetInfo;
diff --git a/indra/llappearance/lltexturemanagerbridge.h b/indra/llappearance/lltexturemanagerbridge.h
index 99c01755d4d00eb5c456ed908d2f8de3fafd47cc..4b814b522dd49ff23dff72fc6da4ab36f7c26e75 100644
--- a/indra/llappearance/lltexturemanagerbridge.h
+++ b/indra/llappearance/lltexturemanagerbridge.h
@@ -27,6 +27,7 @@
 #ifndef LL_TEXTUREMANAGERBRIDGE_H
 #define LL_TEXTUREMANAGERBRIDGE_H
 
+#include "llavatarappearancedefines.h"
 #include "llpointer.h"
 #include "llgltexture.h"
 
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 9e73a6669a1f9a945ed65f10e7059098754bfba0..78ff510909529493cd49ad0757562180f48843c3 100755
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -62,52 +62,41 @@ LLAssetType::EType LLWearable::getAssetType() const
 	return LLWearableType::getAssetType(mType);
 }
 
+BOOL LLWearable::exportFile(LLFILE* fp) const
+{
+	llofstream ofs(fp);
+	return exportStream(ofs);
+}
+
 // virtual
-BOOL LLWearable::exportFile(LLFILE* file) const
+BOOL LLWearable::exportStream( std::ostream& output_stream ) const
 {
-	// header and version
-	if( fprintf( file, "LLWearable version %d\n", mDefinitionVersion ) < 0 )
-	{
-		return FALSE;
-	}
+	if (!output_stream.good()) return FALSE;
 
+	// header and version
+	output_stream << "LLWearable version " << mDefinitionVersion  << "\n";
 	// name
-	if( fprintf( file, "%s\n", mName.c_str() ) < 0 )
-	{
-		return FALSE;
-	}
-
+	output_stream << mName << "\n";
 	// description
-	if( fprintf( file, "%s\n", mDescription.c_str() ) < 0 )
-	{
-		return FALSE;
-	}
-	
+	output_stream << mDescription << "\n";
+
 	// permissions
-	if( !mPermissions.exportFile( file ) )
+	if( !mPermissions.exportStream( output_stream ) )
 	{
 		return FALSE;
 	}
 
 	// sale info
-	if( !mSaleInfo.exportFile( file ) )
+	if( !mSaleInfo.exportStream( output_stream ) )
 	{
 		return FALSE;
 	}
 
 	// wearable type
-	S32 type = (S32)mType;
-	if( fprintf( file, "type %d\n", type ) < 0 )
-	{
-		return FALSE;
-	}
+	output_stream << "type " << (S32) getType() << "\n";
 
 	// parameters
-	S32 num_parameters = mVisualParamIndexMap.size();
-	if( fprintf( file, "parameters %d\n", num_parameters ) < 0 )
-	{
-		return FALSE;
-	}
+	output_stream << "parameters " << mVisualParamIndexMap.size() << "\n";
 
 	for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin();
 		 iter != mVisualParamIndexMap.end(); 
@@ -116,27 +105,17 @@ BOOL LLWearable::exportFile(LLFILE* file) const
 		S32 param_id = iter->first;
 		const LLVisualParam* param = iter->second;
 		F32 param_weight = param->getWeight();
-		if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 )
-		{
-			return FALSE;
-		}
+		output_stream << param_id << " " << terse_F32_to_string( param_weight ) << "\n";
 	}
 
 	// texture entries
-	S32 num_textures = mTEMap.size();
-	if( fprintf( file, "textures %d\n", num_textures ) < 0 )
-	{
-			return FALSE;
-	}
+	output_stream << "textures " << mTEMap.size() << "\n";
 
 	for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
 	{
 			S32 te = iter->first;
 			const LLUUID& image_id = iter->second->getID();
-			if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 )
-			{
-					return FALSE;
-			}
+			output_stream << te << " " << image_id << "\n";
 	}
 	return TRUE;
 }
@@ -195,29 +174,49 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp)
 	}
 }
 
+LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp )
+{
+	llifstream ifs(fp);
+	return importStream(ifs, avatarp);
+}
+
 // virtual
-LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearance* avatarp )
+LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp )
 {
 	// *NOTE: changing the type or size of this buffer will require
-	// changes in the fscanf() code below. You would be better off
-	// rewriting this to use streams and not require an open FILE.
-	char text_buffer[2048];		/* Flawfinder: ignore */
-	S32 fields_read = 0;
+	// changes in the fscanf() code below.
+	// We are using a local max buffer size here to avoid issues
+	// if MAX_STRING size changes.
+	const U32 PARSE_BUFFER_SIZE = 2048;
+	char buffer[2048];		/* Flawfinder: ignore */
+	char uuid_buffer[37];	/* Flawfinder: ignore */
+
+	// This data is being generated on the viewer.
+	// Impose some sane limits on parameter and texture counts.
+	const S32 MAX_WEARABLE_ASSET_TEXTURES = 100;
+	const S32 MAX_WEARABLE_ASSET_PARAMETERS = 1000;
 
-	// read header and version 
-	fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion );
-	if( fields_read != 1 )
+	if(!avatarp)
 	{
-		return LLWearable::BAD_HEADER;
+		return LLWearable::FAILURE;
 	}
 
-	if(!avatarp)
+	// read header and version 
+	if (!input_stream.good())
 	{
+		llwarns << "Failed to read wearable asset input stream." << llendl;
 		return LLWearable::FAILURE;
 	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	if ( 1 != sscanf( /* Flawfinder: ignore */
+				buffer,
+				"LLWearable version %d\n",
+				&mDefinitionVersion ) )
+	{
+		return LLWearable::BAD_HEADER;
+	}
 
-
-	// Temporary hack to allow wearables with definition version 24 to still load.
+	// Hack to allow wearables with definition version 24 to still load.
 	// This should only affect lindens and NDA'd testers who have saved wearables in 2.0
 	// the extra check for version == 24 can be removed before release, once internal testers
 	// have loaded these wearables again. See hack pt 2 at bottom of function to ensure that
@@ -229,68 +228,58 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 	}
 
 	// name
-	int next_char = fgetc( file );		/* Flawfinder: ignore */
-	if( '\n' == next_char )
-	{
-		// no name
-		mName = "";
-	}
-	else
+	if (!input_stream.good())
 	{
-		ungetc( next_char, file );
-		fields_read = fscanf(	/* Flawfinder: ignore */
-			file,
-			"%2047[^\n]",
-			text_buffer);
-		if( (1 != fields_read) || (fgetc( file ) != '\n') )		/* Flawfinder: ignore */
-		{
-			llwarns << "Bad Wearable asset: early end of file" << llendl;
-			return LLWearable::FAILURE;
-		}
-		mName = text_buffer;
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading name" << llendl;
+		return LLWearable::FAILURE;
 	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	mName = buffer;
 
 	// description
-	next_char = fgetc( file );		/* Flawfinder: ignore */
-	if( '\n' == next_char )
+	if (!input_stream.good())
 	{
-		// no description
-		mDescription = "";
-	}
-	else
-	{
-		ungetc( next_char, file );
-		fields_read = fscanf(	/* Flawfinder: ignore */
-			file,
-			"%2047[^\n]",
-			text_buffer );
-		if( (1 != fields_read) || (fgetc( file ) != '\n') )		/* Flawfinder: ignore */
-		{
-			llwarns << "Bad Wearable asset: early end of file" << llendl;
-			return LLWearable::FAILURE;
-		}
-		mDescription = text_buffer;
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading description" << llendl;
+		return LLWearable::FAILURE;
 	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	mDescription = buffer;
 
 	// permissions
-	S32 perm_version;
-	fields_read = fscanf( file, " permissions %d\n", &perm_version );
-	if( (fields_read != 1) || (perm_version != 0) )
+	if (!input_stream.good())
+	{
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading permissions" << llendl;
+		return LLWearable::FAILURE;
+	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	S32 perm_version = -1;
+	if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) ||
+		 perm_version != 0 )
 	{
-		llwarns << "Bad Wearable asset: missing permissions" << llendl;
+		llwarns << "Bad Wearable asset: missing valid permissions" << llendl;
 		return LLWearable::FAILURE;
 	}
-	if( !mPermissions.importFile( file ) )
+	if( !mPermissions.importStream( input_stream ) )
 	{
 		return LLWearable::FAILURE;
 	}
 
 	// sale info
-	S32 sale_info_version;
-	fields_read = fscanf( file, " sale_info %d\n", &sale_info_version );
-	if( (fields_read != 1) || (sale_info_version != 0) )
+	if (!input_stream.good())
 	{
-		llwarns << "Bad Wearable asset: missing sale_info" << llendl;
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading sale info" << llendl;
+		return LLWearable::FAILURE;
+	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	S32 sale_info_version = -1;
+	if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) ||
+		sale_info_version != 0 )
+	{
+		llwarns << "Bad Wearable asset: missing valid sale_info" << llendl;
 		return LLWearable::FAILURE;
 	}
 	// Sale info used to contain next owner perm. It is now in the
@@ -299,7 +288,7 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 	// up the vast majority of the tasks.
 	BOOL has_perm_mask = FALSE;
 	U32 perm_mask = 0;
-	if( !mSaleInfo.importFile(file, has_perm_mask, perm_mask) )
+	if( !mSaleInfo.importStream(input_stream, has_perm_mask, perm_mask) )
 	{
 		return LLWearable::FAILURE;
 	}
@@ -314,9 +303,15 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 	}
 
 	// wearable type
+	if (!input_stream.good())
+	{
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading type" << llendl;
+		return LLWearable::FAILURE;
+	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
 	S32 type = -1;
-	fields_read = fscanf( file, "type %d\n", &type );
-	if( fields_read != 1 )
+	if ( 1 != sscanf( buffer, "type %d\n", &type ) )
 	{
 		llwarns << "Bad Wearable asset: bad type" << llendl;
 		return LLWearable::FAILURE;
@@ -333,27 +328,48 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 	}
 
 	// parameters header
-	S32 num_parameters = 0;
-	fields_read = fscanf( file, "parameters %d\n", &num_parameters );
-	if( fields_read != 1 )
+	if (!input_stream.good())
+	{
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading parameters header" << llendl;
+		return LLWearable::FAILURE;
+	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	S32 num_parameters = -1;
+	if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) )
 	{
 		llwarns << "Bad Wearable asset: missing parameters block" << llendl;
 		return LLWearable::FAILURE;
 	}
-
+	if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS )
+	{
+		llwarns << "Bad Wearable asset: too many parameters, "
+				<< num_parameters << llendl;
+		return LLWearable::FAILURE;
+	}
 	if( num_parameters != mVisualParamIndexMap.size() )
 	{
-		llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. type: " <<  mType << llendl;
+		llwarns << "Wearable parameter mismatch. Reading in " 
+				<< num_parameters << " from file, but created " 
+				<< mVisualParamIndexMap.size() 
+				<< " from avatar parameters. type: " 
+				<<  getType() << llendl;
 	}
 
 	// parameters
 	S32 i;
 	for( i = 0; i < num_parameters; i++ )
 	{
+		if (!input_stream.good())
+		{
+			llwarns << "Bad Wearable asset: early end of input stream " 
+					<< "while reading parameter #" << i << llendl;
+			return LLWearable::FAILURE;
+		}
+		input_stream.getline(buffer, PARSE_BUFFER_SIZE);
 		S32 param_id = 0;
 		F32 param_weight = 0.f;
-		fields_read = fscanf( file, "%d %f\n", &param_id, &param_weight );
-		if( fields_read != 2 )
+		if ( 2 != sscanf( buffer, "%d %f\n", &param_id, &param_weight ) )
 		{
 			llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl;
 			return LLWearable::FAILURE;
@@ -362,34 +378,53 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 	}
 
 	// textures header
-	S32 num_textures = 0;
-	fields_read = fscanf( file, "textures %d\n", &num_textures);
-	if( fields_read != 1 )
+	if (!input_stream.good())
+	{
+		llwarns << "Bad Wearable asset: early end of input stream " 
+				<< "while reading textures header" << i << llendl;
+		return LLWearable::FAILURE;
+	}
+	input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+	S32 num_textures = -1;
+	if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) )
 	{
 		llwarns << "Bad Wearable asset: missing textures block" << llendl;
 		return LLWearable::FAILURE;
 	}
+	if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES )
+	{
+		llwarns << "Bad Wearable asset: too many textures, "
+				<< num_textures << llendl;
+		return LLWearable::FAILURE;
+	}
 
 	// textures
 	for( i = 0; i < num_textures; i++ )
 	{
+		if (!input_stream.good())
+		{
+			llwarns << "Bad Wearable asset: early end of input stream " 
+					<< "while reading textures #" << i << llendl;
+			return LLWearable::FAILURE;
+		}
+		input_stream.getline(buffer, PARSE_BUFFER_SIZE);
 		S32 te = 0;
-		fields_read = fscanf(   /* Flawfinder: ignore */
-				file,
-				"%d %2047s\n",
-				&te, text_buffer);
-		if( fields_read != 2 )
+		if ( 2 != sscanf(   /* Flawfinder: ignore */
+				buffer,
+				"%d %36s\n",
+				&te, uuid_buffer) )
 		{
 				llwarns << "Bad Wearable asset: bad texture, #" << i << llendl;
 				return LLWearable::FAILURE;
 		}
 	
-		if( !LLUUID::validate( text_buffer ) )
+		if( !LLUUID::validate( uuid_buffer ) )
 		{
-				llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl;
+				llwarns << "Bad Wearable asset: bad texture uuid: " 
+						<< uuid_buffer << llendl;
 				return LLWearable::FAILURE;
 		}
-		LLUUID id = LLUUID(text_buffer);
+		LLUUID id = LLUUID(uuid_buffer);
 		LLGLTexture* image = gTextureManagerBridgep->getFetchedTexture( id );
 		if( mTEMap.find(te) != mTEMap.end() )
 		{
@@ -400,12 +435,15 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file, LLAvatarAppearan
 				delete mSavedTEMap[te];
 		}
 	
-		LLUUID textureid(text_buffer);
+		LLUUID textureid(uuid_buffer);
 		mTEMap[te] = new LLLocalTextureObject(image, textureid);
 		mSavedTEMap[te] = new LLLocalTextureObject(image, textureid);
 		createLayers(te, avatarp);
 	}
 
+	// copy all saved param values to working params
+	revertValues();
+
 	return LLWearable::SUCCESS;
 }
 
@@ -417,6 +455,171 @@ void LLWearable::setType(LLWearableType::EType type, LLAvatarAppearance *avatarp
 }
 
 
+LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index)
+{
+	te_map_t::iterator iter = mTEMap.find(index);
+	if( iter != mTEMap.end() )
+	{
+		LLLocalTextureObject* lto = iter->second;
+		return lto;
+	}
+	return NULL;
+}
+
+const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const
+{
+	te_map_t::const_iterator iter = mTEMap.find(index);
+	if( iter != mTEMap.end() )
+	{
+		const LLLocalTextureObject* lto = iter->second;
+		return lto;
+	}
+	return NULL;
+}
+
+std::vector<LLLocalTextureObject*> LLWearable::getLocalTextureListSeq()
+{
+	std::vector<LLLocalTextureObject*> result;
+
+	for(te_map_t::const_iterator iter = mTEMap.begin();
+		iter != mTEMap.end(); iter++)
+	{
+		LLLocalTextureObject* lto = iter->second;
+		result.push_back(lto);
+	}
+
+	return result;
+}
+
+void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject &lto)
+{
+	if( mTEMap.find(index) != mTEMap.end() )
+	{
+		mTEMap.erase(index);
+	}
+	mTEMap[index] = new LLLocalTextureObject(lto);
+}
+
+void LLWearable::revertValues()
+{
+	//update saved settings so wearable is no longer dirty
+	// non-driver params first
+	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+	{
+		S32 id = iter->first;
+		F32 value = iter->second;
+		LLVisualParam *param = getVisualParam(id);
+		if(param &&  !dynamic_cast<LLDriverParam*>(param) )
+		{
+			setVisualParamWeight(id, value, TRUE);
+		}
+	}
+
+	//then driver params
+	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+	{
+		S32 id = iter->first;
+		F32 value = iter->second;
+		LLVisualParam *param = getVisualParam(id);
+		if(param &&  dynamic_cast<LLDriverParam*>(param) )
+		{
+			setVisualParamWeight(id, value, TRUE);
+		}
+	}
+
+	// make sure that saved values are sane
+	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+	{
+		S32 id = iter->first;
+		LLVisualParam *param = getVisualParam(id);
+		if( param )
+		{
+			mSavedVisualParamMap[id] = param->getWeight();
+		}
+	}
+
+	syncImages(mSavedTEMap, mTEMap);
+}
+
+void LLWearable::saveValues()
+{
+	//update saved settings so wearable is no longer dirty
+	mSavedVisualParamMap.clear();
+	for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
+	{
+		S32 id = iter->first;
+		LLVisualParam *wearable_param = iter->second;
+		F32 value = wearable_param->getWeight();
+		mSavedVisualParamMap[id] = value;
+	}
+
+	// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
+	syncImages(mTEMap, mSavedTEMap);
+}
+
+void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
+{
+	// Deep copy of src (copies only those tes that are current, filling in defaults where needed)
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
+	{
+		if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType)
+		{
+			te_map_t::const_iterator iter = src.find(te);
+			LLUUID image_id;
+			LLGLTexture *image = NULL;
+			LLLocalTextureObject *lto = NULL;
+			if(iter != src.end())
+			{
+				// there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map.
+				lto = iter->second;
+				image = lto->getImage();
+				image_id = lto->getID();
+			}
+			else
+			{
+				// there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map.
+				image_id = getDefaultTextureImageID((ETextureIndex) te);
+				image = gTextureManagerBridgep->getFetchedTexture( image_id );
+			}
+
+			if( dst.find(te) != dst.end() )
+			{
+				// there's already an entry in the destination map for the texture. Just update its values.
+				dst[te]->setImage(image);
+				dst[te]->setID(image_id);
+			}
+			else
+			{
+				// no entry found in the destination map, we need to create a new Local Texture Object
+				dst[te] = new LLLocalTextureObject(image, image_id);
+			}
+
+			if( lto )
+			{
+				// If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map.
+				dst[te]->setBakedReady(lto->getBakedReady());
+				dst[te]->setDiscard(lto->getDiscard());
+			}
+		}
+	}
+}
+
+void LLWearable::destroyTextures()
+{
+	for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
+	{
+		LLLocalTextureObject *lto = iter->second;
+		delete lto;
+	}
+	mTEMap.clear();
+	for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
+	{
+		LLLocalTextureObject *lto = iter->second;
+		delete lto;
+	}
+	mSavedTEMap.clear();
+}
+
 void LLWearable::addVisualParam(LLVisualParam *param)
 {
 	if( mVisualParamIndexMap[param->getID()] )
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
index b8bbf82a6e0837adc126a349b92ddfeb8bfb3940..bc73ed4d8c55fe9a0d72a5f3bc5c82ee9fe4fbcd 100644
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -27,6 +27,7 @@
 #ifndef LL_LLWEARABLE_H
 #define LL_LLWEARABLE_H
 
+#include "llavatarappearancedefines.h"
 #include "llextendedstatus.h"
 #include "llpermissions.h"
 #include "llsaleinfo.h"
@@ -79,14 +80,19 @@ class LLWearable
 		SUCCESS,
 		BAD_HEADER
 	};
-	virtual BOOL				exportFile(LLFILE* file) const;
-	virtual EImportResult		importFile(LLFILE* file, LLAvatarAppearance* avatarp);
-
-
+	BOOL				exportFile(LLFILE* file) const;
+	EImportResult		importFile(LLFILE* file, LLAvatarAppearance* avatarp );
+	virtual BOOL				exportStream( std::ostream& output_stream ) const;
+	virtual EImportResult		importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
 
 	static void			setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; }
+	virtual LLUUID		getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const = 0;
+
+	LLLocalTextureObject* getLocalTextureObject(S32 index);
+	const LLLocalTextureObject* getLocalTextureObject(S32 index) const;
+	std::vector<LLLocalTextureObject*> getLocalTextureListSeq();
 
-	virtual LLLocalTextureObject* getLocalTextureObject(S32 index) = 0;
+	void				setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
 	void				addVisualParam(LLVisualParam *param);
 	void 				setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
 	F32					getVisualParamWeight(S32 index) const;
@@ -97,6 +103,9 @@ class LLWearable
 	LLColor4			getClothesColor(S32 te) const;
 	void 				setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
 
+	virtual void		revertValues();
+	virtual void		saveValues();
+
 	// Something happened that requires the wearable to be updated (e.g. worn/unworn).
 	virtual void		setUpdated() const = 0;
 
@@ -104,6 +113,9 @@ class LLWearable
 	virtual void		addToBakedTextureHash(LLMD5& hash) const = 0;
 
 protected:
+	typedef std::map<S32, LLLocalTextureObject*> te_map_t;
+	void				syncImages(te_map_t &src, te_map_t &dst);
+	void				destroyTextures();
 	void			 	createVisualParams(LLAvatarAppearance *avatarp);
 	void 				createLayers(S32 te, LLAvatarAppearance *avatarp);
 
@@ -121,7 +133,6 @@ class LLWearable
 	typedef std::map<S32, LLVisualParam *>    visual_param_index_map_t;
 	visual_param_index_map_t mVisualParamIndexMap;
 
-	typedef std::map<S32, LLLocalTextureObject*> te_map_t;
 	te_map_t mTEMap;				// maps TE to LocalTextureObject
 	te_map_t mSavedTEMap;			// last saved version of TEMap
 };
diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h
index 2931424131f557f65ff3a9053c7c60c14c36e1b5..379384a989c54612e5fed21497ea4c807ee0af69 100644
--- a/indra/llappearance/llwearabledata.h
+++ b/indra/llappearance/llwearabledata.h
@@ -28,6 +28,7 @@
 #define LL_WEARABLEDATA_H
 
 #include "llavatarappearancedefines.h"
+#include "llwearable.h"
 #include "llerror.h"
 
 class LLAvatarAppearance;
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index bc3bc3e74ac1cca5601a425a53891175c3e18555..c752859a3661f1116f8bc41ec43a36282dfc40ad 100644
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -30,6 +30,8 @@
 #include <map>
 #include <string>
 
+#include "llerror.h"
+
 struct LL_COMMON_API LLDictionaryEntry
 {
 	LLDictionaryEntry(const std::string &name);
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c51d042a3d312d908d5c8b56cd47341ee43dad51..38b0dfdaf175f94b1b8bbd5f0351164002157848 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -56,6 +56,8 @@ std::string strerr(int errn)
 	return buffer;
 }
 
+typedef std::basic_ios<char,std::char_traits < char > > _Myios;
+
 #else
 // On Posix we want to call strerror_r(), but alarmingly, there are two
 // different variants. The one that returns int always populates the passed
@@ -324,9 +326,10 @@ const char *LLFile::tmpdir()
 
 /***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
 
-#if USE_LLFILESTREAMS
+#if LL_WINDOWS
 
-LLFILE *	LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int)	// protection currently unused
+LLFILE *	LLFile::_Fiopen(const std::string& filename, 
+		std::ios::openmode mode,int)	// protection currently unused
 {	// open a file
 	static const char *mods[] =
 	{	// fopen mode strings corresponding to valid[i]
@@ -385,117 +388,677 @@ LLFILE *	LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,in
 	return (0);
 }
 
-/************** input file stream ********************************/
+#endif /* LL_WINDOWS */
 
-void llifstream::close()
-{	// close the C stream
-	if (_Filebuffer && _Filebuffer->close() == 0)
+/************** llstdio file buffer ********************************/
+
+
+//llstdio_filebuf* llstdio_filebuf::open(const char *_Filename,
+//	ios_base::openmode _Mode)
+//{
+//#if LL_WINDOWS
+//	_Filet *_File;
+//	if (is_open() || (_File = LLFILE::_Fiopen(_Filename, _Mode)) == 0)
+//		return (0);	// open failed
+//
+//	_Init(_File, _Openfl);
+//	_Initcvt(&_USE(_Mysb::getloc(), _Cvt));
+//	return (this);	// open succeeded
+//#else
+//	std::filebuf* _file = std::filebuf::open(_Filename, _Mode);
+//	if (NULL == _file) return NULL;
+//	return this;
+//#endif
+//}
+
+llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c)
+{
+	int_type __ret = traits_type::eof();
+	const bool __testeof = traits_type::eq_int_type(__c, __ret);
+	const bool __testout = _M_mode & ios_base::out;
+	if (__testout && !_M_reading)
 	{
-		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
+		if (this->pbase() < this->pptr())
+		{
+			// If appropriate, append the overflow char.
+			if (!__testeof)
+			{
+				*this->pptr() = traits_type::to_char_type(__c);
+				this->pbump(1);
+			}
+
+			// Convert pending sequence to external representation,
+			// and output.
+			if (_convert_to_external(this->pbase(),
+					 this->pptr() - this->pbase()))
+			{
+				_M_set_buffer(0);
+				__ret = traits_type::not_eof(__c);
+			}
+		}
+		else if (_M_buf_size > 1)
+		{
+			// Overflow in 'uncommitted' mode: set _M_writing, set
+			// the buffer to the initial 'write' mode, and put __c
+			// into the buffer.
+			_M_set_buffer(0);
+			_M_writing = true;
+			if (!__testeof)
+			{
+				*this->pptr() = traits_type::to_char_type(__c);
+				this->pbump(1);
+			}
+			__ret = traits_type::not_eof(__c);
+		}
+		else
+		{
+			// Unbuffered.
+			char_type __conv = traits_type::to_char_type(__c);
+			if (__testeof || _convert_to_external(&__conv, 1))
+			{
+				_M_writing = true;
+				__ret = traits_type::not_eof(__c);
+			}
+		}
 	}
+	return __ret;
 }
 
-void llifstream::open(const std::string& _Filename,	/* Flawfinder: ignore */
-	ios_base::openmode _Mode,
-	int _Prot)
-{	// open a C stream with specified mode
+bool llstdio_filebuf::_convert_to_external(char_type* __ibuf,
+						std::streamsize __ilen)
+{
+	// Sizes of external and pending output.
+	streamsize __elen;
+	streamsize __plen;
+	if (__check_facet(_M_codecvt).always_noconv())
+	{
+		//__elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
+		__elen = fwrite(reinterpret_cast<void*>(__ibuf), 1,
+						__ilen, _M_file.file());
+		__plen = __ilen;
+	}
+	else
+	{
+		// Worst-case number of external bytes needed.
+		// XXX Not done encoding() == -1.
+		streamsize __blen = __ilen * _M_codecvt->max_length();
+		char* __buf = static_cast<char*>(__builtin_alloca(__blen));
+
+		char* __bend;
+		const char_type* __iend;
+		codecvt_base::result __r;
+		__r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
+				__iend, __buf, __buf + __blen, __bend);
 
-	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
-	if(filep == NULL)
+		if (__r == codecvt_base::ok || __r == codecvt_base::partial)
+			__blen = __bend - __buf;
+		else if (__r == codecvt_base::noconv)
+		{
+			// Same as the always_noconv case above.
+			__buf = reinterpret_cast<char*>(__ibuf);
+			__blen = __ilen;
+		}
+		else
+			__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
+									"conversion error"));
+  
+		//__elen = _M_file.xsputn(__buf, __blen);
+		__elen = fwrite(__buf, 1, __blen, _M_file.file());
+		__plen = __blen;
+
+		// Try once more for partial conversions.
+		if (__r == codecvt_base::partial && __elen == __plen)
+		{
+			const char_type* __iresume = __iend;
+			streamsize __rlen = this->pptr() - __iend;
+			__r = _M_codecvt->out(_M_state_cur, __iresume,
+					__iresume + __rlen, __iend, __buf,
+					__buf + __blen, __bend);
+			if (__r != codecvt_base::error)
+			{
+				__rlen = __bend - __buf;
+				//__elen = _M_file.xsputn(__buf, __rlen);
+				__elen = fwrite(__buf, 1, __rlen, _M_file.file());
+				__plen = __rlen;
+			}
+			else
+			{
+				__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
+										"conversion error"));
+			}
+		}
+	}
+	return __elen == __plen;
+}
+
+llstdio_filebuf::int_type llstdio_filebuf::underflow()
+{
+	int_type __ret = traits_type::eof();
+	const bool __testin = _M_mode & ios_base::in;
+	if (__testin)
 	{
-		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
-		return;
+		if (_M_writing)
+		{
+			if (overflow() == traits_type::eof())
+			return __ret;
+			//_M_set_buffer(-1);
+			//_M_writing = false;
+		}
+		// Check for pback madness, and if so switch back to the
+		// normal buffers and jet outta here before expensive
+		// fileops happen...
+		_M_destroy_pback();
+
+		if (this->gptr() < this->egptr())
+			return traits_type::to_int_type(*this->gptr());
+
+		// Get and convert input sequence.
+		const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
+
+		// Will be set to true if ::fread() returns 0 indicating EOF.
+		bool __got_eof = false;
+		// Number of internal characters produced.
+		streamsize __ilen = 0;
+		codecvt_base::result __r = codecvt_base::ok;
+		if (__check_facet(_M_codecvt).always_noconv())
+		{
+			//__ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()),
+			//			__buflen);
+			__ilen = fread(reinterpret_cast<void*>(this->eback()), 1,
+						__buflen, _M_file.file());
+			if (__ilen == 0)
+				__got_eof = true;
+		}
+		else
+	    {
+			// Worst-case number of external bytes.
+			// XXX Not done encoding() == -1.
+			const int __enc = _M_codecvt->encoding();
+			streamsize __blen; // Minimum buffer size.
+			streamsize __rlen; // Number of chars to read.
+			if (__enc > 0)
+				__blen = __rlen = __buflen * __enc;
+			else
+			{
+				__blen = __buflen + _M_codecvt->max_length() - 1;
+				__rlen = __buflen;
+			}
+			const streamsize __remainder = _M_ext_end - _M_ext_next;
+			__rlen = __rlen > __remainder ? __rlen - __remainder : 0;
+
+			// An imbue in 'read' mode implies first converting the external
+			// chars already present.
+			if (_M_reading && this->egptr() == this->eback() && __remainder)
+				__rlen = 0;
+
+			// Allocate buffer if necessary and move unconverted
+			// bytes to front.
+			if (_M_ext_buf_size < __blen)
+			{
+				char* __buf = new char[__blen];
+				if (__remainder)
+					__builtin_memcpy(__buf, _M_ext_next, __remainder);
+
+				delete [] _M_ext_buf;
+				_M_ext_buf = __buf;
+				_M_ext_buf_size = __blen;
+			}
+			else if (__remainder)
+				__builtin_memmove(_M_ext_buf, _M_ext_next, __remainder);
+
+			_M_ext_next = _M_ext_buf;
+			_M_ext_end = _M_ext_buf + __remainder;
+			_M_state_last = _M_state_cur;
+
+			do
+			{
+				if (__rlen > 0)
+				{
+					// Sanity check!
+					// This may fail if the return value of
+					// codecvt::max_length() is bogus.
+					if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
+					{
+						__throw_ios_failure(__N("llstdio_filebuf::underflow "
+							"codecvt::max_length() "
+							"is not valid"));
+					}
+					//streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
+					streamsize __elen = fread(_M_ext_end, 1,
+						__rlen, _M_file.file());
+					if (__elen == 0)
+						__got_eof = true;
+					else if (__elen == -1)
+					break;
+					//_M_ext_end += __elen;
+				}
+
+				char_type* __iend = this->eback();
+				if (_M_ext_next < _M_ext_end)
+				{
+					__r = _M_codecvt->in(_M_state_cur, _M_ext_next,
+							_M_ext_end, _M_ext_next,
+							this->eback(),
+							this->eback() + __buflen, __iend);
+				}
+				if (__r == codecvt_base::noconv)
+				{
+					size_t __avail = _M_ext_end - _M_ext_buf;
+					__ilen = std::min(__avail, __buflen);
+					traits_type::copy(this->eback(),
+						reinterpret_cast<char_type*>
+						(_M_ext_buf), __ilen);
+					_M_ext_next = _M_ext_buf + __ilen;
+				}
+				else
+					__ilen = __iend - this->eback();
+
+				// _M_codecvt->in may return error while __ilen > 0: this is
+				// ok, and actually occurs in case of mixed encodings (e.g.,
+				// XML files).
+				if (__r == codecvt_base::error)
+					break;
+
+				__rlen = 1;
+			} while (__ilen == 0 && !__got_eof);
+		}
+
+		if (__ilen > 0)
+		{
+			_M_set_buffer(__ilen);
+			_M_reading = true;
+			__ret = traits_type::to_int_type(*this->gptr());
+		}
+		else if (__got_eof)
+		{
+			// If the actual end of file is reached, set 'uncommitted'
+			// mode, thus allowing an immediate write without an
+			// intervening seek.
+			_M_set_buffer(-1);
+			_M_reading = false;
+			// However, reaching it while looping on partial means that
+			// the file has got an incomplete character.
+			if (__r == codecvt_base::partial)
+				__throw_ios_failure(__N("llstdio_filebuf::underflow "
+					"incomplete character in file"));
+		}
+		else if (__r == codecvt_base::error)
+			__throw_ios_failure(__N("llstdio_filebuf::underflow "
+					"invalid byte sequence in file"));
+		else
+			__throw_ios_failure(__N("llstdio_filebuf::underflow "
+					"error reading the file"));
 	}
-	llassert(_Filebuffer == NULL);
-	_Filebuffer = new _Myfb(filep);
-	_ShouldClose = true;
-	_Myios::init(_Filebuffer);
+	return __ret;
 }
 
-bool llifstream::is_open() const
-{	// test if C stream has been opened
-	if(_Filebuffer)
-		return (_Filebuffer->is_open());
-	return false;
+std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n)
+{
+	// Clear out pback buffer before going on to the real deal...
+	streamsize __ret = 0;
+	if (_M_pback_init)
+	{
+		if (__n > 0 && this->gptr() == this->eback())
+		{
+			*__s++ = *this->gptr();
+			this->gbump(1);
+			__ret = 1;
+			--__n;
+		}
+		_M_destroy_pback();
+	}
+       
+	// Optimization in the always_noconv() case, to be generalized in the
+	// future: when __n > __buflen we read directly instead of using the
+	// buffer repeatedly.
+	const bool __testin = _M_mode & ios_base::in;
+	const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
+
+	if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
+		&& __testin && !_M_writing)
+	{
+		// First, copy the chars already present in the buffer.
+		const streamsize __avail = this->egptr() - this->gptr();
+		if (__avail != 0)
+		{
+			if (__avail == 1)
+				*__s = *this->gptr();
+			else
+				traits_type::copy(__s, this->gptr(), __avail);
+			__s += __avail;
+			this->gbump(__avail);
+			__ret += __avail;
+			__n -= __avail;
+		}
+
+		// Need to loop in case of short reads (relatively common
+		// with pipes).
+		streamsize __len;
+		for (;;)
+		{
+			//__len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n);
+			__len = fread(reinterpret_cast<void*>(__s), 1, 
+						__n, _M_file.file());
+			if (__len == -1)
+				__throw_ios_failure(__N("llstdio_filebuf::xsgetn "
+										"error reading the file"));
+			if (__len == 0)
+				break;
+
+			__n -= __len;
+			__ret += __len;
+			if (__n == 0)
+				break;
+
+			__s += __len;
+		}
+
+		if (__n == 0)
+		{
+			_M_set_buffer(0);
+			_M_reading = true;
+		}
+		else if (__len == 0)
+		{
+			// If end of file is reached, set 'uncommitted'
+			// mode, thus allowing an immediate write without
+			// an intervening seek.
+			_M_set_buffer(-1);
+			_M_reading = false;
+		}
+	}
+	else
+		__ret += __streambuf_type::xsgetn(__s, __n);
+
+	return __ret;
 }
-llifstream::~llifstream()
+
+std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n)
 {
-	if (_ShouldClose)
+	// Optimization in the always_noconv() case, to be generalized in the
+	// future: when __n is sufficiently large we write directly instead of
+	// using the buffer.
+	streamsize __ret = 0;
+	const bool __testout = _M_mode & ios_base::out;
+	if (__check_facet(_M_codecvt).always_noconv()
+		&& __testout && !_M_reading)
 	{
-		close();
+		// Measurement would reveal the best choice.
+		const streamsize __chunk = 1ul << 10;
+		streamsize __bufavail = this->epptr() - this->pptr();
+
+		// Don't mistake 'uncommitted' mode buffered with unbuffered.
+		if (!_M_writing && _M_buf_size > 1)
+			__bufavail = _M_buf_size - 1;
+
+		const streamsize __limit = std::min(__chunk, __bufavail);
+		if (__n >= __limit)
+		{
+			const streamsize __buffill = this->pptr() - this->pbase();
+			const char* __buf = reinterpret_cast<const char*>(this->pbase());
+			//__ret = _M_file.xsputn_2(__buf, __buffill,
+			//			reinterpret_cast<const char*>(__s), __n);
+			if (__buffill)
+			{
+				__ret = fwrite(__buf, 1, __buffill, _M_file.file());
+			}
+			if (__ret == __buffill)
+			{
+				__ret += fwrite(reinterpret_cast<const char*>(__s), 1,
+								__n, _M_file.file());
+			}
+			if (__ret == __buffill + __n)
+			{
+				_M_set_buffer(0);
+				_M_writing = true;
+			}
+			if (__ret > __buffill)
+				__ret -= __buffill;
+			else
+				__ret = 0;
+		}
+		else
+			__ret = __streambuf_type::xsputn(__s, __n);
 	}
-	delete _Filebuffer;
+	else
+		__ret = __streambuf_type::xsputn(__s, __n);
+    return __ret;
 }
 
-llifstream::llifstream(const std::string& _Filename,
-	ios_base::openmode _Mode,
-	int _Prot)
-	: std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
+int llstdio_filebuf::sync()
+{
+	return (_M_file.sync() == 0 ? 0 : -1);
+}
 
-{	// construct with named file and specified mode
-	open(_Filename, _Mode | ios_base::in, _Prot);	/* Flawfinder: ignore */
+/************** input file stream ********************************/
+
+
+llifstream::llifstream() : _M_filebuf(),
+#if LL_WINDOWS
+	std::istream(&_M_filebuf) {}
+#else
+	std::istream()
+{
+	this->init(&_M_filebuf);
+}
+#endif
+
+// explicit
+llifstream::llifstream(const std::string& _Filename, 
+		ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+	std::istream(&_M_filebuf)
+{
+	if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::in) == 0)
+	{
+		_Myios::setstate(ios_base::failbit);
+	}
+}
+#else
+	std::istream()
+{
+	this->init(&_M_filebuf);
+	this->open(_Filename.c_str(), _Mode | ios_base::in);
 }
+#endif
 
+// explicit
+llifstream::llifstream(const char* _Filename, 
+		ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+	std::istream(&_M_filebuf)
+{
+	if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0)
+	{
+		_Myios::setstate(ios_base::failbit);
+	}
+}
+#else
+	std::istream()
+{
+	this->init(&_M_filebuf);
+	this->open(_Filename, _Mode | ios_base::in);
+}
+#endif
 
-/************** output file stream ********************************/
 
-bool llofstream::is_open() const
+// explicit
+llifstream::llifstream(_Filet *_File,
+		ios_base::openmode _Mode, size_t _Size) :
+	_M_filebuf(_File, _Mode, _Size),
+#if LL_WINDOWS
+	std::istream(&_M_filebuf) {}
+#else
+	std::istream()
+{
+	this->init(&_M_filebuf);
+}
+#endif
+
+#if LL_WINDOWS
+// explicit
+llifstream::llifstream(int __fd,
+		ios_base::openmode _Mode, size_t _Size) :
+	_M_filebuf(__fd, _Mode, _Size),
+	std::istream()
+{
+	this->init(&_M_filebuf);
+}
+#endif
+
+bool llifstream::is_open() const
 {	// test if C stream has been opened
-	if(_Filebuffer)
-		return (_Filebuffer->is_open());
-	return false;
+	return _M_filebuf.is_open();
 }
 
-void llofstream::open(const std::string& _Filename,	/* Flawfinder: ignore */
-	ios_base::openmode _Mode,
-	int _Prot)
+void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
 {	// open a C stream with specified mode
-
-	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
-	if(filep == NULL)
+	if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0)
+#if LL_WINDOWS
 	{
-		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
-		return;
+		_Myios::setstate(ios_base::failbit);
 	}
-	llassert(_Filebuffer==NULL);
-	_Filebuffer = new _Myfb(filep);
-	_ShouldClose = true;
-	_Myios::init(_Filebuffer);
+	else
+	{
+		_Myios::clear();
+	}
+#else
+	{
+		this->setstate(ios_base::failbit);
+	}
+	else
+	{
+		this->clear();
+	}
+#endif
 }
 
-void llofstream::close()
+void llifstream::close()
 {	// close the C stream
-	if(is_open())
+	if (_M_filebuf.close() == 0)
 	{
-		if (_Filebuffer->close() == 0)
-		{
-			_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
-		}
-		delete _Filebuffer;
-		_Filebuffer = NULL;
-		_ShouldClose = false;
+#if LL_WINDOWS
+		_Myios::setstate(ios_base::failbit);
+#else
+		this->setstate(ios_base::failbit);
+#endif
 	}
 }
 
+
+/************** output file stream ********************************/
+
+
+llofstream::llofstream() : _M_filebuf(),
+#if LL_WINDOWS
+	std::ostream(&_M_filebuf) {}
+#else
+	std::ostream()
+{
+	this->init(&_M_filebuf);
+}
+#endif
+
+// explicit
 llofstream::llofstream(const std::string& _Filename,
-	std::ios_base::openmode _Mode,
-	int _Prot)
-		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
-{	// construct with named file and specified mode
-	open(_Filename, _Mode , _Prot);	/* Flawfinder: ignore */
+		ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+	std::ostream(&_M_filebuf)
+{
+	if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::out) == 0)
+	{
+		_Myios::setstate(ios_base::failbit);
+	}
+}
+#else
+	std::ostream()
+{
+	this->init(&_M_filebuf);
+	this->open(_Filename.c_str(), _Mode | ios_base::out);
+}
+#endif
+
+// explicit
+llofstream::llofstream(const char* _Filename,
+		ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+	std::ostream(&_M_filebuf)
+{
+	if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0)
+	{
+		_Myios::setstate(ios_base::failbit);
+	}
+}
+#else
+	std::ostream()
+{
+	this->init(&_M_filebuf);
+	this->open(_Filename, _Mode | ios_base::out);
+}
+#endif
+
+// explicit
+llofstream::llofstream(_Filet *_File,
+			ios_base::openmode _Mode, size_t _Size) :
+	_M_filebuf(_File, _Mode, _Size),
+#if LL_WINDOWS
+	std::ostream(&_M_filebuf) {}
+#else
+	std::ostream()
+{
+	this->init(&_M_filebuf);
 }
+#endif
 
-llofstream::~llofstream()
+#if LL_WINDOWS
+// explicit
+llofstream::llofstream(int __fd,
+			ios_base::openmode _Mode, size_t _Size) :
+	_M_filebuf(__fd, _Mode, _Size),
+	std::ostream()
 {
-	// destroy the object
-	if (_ShouldClose)
+	this->init(&_M_filebuf);
+}
+#endif
+
+bool llofstream::is_open() const
+{	// test if C stream has been opened
+	return _M_filebuf.is_open();
+}
+
+void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
+{	// open a C stream with specified mode
+	if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0)
+#if LL_WINDOWS
+	{
+		_Myios::setstate(ios_base::failbit);
+	}
+	else
 	{
-		close();
+		_Myios::clear();
 	}
-	delete _Filebuffer;
+#else
+	{
+		this->setstate(ios_base::failbit);
+	}
+	else
+	{
+		this->clear();
+	}
+#endif
 }
 
-#endif // #if USE_LLFILESTREAMS
+void llofstream::close()
+{	// close the C stream
+	if (_M_filebuf.close() == 0)
+	{
+#if LL_WINDOWS
+		_Myios::setstate(ios_base::failbit);
+#else
+		this->setstate(ios_base::failbit);
+#endif
+	}
+}
 
 /************** helper functions ********************************/
 
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index dd7d36513a06d13c81638c1d7eafbdac2e60ab9e..7049ab13969f1012e5ac198f676755e97b575231 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -35,16 +35,10 @@
  * Attempts to mostly mirror the POSIX style IO functions.
  */
 
-typedef FILE	LLFILE;
+typedef FILE LLFILE;
 
 #include <fstream>
-
-#ifdef LL_WINDOWS
-#define	USE_LLFILESTREAMS	1
-#else
-#define	USE_LLFILESTREAMS	0
-#endif
-
+#include <bits/postypes.h>
 #include <sys/stat.h>
 
 #if LL_WINDOWS
@@ -52,6 +46,7 @@ typedef FILE	LLFILE;
 typedef struct _stat	llstat;
 #else
 typedef struct stat		llstat;
+#include <ext/stdio_filebuf.h>
 #endif
 
 #ifndef S_ISREG
@@ -83,142 +78,342 @@ class LL_COMMON_API LLFile
 	static	int		stat(const std::string&	filename,llstat*	file_status);
 	static	bool	isdir(const std::string&	filename);
 	static	bool	isfile(const std::string&	filename);
-	static	LLFILE *	_Fiopen(const std::string& filename, std::ios::openmode mode,int);	// protection currently unused
+	static	LLFILE *	_Fiopen(const std::string& filename, 
+			std::ios::openmode mode);
 
 	static  const char * tmpdir();
 };
 
+/**
+ *  @brief Provides a layer of compatibility for C/POSIX.
+ *
+ *  This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and 
+ *  VC's basic_filebuf implementation.
+ *  This file buffer provides extensions for working with standard C FILE*'s 
+ *  and POSIX file descriptors for platforms that support this.
+*/
+namespace
+{
+#if LL_WINDOWS
+typedef std::filebuf						_Myfb;
+#else
+typedef  __gnu_cxx::stdio_filebuf< char >	_Myfb;
+typedef std::__c_file						_Filet;
+#endif /* LL_WINDOWS */
+}
 
-#if USE_LLFILESTREAMS
-
-class LL_COMMON_API llifstream	:	public	std::basic_istream < char , std::char_traits < char > >
+class LL_COMMON_API llstdio_filebuf : public _Myfb
 {
-	// input stream associated with a C stream
 public:
-	typedef std::basic_ifstream<char,std::char_traits < char > > _Myt;
-	typedef std::basic_filebuf<char,std::char_traits< char > > _Myfb;
-	typedef std::basic_ios<char,std::char_traits< char > > _Myios;
-
-	llifstream()
-		: std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
-	{	// construct unopened
-	}
+	/**
+	 * deferred initialization / destruction
+	*/
+	llstdio_filebuf() : _Myfb() {}
+	virtual ~llstdio_filebuf() {} 
+
+	/**
+	 *  @param  f  An open @c FILE*.
+	 *  @param  mode  Same meaning as in a standard filebuf.
+	 *  @param  size  Optimal or preferred size of internal buffer, in chars.
+	 *                Defaults to system's @c BUFSIZ.
+	 *
+	 *  This constructor associates a file stream buffer with an open
+	 *  C @c FILE*.  The @c FILE* will not be automatically closed when the
+	 *  stdio_filebuf is closed/destroyed.
+	*/
+	llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode,
+		    //size_t __size = static_cast<size_t>(BUFSIZ)) :
+		    size_t __size = static_cast<size_t>(1)) :
+#if LL_WINDOWS
+		_Myfb(__f) {}
+#else
+		_Myfb(__f, __mode, __size) {}
+#endif
 
-	explicit llifstream(const std::string& _Filename,
-		ios_base::openmode _Mode = ios_base::in,
-		int _Prot = (int)ios_base::_Openprot);
-
-	explicit llifstream(_Filet *_File)
-		: std::basic_istream<char,std::char_traits< char > >(NULL,true),
-			_Filebuffer(new _Myfb(_File)),
-			_ShouldClose(false)
-	{	// construct with specified C stream
-	}
-	virtual ~llifstream();
-
-	_Myfb *rdbuf() const
-	{	// return pointer to file buffer
-		return _Filebuffer;
-	}
-	bool is_open() const;
-	void open(const std::string& _Filename,	/* Flawfinder: ignore */
-		ios_base::openmode _Mode = ios_base::in,
-		int _Prot = (int)ios_base::_Openprot);	
-	void close();
+	/**
+	 *  @brief  Opens an external file.
+	 *  @param  s  The name of the file.
+	 *  @param  mode  The open mode flags.
+	 *  @return  @c this on success, NULL on failure
+	 *
+	 *  If a file is already open, this function immediately fails.
+	 *  Otherwise it tries to open the file named @a s using the flags
+	 *  given in @a mode.
+	*/
+	//llstdio_filebuf* open(const char *_Filename,
+	//		std::ios_base::openmode _Mode);
+
+	/**
+	 *  @param  fd  An open file descriptor.
+	 *  @param  mode  Same meaning as in a standard filebuf.
+	 *  @param  size  Optimal or preferred size of internal buffer, in chars.
+	 *
+	 *  This constructor associates a file stream buffer with an open
+	 *  POSIX file descriptor. The file descriptor will be automatically
+	 *  closed when the stdio_filebuf is closed/destroyed.
+	*/
+#if !LL_WINDOWS
+	llstdio_filebuf(int __fd, std::ios_base::openmode __mode,
+		//size_t __size = static_cast<size_t>(BUFSIZ)) :
+		size_t __size = static_cast<size_t>(1)) :
+		_Myfb(__fd, __mode, __size) {}
+#endif
 
-private:
-	_Myfb* _Filebuffer;	// the file buffer
-	bool _ShouldClose;
+// *TODO: Seek the underlying c stream for better cross-platform compatibility?
+#if !LL_WINDOWS
+protected:
+	/** underflow() and uflow() functions are called to get the next
+	 *  character from the real input source when the buffer is empty.
+	 *  Buffered input uses underflow()
+	*/
+	/*virtual*/ int_type underflow();
+
+	/*  Convert internal byte sequence to external, char-based
+	 * sequence via codecvt.
+	*/
+	bool _convert_to_external(char_type*, std::streamsize);
+
+	/** The overflow() function is called to transfer characters to the
+	 *  real output destination when the buffer is full. A call to
+	 *  overflow(c) outputs the contents of the buffer plus the
+	 *  character c.
+	 *  Consume some sequence of the characters in the pending sequence.
+	*/
+	/*virtual*/ int_type overflow(int_type __c = traits_type::eof());
+
+	/** sync() flushes the underlying @c FILE* stream.
+	*/
+	/*virtual*/ int sync();
+
+	std::streamsize xsgetn(char_type*, std::streamsize);
+	std::streamsize xsputn(char_type*, std::streamsize);
+#endif
 };
 
 
-class LL_COMMON_API llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
+/**
+ *  @brief  Controlling input for files.
+ *
+ *  This class supports reading from named files, using the inherited
+ *  functions from std::basic_istream.  To control the associated
+ *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
+ *  which allows construction using a pre-exisintg file stream buffer. 
+ *  We refer to this std::basic_filebuf (or derivative) as @c sb.
+*/
+class LL_COMMON_API llifstream	:	public	std::istream
 {
+	// input stream associated with a C stream
 public:
-	typedef std::basic_ostream< char , std::char_traits < char > > _Myt;
-	typedef std::basic_filebuf< char , std::char_traits < char > > _Myfb;
-	typedef std::basic_ios<char,std::char_traits < char > > _Myios;
-
-	llofstream()
-		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
-	{	// construct unopened
-	}
-
-	explicit llofstream(const std::string& _Filename,
-		std::ios_base::openmode _Mode = ios_base::out,
-		int _Prot = (int)std::ios_base::_Openprot);
-	
-
-	explicit llofstream(_Filet *_File)
-		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),
-			_Filebuffer(new _Myfb(_File)),//_File)
-			_ShouldClose(false)
-	{	// construct with specified C stream
-	}
-
-	virtual ~llofstream();
-
-	_Myfb *rdbuf() const
-	{	// return pointer to file buffer
-		return _Filebuffer;
-	}
+	// Constructors:
+	/**
+	 *  @brief  Default constructor.
+	 *
+	 *  Initializes @c sb using its default constructor, and passes
+	 *  @c &sb to the base class initializer.  Does not open any files
+	 *  (you haven't given it a filename to open).
+	*/
+	llifstream();
+
+	/**
+	 *  @brief  Create an input file stream.
+	 *  @param  Filename  String specifying the filename.
+	 *  @param  Mode  Open file in specified mode (see std::ios_base).
+	 *
+     *  @c ios_base::in is automatically included in @a mode.
+	*/
+	explicit llifstream(const std::string& _Filename,
+			ios_base::openmode _Mode = ios_base::in);
+	explicit llifstream(const char* _Filename,
+			ios_base::openmode _Mode = ios_base::in);
+
+	/**
+	 *  @brief  Create a stream using an open c file stream.
+	 *  @param  File  An open @c FILE*.
+        @param  Mode  Same meaning as in a standard filebuf.
+        @param  Size  Optimal or preferred size of internal buffer, in chars.
+                      Defaults to system's @c BUFSIZ.
+	*/
+	explicit llifstream(_Filet *_File,
+			ios_base::openmode _Mode = ios_base::in,
+			//size_t _Size = static_cast<size_t>(BUFSIZ));
+			size_t _Size = static_cast<size_t>(1));
+
+	/**
+	 *  @brief  Create a stream using an open file descriptor.
+	 *  @param  fd    An open file descriptor.
+        @param  Mode  Same meaning as in a standard filebuf.
+        @param  Size  Optimal or preferred size of internal buffer, in chars.
+                      Defaults to system's @c BUFSIZ.
+	*/
+#if !LL_WINDOWS
+	explicit llifstream(int __fd,
+			ios_base::openmode _Mode = ios_base::in,
+			//size_t _Size = static_cast<size_t>(BUFSIZ));
+			size_t _Size = static_cast<size_t>(1));
+#endif
 
+	/**
+	 *  @brief  The destructor does nothing.
+	 *
+	 *  The file is closed by the filebuf object, not the formatting
+	 *  stream.
+	*/
+	virtual ~llifstream() {}
+
+	// Members:
+	/**
+	 *  @brief  Accessing the underlying buffer.
+	 *  @return  The current basic_filebuf buffer.
+	 *
+	 *  This hides both signatures of std::basic_ios::rdbuf().
+	*/
+	llstdio_filebuf* rdbuf() const
+	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
+
+	/**
+	 *  @brief  Wrapper to test for an open file.
+	 *  @return  @c rdbuf()->is_open()
+	*/
 	bool is_open() const;
 
-	void open(const std::string& _Filename,ios_base::openmode _Mode = ios_base::out,int _Prot = (int)ios_base::_Openprot);	/* Flawfinder: ignore */
-
+	/**
+	 *  @brief  Opens an external file.
+	 *  @param  Filename  The name of the file.
+	 *  @param  Node  The open mode flags.
+	 *
+	 *  Calls @c llstdio_filebuf::open(s,mode|in).  If that function
+	 *  fails, @c failbit is set in the stream's error state.
+	*/
+	void open(const std::string& _Filename,
+			ios_base::openmode _Mode = ios_base::in)
+	{ open(_Filename.c_str(), _Mode); }
+	void open(const char* _Filename,
+			ios_base::openmode _Mode = ios_base::in);
+
+	/**
+	 *  @brief  Close the file.
+	 *
+	 *  Calls @c llstdio_filebuf::close().  If that function
+	 *  fails, @c failbit is set in the stream's error state.
+	*/
 	void close();
 
 private:
-	_Myfb *_Filebuffer;	// the file buffer
-	bool _ShouldClose;
-};
-
-
-
-#else
-//Use standard file streams on non windows platforms
-//#define	llifstream	std::ifstream
-//#define	llofstream	std::ofstream
-
-class LL_COMMON_API llifstream	:	public	std::ifstream
-{
-public:
-	llifstream() : std::ifstream()
-	{
-	}
-
-	explicit llifstream(const std::string& _Filename, std::_Ios_Openmode _Mode = in)
-		: std::ifstream(_Filename.c_str(), _Mode)
-	{
-	}
-	void open(const std::string& _Filename, std::_Ios_Openmode _Mode = in)	/* Flawfinder: ignore */
-	{
-		std::ifstream::open(_Filename.c_str(), _Mode);
-	}
+	llstdio_filebuf _M_filebuf;
 };
 
 
-class LL_COMMON_API llofstream	:	public	std::ofstream
+/**
+ *  @brief  Controlling output for files.
+ *
+ *  This class supports writing to named files, using the inherited
+ *  functions from std::basic_ostream.  To control the associated
+ *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
+ *  which allows construction using a pre-exisintg file stream buffer. 
+ *  We refer to this std::basic_filebuf (or derivative) as @c sb.
+*/
+class LL_COMMON_API llofstream	:	public	std::ostream
 {
 public:
-	llofstream() : std::ofstream()
-	{
-	}
+	// Constructors:
+	/**
+	 *  @brief  Default constructor.
+	 *
+	 *  Initializes @c sb using its default constructor, and passes
+	 *  @c &sb to the base class initializer.  Does not open any files
+	 *  (you haven't given it a filename to open).
+	*/
+	llofstream();
+
+	/**
+	 *  @brief  Create an output file stream.
+	 *  @param  Filename  String specifying the filename.
+	 *  @param  Mode  Open file in specified mode (see std::ios_base).
+	 *
+	 *  @c ios_base::out|ios_base::trunc is automatically included in
+	 *  @a mode.
+	*/
+	explicit llofstream(const std::string& _Filename,
+			ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+	explicit llofstream(const char* _Filename,
+			ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+
+	/**
+	 *  @brief  Create a stream using an open c file stream.
+	 *  @param  File  An open @c FILE*.
+        @param  Mode  Same meaning as in a standard filebuf.
+        @param  Size  Optimal or preferred size of internal buffer, in chars.
+                      Defaults to system's @c BUFSIZ.
+	*/
+	explicit llofstream(_Filet *_File,
+			ios_base::openmode _Mode = ios_base::out,
+			//size_t _Size = static_cast<size_t>(BUFSIZ));
+			size_t _Size = static_cast<size_t>(1));
+
+	/**
+	 *  @brief  Create a stream using an open file descriptor.
+	 *  @param  fd    An open file descriptor.
+        @param  Mode  Same meaning as in a standard filebuf.
+        @param  Size  Optimal or preferred size of internal buffer, in chars.
+                      Defaults to system's @c BUFSIZ.
+	*/
+#if !LL_WINDOWS
+	explicit llofstream(int __fd,
+			ios_base::openmode _Mode = ios_base::out,
+			//size_t _Size = static_cast<size_t>(BUFSIZ));
+			size_t _Size = static_cast<size_t>(1));
+#endif
 
-	explicit llofstream(const std::string& _Filename, std::_Ios_Openmode _Mode = out)
-		: std::ofstream(_Filename.c_str(), _Mode)
-	{
-	}
+	/**
+	 *  @brief  The destructor does nothing.
+	 *
+	 *  The file is closed by the filebuf object, not the formatting
+	 *  stream.
+	*/
+	virtual ~llofstream() {}
+
+	// Members:
+	/**
+	 *  @brief  Accessing the underlying buffer.
+	 *  @return  The current basic_filebuf buffer.
+	 *
+	 *  This hides both signatures of std::basic_ios::rdbuf().
+	*/
+	llstdio_filebuf* rdbuf() const
+	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
+
+	/**
+	 *  @brief  Wrapper to test for an open file.
+	 *  @return  @c rdbuf()->is_open()
+	*/
+	bool is_open() const;
 
-	void open(const std::string& _Filename, std::_Ios_Openmode _Mode = out)	/* Flawfinder: ignore */
-	{
-		std::ofstream::open(_Filename.c_str(), _Mode);
-	}
+	/**
+	 *  @brief  Opens an external file.
+	 *  @param  Filename  The name of the file.
+	 *  @param  Node  The open mode flags.
+	 *
+	 *  Calls @c llstdio_filebuf::open(s,mode|out).  If that function
+	 *  fails, @c failbit is set in the stream's error state.
+	*/
+	void open(const std::string& _Filename,
+			ios_base::openmode _Mode = ios_base::out|ios_base::trunc)
+	{ open(_Filename.c_str(), _Mode); }
+	void open(const char* _Filename,
+			ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+
+	/**
+	 *  @brief  Close the file.
+	 *
+	 *  Calls @c llstdio_filebuf::close().  If that function
+	 *  fails, @c failbit is set in the stream's error state.
+	*/
+	void close();
 
+private:
+	llstdio_filebuf _M_filebuf;
 };
 
-#endif
 
 /**
  * @breif filesize helpers.
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index fbf23bc3f09a760eee88c85f29cf41df9a1a5352..2dbc3310368d3cbf8f601c995627f76a64bb1f96 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -824,7 +824,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
 		}
 		else if(0 == strcmp("permissions", keyword))
 		{
-			success = mPermissions.importLegacyStream(input_stream);
+			success = mPermissions.importStream(input_stream);
 		}
 		else if(0 == strcmp("sale_info", keyword))
 		{
@@ -834,7 +834,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
 			// should pick up the vast majority of the tasks.
 			BOOL has_perm_mask = FALSE;
 			U32 perm_mask = 0;
-			success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask);
+			success = mSaleInfo.importStream(input_stream, has_perm_mask, perm_mask);
 			if(has_perm_mask)
 			{
 				if(perm_mask == PERM_NONE)
@@ -950,7 +950,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
 	output_stream << "\t\titem_id\t" << uuid_str << "\n";
 	mParentUUID.toString(uuid_str);
 	output_stream << "\t\tparent_id\t" << uuid_str << "\n";
-	mPermissions.exportLegacyStream(output_stream);
+	mPermissions.exportStream(output_stream);
 
 	// Check for permissions to see the asset id, and if so write it
 	// out as an asset id. Otherwise, apply our cheesy encryption.
@@ -984,7 +984,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
 	std::string buffer;
 	buffer = llformat( "\t\tflags\t%08x\n", mFlags);
 	output_stream << buffer;
-	mSaleInfo.exportLegacyStream(output_stream);
+	mSaleInfo.exportStream(output_stream);
 	output_stream << "\t\tname\t" << mName.c_str() << "|\n";
 	output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n";
 	output_stream << "\t\tcreation_date\t" << mCreationDate << "\n";
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 7e013de11a1b90f39d7c781619fe550433dbe250..34354e3e8c5c73a38241cd0239924735c6e4d698 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -572,143 +572,17 @@ void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 b
 
 BOOL LLPermissions::importFile(LLFILE* fp)
 {
-	init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
-	const S32 BUFSIZE = 16384;
-
-	// *NOTE: Changing the buffer size will require changing the scanf
-	// calls below.
-	char buffer[BUFSIZE];	/* Flawfinder: ignore */
-	char keyword[256];	/* Flawfinder: ignore */
-	char valuestr[256];	/* Flawfinder: ignore */
-	char uuid_str[256];	/* Flawfinder: ignore */
-	U32 mask;
-
-	keyword[0]  = '\0';
-	valuestr[0] = '\0';
-
-	while (!feof(fp))
-	{
-		if (fgets(buffer, BUFSIZE, fp) == NULL)
-		{
-			buffer[0] = '\0';
-		}
-		
-		sscanf( /* Flawfinder: ignore */
-			buffer,
-			" %255s %255s",
-			keyword, valuestr);
-		if (!strcmp("{", keyword))
-		{
-			continue;
-		}
-		if (!strcmp("}",keyword))
-		{
-			break;
-		}
-		else if (!strcmp("creator_mask", keyword))
-		{
-			// legacy support for "creator" masks
-			sscanf(valuestr, "%x", &mask);
-			mMaskBase = mask;
-			fixFairUse();
-		}
-		else if (!strcmp("base_mask", keyword))
-		{
-			sscanf(valuestr, "%x", &mask);
-			mMaskBase = mask;
-			//fixFairUse();
-		}
-		else if (!strcmp("owner_mask", keyword))
-		{
-			sscanf(valuestr, "%x", &mask);
-			mMaskOwner = mask;
-		}
-		else if (!strcmp("group_mask", keyword))
-		{
-			sscanf(valuestr, "%x", &mask);
-			mMaskGroup = mask;
-		}
-		else if (!strcmp("everyone_mask", keyword))
-		{
-			sscanf(valuestr, "%x", &mask);
-			mMaskEveryone = mask;
-		}
-		else if (!strcmp("next_owner_mask", keyword))
-		{
-			sscanf(valuestr, "%x", &mask);
-			mMaskNextOwner = mask;
-		}
-		else if (!strcmp("creator_id", keyword))
-		{
-			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
-			mCreator.set(uuid_str);
-		}
-		else if (!strcmp("owner_id", keyword))
-		{
-			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
-			mOwner.set(uuid_str);
-		}
-		else if (!strcmp("last_owner_id", keyword))
-		{
-			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
-			mLastOwner.set(uuid_str);
-		}
-		else if (!strcmp("group_id", keyword))
-		{
-			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
-			mGroup.set(uuid_str);
-		}
-		else if (!strcmp("group_owned", keyword))
-		{
-			sscanf(valuestr, "%d", &mask);
-			if(mask) mIsGroupOwned = true;
-			else mIsGroupOwned = false;
-		}
-		else
-		{
-			llinfos << "unknown keyword " << keyword << " in permissions import" << llendl;
-		}
-	}
-	fix();
-	return TRUE;
+	llifstream ifs(fp);
+	return importStream(ifs);
 }
 
-
 BOOL LLPermissions::exportFile(LLFILE* fp) const
 {
-	std::string uuid_str;
-
-	fprintf(fp, "\tpermissions 0\n");
-	fprintf(fp, "\t{\n");
-
-	fprintf(fp, "\t\tbase_mask\t%08x\n",		mMaskBase);
-	fprintf(fp, "\t\towner_mask\t%08x\n",		mMaskOwner);
-	fprintf(fp, "\t\tgroup_mask\t%08x\n",		mMaskGroup);
-	fprintf(fp, "\t\teveryone_mask\t%08x\n",	mMaskEveryone);
-	fprintf(fp, "\t\tnext_owner_mask\t%08x\n",	mMaskNextOwner);
-
-	mCreator.toString(uuid_str);
-	fprintf(fp, "\t\tcreator_id\t%s\n",			uuid_str.c_str());
-
-	mOwner.toString(uuid_str);
-	fprintf(fp, "\t\towner_id\t%s\n",			uuid_str.c_str());
-
-	mLastOwner.toString(uuid_str);
-	fprintf(fp, "\t\tlast_owner_id\t%s\n",		uuid_str.c_str());
-
-	mGroup.toString(uuid_str);
-	fprintf(fp, "\t\tgroup_id\t%s\n",			uuid_str.c_str());
-
-	if(mIsGroupOwned)
-	{
-		fprintf(fp, "\t\tgroup_owned\t1\n");
-	}
-	fprintf(fp,"\t}\n");
-	return TRUE;
+	llofstream ofs(fp);
+	return exportStream(ofs);
 }
 
-
-BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
+BOOL LLPermissions::importStream(std::istream& input_stream)
 {
 	init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
 	const S32 BUFSIZE = 16384;
@@ -727,6 +601,18 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
 	while (input_stream.good())
 	{
 		input_stream.getline(buffer, BUFSIZE);
+		if (input_stream.eof())
+		{
+			llwarns << "Bad permissions: early end of input stream"
+					<< llendl;
+			return FALSE;
+		}
+		if (input_stream.fail())
+		{
+			llwarns << "Bad permissions: failed to read from input stream"
+					<< llendl;
+			return FALSE;
+		}
 		sscanf( /* Flawfinder: ignore */
 			buffer,
 			" %255s %255s",
@@ -800,7 +686,8 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
 		}
 		else
 		{
-			llinfos << "unknown keyword " << keyword << " in permissions import" << llendl;
+			llwarns << "unknown keyword " << keyword 
+					<< " in permissions import" << llendl;
 		}
 	}
 	fix();
@@ -808,36 +695,26 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
 }
 
 
-BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const
+BOOL LLPermissions::exportStream(std::ostream& output_stream) const
 {
-	std::string uuid_str;
-
+	if (!output_stream.good()) return FALSE;
 	output_stream <<  "\tpermissions 0\n";
 	output_stream <<  "\t{\n";
 
-	std::string buffer;
-	buffer = llformat( "\t\tbase_mask\t%08x\n",		mMaskBase);
-	output_stream << buffer;
-	buffer = llformat( "\t\towner_mask\t%08x\n",		mMaskOwner);
-	output_stream << buffer;
-	buffer = llformat( "\t\tgroup_mask\t%08x\n",		mMaskGroup);
-	output_stream << buffer;
-	buffer = llformat( "\t\teveryone_mask\t%08x\n",	mMaskEveryone);
-	output_stream << buffer;
-	buffer = llformat( "\t\tnext_owner_mask\t%08x\n",	mMaskNextOwner);
-	output_stream << buffer;
-
-	mCreator.toString(uuid_str);
-	output_stream <<  "\t\tcreator_id\t" << uuid_str << "\n";
-
-	mOwner.toString(uuid_str);
-	output_stream <<  "\t\towner_id\t" << uuid_str << "\n";
-
-	mLastOwner.toString(uuid_str);
-	output_stream <<  "\t\tlast_owner_id\t" << uuid_str << "\n";
-
-	mGroup.toString(uuid_str);
-	output_stream <<  "\t\tgroup_id\t" << uuid_str << "\n";
+	char prev_fill = output_stream.fill('0');
+	output_stream << std::hex;
+	output_stream << "\t\tbase_mask\t" << std::setw(8) << mMaskBase << "\n";
+	output_stream << "\t\towner_mask\t" << std::setw(8) << mMaskOwner << "\n";
+	output_stream << "\t\tgroup_mask\t" << std::setw(8) << mMaskGroup << "\n";
+	output_stream << "\t\teveryone_mask\t" << std::setw(8) << mMaskEveryone << "\n";
+	output_stream << "\t\tnext_owner_mask\t" << std::setw(8) << mMaskNextOwner << "\n";
+	output_stream << std::dec;
+	output_stream.fill(prev_fill);
+
+	output_stream <<  "\t\tcreator_id\t" << mCreator << "\n";
+	output_stream <<  "\t\towner_id\t" << mOwner << "\n";
+	output_stream <<  "\t\tlast_owner_id\t" << mLastOwner << "\n";
+	output_stream <<  "\t\tgroup_id\t" << mGroup << "\n";
 
 	if(mIsGroupOwned)
 	{
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 3ecc922370a3f3873f644424b8d1854912a0a453..7d3a68d3533cf5aa8cd8b93054235ce306cae901 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -316,8 +316,8 @@ class LLPermissions : public LLReflective
 	BOOL	importFile(LLFILE* fp);
 	BOOL	exportFile(LLFILE* fp) const;
 
-	BOOL	importLegacyStream(std::istream& input_stream);
-	BOOL	exportLegacyStream(std::ostream& output_stream) const;
+	BOOL	importStream(std::istream& input_stream);
+	BOOL	exportStream(std::ostream& output_stream) const;
 
 	bool operator==(const LLPermissions &rhs) const;
 	bool operator!=(const LLPermissions &rhs) const;
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index dd408a8efea74ac755d698ecbbbadbb91c9233a3..a8296679337b36e984f2f15d4cac049d1f9187ad 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -81,15 +81,13 @@ U32 LLSaleInfo::getCRC32() const
 
 BOOL LLSaleInfo::exportFile(LLFILE* fp) const
 {
-	fprintf(fp, "\tsale_info\t0\n\t{\n");
-	fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType));
-	fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice);
-	fprintf(fp,"\t}\n");
-	return TRUE;
+	llofstream ofs(fp);
+	return exportStream(ofs);
 }
 
-BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
+BOOL LLSaleInfo::exportStream(std::ostream& output_stream) const
 {
+	if (!output_stream.good()) return FALSE;
 	output_stream << "\tsale_info\t0\n\t{\n";
 	output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n";
 	output_stream << "\t\tsale_price\t" << mSalePrice << "\n";
@@ -134,80 +132,39 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask)
 
 BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask)
 {
-	has_perm_mask = FALSE;
-
-	// *NOTE: Changing the buffer size will require changing the scanf
-	// calls below.
-	char buffer[MAX_STRING];	/* Flawfinder: ignore */
-	char keyword[MAX_STRING];	/* Flawfinder: ignore */
-	char valuestr[MAX_STRING];	/* Flawfinder: ignore */
-	BOOL success = TRUE;
-
-	keyword[0] = '\0';
-	valuestr[0] = '\0';
-	while(success && (!feof(fp)))
-	{
-		if (fgets(buffer, MAX_STRING, fp) == NULL)
-		{
-			buffer[0] = '\0';
-		}
-
-		sscanf(	/* Flawfinder: ignore */
-			buffer,
-			" %254s %254s",
-			keyword, valuestr);
-		if(!keyword[0])
-		{
-			continue;
-		}
-		if(0 == strcmp("{",keyword))
-		{
-			continue;
-		}
-		if(0 == strcmp("}", keyword))
-		{
-			break;
-		}
-		else if(0 == strcmp("sale_type", keyword))
-		{
-			mSaleType = lookup(valuestr);
-		}
-		else if(0 == strcmp("sale_price", keyword))
-		{
-			sscanf(valuestr, "%d", &mSalePrice);
-			mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
-		}
-		else if (!strcmp("perm_mask", keyword))
-		{
-			//llinfos << "found deprecated keyword perm_mask" << llendl;
-			has_perm_mask = TRUE;
-			sscanf(valuestr, "%x", &perm_mask);
-		}
-		else
-		{
-			llwarns << "unknown keyword '" << keyword
-					<< "' in sale info import" << llendl;
-		}
-	}
-	return success;
+	llifstream ifs(fp);
+	return importStream(ifs, has_perm_mask, perm_mask);
 }
 
-BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask)
+BOOL LLSaleInfo::importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask)
 {
 	has_perm_mask = FALSE;
 
+	const S32 BUFSIZE = 16384;
+
 	// *NOTE: Changing the buffer size will require changing the scanf
 	// calls below.
-	char buffer[MAX_STRING];	/* Flawfinder: ignore */
-	char keyword[MAX_STRING];	/* Flawfinder: ignore */
-	char valuestr[MAX_STRING];	/* Flawfinder: ignore */
-	BOOL success = TRUE;
+	char buffer[BUFSIZE];	/* Flawfinder: ignore */
+	char keyword[255];	/* Flawfinder: ignore */
+	char valuestr[255];	/* Flawfinder: ignore */
 
 	keyword[0] = '\0';
 	valuestr[0] = '\0';
-	while(success && input_stream.good())
+	while(input_stream.good())
 	{
 		input_stream.getline(buffer, MAX_STRING);
+		if (input_stream.eof())
+		{
+			llwarns << "Bad sale info: early end of input stream"
+					<< llendl;
+			return FALSE;
+		}
+		if (input_stream.fail())
+		{
+			llwarns << "Bad sale info: failed to read from input stream"
+					<< llendl;
+			return FALSE;
+		}
 		sscanf(	/* Flawfinder: ignore */
 			buffer,
 			" %254s %254s",
@@ -245,7 +202,7 @@ BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_m
 					<< "' in sale info import" << llendl;
 		}
 	}
-	return success;
+	return TRUE;
 }
 
 void LLSaleInfo::setSalePrice(S32 price)
diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h
index 4e98ccf6ff4d2e3f88d223aa4f184bd99ad90e7b..f7f3f9269c1d3a9046d320c9618c1fa3e2b64a89 100644
--- a/indra/llinventory/llsaleinfo.h
+++ b/indra/llinventory/llsaleinfo.h
@@ -89,11 +89,11 @@ class LLSaleInfo
 	BOOL exportFile(LLFILE* fp) const;
 	BOOL importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask);
 
-	BOOL exportLegacyStream(std::ostream& output_stream) const;
+	BOOL exportStream(std::ostream& output_stream) const;
 	LLSD asLLSD() const;
 	operator LLSD() const { return asLLSD(); }
 	bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask);
-	BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask);
+	BOOL importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask);
 
 	LLSD packMessage() const;
 	void unpackMessage(LLSD sales);
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index f784262e90754fc7bae37d5cc804144508bc7163..ae5efb22870f62f1d4184fe31ad5e5f12ab83c1a 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -34,6 +34,7 @@
 #include "llcharacter.h"
 #include "llcoordframe.h"			// for mFrameAgent
 #include "llavatarappearancedefines.h"
+#include "llpermissionsflags.h"
 
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index ca12fe204577ae63546c879cd7e0b102731ab60f..580b6dfa7e06ffff4ded45e3247b10a59c9bc8e2 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -28,9 +28,11 @@
 #ifndef LL_LOCALBITMAPS_H
 #define LL_LOCALBITMAPS_H
 
+#include "llavatarappearancedefines.h"
 #include "lleventtimer.h"
+#include "llimage.h"
+#include "llpointer.h"
 #include "llwearabletype.h"
-#include "llavatarappearancedefines.h"
 
 class LLScrollListCtrl;
 class LLViewerObject;
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 0d5daf129fc51c471e59ef9242ea34111c4d62ef..148e5a015b199b4397c567cf7f36a6b4b2b3e4b5 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -34,6 +34,7 @@
 #include "llaudioengine.h"
 #include "llviewercontrol.h"
 #include "llfontgl.h"
+#include "llwearable.h"
 #include "sound_ids.h"
 #include "v3math.h"
 #include "v3color.h"
diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h
index 95c339a5b00b7c3b025e3dab1cea22644fad8c2d..9df9474eff1bef9735d08caabf82a1c48c45796c 100644
--- a/indra/newview/llviewertexlayer.h
+++ b/indra/newview/llviewertexlayer.h
@@ -28,6 +28,7 @@
 #define LL_VIEWER_TEXLAYER_H
 
 #include "lldynamictexture.h"
+#include "llextendedstatus.h"
 #include "lltexlayer.h"
 
 class LLVOAvatarSelf;
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index e9fa92e8be57d17e7e3bd53ab8128e1e42fd49b9..162c20837a721826c5a2353ea9802d91075fe6dc 100644
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -90,13 +90,13 @@ LLViewerWearable::~LLViewerWearable()
 }
 
 // virtual
-LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file, LLAvatarAppearance* avatarp )
+LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp )
 {
 	// suppress texlayerset updates while wearables are being imported. Layersets will be updated
 	// when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed.
 	LLOverrideBakedTextureUpdate stop_bakes(false);
 
-	LLWearable::EImportResult result = LLWearable::importFile(file, avatarp);
+	LLWearable::EImportResult result = LLWearable::importStream(input_stream, avatarp);
 	if (LLWearable::FAILURE == result) return result;
 	if (LLWearable::BAD_HEADER == result)
 	{
@@ -129,9 +129,6 @@ LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file, LLAvatarAp
 		}
 	}
 
-	// copy all saved param values to working params
-	revertValues();
-
 	return result;
 }
 
@@ -296,8 +293,8 @@ void LLViewerWearable::setTexturesToDefaults()
 }
 
 
-//static
-const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index)
+// virtual
+LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) const
 {
 	const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index);
 	const std::string &default_image_name = texture_dict->mDefaultImageName;
@@ -475,103 +472,9 @@ void LLViewerWearable::setItemID(const LLUUID& item_id)
 	mItemID = item_id;
 }
 
-
-LLLocalTextureObject* LLViewerWearable::getLocalTextureObject(S32 index)
-{
-	te_map_t::iterator iter = mTEMap.find(index);
-	if( iter != mTEMap.end() )
-	{
-		LLLocalTextureObject* lto = iter->second;
-		return lto;
-	}
-	return NULL;
-}
-
-const LLLocalTextureObject* LLViewerWearable::getLocalTextureObject(S32 index) const
-{
-	te_map_t::const_iterator iter = mTEMap.find(index);
-	if( iter != mTEMap.end() )
-	{
-		const LLLocalTextureObject* lto = iter->second;
-		return lto;
-	}
-	return NULL;
-}
-
-std::vector<LLLocalTextureObject*> LLViewerWearable::getLocalTextureListSeq()
-{
-	std::vector<LLLocalTextureObject*> result;
-
-	for(te_map_t::const_iterator iter = mTEMap.begin();
-		iter != mTEMap.end(); iter++)
-	{
-		LLLocalTextureObject* lto = iter->second;
-		result.push_back(lto);
-	}
-
-	return result;
-}
-
-void LLViewerWearable::setLocalTextureObject(S32 index, LLLocalTextureObject &lto)
-{
-	if( mTEMap.find(index) != mTEMap.end() )
-	{
-		mTEMap.erase(index);
-	}
-	mTEMap[index] = new LLLocalTextureObject(lto);
-}
-
-void LLViewerWearable::setVisualParams()
-{
-	for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++)
-	{
-		S32 id = iter->first;
-		LLVisualParam *wearable_param = iter->second;
-		F32 value = wearable_param->getWeight();
-		gAgentAvatarp->setVisualParamWeight(id, value, FALSE);
-	}
-}
-
 void LLViewerWearable::revertValues()
 {
-	//update saved settings so wearable is no longer dirty
-	// non-driver params first
-	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
-	{
-		S32 id = iter->first;
-		F32 value = iter->second;
-		LLVisualParam *param = getVisualParam(id);
-		if(param &&  !dynamic_cast<LLDriverParam*>(param) )
-		{
-			setVisualParamWeight(id, value, TRUE);
-		}
-	}
-
-	//then driver params
-	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
-	{
-		S32 id = iter->first;
-		F32 value = iter->second;
-		LLVisualParam *param = getVisualParam(id);
-		if(param &&  dynamic_cast<LLDriverParam*>(param) )
-		{
-			setVisualParamWeight(id, value, TRUE);
-		}
-	}
-
-	// make sure that saved values are sane
-	for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
-	{
-		S32 id = iter->first;
-		LLVisualParam *param = getVisualParam(id);
-		if( param )
-		{
-			mSavedVisualParamMap[id] = param->getWeight();
-		}
-	}
-
-	syncImages(mSavedTEMap, mTEMap);
-
+	LLWearable::revertValues();
 
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
 	if( panel )
@@ -582,19 +485,7 @@ void LLViewerWearable::revertValues()
 
 void LLViewerWearable::saveValues()
 {
-	//update saved settings so wearable is no longer dirty
-	mSavedVisualParamMap.clear();
-	for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
-	{
-		S32 id = iter->first;
-		LLVisualParam *wearable_param = iter->second;
-		F32 value = wearable_param->getWeight();
-		mSavedVisualParamMap[id] = value;
-	}
-
-	// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
-	syncImages(mTEMap, mSavedTEMap);
-
+	LLWearable::saveValues();
 
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
 	if( panel )
@@ -603,69 +494,6 @@ void LLViewerWearable::saveValues()
 	}
 }
 
-void LLViewerWearable::syncImages(te_map_t &src, te_map_t &dst)
-{
-	// Deep copy of src (copies only those tes that are current, filling in defaults where needed)
-	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
-	{
-		if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType)
-		{
-			te_map_t::const_iterator iter = src.find(te);
-			LLUUID image_id;
-			LLViewerFetchedTexture *image = NULL;
-			LLLocalTextureObject *lto = NULL;
-			if(iter != src.end())
-			{
-				// there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map.
-				lto = iter->second;
-				image = dynamic_cast<LLViewerFetchedTexture*> (lto->getImage());
-				image_id = lto->getID();
-			}
-			else
-			{
-				// there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map.
-				image_id = getDefaultTextureImageID((ETextureIndex) te);
-				image = LLViewerTextureManager::getFetchedTexture( image_id );
-			}
-
-			if( dst.find(te) != dst.end() )
-			{
-				// there's already an entry in the destination map for the texture. Just update its values.
-				dst[te]->setImage(image);
-				dst[te]->setID(image_id);
-			}
-			else
-			{
-				// no entry found in the destination map, we need to create a new Local Texture Object
-				dst[te] = new LLLocalTextureObject(image, image_id);
-			}
-
-			if( lto )
-			{
-				// If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map.
-				dst[te]->setBakedReady(lto->getBakedReady());
-				dst[te]->setDiscard(lto->getDiscard());
-			}
-		}
-	}
-}
-
-void LLViewerWearable::destroyTextures()
-{
-	for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
-	mTEMap.clear();
-	for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
-	mSavedTEMap.clear();
-}
-
 // virtual
 void LLViewerWearable::setUpdated() const
 { 
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
index d8412b1c65c0cb9c87355434416cb563331a395f..65566f23a5a9981d6b3a5dc7ecac34a5d8d12a6e 100644
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -64,12 +64,12 @@ class LLViewerWearable : public LLWearable
 	void				removeFromAvatar( BOOL upload_bake )	{ LLViewerWearable::removeFromAvatar( mType, upload_bake ); }
 	static void			removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); 
 
-	/*virtual*/ EImportResult	importFile(LLFILE* file, LLAvatarAppearance* avatarp);
+	/*virtual*/ EImportResult	importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
 	
 	void				setParamsToDefaults();
 	void				setTexturesToDefaults();
 
-	static const LLUUID			getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index);
+	/*virtual*/ LLUUID	getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const;
 
 
 	void				saveNewAsset() const;
@@ -79,14 +79,8 @@ class LLViewerWearable : public LLWearable
 
 	friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w);
 
-	/*virtual*/ LLLocalTextureObject* getLocalTextureObject(S32 index);
-	const LLLocalTextureObject* getLocalTextureObject(S32 index) const;
-	std::vector<LLLocalTextureObject*> getLocalTextureListSeq();
-	void				setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
-	void				setVisualParams();
-
-	void				revertValues();
-	void				saveValues();
+	/*virtual*/ void	revertValues();
+	/*virtual*/ void	saveValues();
 
 	// Something happened that requires the wearable's label to be updated (e.g. worn/unworn).
 	/*virtual*/void		setUpdated() const;
@@ -99,8 +93,6 @@ class LLViewerWearable : public LLWearable
 	/*virtual*/void		addToBakedTextureHash(LLMD5& hash) const;
 
 protected:
-	void				syncImages(te_map_t &src, te_map_t &dst);
-	void				destroyTextures();	
 	LLAssetID			mAssetID;
 	LLTransactionID		mTransactionID;
 
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 50beaaec3faa0e273440f01f4645a1b19a1693c3..3dfacd70f3bf97db407ae30f31f92240ba722444 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -112,15 +112,16 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
 	else if (status >= 0)
 	{
 		// read the file
-		LLFILE* fp = LLFile::fopen(std::string(filename), "rb");		/*Flawfinder: ignore*/
-		if( !fp )
+		llifstream ifs(filename, llifstream::binary);
+		if( !ifs.is_open() )
 		{
 			LL_WARNS("Wearable") << "Bad Wearable Asset: unable to open file: '" << filename << "'" << LL_ENDL;
 		}
 		else
 		{
 			wearable = new LLViewerWearable(uuid);
-			LLWearable::EImportResult result = wearable->importFile( fp, avatarp );
+			LLWearable::EImportResult result = wearable->importStream(
+												ifs, avatarp );
 			if (LLWearable::SUCCESS != result)
 			{
 				if (wearable->getType() == LLWearableType::WT_COUNT)
@@ -131,7 +132,6 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
 				wearable = NULL;
 			}
 
-			fclose( fp );
 			if(filename)
 			{
 				LLFile::remove(std::string(filename));
diff --git a/indra/test/llpermissions_tut.cpp b/indra/test/llpermissions_tut.cpp
index bf6766424c60264fe999ca7d4d2cf18c9bc663fb..dff8bca53fc64e03679eacc943b35006ca69187a 100644
--- a/indra/test/llpermissions_tut.cpp
+++ b/indra/test/llpermissions_tut.cpp
@@ -407,7 +407,7 @@ namespace tut
 		LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
 		if(!fp)
 		{
-			llerrs << "file coudnt be opened\n" << llendl;
+			llerrs << "file couldn't be opened\n" << llendl;
 			return;
 		}
 		LLPermissions perm,perm1;
@@ -425,15 +425,15 @@ namespace tut
 
 		perm.initMasks(base, ownerp, everyone, groupp, next);
 
-		perm.exportFile(fp);
+		ensure("Permissions export failed", perm.exportFile(fp));
 		fclose(fp);	
 		fp = LLFile::fopen("linden_file.dat","r+");
 		if(!fp)
 		{
-			llerrs << "file coudnt be opened\n" << llendl;
+			llerrs << "file couldn't be opened\n" << llendl;
 			return;
 		}
-		perm1.importFile(fp);
+		ensure("Permissions import failed", perm1.importFile(fp));
 		fclose(fp);
 		ensure_equals("exportFile()/importFile():failed to export and import the data ", perm1, perm);	
 }
@@ -457,11 +457,11 @@ namespace tut
 		perm.initMasks(base, ownerp, everyone, groupp, next);
 
 		std::ostringstream ostream;
-		perm.exportLegacyStream(ostream);
+		perm.exportStream(ostream);
 		std::istringstream istream(ostream.str());
-		perm1.importLegacyStream(istream);
+		perm1.importStream(istream);
 
-		ensure_equals("exportLegacyStream()/importLegacyStream():failed to export and import the data ", perm1, perm);
+		ensure_equals("exportStream()/importStream():failed to export and import the data ", perm1, perm);
 	}
 
 	template<> template<>
diff --git a/indra/test/llsaleinfo_tut.cpp b/indra/test/llsaleinfo_tut.cpp
index 09fca2abbab19013063aaf558fd511c6f861f680..d5468039476fc9cb2eb8d04d9baea3981fad0927 100644
--- a/indra/test/llsaleinfo_tut.cpp
+++ b/indra/test/llsaleinfo_tut.cpp
@@ -146,16 +146,17 @@ namespace tut
 		LLSaleInfo llsaleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
 		
 		std::ostringstream ostream;
-		llsaleinfo.exportLegacyStream(ostream);
+		llsaleinfo.exportStream(ostream);
 		
 		std::istringstream istream(ostream.str());
 		LLSaleInfo llsaleinfo1;
 		U32 perm_mask = 0;
 		BOOL has_perm_mask = FALSE;
-		llsaleinfo1.importLegacyStream(istream, has_perm_mask, perm_mask);
+		llsaleinfo1.importStream(istream, has_perm_mask, perm_mask);
 					
-		ensure("importLegacyStream() fn failed ", llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice() &&
-										       llsaleinfo.getSaleType() == llsaleinfo1.getSaleType());		
+		ensure("importStream() fn failed ",
+			llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice() &&
+			llsaleinfo.getSaleType() == llsaleinfo1.getSaleType());
 	}
 
 	template<> template<>