diff options
118 files changed, 1904 insertions, 834 deletions
| diff --git a/autobuild.xml b/autobuild.xml index 2470b2e5aa..965f13d3e9 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2187,18 +2187,18 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>40a87f5d505a141b2ec79513a6197c35</string> +              <string>106d16623ee9a580b20777e8072a08cb</string>                <key>hash_algorithm</key>                <string>md5</string>                <key>url</key> -              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76516/728250/llca-202102021657.555615-common-555615.tar.bz2</string> +              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82745/775330/llca-202106010215.560271-common-560271.tar.bz2</string>              </map>              <key>name</key>              <string>common</string>            </map>          </map>          <key>version</key> -        <string>202102021657.555615</string> +        <string>202106010215.560271</string>        </map>        <key>llphysicsextensions_source</key>        <map> diff --git a/doc/contributions.txt b/doc/contributions.txt index 8ae828e738..280bb0ee48 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1356,7 +1356,8 @@ Sovereign Engineer      MAINT-7343      SL-11079      OPEN-343 -	SL-11625 +    SL-11625 +    BUG-229030  	SL-14705  	SL-14706  	SL-14707 diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index a5770c5528..6cd3cd9278 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -61,7 +61,7 @@ if (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)    set(INSTALL_PROPRIETARY ON CACHE BOOL "Install proprietary binaries")  endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)  set(TEMPLATE_VERIFIER_OPTIONS "" CACHE STRING "Options for scripts/template_verifier.py") -set(TEMPLATE_VERIFIER_MASTER_URL "http://bitbucket.org/lindenlab/master-message-template/raw/tip/message_template.msg" CACHE STRING "Location of the master message template") +set(TEMPLATE_VERIFIER_MASTER_URL "https://bitbucket.org/lindenlab/master-message-template-git/raw/master/message_template.msg" CACHE STRING "Location of the master message template")  if (NOT CMAKE_BUILD_TYPE)    set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index af8394b60c..fb0d12f0af 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -70,7 +70,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)  	static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable");  	if( node->getFastAttributeString( wearable_string, wearable) )  	{ -		mWearableType = LLWearableType::typeNameToType( wearable ); +		mWearableType = LLWearableType::getInstance()->typeNameToType( wearable );  	}  	static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 28a36e6e41..e4bc8ff427 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -73,17 +73,17 @@ LLWearable::~LLWearable()  const std::string& LLWearable::getTypeLabel() const  { -	return LLWearableType::getTypeLabel(mType); +	return LLWearableType::getInstance()->getTypeLabel(mType);  }  const std::string& LLWearable::getTypeName() const  { -	return LLWearableType::getTypeName(mType); +	return LLWearableType::getInstance()->getTypeName(mType);  }  LLAssetType::EType LLWearable::getAssetType() const  { -	return LLWearableType::getAssetType(mType); +	return LLWearableType::getInstance()->getAssetType(mType);  }  BOOL LLWearable::exportFile(const std::string& filename) const diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 66cc4f3766..0eaeedb6ee 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -231,10 +231,11 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou  U32 LLWearableData::getClothingLayerCount() const  {  	U32 count = 0; +    LLWearableType *wr_inst = LLWearableType::getInstance();  	for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)  	{  		LLWearableType::EType type = (LLWearableType::EType)i; -		if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING) +		if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING)  		{  			count += getWearableCount(type);  		} @@ -244,7 +245,7 @@ U32 LLWearableData::getClothingLayerCount() const  BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const  { -	LLAssetType::EType a_type = LLWearableType::getAssetType(type); +    LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type);  	if (a_type==LLAssetType::AT_CLOTHING)  	{  		return (getClothingLayerCount() < MAX_CLOTHING_LAYERS); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 281060d01d..4ac611b1de 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -30,153 +30,98 @@  #include "llinventorydefines.h" -struct WearableEntry : public LLDictionaryEntry +LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans)  { -	WearableEntry(LLWearableType& wtype, -				  const std::string &name, -				  const std::string& default_new_name, -				  LLAssetType::EType assetType, -				  LLInventoryType::EIconName iconName, -				  BOOL disable_camera_switch = FALSE, -				  BOOL allow_multiwear = TRUE) : -		LLDictionaryEntry(name), -		mAssetType(assetType), -		mDefaultNewName(default_new_name), -		mLabel(wtype.mTrans->getString(name)), -		mIconName(iconName), -		mDisableCameraSwitch(disable_camera_switch), -		mAllowMultiwear(allow_multiwear) -	{ -		 -	} -	const LLAssetType::EType mAssetType; -	const std::string mLabel; -	const std::string mDefaultNewName; //keep mLabel for backward compatibility -	LLInventoryType::EIconName mIconName; -	BOOL mDisableCameraSwitch; -	BOOL mAllowMultiwear; -}; - -class LLWearableDictionary : public LLParamSingleton<LLWearableDictionary>, -							 public LLDictionary<LLWearableType::EType, WearableEntry> -{ -	LLSINGLETON(LLWearableDictionary, LLWearableType&); -}; - -LLWearableDictionary::LLWearableDictionary(LLWearableType& wtype) -{ -	addEntry(LLWearableType::WT_SHAPE,        new WearableEntry(wtype, "shape",       "New Shape",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); -	addEntry(LLWearableType::WT_SKIN,         new WearableEntry(wtype, "skin",        "New Skin",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); -	addEntry(LLWearableType::WT_HAIR,         new WearableEntry(wtype, "hair",        "New Hair",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); -	addEntry(LLWearableType::WT_EYES,         new WearableEntry(wtype, "eyes",        "New Eyes",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); -	addEntry(LLWearableType::WT_SHIRT,        new WearableEntry(wtype, "shirt",       "New Shirt",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); -	addEntry(LLWearableType::WT_PANTS,        new WearableEntry(wtype, "pants",       "New Pants",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); -	addEntry(LLWearableType::WT_SHOES,        new WearableEntry(wtype, "shoes",       "New Shoes",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); -	addEntry(LLWearableType::WT_SOCKS,        new WearableEntry(wtype, "socks",       "New Socks",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); -	addEntry(LLWearableType::WT_JACKET,       new WearableEntry(wtype, "jacket",      "New Jacket",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); -	addEntry(LLWearableType::WT_GLOVES,       new WearableEntry(wtype, "gloves",      "New Gloves",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); -	addEntry(LLWearableType::WT_UNDERSHIRT,   new WearableEntry(wtype, "undershirt",  "New Undershirt",	LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); -	addEntry(LLWearableType::WT_UNDERPANTS,   new WearableEntry(wtype, "underpants",  "New Underpants",	LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); -	addEntry(LLWearableType::WT_SKIRT,        new WearableEntry(wtype, "skirt",       "New Skirt",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); -	addEntry(LLWearableType::WT_ALPHA,        new WearableEntry(wtype, "alpha",       "New Alpha",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); -	addEntry(LLWearableType::WT_TATTOO,       new WearableEntry(wtype, "tattoo",      "New Tattoo",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); -	addEntry(LLWearableType::WT_UNIVERSAL,    new WearableEntry(wtype, "universal",   "New Universal",     LLAssetType::AT_CLOTHING,   LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); - -	addEntry(LLWearableType::WT_PHYSICS,      new WearableEntry(wtype, "physics",     "New Physics",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - -	addEntry(LLWearableType::WT_INVALID,      new WearableEntry(wtype, "invalid",     "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE)); -	addEntry(LLWearableType::WT_NONE,      	  new WearableEntry(wtype, "none",        "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); +	addEntry(LLWearableType::WT_SHAPE,        new WearableEntry(trans, "shape",       "New Shape",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); +	addEntry(LLWearableType::WT_SKIN,         new WearableEntry(trans, "skin",        "New Skin",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); +	addEntry(LLWearableType::WT_HAIR,         new WearableEntry(trans, "hair",        "New Hair",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); +	addEntry(LLWearableType::WT_EYES,         new WearableEntry(trans, "eyes",        "New Eyes",			LLAssetType::AT_BODYPART, 	LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); +	addEntry(LLWearableType::WT_SHIRT,        new WearableEntry(trans, "shirt",       "New Shirt",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); +	addEntry(LLWearableType::WT_PANTS,        new WearableEntry(trans, "pants",       "New Pants",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); +	addEntry(LLWearableType::WT_SHOES,        new WearableEntry(trans, "shoes",       "New Shoes",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); +	addEntry(LLWearableType::WT_SOCKS,        new WearableEntry(trans, "socks",       "New Socks",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); +	addEntry(LLWearableType::WT_JACKET,       new WearableEntry(trans, "jacket",      "New Jacket",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); +	addEntry(LLWearableType::WT_GLOVES,       new WearableEntry(trans, "gloves",      "New Gloves",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); +	addEntry(LLWearableType::WT_UNDERSHIRT,   new WearableEntry(trans, "undershirt",  "New Undershirt",	LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); +	addEntry(LLWearableType::WT_UNDERPANTS,   new WearableEntry(trans, "underpants",  "New Underpants",	LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); +	addEntry(LLWearableType::WT_SKIRT,        new WearableEntry(trans, "skirt",       "New Skirt",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); +	addEntry(LLWearableType::WT_ALPHA,        new WearableEntry(trans, "alpha",       "New Alpha",			LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); +	addEntry(LLWearableType::WT_TATTOO,       new WearableEntry(trans, "tattoo",      "New Tattoo",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); +	addEntry(LLWearableType::WT_UNIVERSAL,    new WearableEntry(trans, "universal",   "New Universal",     LLAssetType::AT_CLOTHING,   LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); + +	addEntry(LLWearableType::WT_PHYSICS,      new WearableEntry(trans, "physics",     "New Physics",		LLAssetType::AT_CLOTHING, 	LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); + +	addEntry(LLWearableType::WT_INVALID,      new WearableEntry(trans, "invalid",     "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE)); +	addEntry(LLWearableType::WT_NONE,      	  new WearableEntry(trans, "none",        "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryType::ICONNAME_NONE, FALSE, FALSE));  }  // class LLWearableType -LLWearableType::LLWearableType(LLTranslationBridge* trans) +LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans) +:   mDictionary(trans)  { -    // LLTranslationBridge exists, but is not ready at this point in time since strings.xml is not yet loaded -    mTrans = trans;  }  LLWearableType::~LLWearableType()  { -    delete mTrans;  }  void LLWearableType::initSingleton()  { -    // To make sure all wrapping functions will crash without initing LLWearableType; -    LLWearableDictionary::initParamSingleton(*this); - -    // Todo: consider merging LLWearableType and LLWearableDictionary  } -// static  LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name)  { -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const LLWearableType::EType wearable = dict->lookup(type_name); +	const LLWearableType::EType wearable = mDictionary.lookup(type_name);  	return wearable;  } -// static   const std::string& LLWearableType::getTypeName(LLWearableType::EType type)  {  -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return getTypeName(WT_INVALID);  	return entry->mName;  } -//static   const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type)  {  -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return getTypeDefaultNewName(WT_INVALID);  	return entry->mDefaultNewName;  } -// static   const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type)  {  -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return getTypeLabel(WT_INVALID);  	return entry->mLabel;  } -// static   LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type)  { -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return getAssetType(WT_INVALID);  	return entry->mAssetType;  } -// static   LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type)  { -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return getIconName(WT_INVALID);  	return entry->mIconName;  }  -// static   BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)  { -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return FALSE;  	return entry->mDisableCameraSwitch;  } -// static  BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)  { -	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); -	const WearableEntry *entry = dict->lookup(type); +	const WearableEntry *entry = mDictionary.lookup(type);  	if (!entry) return FALSE;  	return entry->mAllowMultiwear;  } diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 57f3ef160d..793a33cc87 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -35,10 +35,9 @@  class LLWearableType : public LLParamSingleton<LLWearableType>  { -	LLSINGLETON(LLWearableType, LLTranslationBridge* trans); +	LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans);  	~LLWearableType();  	void initSingleton(); -	friend struct WearableEntry;  public:   	enum EType  	{ @@ -67,20 +66,53 @@ public:  	// Most methods are wrappers for dictionary, but if LLWearableType is not initialized,  	// they will crash. Whole LLWearableType is just wrapper for convinient calls. -	static const std::string& 			getTypeName(EType type); -	static const std::string& 			getTypeDefaultNewName(EType type); -	static const std::string& 			getTypeLabel(EType type); -	static LLAssetType::EType 			getAssetType(EType type); -	static EType 						typeNameToType(const std::string& type_name); -	static LLInventoryType::EIconName 	getIconName(EType type); -	static BOOL 						getDisableCameraSwitch(EType type); -	static BOOL 						getAllowMultiwear(EType type); +	const std::string& 					getTypeName(EType type); +	const std::string& 					getTypeDefaultNewName(EType type); +	const std::string& 					getTypeLabel(EType type); +	LLAssetType::EType 					getAssetType(EType type); +	EType 								typeNameToType(const std::string& type_name); +	LLInventoryType::EIconName 			getIconName(EType type); +	BOOL 								getDisableCameraSwitch(EType type); +	BOOL 								getAllowMultiwear(EType type);  	static EType						inventoryFlagsToWearableType(U32 flags); -protected: +private: +    struct WearableEntry : public LLDictionaryEntry +    { +        WearableEntry(LLTranslationBridge::ptr_t& trans, +            const std::string &name, +            const std::string& default_new_name, +            LLAssetType::EType assetType, +            LLInventoryType::EIconName iconName, +            BOOL disable_camera_switch = FALSE, +            BOOL allow_multiwear = TRUE) : +            LLDictionaryEntry(name), +            mAssetType(assetType), +            mDefaultNewName(default_new_name), +            mLabel(trans->getString(name)), +            mIconName(iconName), +            mDisableCameraSwitch(disable_camera_switch), +            mAllowMultiwear(allow_multiwear) +        { -	LLTranslationBridge* mTrans; +        } +        const LLAssetType::EType mAssetType; +        const std::string mLabel; +        const std::string mDefaultNewName; +        LLInventoryType::EIconName mIconName; +        BOOL mDisableCameraSwitch; +        BOOL mAllowMultiwear; +    }; + +    class LLWearableDictionary : public LLDictionary<LLWearableType::EType, WearableEntry> +    { +    public: +        LLWearableDictionary(LLTranslationBridge::ptr_t& trans); +        ~LLWearableDictionary() {} +    }; + +    LLWearableDictionary mDictionary;  };  #endif  // LL_LLWEARABLETYPE_H diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f876b8ee4a..012ec08f07 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -435,6 +435,62 @@ namespace  	typedef std::vector<LLError::RecorderPtr> Recorders;  	typedef std::vector<LLError::CallSite*> CallSiteVector; +    class SettingsConfig : public LLRefCount +    { +        friend class Globals; + +    public: +        virtual ~SettingsConfig(); + +        LLError::ELevel                     mDefaultLevel; + +        bool 								mLogAlwaysFlush; + +        U32 								mEnabledLogTypesMask; + +        LevelMap                            mFunctionLevelMap; +        LevelMap                            mClassLevelMap; +        LevelMap                            mFileLevelMap; +        LevelMap                            mTagLevelMap; +        std::map<std::string, unsigned int> mUniqueLogMessages; + +        LLError::FatalFunction              mCrashFunction; +        LLError::TimeFunction               mTimeFunction; + +        Recorders                           mRecorders; +        LLMutex                             mRecorderMutex; + +        int                                 mShouldLogCallCounter; + +    private: +        SettingsConfig(); +    }; + +    typedef LLPointer<SettingsConfig> SettingsConfigPtr; + +    SettingsConfig::SettingsConfig() +        : LLRefCount(), +        mDefaultLevel(LLError::LEVEL_DEBUG), +        mLogAlwaysFlush(true), +        mEnabledLogTypesMask(255), +        mFunctionLevelMap(), +        mClassLevelMap(), +        mFileLevelMap(), +        mTagLevelMap(), +        mUniqueLogMessages(), +        mCrashFunction(NULL), +        mTimeFunction(NULL), +        mRecorders(), +        mRecorderMutex(), +        mShouldLogCallCounter(0) +    { +    } + +    SettingsConfig::~SettingsConfig() +    { +        mRecorders.clear(); +    } +  	class Globals  	{      public: @@ -449,14 +505,21 @@ namespace  		void addCallSite(LLError::CallSite&);  		void invalidateCallSites(); +        SettingsConfigPtr getSettingsConfig(); + +        void resetSettingsConfig(); +        LLError::SettingsStoragePtr saveAndResetSettingsConfig(); +        void restore(LLError::SettingsStoragePtr pSettingsStorage);  	private:  		CallSiteVector callSites; +        SettingsConfigPtr mSettingsConfig;  	};  	Globals::Globals()  		: messageStream(),  		messageStreamInUse(false), -		callSites() +		callSites(), +        mSettingsConfig(new SettingsConfig())  	{  	} @@ -486,120 +549,31 @@ namespace  		callSites.clear();  	} -} - -namespace LLError -{ -	class SettingsConfig : public LLRefCount -	{ -		friend class Settings; - -	public: -		virtual ~SettingsConfig(); - -		LLError::ELevel                     mDefaultLevel; - -        bool 								mLogAlwaysFlush; - -        U32 								mEnabledLogTypesMask; - -		LevelMap                            mFunctionLevelMap; -		LevelMap                            mClassLevelMap; -		LevelMap                            mFileLevelMap; -		LevelMap                            mTagLevelMap; -		std::map<std::string, unsigned int> mUniqueLogMessages; -		 -		LLError::FatalFunction              mCrashFunction; -		LLError::TimeFunction               mTimeFunction; - -		Recorders                           mRecorders; - -		int                                 mShouldLogCallCounter; - -	private: -		SettingsConfig(); -	}; - -	typedef LLPointer<SettingsConfig> SettingsConfigPtr; - -	class Settings -	{ -    public: -        static Settings* getInstance(); -    protected: -		Settings(); -	public: -		SettingsConfigPtr getSettingsConfig(); - -		void reset(); -		SettingsStoragePtr saveAndReset();  -		void restore(SettingsStoragePtr pSettingsStorage); -		 -	private: -		SettingsConfigPtr mSettingsConfig; -	}; - -	SettingsConfig::SettingsConfig() -		: LLRefCount(), -		mDefaultLevel(LLError::LEVEL_DEBUG), -		mLogAlwaysFlush(true), -		mEnabledLogTypesMask(255), -		mFunctionLevelMap(), -		mClassLevelMap(), -		mFileLevelMap(), -		mTagLevelMap(), -		mUniqueLogMessages(), -		mCrashFunction(NULL), -		mTimeFunction(NULL), -		mRecorders(), -		mShouldLogCallCounter(0) -	{ -	} - -	SettingsConfig::~SettingsConfig() -	{ -		mRecorders.clear(); -	} - -	Settings::Settings(): -		mSettingsConfig(new SettingsConfig()) -	{ -	} -    Settings* Settings::getInstance() +    SettingsConfigPtr Globals::getSettingsConfig()      { -        // According to C++11 Function-Local Initialization -        // of static variables is supposed to be thread safe -        // without risk of deadlocks. -        static Settings inst; - -        return &inst; +        return mSettingsConfig;      } -	SettingsConfigPtr Settings::getSettingsConfig() -	{ -		return mSettingsConfig; -	} - -	void Settings::reset() -	{ -		Globals::getInstance()->invalidateCallSites(); -		mSettingsConfig = new SettingsConfig(); -	} +    void Globals::resetSettingsConfig() +    { +        invalidateCallSites(); +        mSettingsConfig = new SettingsConfig(); +    } -	SettingsStoragePtr Settings::saveAndReset() -	{ -		SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); -		reset(); -		return oldSettingsConfig; -	} +    LLError::SettingsStoragePtr Globals::saveAndResetSettingsConfig() +    { +        LLError::SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); +        resetSettingsConfig(); +        return oldSettingsConfig; +    } -	void Settings::restore(SettingsStoragePtr pSettingsStorage) -	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); -		mSettingsConfig = newSettingsConfig; -	} +    void Globals::restore(LLError::SettingsStoragePtr pSettingsStorage) +    { +        invalidateCallSites(); +        SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); +        mSettingsConfig = newSettingsConfig; +    }  }  namespace LLError @@ -723,7 +697,7 @@ namespace  	void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true)  	{ -		LLError::Settings::getInstance()->reset(); +		Globals::getInstance()->resetSettingsConfig();  		LLError::setDefaultLevel(LLError::LEVEL_INFO);  		LLError::setAlwaysFlush(true); @@ -765,13 +739,13 @@ namespace LLError  	void setFatalFunction(const FatalFunction& f)  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		s->mCrashFunction = f;  	}  	FatalFunction getFatalFunction()  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		return s->mCrashFunction;  	} @@ -782,72 +756,77 @@ namespace LLError  	void setTimeFunction(TimeFunction f)  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		s->mTimeFunction = f;  	}  	void setDefaultLevel(ELevel level)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mDefaultLevel = level;  	}  	ELevel getDefaultLevel()  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		return s->mDefaultLevel;  	}  	void setAlwaysFlush(bool flush)  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		s->mLogAlwaysFlush = flush;  	}  	bool getAlwaysFlush()  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		return s->mLogAlwaysFlush;  	}  	void setEnabledLogTypesMask(U32 mask)  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		s->mEnabledLogTypesMask = mask;  	}  	U32 getEnabledLogTypesMask()  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		return s->mEnabledLogTypesMask;  	}  	void setFunctionLevel(const std::string& function_name, ELevel level)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mFunctionLevelMap[function_name] = level;  	}  	void setClassLevel(const std::string& class_name, ELevel level)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mClassLevelMap[class_name] = level;  	}  	void setFileLevel(const std::string& file_name, ELevel level)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mFileLevelMap[file_name] = level;  	}  	void setTagLevel(const std::string& tag_name, ELevel level)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mTagLevelMap[tag_name] = level;  	} @@ -892,8 +871,9 @@ namespace LLError  {  	void configure(const LLSD& config)  	{ -		Globals::getInstance()->invalidateCallSites(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		g->invalidateCallSites(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mFunctionLevelMap.clear();  		s->mClassLevelMap.clear(); @@ -1020,7 +1000,8 @@ namespace LLError  		{  			return;  		} -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); +		LLMutexLock lock(&s->mRecorderMutex);  		s->mRecorders.push_back(recorder);  	} @@ -1030,7 +1011,8 @@ namespace LLError  		{  			return;  		} -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); +		LLMutexLock lock(&s->mRecorderMutex);  		s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),  							s->mRecorders.end());  	} @@ -1042,11 +1024,12 @@ namespace LLError      // with a Recorders::iterator indicating the position of that entry in      // mRecorders. The shared_ptr might be empty (operator!() returns true) if      // there was no such RECORDER subclass instance in mRecorders. +    // +    // NOTE!!! Requires external mutex lock!!!      template <typename RECORDER>      std::pair<boost::shared_ptr<RECORDER>, Recorders::iterator> -    findRecorderPos() +    findRecorderPos(SettingsConfigPtr &s)      { -        SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();          // Since we promise to return an iterator, use a classic iterator          // loop.          auto end{s->mRecorders.end()}; @@ -1077,7 +1060,9 @@ namespace LLError      template <typename RECORDER>      boost::shared_ptr<RECORDER> findRecorder()      { -        return findRecorderPos<RECORDER>().first; +        SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); +        LLMutexLock lock(&s->mRecorderMutex); +        return findRecorderPos<RECORDER>(s).first;      }      // Remove an entry from SettingsConfig::mRecorders whose RecorderPtr @@ -1086,10 +1071,11 @@ namespace LLError      template <typename RECORDER>      bool removeRecorder()      { -        auto found = findRecorderPos<RECORDER>(); +        SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); +        LLMutexLock lock(&s->mRecorderMutex); +        auto found = findRecorderPos<RECORDER>(s);          if (found.first)          { -            SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();              s->mRecorders.erase(found.second);          }          return bool(found.first); @@ -1187,10 +1173,11 @@ namespace  	void writeToRecorders(const LLError::CallSite& site, const std::string& message)  	{  		LLError::ELevel level = site.mLevel; -		LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();          std::string escaped_message; -         + +        LLMutexLock lock(&s->mRecorderMutex);  		for (Recorders::const_iterator i = s->mRecorders.begin();  			i != s->mRecorders.end();  			++i) @@ -1325,7 +1312,8 @@ namespace LLError  			return false;  		} -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		Globals *g = Globals::getInstance(); +		SettingsConfigPtr s = g->getSettingsConfig();  		s->mShouldLogCallCounter++; @@ -1355,7 +1343,7 @@ namespace LLError  			: false);  		site.mCached = true; -		Globals::getInstance()->addCallSite(site); +		g->addCallSite(site);  		return site.mShouldLog = site.mLevel >= compareLevel;  	} @@ -1419,7 +1407,7 @@ namespace LLError  		}  		Globals* g = Globals::getInstance(); -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = g->getSettingsConfig();  		std::string message = out->str();  		if (out == &g->messageStream) @@ -1478,12 +1466,12 @@ namespace LLError  {  	SettingsStoragePtr saveAndResetSettings()  	{ -		return Settings::getInstance()->saveAndReset(); +		return Globals::getInstance()->saveAndResetSettingsConfig();  	}  	void restoreSettings(SettingsStoragePtr pSettingsStorage)  	{ -		return Settings::getInstance()->restore(pSettingsStorage); +		return Globals::getInstance()->restore(pSettingsStorage);  	}  	std::string removePrefix(std::string& s, const std::string& p) @@ -1529,7 +1517,7 @@ namespace LLError  	int shouldLogCallCount()  	{ -		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();  		return s->mShouldLogCallCounter;  	} @@ -1707,8 +1695,8 @@ bool debugLoggingEnabled(const std::string& tag)      {          return false;      } -         -    LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); + +    SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();      LLError::ELevel level = LLError::LEVEL_DEBUG;      bool res = checkLevelMap(s->mTagLevelMap, tag, level);      return res; diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 64fb985951..0a213bddef 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -45,7 +45,6 @@  #include <cctype>  // external library headers  #include <boost/range/iterator_range.hpp> -#include <boost/make_shared.hpp>  #if LL_WINDOWS  #pragma warning (push)  #pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no @@ -285,7 +284,7 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):      // Register every new instance with LLEventPumps      mRegistry(LLEventPumps::instance().getHandle()),      mName(mRegistry.get()->registerNew(*this, name, tweak)), -    mSignal(boost::make_shared<LLStandardSignal>()), +    mSignal(std::make_shared<LLStandardSignal>()),      mEnabled(true)  {} @@ -317,14 +316,24 @@ void LLEventPump::clear()  {      // Destroy the original LLStandardSignal instance, replacing it with a      // whole new one. -    mSignal = boost::make_shared<LLStandardSignal>(); +    mSignal = std::make_shared<LLStandardSignal>();      mConnections.clear();  }  void LLEventPump::reset()  { -    mSignal.reset(); +    // Resetting mSignal is supposed to disconnect everything on its own +    // But due to crash on 'reset' added explicit cleanup to get more data +    ConnectionMap::const_iterator iter = mConnections.begin(); +    ConnectionMap::const_iterator end = mConnections.end(); +    while (iter!=end) +    { +        iter->second.disconnect(); +        iter++; +    }      mConnections.clear(); + +    mSignal.reset();      //mDeps.clear();  } @@ -543,7 +552,7 @@ bool LLEventStream::post(const LLSD& event)      // *stack* instance of the shared_ptr, ensuring that our heap      // LLStandardSignal object will live at least until post() returns, even      // if 'this' gets destroyed during the call. -    boost::shared_ptr<LLStandardSignal> signal(mSignal); +    std::shared_ptr<LLStandardSignal> signal(mSignal);      // Let caller know if any one listener handled the event. This is mostly      // useful when using LLEventStream as a listener for an upstream      // LLEventPump. diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index e380c108f4..ae6e5aabc9 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -49,8 +49,6 @@  #endif  #include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp>  #include <boost/utility.hpp>        // noncopyable  #include <boost/optional/optional.hpp>  #include <boost/visit_each.hpp> @@ -571,7 +569,7 @@ protected:                                          const NameList& before);      /// implement the dispatching -    boost::shared_ptr<LLStandardSignal> mSignal; +    std::shared_ptr<LLStandardSignal> mSignal;      /// valve open?      bool mEnabled; @@ -745,14 +743,4 @@ private:  LL_COMMON_API bool sendReply(const LLSD& reply, const LLSD& request,                               const std::string& replyKey="reply"); -// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to -// listen() fails in Boost code trying to instantiate LLEventListener (i.e. -// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't -// specialized for boost::weak_ptr. This remedies that omission. -namespace boost -{ -    template <typename T> -    T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); } -} -  #endif /* ! defined(LL_LLEVENTS_H) */ diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 98905f3b71..6d531d842d 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -354,8 +354,9 @@ void LLThread::setQuitting()      {          mStatus = QUITTING;      } +    // It's only safe to remove mRunCondition if all locked threads were notified +    mRunCondition->broadcast();      mDataLock->unlock(); -    wake();  }  // static diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp index 2b138f3ad5..229bfdbe07 100644 --- a/indra/llcorehttp/_httpreplyqueue.cpp +++ b/indra/llcorehttp/_httpreplyqueue.cpp @@ -56,7 +56,6 @@ void HttpReplyQueue::addOp(const HttpReplyQueue::opPtr_t &op)  		mQueue.push_back(op);  	} -	mQueueCV.notify_all();  } diff --git a/indra/llcorehttp/_httpreplyqueue.h b/indra/llcorehttp/_httpreplyqueue.h index 928ee10a83..33e205c1c9 100644 --- a/indra/llcorehttp/_httpreplyqueue.h +++ b/indra/llcorehttp/_httpreplyqueue.h @@ -98,7 +98,6 @@ protected:  	OpContainer							mQueue;  	LLCoreInt::HttpMutex				mQueueMutex; -	LLCoreInt::HttpConditionVariable	mQueueCV;  }; // end class HttpReplyQueue diff --git a/indra/llcorehttp/_httprequestqueue.cpp b/indra/llcorehttp/_httprequestqueue.cpp index c6f4ad789f..ad72bdcce6 100644 --- a/indra/llcorehttp/_httprequestqueue.cpp +++ b/indra/llcorehttp/_httprequestqueue.cpp @@ -142,13 +142,19 @@ void HttpRequestQueue::wakeAll()  } -void HttpRequestQueue::stopQueue() +bool HttpRequestQueue::stopQueue()  {  	{  		HttpScopedLock lock(mQueueMutex); -		mQueueStopped = true; -		wakeAll(); +        if (!mQueueStopped) +        { +            mQueueStopped = true; +            wakeAll(); +            return true; +        } +        wakeAll(); +        return false;  	}  } diff --git a/indra/llcorehttp/_httprequestqueue.h b/indra/llcorehttp/_httprequestqueue.h index 3c3d134b07..f0296f30e3 100644 --- a/indra/llcorehttp/_httprequestqueue.h +++ b/indra/llcorehttp/_httprequestqueue.h @@ -124,7 +124,7 @@ public:  	/// them on their way.  	///  	/// Threading:  callable by any thread. -	void stopQueue(); +	bool stopQueue();  protected:  	static HttpRequestQueue *			sInstance; diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 34268d94f6..56f52f1b09 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -87,7 +87,11 @@ HttpService::~HttpService()  		// is a bit tricky.  		if (mRequestQueue)  		{ -			mRequestQueue->stopQueue(); +            if (mRequestQueue->stopQueue()) +            { +                // Give mRequestQueue a chance to finish +                ms_sleep(10); +            }  		}  		if (mThread) diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp index 6cf6af6437..96c1297e0d 100644 --- a/indra/llmessage/lldatapacker.cpp +++ b/indra/llmessage/lldatapacker.cpp @@ -173,6 +173,71 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,  	return ok;  } +BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name) +{ +    for (S32 idx = 0; idx < count; ++idx) +    { +        if (!unpackU16(values[idx], name)) +        { +            LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL; +            return FALSE; +        } +    } +    return TRUE; +} + +BOOL LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name) +{ +    for (S32 idx = 0; idx < count; ++idx) +    { +        if (!unpackS16(values[idx], name)) +        { +            LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL; +            return FALSE; +        } +    } +    return TRUE; +} + +BOOL LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name) +{ +    for (S32 idx = 0; idx < count; ++idx) +    { +        if (!unpackF32(values[idx], name)) +        { +            LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL; +            return FALSE; +        } +    } +    return TRUE; +} + +BOOL LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name) +{ +    for (S32 idx = 0; idx < count; ++idx) +    { +        if (!unpackColor4U(values[idx], name)) +        { +            LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL; +            return FALSE; +        } +    } +    return TRUE; +} + +BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name) +{ +    for (S32 idx = 0; idx < count; ++idx) +    { +        if (!unpackUUID(values[idx], name)) +        { +            LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL; +            return FALSE; +        } +    } +    return TRUE; +} +  //---------------------------------------------------------------------------  // LLDataPackerBinaryBuffer implementation  //--------------------------------------------------------------------------- @@ -319,6 +384,29 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)  	return success;  } +BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name) +{ +    BOOL success = verifyLength(sizeof(S16), name); + +    if (mWriteEnabled && success) +    { +        htolememcpy(mCurBufferp, &value, MVT_S16, 2); +    } +    mCurBufferp += 2; +    return success; +} + +BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name) +{ +    BOOL success = verifyLength(sizeof(S16), name); + +    if (success) +    { +        htolememcpy(&value, mCurBufferp, MVT_S16, 2); +    } +    mCurBufferp += 2; +    return success; +}  BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)  { @@ -884,6 +972,52 @@ BOOL LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)  	return success;  } +BOOL LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name) +{ +    BOOL success = TRUE; +    writeIndentedName(name); +    int numCopied = 0; +    if (mWriteEnabled) +    { +        numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */ +    } +    else +    { +        numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */ +    } + +    // snprintf returns number of bytes that would have been written +    // had the output not being truncated. In that case, it will +    // return either -1 or value >= passed in size value . So a check needs to be added +    // to detect truncation, and if there is any, only account for the +    // actual number of bytes written..and not what could have been +    // written. +    if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize()) +    { +        numCopied = getBufferSize() - getCurrentSize(); +        LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL; +    } + +    mCurBufferp += numCopied; + +    return success; +} + + +BOOL LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name) +{ +    BOOL success = TRUE; +    char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */ +    if (!getValueStr(name, valuestr, DP_BUFSIZE)) +    { +        return FALSE; +    } + +    S32 in_val; +    sscanf(valuestr, "%d", &in_val); +    value = in_val; +    return success; +}  BOOL LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)  { @@ -1587,6 +1721,36 @@ BOOL LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)  	return success;  } +BOOL LLDataPackerAsciiFile::packS16(const S16 value, const char *name) +{ +    BOOL success = TRUE; +    writeIndentedName(name); +    if (mFP) +    { +        fprintf(mFP, "%d\n", value);	 +    } +    else if (mOutputStream) +    { +        *mOutputStream << "" << value << "\n"; +    } +    return success; +} + + +BOOL LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name) +{ +    BOOL success = TRUE; +    char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */ +    if (!getValueStr(name, valuestr, DP_BUFSIZE)) +    { +        return FALSE; +    } + +    S32 in_val; +    sscanf(valuestr, "%d", &in_val); +    value = in_val; +    return success; +}  BOOL LLDataPackerAsciiFile::packU32(const U32 value, const char *name)  { diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index 5140f56c01..ac28cadbce 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -60,6 +60,11 @@ public:  	virtual BOOL		packU16(const U16 value, const char *name) = 0;  	virtual BOOL		unpackU16(U16 &value, const char *name) = 0; +    BOOL                unpackU16s(U16 *value, S32 count, const char *name); +  +    virtual BOOL		packS16(const S16 value, const char *name) = 0; +    virtual BOOL		unpackS16(S16 &value, const char *name) = 0; +    BOOL                unpackS16s(S16 *value, S32 count, const char *name);  	virtual BOOL		packU32(const U32 value, const char *name) = 0;  	virtual BOOL		unpackU32(U32 &value, const char *name) = 0; @@ -69,6 +74,7 @@ public:  	virtual BOOL		packF32(const F32 value, const char *name) = 0;  	virtual BOOL		unpackF32(F32 &value, const char *name) = 0; +    BOOL                unpackF32s(F32 *values, S32 count, const char *name);  	// Packs a float into an integer, using the given size  	// and picks the right U* data type to pack into. @@ -82,6 +88,7 @@ public:  	virtual BOOL		packColor4U(const LLColor4U &value, const char *name) = 0;  	virtual BOOL		unpackColor4U(LLColor4U &value, const char *name) = 0; +    BOOL                unpackColor4Us(LLColor4U *values, S32 count, const char *name);  	virtual BOOL		packVector2(const LLVector2 &value, const char *name) = 0;  	virtual BOOL		unpackVector2(LLVector2 &value, const char *name) = 0; @@ -94,6 +101,7 @@ public:  	virtual BOOL		packUUID(const LLUUID &value, const char *name) = 0;  	virtual BOOL		unpackUUID(LLUUID &value, const char *name) = 0; +    BOOL                unpackUUIDs(LLUUID *values, S32 count, const char *name);  			U32			getPassFlags() const	{ return mPassFlags; }  			void		setPassFlags(U32 flags)	{ mPassFlags = flags; }  protected: @@ -139,6 +147,9 @@ public:  	/*virtual*/ BOOL		packU16(const U16 value, const char *name);  	/*virtual*/ BOOL		unpackU16(U16 &value, const char *name); +    /*virtual*/ BOOL		packS16(const S16 value, const char *name); +    /*virtual*/ BOOL		unpackS16(S16 &value, const char *name); +  	/*virtual*/ BOOL		packU32(const U32 value, const char *name);  	/*virtual*/ BOOL		unpackU32(U32 &value, const char *name); @@ -247,6 +258,9 @@ public:  	/*virtual*/ BOOL		packU16(const U16 value, const char *name);  	/*virtual*/ BOOL		unpackU16(U16 &value, const char *name); +    /*virtual*/ BOOL		packS16(const S16 value, const char *name); +    /*virtual*/ BOOL		unpackS16(S16 &value, const char *name); +  	/*virtual*/ BOOL		packU32(const U32 value, const char *name);  	/*virtual*/ BOOL		unpackU32(U32 &value, const char *name); @@ -375,6 +389,9 @@ public:  	/*virtual*/ BOOL		packU16(const U16 value, const char *name);  	/*virtual*/ BOOL		unpackU16(U16 &value, const char *name); +    /*virtual*/ BOOL		packS16(const S16 value, const char *name); +    /*virtual*/ BOOL		unpackS16(S16 &value, const char *name); +  	/*virtual*/ BOOL		packU32(const U32 value, const char *name);  	/*virtual*/ BOOL		unpackU32(U32 &value, const char *name); diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index fba5b7453d..219b1855d2 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -281,6 +281,13 @@ char const* const _PREHASH_PricePerMeter = LLMessageStringTable::getInstance()->  char const* const _PREHASH_RegionFlags = LLMessageStringTable::getInstance()->getString("RegionFlags");  char const* const _PREHASH_RegionFlagsExtended = LLMessageStringTable::getInstance()->getString("RegionFlagsExtended");  char const* const _PREHASH_RegionProtocols = LLMessageStringTable::getInstance()->getString("RegionProtocols"); +char const* const _PREHASH_ChatWhisperRange = LLMessageStringTable::getInstance()->getString("ChatWhisperRange"); +char const* const _PREHASH_ChatNormalRange = LLMessageStringTable::getInstance()->getString("ChatNormalRange"); +char const* const _PREHASH_ChatShoutRange = LLMessageStringTable::getInstance()->getString("ChatShoutRange"); +char const* const _PREHASH_ChatWhisperOffset = LLMessageStringTable::getInstance()->getString("ChatWhisperOffset"); +char const* const _PREHASH_ChatNormalOffset = LLMessageStringTable::getInstance()->getString("ChatNormalOffset"); +char const* const _PREHASH_ChatShoutOffset = LLMessageStringTable::getInstance()->getString("ChatShoutOffset"); +char const* const _PREHASH_ChatFlags = LLMessageStringTable::getInstance()->getString("ChatFlags");  char const* const _PREHASH_VoteResult = LLMessageStringTable::getInstance()->getString("VoteResult");  char const* const _PREHASH_ParcelDirFeeEstimate = LLMessageStringTable::getInstance()->getString("ParcelDirFeeEstimate");  char const* const _PREHASH_ModifyBlock = LLMessageStringTable::getInstance()->getString("ModifyBlock"); @@ -309,6 +316,7 @@ char const* const _PREHASH_DuplicateFlags = LLMessageStringTable::getInstance()-  char const* const _PREHASH_RegionInfo2 = LLMessageStringTable::getInstance()->getString("RegionInfo2");  char const* const _PREHASH_RegionInfo3 = LLMessageStringTable::getInstance()->getString("RegionInfo3");  char const* const _PREHASH_RegionInfo4 = LLMessageStringTable::getInstance()->getString("RegionInfo4"); +char const* const _PREHASH_RegionInfo5 = LLMessageStringTable::getInstance()->getString("RegionInfo5");  char const* const _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextColor");  char const* const _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID");  char const* const _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 4f72c01ddf..8f6ee5a327 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -281,6 +281,13 @@ extern char const* const _PREHASH_PricePerMeter;  extern char const* const _PREHASH_RegionFlags;  extern char const* const _PREHASH_RegionFlagsExtended;  extern char const* const _PREHASH_RegionProtocols; +extern char const* const _PREHASH_ChatWhisperRange; +extern char const* const _PREHASH_ChatNormalRange; +extern char const* const _PREHASH_ChatShoutRange; +extern char const* const _PREHASH_ChatWhisperOffset; +extern char const* const _PREHASH_ChatNormalOffset; +extern char const* const _PREHASH_ChatShoutOffset; +extern char const* const _PREHASH_ChatFlags;  extern char const* const _PREHASH_VoteResult;  extern char const* const _PREHASH_ParcelDirFeeEstimate;  extern char const* const _PREHASH_ModifyBlock; @@ -309,6 +316,7 @@ extern char const* const _PREHASH_DuplicateFlags;  extern char const* const _PREHASH_RegionInfo2;  extern char const* const _PREHASH_RegionInfo3;  extern char const* const _PREHASH_RegionInfo4; +extern char const* const _PREHASH_RegionInfo5;  extern char const* const _PREHASH_TextColor;  extern char const* const _PREHASH_SlaveID;  extern char const* const _PREHASH_Charter; diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp index 37c718b4c6..58b2d00d44 100644 --- a/indra/llprimitive/llmaterialtable.cpp +++ b/indra/llprimitive/llmaterialtable.cpp @@ -559,6 +559,23 @@ LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2)  	}  } +bool LLMaterialTable::isCollisionSound(const LLUUID &uuid) +{ +	for (U8 i = 0; i < LL_MCODE_END; i++) +	{ +		for (U8 j = 0; j < LL_MCODE_END; j++) +		{ +			i &= LL_MCODE_MASK; +			j &= LL_MCODE_MASK; +			if (mCollisionSoundMatrix[i * LL_MCODE_END + j] == uuid) +			{ +				return true; +			} +		} +	} +	return false; +} +  LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2)  {	  	mcode &= LL_MCODE_MASK; diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h index a17e0103ff..0cf5e626ef 100644 --- a/indra/llprimitive/llmaterialtable.h +++ b/indra/llprimitive/llmaterialtable.h @@ -128,6 +128,8 @@ public:  	F32 getDamageMod(U8 mcode);  	F32 getEPMod(U8 mcode); +	bool isCollisionSound(const LLUUID &uuid); +  	LLUUID getCollisionSoundUUID(U8 mcode, U8 mcode2);   	LLUUID getSlidingSoundUUID(U8 mcode, U8 mcode2);   	LLUUID getRollingSoundUUID(U8 mcode, U8 mcode2);  diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 53b83a40d7..67c225d25d 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -114,6 +114,35 @@ const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; //  // can't be divided by 2.   See DEV-19108  const F32	TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000); +struct material_id_type // originally from llrendermaterialtable +{ +    material_id_type() +    { +        memset((void*)m_value, 0, sizeof(m_value)); +    } + +    bool operator==(const material_id_type& other) const +    { +        return (memcmp(m_value, other.m_value, sizeof(m_value)) == 0); +    } + +    bool operator!=(const material_id_type& other) const +    { +        return !operator==(other); +    } + +    bool isNull() const +    { +        return (memcmp(m_value, s_null_id, sizeof(m_value)) == 0); +    } + +    U8 m_value[MATERIAL_ID_SIZE]; // server side this is MD5RAW_BYTES + +    static const U8 s_null_id[MATERIAL_ID_SIZE]; +}; + +const U8 material_id_type::s_null_id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; +  //static   // LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global  // TODO -- eliminate this global from the codebase! @@ -1079,50 +1108,85 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa  	return (S32)(cur_ptr - start_loc);  } -S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type) -{ -	U8 *start_loc = cur_ptr; -	U64 i; -	htolememcpy(data_ptr,cur_ptr, type,data_size); -	cur_ptr += data_size; - -	for (i = 1; i < face_count; i++) -	{ -		// Already unswizzled, don't need to unswizzle it again! -		memcpy(data_ptr+(i*data_size),data_ptr,data_size);	/* Flawfinder: ignore */  -	} -	 -	while ((cur_ptr < buffer_end) && (*cur_ptr != 0)) -	{ -		LL_DEBUGS("TEFieldDecode") << "TE exception" << LL_ENDL; -		i = 0; -		while (*cur_ptr & 0x80) -		{ -			i |= ((*cur_ptr++) & 0x7F); -			i = i << 7; -		} - -		i |= *cur_ptr++; - -		for (S32 j = 0; j < face_count; j++) -		{ -			if (i & 0x01) -			{ -				htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size); -				LL_DEBUGS("TEFieldDecode") << "Assigning " ; -				char foo[64]; -				sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1)); -				LL_CONT << foo << " to face " << j << LL_ENDL; -			} -			i = i >> 1; -		} -		cur_ptr += data_size;		 -	} -	llassert(cur_ptr <= buffer_end); // buffer underrun -	return (S32)(cur_ptr - start_loc); +namespace +{ +    template< typename T > +    bool unpack_TEField(T dest[], U8 dest_count, U8 * &source, U8 *source_end, EMsgVariableType type) +    { +        const size_t size(sizeof(T)); + +        LL_DEBUGS("TEXTUREENTRY") << "Request to read items of size " << size << " with swizzle " << type << " froum buffer sized " << (source_end - source) << LL_ENDL; + +        if ((source + size + 1) > source_end) +        { +            // we add 1 above to take into account the byte that we know must follow the value. +            LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL; +            source = source_end; +            return false; +        } + +        // Extract the default value and fill the array.  +        htolememcpy(dest, source, type, size); +        source += size; +        for (S32 idx = 1; idx < dest_count; ++idx) +        { +            dest[idx] = dest[0]; +        } + +        while (source < source_end) +        { +            U64 index_flags(0); +            U8  sbit(0); + +            // Unpack the variable length bitfield. Each bit represents whether the following  +            // value will be placed at the corresponding array index. +            do +            { +                if (source >= source_end) +                { +                    LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Reading index flags." << LL_ENDL; +                    source = source_end; +                    return false; +                } + +                sbit = *source++; +                index_flags <<= 7;    // original code had this after? +                index_flags |= (sbit & 0x7F); +            } while (sbit & 0x80); + +            if (!index_flags) +            {   // We've hit the terminating 0 byte. +                break; +            } + +            if ((source + size + 1) > source_end) +            { +                // we add 1 above to take into account the byte that we know must follow the value. +                LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL; +                source = source_end; +                return false; +            } + +            // get the value for the indexs. +            T value; +            htolememcpy(&value, source, type, size); +            source += size; + +            for (S32 idx = 0; idx < dest_count; idx++) +            { +                if (index_flags & 1ULL << idx) +                { +                    dest[idx] = value; +                } +            } + +        } +        return true; +    }  } +  // Pack information about all texture entries into container:  // { TextureEntry Variable 2 }  // Includes information about image ID, color, scale S,T, offset S,T and rotation @@ -1298,9 +1362,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const  S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec)  {  	S32 retval = 0; -   // temp buffer for material ID processing -   // data will end up in tec.material_id[]	 -   U8 material_data[LLTEContents::MAX_TES*16]; +    // temp buffer for material ID processing +    // data will end up in tec.material_id[]	 +    material_id_type material_data[LLTEContents::MAX_TES];  	if (block_num < 0)  	{ @@ -1316,54 +1380,49 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name  		tec.face_count = 0;  		return retval;  	} +    else if (tec.size >= LLTEContents::MAX_TE_BUFFER) +    { +        LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; +        tec.size = LLTEContents::MAX_TE_BUFFER - 1; +    } -	if (block_num < 0) -	{ -		mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER); -	} -	else -	{ -		mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER); -	} +    // if block_num < 0 ask for block 0 +    mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, std::max(block_num, 0), LLTEContents::MAX_TE_BUFFER - 1); -	 +    // The last field is not zero terminated.   +    // Rather than special case the upack functions.  Just make it 0x00 terminated. +    tec.packed_buffer[tec.size] = 0x00; +    ++tec.size;  	tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES);  	U8 *cur_ptr = tec.packed_buffer; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8); - -	if (cur_ptr < tec.packed_buffer + tec.size) -	{ -		cur_ptr++; -		cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)material_data, 16, tec.face_count, MVT_LLUUID); -	} -	else -	{ -		memset(material_data, 0, sizeof(material_data)); +    LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffere sized: " << tec.size << LL_ENDL; +    U8 *buffer_end = tec.packed_buffer + tec.size; + +    if (!(  unpack_TEField<LLUUID>(tec.image_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID) && +            unpack_TEField<LLColor4U>(tec.colors, tec.face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<F32>(tec.scale_s, tec.face_count, cur_ptr, buffer_end, MVT_F32) && +            unpack_TEField<F32>(tec.scale_t, tec.face_count, cur_ptr, buffer_end, MVT_F32) && +            unpack_TEField<S16>(tec.offset_s, tec.face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<S16>(tec.offset_t, tec.face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<S16>(tec.image_rot, tec.face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<U8>(tec.bump, tec.face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<U8>(tec.media_flags, tec.face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<U8>(tec.glow, tec.face_count, cur_ptr, buffer_end, MVT_U8))) +    { +        LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL; +        return 0; +    } + +	if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID)) +	{ +		memset((void*)material_data, 0, sizeof(material_data));  	}  	for (U32 i = 0; i < tec.face_count; i++)  	{ -		tec.material_ids[i].set(&material_data[i * 16]); +		tec.material_ids[i].set(&(material_data[i]));  	}  	retval = 1; @@ -1375,7 +1434,6 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)  	S32 retval = 0;  	LLColor4 color; -	LLColor4U coloru;  	for (U32 i = 0; i < tec.face_count; i++)  	{  		LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; @@ -1388,20 +1446,15 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)  		retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF);  		retval |= setTEMaterialID(i, tec.material_ids[i]); -		coloru = LLColor4U(tec.colors + 4*i); -  		// Note:  This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)  		// as all zeros.  However, the subtraction and addition must be done in unsigned  		// byte space, not in float space, otherwise off-by-one errors occur. JC -		color.mV[VRED]		= F32(255 - coloru.mV[VRED])   / 255.f; -		color.mV[VGREEN]	= F32(255 - coloru.mV[VGREEN]) / 255.f; -		color.mV[VBLUE]		= F32(255 - coloru.mV[VBLUE])  / 255.f; -		color.mV[VALPHA]	= F32(255 - coloru.mV[VALPHA]) / 255.f; +		color.mV[VRED]		= F32(255 - tec.colors[i].mV[VRED])   / 255.f; +		color.mV[VGREEN]	= F32(255 - tec.colors[i].mV[VGREEN]) / 255.f; +		color.mV[VBLUE]		= F32(255 - tec.colors[i].mV[VBLUE])  / 255.f; +		color.mV[VALPHA]	= F32(255 - tec.colors[i].mV[VALPHA]) / 255.f;  		retval |= setTEColor(i, color); - -		 -  	}  	return retval; @@ -1423,24 +1476,32 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)  	const U32 MAX_TES = 45;  	// Avoid construction of 32 UUIDs per call -	static LLUUID image_ids[MAX_TES];  	static LLMaterialID material_ids[MAX_TES]; -	U8     image_data[MAX_TES*16]; -	U8	   colors[MAX_TES*4]; -	F32    scale_s[MAX_TES]; -	F32    scale_t[MAX_TES]; -	S16    offset_s[MAX_TES]; -	S16    offset_t[MAX_TES]; -	S16    image_rot[MAX_TES]; -	U8	   bump[MAX_TES]; -	U8	   media_flags[MAX_TES]; -    U8     glow[MAX_TES]; -	U8     material_data[MAX_TES*16]; - -	const U32 MAX_TE_BUFFER = 4096; -	U8 packed_buffer[MAX_TE_BUFFER]; -	U8 *cur_ptr = packed_buffer; +    const U32 MAX_TE_BUFFER = 4096; +    U8 packed_buffer[MAX_TE_BUFFER]; +    memset((void*)packed_buffer, 0, MAX_TE_BUFFER); + +    LLUUID      image_data[MAX_TES]; +    LLColor4U   colors[MAX_TES]; +    F32         scale_s[MAX_TES]; +    F32         scale_t[MAX_TES]; +    S16         offset_s[MAX_TES]; +    S16         offset_t[MAX_TES]; +    S16         image_rot[MAX_TES]; +    U8          bump[MAX_TES]; +    U8          media_flags[MAX_TES]; +    U8          glow[MAX_TES]; +    material_id_type material_data[MAX_TES]; +     +    memset((void*)scale_s, 0, sizeof(scale_s)); +    memset((void*)scale_t, 0, sizeof(scale_t)); +    memset((void*)offset_s, 0, sizeof(offset_s)); +    memset((void*)offset_t, 0, sizeof(offset_t)); +    memset((void*)image_rot, 0, sizeof(image_rot)); +    memset((void*)bump, 0, sizeof(bump)); +    memset((void*)media_flags, 0, sizeof(media_flags)); +    memset((void*)glow, 0, sizeof(glow));  	S32 size;  	U32 face_count = 0; @@ -1456,50 +1517,52 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)  	{  		return retval;  	} +    else if (size >= MAX_TE_BUFFER) +    { +        LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; +        size = MAX_TE_BUFFER - 1; +    } +    // The last field is not zero terminated.   +    // Rather than special case the upack functions.  Just make it 0x00 terminated. +    packed_buffer[size] = 0x00; +    ++size;  	face_count = llmin((U32) getNumTEs(), MAX_TES);  	U32 i; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); -	cur_ptr++; -	cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8); -	if (cur_ptr < packed_buffer + size) -	{ -		cur_ptr++; -		cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID); -	} -	else +    U8 *cur_ptr = packed_buffer; +    LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffer sized: " << size << LL_ENDL; +    U8 *buffer_end = packed_buffer + size; + +    if (!(  unpack_TEField<LLUUID>(image_data, face_count, cur_ptr, buffer_end, MVT_LLUUID) && +            unpack_TEField<LLColor4U>(colors, face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<F32>(scale_s, face_count, cur_ptr, buffer_end, MVT_F32) && +            unpack_TEField<F32>(scale_t, face_count, cur_ptr, buffer_end, MVT_F32) && +            unpack_TEField<S16>(offset_s, face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<S16>(offset_t, face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<S16>(image_rot, face_count, cur_ptr, buffer_end, MVT_S16) && +            unpack_TEField<U8>(bump, face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<U8>(media_flags, face_count, cur_ptr, buffer_end, MVT_U8) && +            unpack_TEField<U8>(glow, face_count, cur_ptr, buffer_end, MVT_U8))) +    { +        LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL; +        return 0; +    } + +	if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID))  	{ -		memset(material_data, 0, sizeof(material_data)); +		memset((void*)material_data, 0, sizeof(material_data));  	}  	for (i = 0; i < face_count; i++)  	{ -		memcpy(image_ids[i].mData,&image_data[i*16],16);	/* Flawfinder: ignore */ 	 -		material_ids[i].set(&material_data[i * 16]); +		material_ids[i].set(&(material_data[i]));  	}  	LLColor4 color; -	LLColor4U coloru;  	for (i = 0; i < face_count; i++)  	{ -		retval |= setTETexture(i, image_ids[i]); +        retval |= setTETexture(i, ((LLUUID*)image_data)[i]);  		retval |= setTEScale(i, scale_s[i], scale_t[i]);  		retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);  		retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); @@ -1507,15 +1570,14 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)  		retval |= setTEMediaTexGen(i, media_flags[i]);  		retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);  		retval |= setTEMaterialID(i, material_ids[i]); -		coloru = LLColor4U(colors + 4*i);  		// Note:  This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)  		// as all zeros.  However, the subtraction and addition must be done in unsigned  		// byte space, not in float space, otherwise off-by-one errors occur. JC -		color.mV[VRED]		= F32(255 - coloru.mV[VRED])   / 255.f; -		color.mV[VGREEN]	= F32(255 - coloru.mV[VGREEN]) / 255.f; -		color.mV[VBLUE]		= F32(255 - coloru.mV[VBLUE])  / 255.f; -		color.mV[VALPHA]	= F32(255 - coloru.mV[VALPHA]) / 255.f; +		color.mV[VRED]		= F32(255 - colors[i].mV[VRED])   / 255.f; + 		color.mV[VGREEN]	= F32(255 - colors[i].mV[VGREEN]) / 255.f; + 		color.mV[VBLUE]		= F32(255 - colors[i].mV[VBLUE])  / 255.f; + 		color.mV[VALPHA]	= F32(255 - colors[i].mV[VALPHA]) / 255.f;  		retval |= setTEColor(i, color);  	} diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index b1f8112223..309b18faa9 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -330,8 +330,8 @@ struct LLTEContents  {  	static const U32 MAX_TES = 45; -	U8     image_data[MAX_TES*16]; -	U8	  colors[MAX_TES*4]; +    LLUUID      image_data[MAX_TES]; +    LLColor4U   colors[MAX_TES];  	F32    scale_s[MAX_TES];  	F32    scale_t[MAX_TES];  	S16    offset_s[MAX_TES]; @@ -423,7 +423,6 @@ public:  	void copyTEs(const LLPrimitive *primitive);  	S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; -	S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type);  	BOOL packTEMessage(LLMessageSystem *mesgsys) const;  	BOOL packTEMessage(LLDataPacker &dp) const;  	S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 52dc908655..bcc653a602 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -1037,6 +1037,43 @@ void LLComboBox::prearrangeList(std::string filter)  	}  } + +//============================================================================ +// ll::ui::SearchableControl functions + +//virtual +std::string LLComboBox::_getSearchText() const +{ +    std::string res; +    if (mList) +    { +        // getAllData returns a full copy of content, might be a +        // better option to implement an mList->getSearchText(column) +        std::vector<LLScrollListItem*> data = mList->getAllData(); +        std::vector<LLScrollListItem*>::iterator iter = data.begin(); +        while (iter != data.end()) +        { +            LLScrollListCell* cell = (*iter)->getColumn(0); +            if (cell) +            { +                std::string whitelist_url = cell->getValue().asString(); +                res += cell->getValue().asString(); +            } +            iter++; +        } +    } +    return res + getToolTip(); +} + +//virtual +void LLComboBox::onSetHighlight() const +{ +    if (mButton) +    { +        mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted()); +    } +} +  //============================================================================  // LLCtrlListInterface functions diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 4af3313162..e17d6cdfb4 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -44,7 +44,9 @@ class LLFontGL;  class LLViewBorder;  class LLComboBox -:	public LLUICtrl, public LLCtrlListInterface +: public LLUICtrl +, public LLCtrlListInterface +, public ll::ui::SearchableControl  {  public:	  	typedef enum e_preferred_position @@ -100,6 +102,9 @@ protected:  	void	initFromParams(const Params&);  	void	prearrangeList(std::string filter = ""); +    virtual std::string _getSearchText() const; +    virtual void onSetHighlight() const; +  public:  	// LLView interface  	virtual void	onFocusLost(); diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h index acc047527f..580f353c7d 100644 --- a/indra/llui/llnotificationptr.h +++ b/indra/llui/llnotificationptr.h @@ -27,9 +27,8 @@  // Many classes just store a single LLNotificationPtr  // and llnotifications.h is very large, so define this ligher header. -#include <boost/shared_ptr.hpp>  class LLNotification; -typedef boost::shared_ptr<LLNotification> LLNotificationPtr; +typedef std::shared_ptr<LLNotification> LLNotificationPtr;  #endif diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index b0b56cf599..94c8a14837 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -84,8 +84,6 @@  #include <sstream>  #include <boost/utility.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp>  #include <boost/type_traits.hpp>  #include <boost/signals2.hpp>  #include <boost/range.hpp> @@ -132,7 +130,7 @@ public:  typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder; -typedef boost::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr; +typedef std::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;  typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;  typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration; @@ -277,19 +275,19 @@ private:  	bool								mInvertSetting;  }; -typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr; +typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;  struct LLNotificationTemplate;  // we want to keep a map of these by name, and it's best to manage them  // with smart pointers -typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr; +typedef std::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;  struct LLNotificationVisibilityRule; -typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr; +typedef std::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;  /**   * @class LLNotification @@ -305,7 +303,7 @@ typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibility   */  class LLNotification  :   	boost::noncopyable, -	public boost::enable_shared_from_this<LLNotification> +	public std::enable_shared_from_this<LLNotification>  {  LOG_CLASS(LLNotification);  friend class LLNotifications; @@ -744,7 +742,14 @@ public:  	:	mFilter(filter),   		mItems()   	{} -	virtual ~LLNotificationChannelBase() {} +    virtual ~LLNotificationChannelBase() +    { +        // explicit cleanup for easier issue detection +        mChanged.disconnect_all_slots(); +        mPassedFilter.disconnect_all_slots(); +        mFailedFilter.disconnect_all_slots(); +        mItems.clear(); +    }  	// you can also connect to a Channel, so you can be notified of  	// changes to this channel      LLBoundListener connectChanged(const LLEventListener& slot) diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index f9f7641de6..4bab377626 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -31,7 +31,6 @@  #include "lleventapi.h"  #include "llnotificationptr.h" -#include <boost/shared_ptr.hpp>  #include <map>  #include <string> @@ -61,7 +60,7 @@ private:      static LLSD asLLSD(LLNotificationPtr);      class Forwarder; -    typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; +    typedef std::map<std::string, std::shared_ptr<Forwarder> > ForwarderMap;      ForwarderMap mForwarders;  	LLNotifications & mNotifications;  }; diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 20cbc89ede..a8902486e4 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -31,7 +31,7 @@  #include "llinitparam.h"  #include "llnotifications.h" -typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr; +typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;  // This is the class of object read from the XML file (notifications.xml,   // from the appropriate local language directory). diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 20bea7fe24..05788f1b6c 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -184,6 +184,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mFontShadow(p.font_shadow),  	mPopupMenuHandle(),  	mReadOnly(p.read_only), +	mSkipTripleClick(false),  	mSkipLinkUnderline(p.skip_link_underline),  	mSpellCheck(p.spellcheck),  	mSpellCheckStart(-1), @@ -1017,6 +1018,11 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)  	// handle triple click  	if (!mTripleClickTimer.hasExpired())  	{ +		if (mSkipTripleClick) +		{ +			return TRUE; +		} +		  		S32 real_line = getLineNumFromDocIndex(mCursorPos, false);  		S32 line_start = -1;  		S32 line_end = -1; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 4e966b7cef..2e2e1b9833 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -699,7 +699,7 @@ protected:  	bool						mPlainText;			// didn't use Image or Icon segments  	bool						mAutoIndent;  	S32							mMaxTextByteLength;	// Maximum length mText is allowed to be in bytes - +	bool						mSkipTripleClick;  	bool						mSkipLinkUnderline;  	// support widgets diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 134afc005b..c567451973 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -45,7 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)  :	LLTextBase(p),  	mClickedCallback(NULL),  	mShowCursorHand(true) -{} +{ +	mSkipTripleClick = true; +}  LLTextBox::~LLTextBox()  {} diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 20dda54771..29a6e86819 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -181,11 +181,51 @@ bool LLUrlEntryBase::isLinkDisabled() const  	return globally_disabled;  } -bool LLUrlEntryBase::isWikiLinkCorrect(std::string url) -{ -	LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url)); -	label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end()); -	return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true; +bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const +{ +	LLWString wlabel = utf8str_to_wstring(getLabelFromWikiLink(labeled_url)); +	wlabel.erase(std::remove(wlabel.begin(), wlabel.end(), L'\u200B'), wlabel.end()); + +    // Unicode URL validation, see SL-15243 +    std::replace_if(wlabel.begin(), +                    wlabel.end(), +                    [](const llwchar &chr) +                    { +                        return (chr == L'\u2024') // "One Dot Leader" +                               || (chr == L'\uFE52') // "Small Full Stop" +                               || (chr == L'\uFF0E') // "Fullwidth Full Stop" +                               // Not a decomposition, but suficiently similar +                               || (chr == L'\u05C5'); // "Hebrew Mark Lower Dot" +                    }, +                    L'\u002E'); // Dot "Full Stop" + +    std::replace_if(wlabel.begin(), +        wlabel.end(), +        [](const llwchar &chr) +    { +        return (chr == L'\u02D0') // "Modifier Letter Colon" +            || (chr == L'\uFF1A') // "Fullwidth Colon" +            || (chr == L'\uFE55'); // "Small Colon" +    }, +        L'\u003A'); // Colon + +    std::replace_if(wlabel.begin(), +        wlabel.end(), +        [](const llwchar &chr) +    { +        return (chr == L'\uFF0F'); // "Fullwidth Solidus" +    }, +        L'\u002F'); // Solidus + +    std::string label = wstring_to_utf8str(wlabel); +    if ((label.find(".com") != std::string::npos +         || label.find("www.") != std::string::npos) +        && label.find("://") == std::string::npos) +    { +        label = "http://" + label; +    } + +	return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;  }  std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 4af1ab5096..102e0a4fd9 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -105,7 +105,7 @@ public:  	bool isLinkDisabled() const; -	bool isWikiLinkCorrect(std::string url); +	bool isWikiLinkCorrect(const std::string &url) const;  	virtual bool isSLURLvalid(const std::string &url) const { return TRUE; }; diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 9e9abbadff..7a30cd4cea 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -888,6 +888,11 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)  	return name;  } +std::string LLDir::getDumpLogsDirPath(const std::string &file_name) +{ +    return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "dump_logs", file_name); +} +  // static  std::string LLDir::getForbiddenFileChars()  { diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 4988b9c6e3..c114f9957b 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -174,6 +174,8 @@ class LLDir  	// random filename in common temporary directory  	std::string getTempFilename() const; +    static std::string getDumpLogsDirPath(const std::string &file_name = ""); +  	// For producing safe download file names from potentially unsafe ones  	static std::string getScrubbedFileName(const std::string uncleanFileName);  	static std::string getForbiddenFileChars(); diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index 0b38647b4a..ceda7ff74c 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -33,6 +33,7 @@  	LLNonInlineTextView *inputView;  	NSTimer *frameTimer;  	NSString *currentInputLanguage; +    std::string secondLogPath;  }  @property (assign) IBOutlet LLNSWindow *window; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a2933b85a5..80ab8af1de 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3748,6 +3748,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>EnableCollisionSounds</key> +    <map> +      <key>Comment</key> +      <string>Play sounds on collision</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>EnableMouselook</key>      <map>        <key>Comment</key> @@ -12674,6 +12685,17 @@        <key>Value</key>        <integer>50</integer>      </map> +    <key>TextureSaveLocation</key> +    <map> +      <key>Comment</key> +      <string>Current location for bulk saving textures to disk</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string /> +    </map>      <key>ThrottleBandwidthKBPS</key>      <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl index b768d609f4..d87403c78f 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl @@ -43,13 +43,13 @@ void default_lighting()  {  	vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); -	color *= vertex_color; -  	if (color.a < minimum_alpha)  	{  		discard;  	} -	 + +	color *= vertex_color; +  	color.rgb = atmosLighting(color.rgb);  	color.rgb = scaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl index d04cd79f4b..37cac5f437 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -43,13 +43,13 @@ void fullbright_lighting_water()  {  	vec4 color = diffuseLookup(vary_texcoord0.xy); -	color.rgb *= vertex_color.rgb; -  	if (color.a < minimum_alpha)  	{  		discard;  	} +	color.rgb *= vertex_color.rgb; +  	color.rgb = fullbrightAtmosTransport(color.rgb);  	frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl index 3b9c04b22b..c98db4795c 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl @@ -41,13 +41,15 @@ VARYING vec2 vary_texcoord0;  void fullbright_lighting_water()  { -	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color; +	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);  	if (color.a < minimum_alpha)  	{  		discard;  	} +	color.rgb *= vertex_color.rgb; +  	color.rgb = fullbrightAtmosTransport(color.rgb);  	frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl index 0916797259..9c89c09573 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl @@ -41,13 +41,13 @@ void default_lighting_water()  {  	vec4 color = diffuseLookup(vary_texcoord0.xy); -	color.rgb *= vertex_color.rgb; -  	if (color.a < minimum_alpha)  	{  		discard;  	} +	color.rgb *= vertex_color.rgb; +  	color.rgb = atmosLighting(color.rgb);  	frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl index f2a84f1d42..9de7a03180 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl @@ -43,13 +43,13 @@ void default_lighting_water()  {  	vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); -	color.rgb *= vertex_color.rgb; -  	if (color.a < minimum_alpha)  	{  		discard;  	} +	color.rgb *= vertex_color.rgb; +  	color.rgb = atmosLighting(color.rgb);  	color = applyWaterFog(color); diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsiBinary files differ index 05977847b9..865e8bdeee 100644 --- a/indra/newview/installers/windows/lang_pl.nsi +++ b/indra/newview/installers/windows/lang_pl.nsi diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 7f18ea6fe2..be168ff5dd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1049,13 +1049,14 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it  	}  	// updating inventory +    LLWearableType* wearable_type_inst = LLWearableType::getInstance();  	// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later  	// 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++)  	{ -		if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING) +		if (wearable_type_inst->getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)  		{  			removeWearable((LLWearableType::EType)j, true, 0);  		} @@ -1075,7 +1076,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it  			new_wearable->setName(new_item->getName());  			new_wearable->setItemID(new_item->getUUID()); -			if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART) +			if (wearable_type_inst->getAssetType(type) == LLAssetType::AT_BODYPART)  			{  				// exactly one wearable per body part  				setWearable(type,0,new_wearable); @@ -1162,7 +1163,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearab  			if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&  				(old_item_id == new_item->getUUID()))  			{ -				LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName(type) << LL_ENDL; +				LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getInstance()->getTypeName(type) << LL_ENDL;  				return;  			} @@ -1594,7 +1595,7 @@ void LLAgentWearables::editWearable(const LLUUID& item_id)  		return;  	} -	const BOOL disable_camera_switch = LLWearableType::getDisableCameraSwitch(wearable->getType()); +	const BOOL disable_camera_switch = LLWearableType::getInstance()->getDisableCameraSwitch(wearable->getType());  	LLPanel* panel = LLFloaterSidePanelContainer::getPanel("appearance");  	LLSidepanelAppearance::editWearable(wearable, panel, disable_camera_switch);  } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 3f1b5139c5..8063d7fda3 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -299,6 +299,12 @@ struct AttachmentInfo          AttachmentInfo(metadata.staticDebugPathname,  "text/xml")      }; +    secondLogPath = metadata.secondLogFilePathname; +    if(!secondLogPath.empty()) +    { +        info.push_back(AttachmentInfo(secondLogPath,  "text/xml")); +    } +      // We "happen to know" that info[0].basename is "SecondLife.old" -- due to      // the fact that BugsplatMac only notices a crash during the viewer run      // following the crash. Replace .old with .log to reduce confusion. @@ -333,6 +339,12 @@ struct AttachmentInfo  - (void)bugsplatStartupManagerDidFinishSendingCrashReport:(BugsplatStartupManager *)bugsplatStartupManager  {      infos("Sent crash report to BugSplat"); + +    if(!secondLogPath.empty()) +    { +        boost::filesystem::remove(secondLogPath); +    } +    clearDumpLogsDir();  }  - (void)bugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager didFailWithError:(NSError *)error diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e8a3305645..fd712ea5d0 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -957,7 +957,7 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L  		// runway skip here?  	} -	LL_INFOS() << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL; +	LL_INFOS("Avatar") << "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); @@ -1021,8 +1021,8 @@ 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; +	LL_DEBUGS("Avatar") << "Wearable of type '" << LLWearableType::getInstance()->getTypeName(type) +				<< "' 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. @@ -3626,7 +3626,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd      }      llcoro::suspend(); -    if (LLApp::isQuitting()) +    if (LLApp::isExiting())      {          return;      } @@ -3693,7 +3693,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd          LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); -        if (LLApp::isQuitting()) +        if (LLApp::isExiting())          {              return;          } @@ -3733,7 +3733,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd                  LL_WARNS("Avatar") << "Bake retry #" << retryCount << " in " << timeout << " seconds." << LL_ENDL;                  llcoro::suspendUntilTimeout(timeout);  -                if (LLApp::isQuitting()) +                if (LLApp::isExiting())                  {                      return;                  } @@ -4267,6 +4267,17 @@ public:  	}  	virtual void done()  	{ +        if (mComplete.size() <= 0) +        { +            // Ex: timeout +            LL_WARNS() << "Failed to load data. Removing observer " << LL_ENDL; +            gInventory.removeObserver(this); +            doOnIdleOneTime(mCallable); + +            delete this; +            return; +        } +  		// What we do here is get the complete information on the  		// items in the requested category, and set up an observer  		// that will wait for that to happen. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c0971ba943..a919e3f34e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -717,8 +717,6 @@ LLAppViewer::LLAppViewer()  	gLoggedInTime.stop(); -	initLoggingAndGetLastDuration(); -  	processMarkerFiles();  	//  	// OK to write stuff to logs now, we've now crash reported if necessary @@ -782,10 +780,6 @@ bool LLAppViewer::init()  	// Start of the application  	// -	// initialize LLWearableType translation bridge. -	// Memory will be cleaned up in ::cleanupClass() -	LLWearableType::initParamSingleton(new LLUITranslationBridge()); -      // initialize the LLSettingsType translation bridge.      LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>();      LLSettingsType::initParamSingleton(trans); @@ -807,6 +801,7 @@ bool LLAppViewer::init()  	//  	init_default_trans_args(); +    // inits from settings.xml and from strings.xml  	if (!initConfiguration())  		return false; @@ -873,6 +868,10 @@ bool LLAppViewer::init()  	// Setup LLTrans after LLUI::initClass has been called.  	initStrings(); +    // initialize LLWearableType translation bridge. +    // Will immediately use LLTranslationBridge to init LLWearableDictionary +    LLWearableType::initParamSingleton(trans); +  	// Setup notifications after LLUI::initClass() has been called.  	LLNotifications::instance();  	LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; @@ -1345,6 +1344,13 @@ bool LLAppViewer::init()  	// Load User's bindings  	loadKeyBindings(); +#if LL_WINDOWS +    if (!mSecondInstance) +    { +        gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath()); +    } +#endif +  	return true;  } @@ -2274,75 +2280,87 @@ void errorCallback(const std::string &error_string)  void LLAppViewer::initLoggingAndGetLastDuration()  { -	// -	// Set up logging defaults for the viewer -	// -	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") +    // +    // Set up logging defaults for the viewer +    // +    LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")                                  ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")                                  ); -	LLError::setFatalFunction(errorCallback); -	//LLError::setTimeFunction(getRuntime); - -	// Remove the last ".old" log file. -	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, -							     "SecondLife.old"); -	LLFile::remove(old_log_file); - -	// Get name of the log file -	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, -							     "SecondLife.log"); - 	/* -	 * Before touching any log files, compute the duration of the last run -	 * by comparing the ctime of the previous start marker file with the ctime -	 * of the last log file. -	 */ -	std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME); -	llstat start_marker_stat; -	llstat log_file_stat; -	std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below -	int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat); -	int log_stat_result = LLFile::stat(log_file, &log_file_stat); -	if ( 0 == start_stat_result && 0 == log_stat_result ) -	{ -		int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime; -		// only report a last run time if the last viewer was the same version -		// because this stat will be counted against this version -		if ( markerIsSameVersion(start_marker_file_name) ) -		{ -			gLastExecDuration = elapsed_seconds; -		} -		else -		{ -			duration_log_stream << "start marker from some other version; duration is not reported"; -			gLastExecDuration = -1; -		} -	} -	else -	{ -		// at least one of the LLFile::stat calls failed, so we can't compute the run time -		duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result; -		gLastExecDuration = -1; // unknown -	} -	std::string duration_log_msg(duration_log_stream.str()); +    LLError::setFatalFunction(errorCallback); +    //LLError::setTimeFunction(getRuntime); -	// Create a new start marker file for comparison with log file time for the next run -	LLAPRFile start_marker_file ; -	start_marker_file.open(start_marker_file_name, LL_APR_WB); -	if (start_marker_file.getFileHandle()) -	{ -		recordMarkerVersion(start_marker_file); -		start_marker_file.close(); -	} -	// Rename current log file to ".old" -	LLFile::rename(log_file, old_log_file); +    if (mSecondInstance) +    { +        LLFile::mkdir(gDirUtilp->getDumpLogsDirPath()); +  +        LLUUID uid; +        uid.generate(); +        LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log")); +    } +    else +    { +        // Remove the last ".old" log file. +        std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, +            "SecondLife.old"); +        LLFile::remove(old_log_file); + +        // Get name of the log file +        std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, +            "SecondLife.log"); +        /* +        * Before touching any log files, compute the duration of the last run +        * by comparing the ctime of the previous start marker file with the ctime +        * of the last log file. +        */ +        std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME); +        llstat start_marker_stat; +        llstat log_file_stat; +        std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below +        int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat); +        int log_stat_result = LLFile::stat(log_file, &log_file_stat); +        if (0 == start_stat_result && 0 == log_stat_result) +        { +            int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime; +            // only report a last run time if the last viewer was the same version +            // because this stat will be counted against this version +            if (markerIsSameVersion(start_marker_file_name)) +            { +                gLastExecDuration = elapsed_seconds; +            } +            else +            { +                duration_log_stream << "start marker from some other version; duration is not reported"; +                gLastExecDuration = -1; +            } +        } +        else +        { +            // at least one of the LLFile::stat calls failed, so we can't compute the run time +            duration_log_stream << "duration stat failure; start: " << start_stat_result << " log: " << log_stat_result; +            gLastExecDuration = -1; // unknown +        } +        std::string duration_log_msg(duration_log_stream.str()); -	// Set the log file to SecondLife.log -	LLError::logToFile(log_file); -	if (!duration_log_msg.empty()) -	{ -		LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; -	} +        // Create a new start marker file for comparison with log file time for the next run +        LLAPRFile start_marker_file; +        start_marker_file.open(start_marker_file_name, LL_APR_WB); +        if (start_marker_file.getFileHandle()) +        { +            recordMarkerVersion(start_marker_file); +            start_marker_file.close(); +        } + +        // Rename current log file to ".old" +        LLFile::rename(log_file, old_log_file); + +        // Set the log file to SecondLife.log +        LLError::logToFile(log_file); +        if (!duration_log_msg.empty()) +        { +            LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; +        } +    }  }  bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, @@ -3786,6 +3804,7 @@ void LLAppViewer::processMarkerFiles()  	// - Other Crash (SecondLife.error_marker present)  	// These checks should also remove these files for the last 2 cases if they currently exist +	std::ostringstream marker_log_stream;  	bool marker_is_same_version = true;  	// first, look for the marker created at startup and deleted on a clean exit  	mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); @@ -3796,12 +3815,12 @@ void LLAppViewer::processMarkerFiles()  		marker_is_same_version = markerIsSameVersion(mMarkerFileName);  		// now test to see if this file is locked by a running process (try to open for write) -		LL_DEBUGS("MarkerFile") << "Checking exec marker file for lock..." << LL_ENDL; +		marker_log_stream << "Checking exec marker file for lock...";  		mMarkerFile.open(mMarkerFileName, LL_APR_WB);  		apr_file_t* fMarker = mMarkerFile.getFileHandle() ;  		if (!fMarker)  		{ -			LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL; +			marker_log_stream << "Exec marker file open failed - assume it is locked.";  			mSecondInstance = true; // lock means that instance is running.  		}  		else @@ -3809,16 +3828,20 @@ void LLAppViewer::processMarkerFiles()  			// We were able to open it, now try to lock it ourselves...  			if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)  			{ -				LL_WARNS_ONCE("MarkerFile") << "Locking exec marker failed." << LL_ENDL; +				marker_log_stream << "Locking exec marker failed.";  				mSecondInstance = true; // lost a race? be conservative  			}  			else  			{  				// No other instances; we've locked this file now, so record our version; delete on quit.  				recordMarkerVersion(mMarkerFile); -				LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL; +				marker_log_stream << "Exec marker file existed but was not locked; rewritten.";  			}  		} +		initLoggingAndGetLastDuration(); + +		std::string marker_log_msg(marker_log_stream.str()); +		LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL;  		if (mSecondInstance)  		{ @@ -3838,6 +3861,7 @@ void LLAppViewer::processMarkerFiles()  	}  	else // marker did not exist... last exec (if any) did not freeze  	{ +		initLoggingAndGetLastDuration();  		// Create the marker file for this execution & lock it; it will be deleted on a clean exit  		apr_status_t s;  		s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE); @@ -3965,6 +3989,13 @@ void LLAppViewer::removeDumpDir()      //its locking table for us.      std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");      gDirUtilp->deleteDirAndContents(dump_dir); + +    if (mSecondInstance && !isError()) +    { +        std::string log_filename = LLError::logFileName(); +        LLError::logToFile(""); +        LLFile::remove(log_filename); +    }  }  void LLAppViewer::forceQuit() diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index 79c3efff91..94bfa2491b 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -31,6 +31,7 @@ bool pumpMainLoop();  void handleQuit();  void cleanupViewer();  void infos(const std::string& message); +void clearDumpLogsDir();  // This struct is malleable; it only serves as a way to convey a number of  // fields from llappviewermacosx.cpp's CrashMetadata_instance() function to the @@ -47,6 +48,7 @@ struct CrashMetadata      std::string agentFullname;      std::string regionName;      std::string fatalMessage; +    std::string secondLogFilePathname;  };  CrashMetadata& CrashMetadata_instance(); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 662164af2d..75ce26fb18 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -57,6 +57,7 @@  #include <fstream>  #include "lldir.h" +#include "lldiriterator.h"  #include <signal.h>  #include <CoreAudio/CoreAudio.h>	// for systemwide mute  class LLMediaCtrl;		// for LLURLDispatcher @@ -154,6 +155,14 @@ void cleanupViewer()  	gViewerAppPtr = NULL;  } +void clearDumpLogsDir() +{ +    if (!LLAppViewer::instance()->isSecondInstance()) +    { +        gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath()); +    } +} +  // The BugsplatMac API is structured as a number of different method  // overrides, each returning a different piece of metadata. But since we  // obtain such metadata by opening and parsing a file, it seems ridiculous to @@ -199,6 +208,7 @@ CrashMetadataSingleton::CrashMetadataSingleton()      else      {          LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL; +          logFilePathname         = get_metadata(info, "SLLog");          userSettingsPathname    = get_metadata(info, "SettingsFilename");          accountSettingsPathname = get_metadata(info, "PerAccountSettingsFilename"); @@ -208,6 +218,24 @@ CrashMetadataSingleton::CrashMetadataSingleton()          LLStringUtil::replaceChar(agentFullname, '_', ' ');          regionName           = get_metadata(info, "CurrentRegion");          fatalMessage         = get_metadata(info, "FatalMessage"); +         +        if (gDirUtilp->fileExists(gDirUtilp->getDumpLogsDirPath())) +        { +            LLDirIterator file_iter(gDirUtilp->getDumpLogsDirPath(), "*.log"); +            std::string file_name; +            bool found = true; +            while(found) +            { +                if((found = file_iter.next(file_name))) +                { +                    std::string log_filename = gDirUtilp->getDumpLogsDirPath(file_name); +                    if(LLError::logFileName() != log_filename) +                    { +                        secondLogFilePathname = log_filename; +                    } +                } +            } +        }      }  } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 9b1c0d1f8b..60fcad07f1 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -121,7 +121,7 @@ namespace              // send the main viewer log file              // widen to wstring, convert to __wchar_t, then pass c_str()              sBugSplatSender->sendAdditionalFile( -                WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); +                WCSTR(LLError::logFileName()));              sBugSplatSender->sendAdditionalFile(                  WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index b31981b235..aa2ba752b7 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -74,7 +74,7 @@ protected:  		}  		// Set proper label for the "Create new <WEARABLE_TYPE>" menu item. -		std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); +		std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));  		menu_item->setLabel(new_label);  	} diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 3aaaaf52f5..bf10a9f2b4 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -347,7 +347,7 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren  bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,      const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)  { -    if (LLApp::isQuitting()) +    if (LLApp::isExiting())      {          // Reply from coroutine came on shutdown          // We are quiting, don't start any more coroutines! diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index ef1b644ad4..934a38bb8e 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -113,7 +113,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)  		}  	} -	if(!LLApp::isQuitting()) +	if(!LLApp::isExiting())  	{  		LLNotificationsUtil::add(ent.mNotifyName, args);  	} diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 4b5fd8a758..6f3f6e9166 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -47,7 +47,7 @@ namespace LLEventPolling  namespace Details  { -    class LLEventPollImpl: public boost::enable_shared_from_this<LLEventPollImpl> +    class LLEventPollImpl: public std::enable_shared_from_this<LLEventPollImpl>      {      public:          LLEventPollImpl(const LLHost &sender); @@ -284,7 +284,7 @@ namespace Details  LLEventPoll::LLEventPoll(const std::string&	poll_url, const LLHost& sender):      mImpl()  {  -    mImpl = boost::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender); +    mImpl = std::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender);      mImpl->start(poll_url);  } diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h index 65766dbb2a..d6da04b281 100644 --- a/indra/newview/lleventpoll.h +++ b/indra/newview/lleventpoll.h @@ -51,7 +51,7 @@ public:  private: -    boost::shared_ptr<LLEventPolling::Details::LLEventPollImpl>  mImpl; +    std::shared_ptr<LLEventPolling::Details::LLEventPollImpl>  mImpl;  }; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 83b5bf3f25..cca6b9ce32 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -682,8 +682,12 @@ void LLFavoritesBarCtrl::changed(U32 mask)  //virtual  void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)  { +    S32 delta_width = width - getRect().getWidth(); +    S32 delta_height = height - getRect().getHeight(); + +    bool force_update = delta_width || delta_height || sForceReshape;  	LLUICtrl::reshape(width, height, called_from_parent); -	updateButtons(); +	updateButtons(force_update);  }  void LLFavoritesBarCtrl::draw() @@ -746,8 +750,13 @@ const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()  	return button_params;  } -void LLFavoritesBarCtrl::updateButtons() +void LLFavoritesBarCtrl::updateButtons(bool force_update)  { +    if (LLApp::isExiting()) +    { +        return; +    } +  	mItems.clear();  	if (!collectFavoriteItems(mItems)) @@ -778,28 +787,29 @@ void LLFavoritesBarCtrl::updateButtons()  	const child_list_t* childs = getChildList();  	child_list_const_iter_t child_it = childs->begin();  	int first_changed_item_index = 0; -	int rightest_point = getRect().mRight - mMoreTextBox->getRect().getWidth(); -	//lets find first changed button -	while (child_it != childs->end() && first_changed_item_index < mItems.size()) -	{ -		LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it); -		if (button) -		{ -			const LLViewerInventoryItem *item = mItems[first_changed_item_index].get(); -			if (item) -			{ -			    // an child's order  and mItems  should be same -				if (button->getLandmarkId() != item->getUUID() // sort order has been changed -					|| button->getLabelSelected() != item->getName() // favorite's name has been changed -					|| button->getRect().mRight < rightest_point) // favbar's width has been changed -				{ -					break; -				} -			} -			first_changed_item_index++; -		} -		child_it++; -	} +    if (!force_update) +    { +        //lets find first changed button +        while (child_it != childs->end() && first_changed_item_index < mItems.size()) +        { +            LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it); +            if (button) +            { +                const LLViewerInventoryItem *item = mItems[first_changed_item_index].get(); +                if (item) +                { +                    // an child's order  and mItems  should be same +                    if (button->getLandmarkId() != item->getUUID() // sort order has been changed +                        || button->getLabelSelected() != item->getName()) // favorite's name has been changed +                    { +                        break; +                    } +                } +                first_changed_item_index++; +            } +            child_it++; +        } +    }  	// now first_changed_item_index should contains a number of button that need to change  	if (first_changed_item_index <= mItems.size()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 3bb940948b..2d7ba9df67 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -75,7 +75,7 @@ public:  	void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }  protected: -	void updateButtons(); +    void updateButtons(bool force_update = false);  	LLButton* createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset );  	const LLButton::Params& getButtonParams();  	BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items); diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 0501c287ad..281d4f68f5 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -1457,14 +1457,22 @@ void LLFloaterEditExtDayCycle::reblendSettings()  {      F64 position = mTimeSlider->getCurSliderValue(); -    if ((mSkyBlender->getTrack() != mCurrentTrack) && (mCurrentTrack != LLSettingsDay::TRACK_WATER)) +    if (mSkyBlender)      { -        mSkyBlender->switchTrack(mCurrentTrack, position); +        if ((mSkyBlender->getTrack() != mCurrentTrack) && (mCurrentTrack != LLSettingsDay::TRACK_WATER)) +        { +            mSkyBlender->switchTrack(mCurrentTrack, position); +        } +        else +        { +            mSkyBlender->setPosition(position); +        }      } -    else -        mSkyBlender->setPosition(position); -    mWaterBlender->setPosition(position);     +    if (mWaterBlender) +    { +        mWaterBlender->setPosition(position); +    }  }  void LLFloaterEditExtDayCycle::doApplyCommit(LLSettingsDay::ptr_t day) diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index adc7f71586..4b22f7427b 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -248,6 +248,29 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)  		region_flags = flags;  	} +	if (msg->has(_PREHASH_RegionInfo5)) +	{ +		F32 chat_whisper_range; +		F32 chat_normal_range; +		F32 chat_shout_range; +		F32 chat_whisper_offset; +		F32 chat_normal_offset; +		F32 chat_shout_offset; +		U32 chat_flags; + +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset); +		msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags); + +		LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range +			<< " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset +			<< " chat flags: " << chat_flags << LL_ENDL; +	} +  	if (host != gAgent.getRegionHost())  	{  		// Update is for a different region than the one we're in. diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 7541bb5efe..441979389e 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -518,9 +518,12 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p  	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);  	// If not already present, create the participant view and attach it to the root, otherwise, just refresh it -	if (widget && update_view) +	if (widget)  	{ -		updateConversationViewParticipant(uuid); // overkill? +        if (update_view) +        { +            updateConversationViewParticipant(uuid); // overkill? +        }  	}  	else  	{ diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp index 595d584799..8ee7a72055 100644 --- a/indra/newview/llfloaterlinkreplace.cpp +++ b/indra/newview/llfloaterlinkreplace.cpp @@ -162,7 +162,7 @@ void LLFloaterLinkReplace::onStartClicked()  		else  		{  			LLSD args; -			args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType()); +			args["TYPE"] = LLWearableType::getInstance()->getTypeName(source_item->getWearableType());  			params.substitutions(args);  			LLNotifications::instance().add(params);  		} diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 6bf2136f60..7676487587 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -263,7 +263,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	mGotPersonalInfo(false),  	mOriginalIMViaEmail(false),  	mLanguageChanged(false), -	mAvatarDataInitialized(false) +	mAvatarDataInitialized(false), +	mSearchDataDirty(true)  {  	LLConversationLog::instance().addObserver(this); @@ -2150,6 +2151,11 @@ void LLFloaterPreference::updateClickActionViews()  	getChild<LLComboBox>("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk);  } +void LLFloaterPreference::updateSearchableItems() +{ +    mSearchDataDirty = true; +} +  void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)  {  	LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue())); @@ -2332,7 +2338,7 @@ BOOL LLPanelPreference::postBuild()  	}  	//////////////////////PanelSetup /////////////////// -	if (hasChild("max_bandwidth"), TRUE) +	if (hasChild("max_bandwidth", TRUE))  	{  		mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT);  		gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2)); @@ -2906,10 +2912,19 @@ void LLPanelPreferenceControls::populateControlTable()          filename = "control_table_contents_columns_basic.xml";          break;      default: -        // Either unknown mode or MODE_SAVED_SETTINGS -        // It doesn't have UI or actual settings yet -        LL_INFOS() << "Unimplemented mode" << LL_ENDL; -        return; +        { +            // Either unknown mode or MODE_SAVED_SETTINGS +            // It doesn't have UI or actual settings yet +            LL_WARNS() << "Unimplemented mode" << LL_ENDL; + +            // Searchable columns were removed, mark searchables for an update +            LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); +            if (instance) +            { +                instance->updateSearchableItems(); +            } +            return; +        }      }      addControlTableColumns(filename); @@ -2940,8 +2955,15 @@ void LLPanelPreferenceControls::populateControlTable()      }      else      { -        LL_INFOS() << "Unimplemented mode" << LL_ENDL; -        return; +        LL_WARNS() << "Unimplemented mode" << LL_ENDL; +    } + +    // Searchable columns were removed and readded, mark searchables for an update +    // Note: at the moment tables/lists lack proper llsearchableui support +    LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); +    if (instance) +    { +        instance->updateSearchableItems();      }  } @@ -3559,6 +3581,12 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force)  	if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force))  		return; +    if (mSearchDataDirty) +    { +        // Data exists, but is obsolete, regenerate +        collectSearchableItems(); +    } +  	mSearchData->mLastFilter = seachValue;  	if( !mSearchData->mRootTab ) @@ -3656,4 +3684,5 @@ void LLFloaterPreference::collectSearchableItems()  		collectChildren( this, ll::prefs::PanelDataPtr(), pRootTabcontainer );  	} +	mSearchDataDirty = false;  } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 1268935712..e9e19e9acb 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -108,6 +108,7 @@ public:  	void getControlNames(std::vector<std::string>& names);  	// updates click/double-click action controls depending on values from settings.xml  	void updateClickActionViews(); +    void updateSearchableItems();  protected:	  	void		onBtnOK(const LLSD& userdata); @@ -220,6 +221,7 @@ private:  	LLSearchEditor *mFilterEdit;  	std::unique_ptr< ll::prefs::SearchData > mSearchData; +	bool mSearchDataDirty;  	void onUpdateFilterTerm( bool force = false );  	void collectSearchableItems(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index ec1909d02a..17e55b5f2c 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -470,6 +470,29 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)  		region_flags = flags;  	} +	if (msg->has(_PREHASH_RegionInfo5)) +	{ +		F32 chat_whisper_range; +		F32 chat_normal_range; +		F32 chat_shout_range; +		F32 chat_whisper_offset; +		F32 chat_normal_offset; +		F32 chat_shout_offset; +		U32 chat_flags; + +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset); +		msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags); + +		LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range +			<< " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset +			<< " chat flags: " << chat_flags << LL_ENDL; +	} +  	// GENERAL PANEL  	panel = tab->getChild<LLPanel>("General");  	panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name)); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8b61e6c61a..86ee7e7a82 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5458,11 +5458,20 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		getClipboardEntries(true, items, disabled_items, flags);  		items.push_back(std::string("Texture Separator")); -		items.push_back(std::string("Save As")); -		if (!canSaveTexture()) -		{ -			disabled_items.push_back(std::string("Save As")); -		} +		 +        if ((flags & ITEM_IN_MULTI_SELECTION) != 0) +        { +            items.push_back(std::string("Save Selected As")); +        } +        else +        { +            items.push_back(std::string("Save As")); +            if (!canSaveTexture()) +            { +                disabled_items.push_back(std::string("Save As")); +            } +        } +  	}  	addLinkReplaceMenuOption(items, disabled_items);  	hide_context_entries(menu, items, disabled_items);	 @@ -5480,6 +5489,23 @@ void LLTextureBridge::performAction(LLInventoryModel* model, std::string action)  			preview_texture->saveAs();  		}  	} +    else if ("save_selected_as" == action) +    { +        openItem(); +        if (canSaveTexture()) +        { +            LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUID); +            if (preview_texture) +            { +                preview_texture->saveMultipleToFile(mFileName); +            } +        } +        else +        { +            LL_WARNS() << "You don't have permission to save " << getName() << " to disk." << LL_ENDL; +        } + +    }  	else LLItemBridge::performAction(model, action);  } @@ -6809,7 +6835,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  						disabled_items.push_back(std::string("Wearable Edit"));  					} -					if (LLWearableType::getAllowMultiwear(mWearableType)) +					if (LLWearableType::getInstance()->getAllowMultiwear(mWearableType))  					{  						items.push_back(std::string("Wearable Add"));  						if (!gAgentWearables.canAddWearable(mWearableType)) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 9af8664388..7db9c640f2 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -403,6 +403,9 @@ public:  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual void performAction(LLInventoryModel* model, std::string action);  	bool canSaveTexture(void); +    void setFileName(std::string& file_name) { mFileName = file_name; } +protected: +    std::string mFileName;  };  class LLSoundBridge : public LLItemBridge diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f2e06d19f3..9cc67766ca 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -47,6 +47,7 @@  #include "llappviewer.h"  #include "llavataractions.h"  #include "llclipboard.h" +#include "lldirpicker.h"  #include "lldonotdisturbnotificationstorage.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h" @@ -2517,6 +2518,10 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root      {          LLAppearanceMgr::instance().removeItemsFromAvatar(ids);      } +    else if ("save_selected_as" == action) +    { +        (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile(); +    }      else      {          std::set<LLFolderViewItem*>::iterator set_iter; @@ -2544,6 +2549,41 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root  	}  } +void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model) +{ +    gSavedSettings.setString("TextureSaveLocation", filenames[0]); +  +    LLMultiPreview* multi_previewp = new LLMultiPreview(); +    gFloaterView->addChild(multi_previewp); + +    LLFloater::setFloaterHost(multi_previewp); + +    std::map<std::string, S32> tex_names_map; +    std::set<LLFolderViewItem*>::iterator set_iter; +    +    for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) +    { +        LLFolderViewItem* folder_item = *set_iter; +        if(!folder_item) continue; +        LLTextureBridge* bridge = (LLTextureBridge*)folder_item->getViewModelItem(); +        if(!bridge) continue; + +        std::string tex_name = bridge->getName(); +        if(!tex_names_map.insert(std::pair<std::string, S32>(tex_name, 0)).second)  +        {  +            tex_names_map[tex_name]++; +            bridge->setFileName(tex_name + llformat("_%.3d", tex_names_map[tex_name]));             +        } +        bridge->performAction(model, "save_selected_as"); +    } + +    LLFloater::setFloaterHost(NULL); +    if (multi_previewp) +    { +        multi_previewp->openFloater(LLSD()); +    } +} +  void LLInventoryAction::removeItemFromDND(LLFolderView* root)  {      if(gAgent.isDoNotDisturb()) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 37c3c47336..2cb2b1e877 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -468,6 +468,8 @@ struct LLInventoryAction  	static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);  	static void removeItemFromDND(LLFolderView* root); +    static void saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model); +  	static const int sConfirmOnDeleteItemsNumber;  private: diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 81c001b8bd..44e493fdf4 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -196,7 +196,7 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx)  LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag)  {  	const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag); -	return LLWearableType::getIconName(wearable_type); +	return LLWearableType::getInstance()->getIconName(wearable_type);  }  LLInventoryType::EIconName LLInventoryIcon::assignSettingsIcon(U32 misc_flag) diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp index 57a6ecb604..c7a0665630 100644 --- a/indra/newview/llmachineid.cpp +++ b/indra/newview/llmachineid.cpp @@ -33,237 +33,445 @@  using namespace std;  #include <comdef.h>  #include <Wbemidl.h> +#elif LL_DARWIN +#include <CoreFoundation/CoreFoundation.h> +#include <IOKit/IOKitLib.h>  #endif  unsigned char static_unique_id[] =  {0,0,0,0,0,0}; +unsigned char static_legacy_id[] =  {0,0,0,0,0,0};  bool static has_static_unique_id = false; +bool static has_static_legacy_id = false;  #if	LL_WINDOWS -class LLComInitialize +class LLWMIMethods  { -    HRESULT mHR;  public: -    LLComInitialize() +    LLWMIMethods() +    :   pLoc(NULL), +        pSvc(NULL)      { -        mHR = CoInitializeEx(0, COINIT_MULTITHREADED); -        if (FAILED(mHR)) -            LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hex << mHR << LL_ENDL; +        initCOMObjects();      } -    ~LLComInitialize() +    ~LLWMIMethods()      { -        if (SUCCEEDED(mHR)) -            CoUninitialize(); +        if (isInitialized()) +        { +            cleanCOMObjects(); +        }      } -}; -#endif //LL_WINDOWS +    bool isInitialized() { return SUCCEEDED(mHR); } +    bool getWindowsProductNumber(unsigned char *unique_id, size_t len); +    bool getDiskDriveSerialNumber(unsigned char *unique_id, size_t len); +    bool getProcessorSerialNumber(unsigned char *unique_id, size_t len); +    bool getMotherboardSerialNumber(unsigned char *unique_id, size_t len); +    bool getComputerSystemProductUUID(unsigned char *unique_id, size_t len); +    bool getGenericSerialNumber(const BSTR &select, const LPCWSTR &variable, unsigned char *unique_id, size_t len, bool validate_as_uuid = false); -// get an unique machine id. -// NOT THREAD SAFE - do before setting up threads. -// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot,  Go figure?? +private: +    void initCOMObjects(); +    void cleanCOMObjects(); -S32 LLMachineID::init() +    HRESULT mHR; +    IWbemLocator *pLoc; +    IWbemServices *pSvc; +}; + + +void LLWMIMethods::initCOMObjects()  { -    size_t len = sizeof(static_unique_id); -    memset(static_unique_id, 0, len); -    S32 ret_code = 0; -#if	LL_WINDOWS  # pragma comment(lib, "wbemuuid.lib") +    // Step 1: -------------------------------------------------- +    // Initialize COM. ------------------------------------------ -        // algorithm to detect BIOS serial number found at: -        // http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx -        // we can't use the MAC address since on Windows 7, the first returned MAC address changes with every reboot. +    mHR = CoInitializeEx(0, COINIT_MULTITHREADED); +    if (FAILED(mHR)) +    { +        LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hex << mHR << LL_ENDL; +        return; +    } +    // Step 2: -------------------------------------------------- +    // Set general COM security levels -------------------------- +    // Note: If you are using Windows 2000, you need to specify - +    // the default authentication credentials for a user by using +    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- +    // parameter of CoInitializeSecurity ------------------------ + +    mHR = CoInitializeSecurity( +        NULL, +        -1,                          // COM authentication +        NULL,                        // Authentication services +        NULL,                        // Reserved +        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication  +        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation   +        NULL,                        // Authentication info +        EOAC_NONE,                   // Additional capabilities  +        NULL                         // Reserved +    ); + +    if (FAILED(mHR)) +    { +        LL_WARNS("AppInit") << "Failed to initialize security. Error code = 0x" << hex << mHR << LL_ENDL; +        CoUninitialize(); +        return;               // Program has failed. +    } -        HRESULT hres; +    // Step 3: --------------------------------------------------- +    // Obtain the initial locator to WMI ------------------------- -        // Step 1: -------------------------------------------------- -        // Initialize COM. ------------------------------------------ +    mHR = CoCreateInstance( +        CLSID_WbemLocator, +        0, +        CLSCTX_INPROC_SERVER, +        IID_IWbemLocator, (LPVOID *)&pLoc); -        LLComInitialize comInit; +    if (FAILED(mHR)) +    { +        LL_WARNS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << mHR << LL_ENDL; +        CoUninitialize(); +        return;               // Program has failed. +    } -        // Step 2: -------------------------------------------------- -        // Set general COM security levels -------------------------- -        // Note: If you are using Windows 2000, you need to specify - -        // the default authentication credentials for a user by using -        // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- -        // parameter of CoInitializeSecurity ------------------------ +    // Step 4: ----------------------------------------------------- +    // Connect to WMI through the IWbemLocator::ConnectServer method + +    // Connect to the root\cimv2 namespace with +    // the current user and obtain pointer pSvc +    // to make IWbemServices calls. +    mHR = pLoc->ConnectServer( +        _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace +        NULL,                    // User name. NULL = current user +        NULL,                    // User password. NULL = current +        0,                       // Locale. NULL indicates current +        NULL,                    // Security flags. +        0,                       // Authority (e.g. Kerberos) +        0,                       // Context object  +        &pSvc                    // pointer to IWbemServices proxy +    ); + +    if (FAILED(mHR)) +    { +        LL_WARNS("AppInit") << "Could not connect. Error code = 0x" << hex << mHR << LL_ENDL; +        pLoc->Release(); +        CoUninitialize(); +        return;               // Program has failed. +    } -        hres =  CoInitializeSecurity( -            NULL,  -            -1,                          // COM authentication -            NULL,                        // Authentication services -            NULL,                        // Reserved -            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication  -            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation   -            NULL,                        // Authentication info -            EOAC_NONE,                   // Additional capabilities  -            NULL                         // Reserved -            ); +    LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL; -                           -        if (FAILED(hres)) -        { -            LL_WARNS("AppInit") << "Failed to initialize security. Error code = 0x"  << hex << hres << LL_ENDL; -            return 1;                    // Program has failed. -        } -         -        // Step 3: --------------------------------------------------- -        // Obtain the initial locator to WMI ------------------------- - -        IWbemLocator *pLoc = NULL; - -        hres = CoCreateInstance( -            CLSID_WbemLocator,              -            0,  -            CLSCTX_INPROC_SERVER,  -            IID_IWbemLocator, (LPVOID *) &pLoc); -      -        if (FAILED(hres)) -        { -            LL_WARNS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << LL_ENDL; -            return 1;                 // Program has failed. -        } +    // Step 5: -------------------------------------------------- +    // Set security levels on the proxy ------------------------- -        // Step 4: ----------------------------------------------------- -        // Connect to WMI through the IWbemLocator::ConnectServer method - -        IWbemServices *pSvc = NULL; -    	 -        // Connect to the root\cimv2 namespace with -        // the current user and obtain pointer pSvc -        // to make IWbemServices calls. -        hres = pLoc->ConnectServer( -             _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace -             NULL,                    // User name. NULL = current user -             NULL,                    // User password. NULL = current -             0,                       // Locale. NULL indicates current -             NULL,                    // Security flags. -             0,                       // Authority (e.g. Kerberos) -             0,                       // Context object  -             &pSvc                    // pointer to IWbemServices proxy -             ); -         -        if (FAILED(hres)) -        { -            LL_WARNS("AppInit") << "Could not connect. Error code = 0x"  << hex << hres << LL_ENDL; -            pLoc->Release();      -            return 1;                // Program has failed. -        } +    mHR = CoSetProxyBlanket( +        pSvc,                        // Indicates the proxy to set +        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx +        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx +        NULL,                        // Server principal name  +        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx  +        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx +        NULL,                        // client identity +        EOAC_NONE                    // proxy capabilities  +    ); + +    if (FAILED(mHR)) +    { +        LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hex << mHR << LL_ENDL; +        cleanCOMObjects(); +        return;               // Program has failed. +    } +} + + +void LLWMIMethods::cleanCOMObjects() +{ +    pSvc->Release(); +    pLoc->Release(); +    CoUninitialize(); +} + +bool LLWMIMethods::getWindowsProductNumber(unsigned char *unique_id, size_t len) +{ +    // wmic path Win32_ComputerSystemProduct get UUID +    return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_OperatingSystem"), L"SerialNumber", unique_id, len); +} + +bool LLWMIMethods::getDiskDriveSerialNumber(unsigned char *unique_id, size_t len) +{ +    // wmic path Win32_DiskDrive get DeviceID,SerialNumber +    return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_DiskDrive"), L"SerialNumber", unique_id, len); +} + +bool LLWMIMethods::getProcessorSerialNumber(unsigned char *unique_id, size_t len) +{ +    // wmic path Win32_Processor get DeviceID,ProcessorId +    return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_Processor"), L"ProcessorId", unique_id, len); +} -        LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL; +bool LLWMIMethods::getMotherboardSerialNumber(unsigned char *unique_id, size_t len) +{ +    // wmic path Win32_Processor get DeviceID,ProcessorId +    return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_BaseBoard"), L"SerialNumber", unique_id, len); +} + +bool LLWMIMethods::getComputerSystemProductUUID(unsigned char *unique_id, size_t len) +{ +    // UUID from Win32_ComputerSystemProduct is motherboard's uuid and is identical to csproduct's uuid +    // wmic csproduct get name,identifyingnumber,uuid +    // wmic path Win32_ComputerSystemProduct get UUID +    return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_ComputerSystemProduct"), L"UUID", unique_id, len, true); +} +bool LLWMIMethods::getGenericSerialNumber(const BSTR &select, const LPCWSTR &variable, unsigned char *unique_id, size_t len, bool validate_as_uuid) +{ +    if (!isInitialized()) +    { +        return false; +    } -        // Step 5: -------------------------------------------------- -        // Set security levels on the proxy ------------------------- +    HRESULT hres; -        hres = CoSetProxyBlanket( -           pSvc,                        // Indicates the proxy to set -           RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx -           RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx -           NULL,                        // Server principal name  -           RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx  -           RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx -           NULL,                        // client identity -           EOAC_NONE                    // proxy capabilities  -        ); +    // Step 6: -------------------------------------------------- +    // Use the IWbemServices pointer to make requests of WMI ---- -        if (FAILED(hres)) +    // For example, get the name of the operating system +    IEnumWbemClassObject* pEnumerator = NULL; +    hres = pSvc->ExecQuery( +        bstr_t("WQL"), +        select, +        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, +        NULL, +        &pEnumerator); + +    if (FAILED(hres)) +    { +        LL_WARNS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << hex << hres << LL_ENDL; +        return false;               // Program has failed. +    } + +    // Step 7: ------------------------------------------------- +    // Get the data from the query in step 6 ------------------- + +    IWbemClassObject *pclsObj = NULL; +    ULONG uReturn = 0; +    bool found = false; + +    while (pEnumerator) +    { +        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, +            &pclsObj, &uReturn); + +        if (0 == uReturn)          { -            LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x"   << hex << hres << LL_ENDL; -            pSvc->Release(); -            pLoc->Release();      -            return 1;               // Program has failed. +            break;          } -        // Step 6: -------------------------------------------------- -        // Use the IWbemServices pointer to make requests of WMI ---- - -        // For example, get the name of the operating system -        IEnumWbemClassObject* pEnumerator = NULL; -        hres = pSvc->ExecQuery( -            bstr_t("WQL"),  -            bstr_t("SELECT * FROM Win32_OperatingSystem"), -            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,  -            NULL, -            &pEnumerator); -         -        if (FAILED(hres)) +        VARIANT vtProp; + +        // Get the value of the Name property +        hr = pclsObj->Get(variable, 0, &vtProp, 0, 0); +        if (FAILED(hr))          { -            LL_WARNS("AppInit") << "Query for operating system name failed." << " Error code = 0x"  << hex << hres << LL_ENDL; -            pSvc->Release(); -            pLoc->Release(); -            return 1;               // Program has failed. +            LL_WARNS() << "Failed to get SerialNumber. Error code = 0x" << hex << hres << LL_ENDL; +            pclsObj->Release(); +            pclsObj = NULL; +            continue;          } -        // Step 7: ------------------------------------------------- -        // Get the data from the query in step 6 ------------------- -      -        IWbemClassObject *pclsObj = NULL; -        ULONG uReturn = 0; -        -        while (pEnumerator) +        // use characters in the returned Serial Number to create a byte array of size len +        BSTR serialNumber(vtProp.bstrVal); +        unsigned int serial_size = SysStringLen(serialNumber); +        if (serial_size < 1) // < len?          { -            HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,  -                &pclsObj, &uReturn); +            VariantClear(&vtProp); +            pclsObj->Release(); +            pclsObj = NULL; +            continue; +        } -            if(0 == uReturn) +        if (validate_as_uuid) +        { +            std::wstring ws(serialNumber, serial_size); +            std::string str(ws.begin(), ws.end()); + +            if (!LLUUID::validate(str))              { -                break; +                VariantClear(&vtProp); +                pclsObj->Release(); +                pclsObj = NULL; +                continue;              } -            VARIANT vtProp; +            static const LLUUID f_uuid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"); +            LLUUID id(str); -            // Get the value of the Name property -            hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); -            if (FAILED(hr)) +            if (id.isNull() || id == f_uuid)              { -                LL_WARNS() << "Failed to get SerialNumber. Error code = 0x" << hex << hres << LL_ENDL; +                // Not unique id +                VariantClear(&vtProp);                  pclsObj->Release();                  pclsObj = NULL;                  continue;              } -            LL_INFOS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL; +        } +        LL_INFOS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL; -            // use characters in the returned Serial Number to create a byte array of size len -            BSTR serialNumber ( vtProp.bstrVal); -            unsigned int serial_size = SysStringLen(serialNumber); -            unsigned int j = 0; +        unsigned int j = 0; -            while (j < serial_size && vtProp.bstrVal[j] != 0) +        while (j < serial_size && vtProp.bstrVal[j] != 0) +        { +            for (unsigned int i = 0; i < len; i++)              { -                for (unsigned int i = 0; i < len; i++) +                if (j >= serial_size || vtProp.bstrVal[j] == 0) +                    break; + +                unique_id[i] = (unsigned int)(unique_id[i] + serialNumber[j]); +                j++; +            } +        } +        VariantClear(&vtProp); + +        pclsObj->Release(); +        pclsObj = NULL; +        found = true; +        break; +    } + +    // Cleanup +    // ======== + +    if (pEnumerator) +        pEnumerator->Release(); + +    return found; +} +#elif LL_DARWIN +bool getSerialNumber(unsigned char *unique_id, size_t len) +{ +    CFStringRef serial_cf_str = NULL; +    io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, +                                                                 IOServiceMatching("IOPlatformExpertDevice")); +    if (platformExpert) +    { +        serial_cf_str = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert, +                                                                     CFSTR(kIOPlatformSerialNumberKey), +                                                                     kCFAllocatorDefault, 0); +        IOObjectRelease(platformExpert); +    } +     +    if (serial_cf_str) +    { +        char buffer[64] = {0}; +        std::string serial_str(""); +        if (CFStringGetCString(serial_cf_str, buffer, 64, kCFStringEncodingUTF8)) +        { +            serial_str = buffer; +        } + +        S32 serial_size = serial_str.size(); +         +        if(serial_str.size() > 0) +        { +            S32 j = 0; +            while (j < serial_size) +            { +                for (S32 i = 0; i < len; i++)                  { -                    if (j >= serial_size || vtProp.bstrVal[j] == 0) +                    if (j >= serial_size)                          break; -                     -                    static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]); + +                    unique_id[i] = (unsigned int)(unique_id[i] + serial_str[j]);                      j++;                  }              } -            VariantClear(&vtProp); +            return true; +        } +    } +    return false; +} +#endif -            pclsObj->Release(); -            pclsObj = NULL; -            break; +// get an unique machine id. +// NOT THREAD SAFE - do before setting up threads. +// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot,  Go figure?? + +S32 LLMachineID::init() +{ +    size_t len = sizeof(static_unique_id); +    memset(static_unique_id, 0, len); +    S32 ret_code = 0; +#if	LL_WINDOWS + +    LLWMIMethods comInit; + +    if (comInit.getWindowsProductNumber(static_legacy_id, len)) +    { +        // Bios id can change on windows update, so it is not the best id to use +        // but since old viewer already use them, we might need this id to decode +        // passwords +        has_static_legacy_id = true; +    } + +    // Try motherboard/bios id, if it is present it is supposed to be sufficiently unique +    if (comInit.getComputerSystemProductUUID(static_unique_id, len)) +    { +        has_static_unique_id = true; +        LL_DEBUGS("AppInit") << "Using product uuid as unique id" << LL_ENDL; +    } + +    // Fallback to legacy +    if (!has_static_unique_id) +    { +        if (has_static_legacy_id) +        { +            memcpy(static_unique_id, &static_legacy_id, len); +            // Since ids are identical, mark legacy as not present +            // to not cause retry's in sechandler +            has_static_legacy_id = false; +            has_static_unique_id = true; +            LL_DEBUGS("AppInit") << "Using legacy serial" << LL_ENDL; +        } +        else +        { +            return 1; // Program has failed.          } +    } -        // Cleanup -        // ======== -         -        if (pSvc) -            pSvc->Release(); -        if (pLoc) -            pLoc->Release(); -        if (pEnumerator) -            pEnumerator->Release(); -        ret_code=0; -#else -        unsigned char * staticPtr = (unsigned char *)(&static_unique_id[0]); +    ret_code=0; +#elif LL_DARWIN +    if (getSerialNumber(static_unique_id, len)) +    { +        has_static_unique_id = true; +        LL_DEBUGS("AppInit") << "Using Serial number as unique id" << LL_ENDL; +    } + +    { +        unsigned char * staticPtr = (unsigned char *)(&static_legacy_id[0]);          ret_code = LLUUID::getNodeID(staticPtr); +        has_static_legacy_id = true; +    } + +    // Fallback to legacy +    if (!has_static_unique_id) +    { +        if (has_static_legacy_id) +        { +            memcpy(static_unique_id, &static_legacy_id, len); +            // Since ids are identical, mark legacy as not present +            // to not cause retry's in sechandler +            has_static_legacy_id = false; +            has_static_unique_id = true; +            LL_DEBUGS("AppInit") << "Using legacy serial" << LL_ENDL; +        } +    } +#else +    unsigned char * staticPtr = (unsigned char *)(&static_legacy_id[0]); +    ret_code = LLUUID::getNodeID(staticPtr); +    has_static_unique_id = true; +    has_static_legacy_id = false;  #endif -        has_static_unique_id = true;          LL_INFOS("AppInit") << "UniqueID: 0x";          // Code between here and LL_ENDL is not executed unless the LL_DEBUGS @@ -292,3 +500,13 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)      }      return 0;  } + +S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len) +{ +    if (has_static_legacy_id) +    { +        memcpy(unique_id, &static_legacy_id, len); +        return 1; +    } +    return 0; +} diff --git a/indra/newview/llmachineid.h b/indra/newview/llmachineid.h index 6ef8c36fdb..ec1e855031 100644 --- a/indra/newview/llmachineid.h +++ b/indra/newview/llmachineid.h @@ -34,6 +34,8 @@ public:  	LLMachineID();  	virtual	~LLMachineID();      static S32 getUniqueID(unsigned char *unique_id, size_t len); +    // fallback id for windows +    static S32 getLegacyID(unsigned char *unique_id, size_t len);      static S32 init();  protected: diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index c3e39429a2..7c942e8b53 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -105,7 +105,10 @@ void LLManipRotate::handleSelect()  {  	// *FIX: put this in mouseDown?  	LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); -	gFloaterTools->setStatusText("rotate"); +    if (gFloaterTools) +    { +        gFloaterTools->setStatusText("rotate"); +    }  	LLManip::handleSelect();  } diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 9a8222d941..e74fd1241b 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -170,7 +170,10 @@ void LLManipScale::handleSelect()  	LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();  	updateSnapGuides(bbox);  	LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); -	gFloaterTools->setStatusText("scale"); +    if (gFloaterTools) +    { +        gFloaterTools->setStatusText("scale"); +    }  	LLManip::handleSelect();  } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 9248c160c6..8736d3b51f 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -287,7 +287,10 @@ LLManipTranslate::~LLManipTranslate()  void LLManipTranslate::handleSelect()  {  	LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); -	gFloaterTools->setStatusText("move"); +    if (gFloaterTools) +    { +        gFloaterTools->setStatusText("move"); +    }  	LLManip::handleSelect();  } diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 958c76f261..bd24c47a4f 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -31,6 +31,7 @@  #include "lluictrl.h"  #include "llframetimer.h" +#include "llnotificationptr.h"  class LLViewBorder;  class LLUICtrlFactory; @@ -145,7 +146,7 @@ public:  		void setTextureSize(S32 width, S32 height); -		void showNotification(boost::shared_ptr<class LLNotification> notify); +		void showNotification(LLNotificationPtr notify);  		void hideNotification();  		void setTrustedContent(bool trusted); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 3e8731dfe6..2c1c1191da 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -881,7 +881,7 @@ void LLMeshRepoThread::run()  		LL_WARNS(LOG_MESH) << "Convex decomposition unable to be loaded.  Expect severe problems." << LL_ENDL;  	} -	while (!LLApp::isQuitting()) +	while (!LLApp::isExiting())  	{  		// *TODO:  Revise sleep/wake strategy and try to move away  		// from polling operations in this thread.  We can sleep @@ -898,7 +898,7 @@ void LLMeshRepoThread::run()  		mSignal->wait(); -		if (LLApp::isQuitting()) +		if (LLApp::isExiting())  		{  			break;  		} @@ -1168,7 +1168,7 @@ void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id)  void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  { -	if (!LLAppViewer::isQuitting()) +	if (!LLAppViewer::isExiting())  	{  		loadMeshLOD(mesh_params, lod);  	} @@ -2654,7 +2654,7 @@ void LLMeshUploadThread::doWholeModelUpload()  			LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;  			mHttpRequest->update(0); -			while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) +			while (! LLApp::isExiting() && ! finished() && ! isDiscarded())  			{  				ms_sleep(sleep_time);  				sleep_time = llmin(250U, sleep_time + sleep_time); @@ -2703,7 +2703,7 @@ void LLMeshUploadThread::requestWholeModelFee()  		U32 sleep_time(10);  		mHttpRequest->update(0); -		while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) +		while (! LLApp::isExiting() && ! finished() && ! isDiscarded())  		{  			ms_sleep(sleep_time);  			sleep_time = llmin(250U, sleep_time + sleep_time); @@ -3149,7 +3149,7 @@ common_exit:  LLMeshHeaderHandler::~LLMeshHeaderHandler()  { -	if (!LLApp::isQuitting()) +	if (!LLApp::isExiting())  	{  		if (! mProcessed)  		{ @@ -3292,7 +3292,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b  LLMeshLODHandler::~LLMeshLODHandler()  { -	if (! LLApp::isQuitting()) +	if (! LLApp::isExiting())  	{  		if (! mProcessed)  		{ @@ -3553,7 +3553,7 @@ void LLMeshRepository::shutdown()  		mUploads[i]->discard() ; //discard the uploading requests.  	} -	mThread->mSignal->signal(); +	mThread->mSignal->broadcast();  	while (!mThread->isStopped())  	{ @@ -4682,7 +4682,8 @@ void LLPhysicsDecomp::shutdown()  	if (mSignal)  	{  		mQuitting = true; -		mSignal->signal(); +		// There is only one wait(), but just in case 'broadcast' +		mSignal->broadcast();  		while (!isStopped())  		{ diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index a6f20a9f27..b06131cf38 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -63,7 +63,7 @@ void LLNotificationManager::init()  	mChannels.push_back(new LLBrowserNotification());  	mChannels.push_back(new LLIMHandler()); -	mChatHandler = boost::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler()); +	mChatHandler = std::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler());  }  //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 52c79cc689..cf987ff4e9 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -35,8 +35,6 @@  #include <map>  #include <string> -#include <boost/shared_ptr.hpp> -  namespace LLNotificationsUI {  class LLToast; @@ -60,7 +58,7 @@ public:  	void onChat(const LLChat& msg, const LLSD &args);  private: -	boost::shared_ptr<class LLFloaterIMNearbyChatHandler> mChatHandler; +	std::shared_ptr<class LLFloaterIMNearbyChatHandler> mChatHandler;  	std::vector<LLNotificationChannelPtr> mChannels;  }; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 272e7ae351..593b27f839 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -893,7 +893,7 @@ void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notifi  void LLOutfitGalleryContextMenu::onCreate(const LLSD& data)  { -    LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); +    LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString());      if (type == LLWearableType::WT_NONE)      {          LL_WARNS() << "Invalid wearable type" << LL_ENDL; @@ -1111,7 +1111,7 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)          }      } -    if (mGalleryCreated && !LLApp::isQuitting()) +    if (mGalleryCreated && !LLApp::isExiting())      {          reArrangeRows();      } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 71ab826e1c..a71432e314 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -1210,7 +1210,7 @@ void LLOutfitListGearMenuBase::onRename()  void LLOutfitListGearMenuBase::onCreate(const LLSD& data)  { -    LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); +    LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString());      if (type == LLWearableType::WT_NONE)      {          LL_WARNS() << "Invalid wearable type" << LL_ENDL; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index c601a6c210..be11a4a9f3 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1276,7 +1276,7 @@ void LLPanelEditWearable::changeCamera(U8 subpart)  {  	// Don't change the camera if this type doesn't have a camera switch.  	// Useful for wearables like physics that don't have an associated physical body part. -	if (LLWearableType::getDisableCameraSwitch(mWearablePtr->getType())) +	if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType()))  	{  		return;  	} diff --git a/indra/newview/llpanelgroupcreate.cpp b/indra/newview/llpanelgroupcreate.cpp index 052212dc27..52be75072c 100644 --- a/indra/newview/llpanelgroupcreate.cpp +++ b/indra/newview/llpanelgroupcreate.cpp @@ -45,6 +45,7 @@  #include "llfloaterreg.h"  #include "llfloater.h"  #include "llgroupmgr.h" +#include "llstatusbar.h" // to re-request balance  #include "lltrans.h"  #include "llnotificationsutil.h"  #include "lluicolortable.h" @@ -117,6 +118,7 @@ void LLPanelGroupCreate::refreshCreatedGroup(const LLUUID& group_id)      params["group_id"] = group_id;      params["open_tab_name"] = "panel_group_info_sidetray";      LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params); +    LLStatusBar::sendMoneyBalanceRequest();  }  void LLPanelGroupCreate::addMembershipRow(const std::string &name) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 5be9ab6095..35582d2967 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -98,7 +98,7 @@ std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type,  {  	const std::string prefix = "MarketplaceURL";  	const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; -	const std::string type_str = LLWearableType::getTypeName(wearable_type); +	const std::string type_str = LLWearableType::getInstance()->getTypeName(wearable_type);  	std::string setting_name = prefix; @@ -174,7 +174,7 @@ public:  private:  	static void onCreate(const LLSD& param)  	{ -		LLWearableType::EType type = LLWearableType::typeNameToType(param.asString()); +		LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(param.asString());  		if (type == LLWearableType::WT_NONE)  		{  			LL_WARNS() << "Invalid wearable type" << LL_ENDL; @@ -189,19 +189,20 @@ private:  	{  		LLView* menu_clothes	= gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE);  		LLView* menu_bp			= gMenuHolder->getChildView("COF.Gear.New_Body_Parts", FALSE); +		LLWearableType * wearable_type_inst = LLWearableType::getInstance();  		for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)  		{  			LLWearableType::EType type = (LLWearableType::EType) i; -			const std::string& type_name = LLWearableType::getTypeName(type); +			const std::string& type_name = wearable_type_inst->getTypeName(type);  			LLMenuItemCallGL::Params p;  			p.name = type_name; -			p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); +			p.label = LLTrans::getString(wearable_type_inst->getTypeDefaultNewName(type));  			p.on_click.function_name = "Wearable.Create";  			p.on_click.parameter = LLSD(type_name); -            LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; +			LLView* parent = wearable_type_inst->getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp;  			LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);  		}  	} diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 1b60610668..59be35fe92 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -232,6 +232,7 @@ void LLPreviewNotecard::loadAsset()  	if (!editor)  		return; +	bool fail = false;  	if(item)  	{ @@ -315,7 +316,31 @@ void LLPreviewNotecard::loadAsset()  			getChildView("Delete")->setEnabled(TRUE);  		}  	} -	else +    else if (mObjectUUID.notNull() && mItemUUID.notNull()) +    { +        LLViewerObject* objectp = gObjectList.findObject(mObjectUUID); +        if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty())) +        { +            // It's a notecard in object's inventory and we failed to get it because inventory is not up to date. +            // Subscribe for callback and retry at inventoryChanged() +            registerVOInventoryListener(objectp, NULL); //removes previous listener + +            if (objectp->isInventoryDirty()) +            { +                objectp->requestInventory(); +            } +        } +        else +        { +            fail = true; +        } +    } +    else +    { +        fail = true; +    } + +	if (fail)  	{  		editor->setText(LLStringUtil::null);  		editor->makePristine(); @@ -600,6 +625,17 @@ void LLPreviewNotecard::syncExternal()  	}  } +/*virtual*/ +void LLPreviewNotecard::inventoryChanged(LLViewerObject* object, +    LLInventoryObject::object_list_t* inventory, +    S32 serial_num, +    void* user_data) +{ +    removeVOInventoryListener(); +    loadAsset(); +} + +  void LLPreviewNotecard::deleteNotecard()  {  	LLNotificationsUtil::add("DeleteNotecard", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleConfirmDeleteDialog,this, _1, _2)); diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index d9c14815c1..3a706b8645 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -31,6 +31,7 @@  #include "llassetstorage.h"  #include "llpreviewscript.h"  #include "lliconctrl.h" +#include "llvoinventorylistener.h"  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLPreviewNotecard @@ -41,7 +42,7 @@  class LLViewerTextEditor;  class LLButton; -class LLPreviewNotecard : public LLPreview +class LLPreviewNotecard : public LLPreview, public LLVOInventoryListener  {  public:  	LLPreviewNotecard(const LLSD& key); @@ -75,6 +76,11 @@ public:  	void syncExternal(); +    void inventoryChanged(LLViewerObject* object, +        LLInventoryObject::object_list_t* inventory, +        S32 serial_num, +        void* user_data) override; +  protected:  	void updateTitleButtons() override; diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 1e91da529c..cd7b93aba7 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -50,6 +50,7 @@  #include "llviewertexture.h"  #include "llviewertexturelist.h"  #include "lluictrlfactory.h" +#include "llviewercontrol.h"  #include "llviewerwindow.h"  #include "lllineeditor.h" @@ -317,6 +318,44 @@ void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenam  		0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList);  } + +void LLPreviewTexture::saveMultipleToFile(const std::string& file_name) +{ +    std::string texture_location(gSavedSettings.getString("TextureSaveLocation"));	 +    std::string texture_name = file_name.empty() ? getItem()->getName() : file_name; +     +    std::string filepath; +    S32 i = 0; +    S32 err = 0; +    std::string extension(".png"); +    do +    { +        filepath = texture_location; +        filepath += gDirUtilp->getDirDelimiter(); +        filepath += texture_name; + +        if (i != 0) +        { +            filepath += llformat("_%.3d", i); +        } + +        filepath += extension; + +        llstat stat_info; +        err = LLFile::stat( filepath, &stat_info ); +        i++; +    } while (-1 != err);  // Search until the file is not found (i.e., stat() gives an error). +     +     +    mSaveFileName = filepath; +    mLoadingFullImage = TRUE; +    getWindow()->incBusyCount(); + +    mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed. +    mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave, +        0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList); +} +  // virtual  void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent)  { diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index ad77d9e118..9b6a843875 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -63,6 +63,7 @@ public:  	void 				openToSave();  	void				saveTextureToFile(const std::vector<std::string>& filenames); +    void                saveMultipleToFile(const std::string& file_name = "");  	static void			onSaveAsBtn(void* data); diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp index 7daaa7ef8e..6caec6ec4a 100644 --- a/indra/newview/llregioninfomodel.cpp +++ b/indra/newview/llregioninfomodel.cpp @@ -173,6 +173,29 @@ void LLRegionInfoModel::update(LLMessageSystem* msg)  		mRegionFlags = flags;  	} +	if (msg->has(_PREHASH_RegionInfo5)) +	{ +		F32 chat_whisper_range; +		F32 chat_normal_range; +		F32 chat_shout_range; +		F32 chat_whisper_offset; +		F32 chat_normal_offset; +		F32 chat_shout_offset; +		U32 chat_flags; + +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset); +		msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset); +		msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags); + +		LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range +			<< " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset +			<< " chat flags: " << chat_flags << LL_ENDL; +	} +  	// the only reasonable way to decide if we actually have any data is to  	// check to see if any of these fields have nonzero sizes  	if (msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductSKU) > 0 || diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 737ef30ada..dcedf5858a 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1302,8 +1302,8 @@ LLSecAPIBasicHandler::~LLSecAPIBasicHandler()  	_writeProtectedData();  } -void LLSecAPIBasicHandler::_readProtectedData() -{	 +void LLSecAPIBasicHandler::_readProtectedData(unsigned char *unique_id, U32 id_len) +{  	// attempt to load the file into our map  	LLPointer<LLSDParser> parser = new LLSDXMLParser();  	llifstream protected_data_stream(mProtectedDataFilename.c_str(),  @@ -1314,9 +1314,7 @@ void LLSecAPIBasicHandler::_readProtectedData()  		U8 buffer[BUFFER_READ_SIZE];  		U8 decrypted_buffer[BUFFER_READ_SIZE];  		int decrypted_length;	 -		unsigned char unique_id[MAC_ADDRESS_BYTES]; -        LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); -		LLXORCipher cipher(unique_id, sizeof(unique_id)); +		LLXORCipher cipher(unique_id, id_len);  		// read in the salt and key  		protected_data_stream.read((char *)salt, STORE_SALT_SIZE); @@ -1367,6 +1365,30 @@ void LLSecAPIBasicHandler::_readProtectedData()  	}  } +void LLSecAPIBasicHandler::_readProtectedData() +{ +    unsigned char unique_id[MAC_ADDRESS_BYTES]; +    try +    { +        // try default id +        LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); +        _readProtectedData(unique_id, sizeof(unique_id)); +    } +    catch(LLProtectedDataException&) +    { +        // try with legacy id, it will return false if it is identical to getUniqueID +        // or if it is not assigned/not in use +        if (LLMachineID::getLegacyID(unique_id, sizeof(unique_id))) +        { +            _readProtectedData(unique_id, sizeof(unique_id)); +        } +        else +        { +            throw; +        } +    } +} +  void LLSecAPIBasicHandler::_writeProtectedData()  {	  	std::ostringstream formatted_data_ostream; diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h index 0bc7f5230f..b21a5d08f9 100644 --- a/indra/newview/llsechandler_basic.h +++ b/indra/newview/llsechandler_basic.h @@ -326,6 +326,7 @@ public:  protected: +	void _readProtectedData(unsigned char *unique_id, U32 id_len);  	void _readProtectedData();  	void _writeProtectedData();  	std::string _legacyLoadPassword(); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 6dfe40c29a..aed9dba7ef 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -210,7 +210,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)  			// when editing its physics.  			if (!gAgentCamera.cameraCustomizeAvatar())  			{ -				LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); +				LLVOAvatarSelf::onCustomizeStart(LLWearableType::getInstance()->getDisableCameraSwitch(wearable_ptr->getType()));  			}  			if (is_wearable_edit_visible)  			{ diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 3fcf193dec..fa2dd60ee0 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -405,7 +405,7 @@ void LLToolMgr::clearTransientTool()  void LLToolMgr::onAppFocusLost()  { -	if (LLApp::isQuitting()) +	if (LLApp::isExiting())  		return;  	if (mSelectedTool) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 322d0bc727..486599af8d 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1094,8 +1094,6 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l  				final_name = LLTrans::getString("TooltipPerson");;  			} -			// *HACK: We may select this object, so pretend it was clicked -			mPick = mHoverPick;  			LLInspector::Params p;  			p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  			p.message(final_name); @@ -1207,8 +1205,6 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l  			if (show_all_object_tips || needs_tip)  			{ -				// We may select this object, so pretend it was clicked -				mPick = mHoverPick;  				LLInspector::Params p;  				p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  				p.message(tooltip_msg); diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 7842d24279..9ac84b0635 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -544,7 +544,7 @@ void LLViewerAssetStorage::assetRequestCoro(      LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts); -    if (LLApp::isQuitting() || !gAssetStorage) +    if (LLApp::isExiting() || !gAssetStorage)      {          // Bail out if result arrives after shutdown has been started.          return; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 76dc9a6790..89c600fc2c 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -143,6 +143,20 @@ static bool handleSetShaderChanged(const LLSD& newvalue)  	gBumpImageList.destroyGL();  	gBumpImageList.restoreGL(); +    if (gPipeline.isInit()) +    { +        // ALM depends onto atmospheric shaders, state might have changed +        bool old_state = LLPipeline::sRenderDeferred; +        LLPipeline::refreshCachedSettings(); +        gPipeline.updateRenderDeferred(); +        if (old_state != LLPipeline::sRenderDeferred) +        { +            gPipeline.releaseGLBuffers(); +            gPipeline.createGLBuffers(); +            gPipeline.resetVertexBuffers(); +        } +    } +  	// else, leave terrain detail as is  	LLViewerShaderMgr::instance()->setShaders();  	return true; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index bbed741a33..55ac817479 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1756,7 +1756,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,  	else  	{  		// Use for all clothing and body parts.  Adding new wearable types requires updating LLWearableDictionary. -		LLWearableType::EType wearable_type = LLWearableType::typeNameToType(type_name); +		LLWearableType::EType wearable_type = LLWearableType::getInstance()->typeNameToType(type_name);  		if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT)  		{  			const LLUUID parent_id = bridge ? bridge->getUUID() : LLUUID::null; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index fbf057603e..a151e0ec53 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8516,7 +8516,7 @@ class LLEditEnableTakeOff : public view_listener_t  	bool handleEvent(const LLSD& userdata)  	{  		std::string clothing = userdata.asString(); -		LLWearableType::EType type = LLWearableType::typeNameToType(clothing); +		LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);  		if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)  			return LLAgentWearables::selfHasWearable(type);  		return false; @@ -8532,7 +8532,7 @@ class LLEditTakeOff : public view_listener_t  			LLAppearanceMgr::instance().removeAllClothesFromAvatar();  		else  		{ -			LLWearableType::EType type = LLWearableType::typeNameToType(clothing); +			LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);  			if (type >= LLWearableType::WT_SHAPE   				&& type < LLWearableType::WT_COUNT  				&& (gAgentWearables.getWearableCount(type) > 0)) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 39c891c9c1..9d85586dae 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -38,6 +38,7 @@  #include "llfollowcamparams.h"  #include "llinventorydefines.h"  #include "lllslconstants.h" +#include "llmaterialtable.h"  #include "llregionhandle.h"  #include "llsd.h"  #include "llsdserialize.h" @@ -3855,6 +3856,11 @@ void process_sound_trigger(LLMessageSystem *msg, void **)  		return;  	} +	if (LLMaterialTable::basic.isCollisionSound(sound_id) && !gSavedSettings.getBOOL("EnableCollisionSounds")) +	{ +		return; +	} +  	gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global);  } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2fde4fe49c..d337f2fb6d 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2807,7 +2807,6 @@ void LLViewerRegion::unpackRegionHandshake()  		mProductName = productName;  	} -  	mCentralBakeVersion = region_protocols & 1; // was (S32)gSavedSettings.getBOOL("UseServerTextureBaking");  	LLVLComposition *compp = getComposition();  	if (compp) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index be5c22e7c3..945b51d819 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -466,8 +466,8 @@ void LLViewerShaderMgr::setShaders()      bool canRenderDeferred       = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");      bool hasWindLightShaders     = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");      S32 shadow_detail            = gSavedSettings.getS32("RenderShadowDetail"); -    bool useRenderDeferred       = canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");      bool doingWindLight          = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders"); +    bool useRenderDeferred       = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");      //using shaders, disable fixed function      LLGLSLShader::sNoFixedFunction = true; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ca01bb46aa..7fbc4d789b 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3518,11 +3518,22 @@ BOOL LLViewerMediaTexture::findFaces()  	for(; iter != obj_list->end(); ++iter)  	{  		LLVOVolume* obj = *iter; -		if(obj->mDrawable.isNull()) -		{ -			ret = FALSE; -			continue; -		} +        if (obj->isDead()) +        { +            // Isn't supposed to happen, objects are supposed to detach +            // themselves on markDead() +            // If this happens, viewer is likely to crash +            llassert(0); +            LL_WARNS() << "Dead object in mMediaImplp's object list" << LL_ENDL; +            ret = FALSE; +            continue; +        } + +        if (obj->mDrawable.isNull() || obj->mDrawable->isDead()) +        { +            ret = FALSE; +            continue; +        }  		S32 face_id = -1;  		S32 num_faces = obj->mDrawable->getNumFaces(); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 9c4dfd1ca2..c80cf27bda 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -562,7 +562,7 @@ void LLViewerWearable::saveNewAsset() const  void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)  {  	LLWearableSaveData* data = (LLWearableSaveData*)userdata; -	const std::string& type_name = LLWearableType::getTypeName(data->mType); +	const std::string& type_name = LLWearableType::getInstance()->getTypeName(data->mType);  	if(0 == status)  	{  		// Success @@ -588,7 +588,7 @@ void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void*  std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w)  { -	s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; +	s << "wearable " << LLWearableType::getInstance()->getTypeName(w.mType) << "\n";  	s << "    Name: " << w.mName << "\n";  	s << "    Desc: " << w.mDescription << "\n";  	//w.mPermissions diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f69b9b3861..1a26308b60 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8952,7 +8952,7 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value)  	S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight());  	apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" display=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\" group=\"%d\"/>\n",  					viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getDisplayName().c_str(), value, u8_value, type_string.c_str(), -					LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str(), +					LLWearableType::getInstance()->getTypeName(LLWearableType::EType(wtype)).c_str(),  					viewer_param->getGroup());  	} @@ -9730,6 +9730,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara  	std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");  	LLAPRFile outfile; +    LLWearableType *wr_inst = LLWearableType::getInstance();  	std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);  	if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB ))  	{ @@ -9746,7 +9747,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara  		{  			for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++)  			{ -				const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); +				const std::string& wearable_name = wr_inst->getTypeName((LLWearableType::EType)type);  				apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() );  				for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 7faca2ee5b..60a69a4ac4 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2036,6 +2036,7 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini  const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const  {  	std::ostringstream outbuf; +    LLWearableType *wr_inst = LLWearableType::getInstance();  	for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter =  			 sAvatarDictionary->getBakedTextures().begin();  		 baked_iter != sAvatarDictionary->getBakedTextures().end(); @@ -2059,7 +2060,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV  				{  					for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)  					{ -						outbuf << "    " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":"; +						outbuf << "    " << wr_inst->getTypeName(wearable_type) << " " << wearable_index << ":";  						const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index);  						if (local_tex_obj)  						{ @@ -2114,6 +2115,7 @@ void LLVOAvatarSelf::dumpAllTextures() const  const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const  {  	std::string text=""; +    LLWearableType *wr_inst = LLWearableType::getInstance();  	text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset)); @@ -2137,7 +2139,7 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe  				const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);  				if (wearable_count > 0)  				{ -					text += LLWearableType::getTypeName(wearable_type) + ":"; +					text += wr_inst->getTypeName(wearable_type) + ":";  					for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)  					{  						const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index); @@ -2844,9 +2846,10 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)  	apr_file_printf( file, "\n<wearable_info>\n" );  	LLWearableData *wd = getWearableData(); +    LLWearableType *wr_inst = LLWearableType::getInstance();  	for (S32 type = 0; type < LLWearableType::WT_COUNT; type++)  	{ -		const std::string& type_name = LLWearableType::getTypeName((LLWearableType::EType)type); +		const std::string& type_name = wr_inst->getTypeName((LLWearableType::EType)type);  		for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++)  		{  			LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 7d8aa6fbbd..0c72cf35da 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1341,6 +1341,11 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait)                  result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult); +                if (sShuttingDown) +                { +                    break; +                } +                  LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;                  // Don't get confused by prior queued events -- note that it's                  // very important that mVivoxPump is an LLEventMailDrop, which @@ -1774,7 +1779,7 @@ bool LLVivoxVoiceClient::waitForChannel()          if (sShuttingDown)          { -            logoutOfVivox(true); +            logoutOfVivox(false);              return false;          } @@ -1866,9 +1871,9 @@ bool LLVivoxVoiceClient::waitForChannel()          mIsProcessingChannels = false; -        logoutOfVivox(true); +        logoutOfVivox(!sShuttingDown /*bool wait*/); -        if (mRelogRequested) +        if (mRelogRequested && !sShuttingDown)          {              LL_DEBUGS("Voice") << "Relog Requested, restarting provisioning" << LL_ENDL;              if (!provisionVoiceAccount()) @@ -4686,6 +4691,12 @@ bool LLVivoxVoiceClient::switchChannel(  			// The old session may now need to be deleted.  			reapSession(oldSession); +            // If voice was on, turn it off +            if (LLVoiceClient::getInstance()->getUserPTTState()) +            { +                LLVoiceClient::getInstance()->setUserPTTState(false); +            } +  			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);  		}  		else diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 9acc0f8d2f..bf4db81475 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -820,7 +820,7 @@ void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, LLWearableTyp  	setMenuItemVisible(menup, "wearable_attach_to", false);  	setMenuItemVisible(menup, "wearable_attach_to_hud", false); -	std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); +	std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));  	LLMenuItemGL* menu_item = menup->getChild<LLMenuItemGL>("create_new");  	menu_item->setLabel(new_label); @@ -1005,7 +1005,7 @@ void LLWearableItemsList::ContextMenu::updateItemsLabels(LLContextMenu* menu)  	if (!item || !item->isWearableType()) return;  	LLWearableType::EType w_type = item->getWearableType(); -	std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); +	std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));  	LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");  	menu_item->setLabel(new_label); diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index b61fbbd073..00f8bace70 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -241,7 +241,7 @@ LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type,  	LLViewerWearable *wearable = generateNewWearable();  	wearable->setType( type, avatarp ); -	std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) ); +	std::string name = LLWearableType::getInstance()->getTypeLabel(wearable->getType());  	wearable->setName( name );  	LLPermissions perm; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index a1a1db35d6..fb3fc55a94 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1194,6 +1194,11 @@ public:  	virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const  	{ +        if (LLApp::isExiting()) +        { +            return; +        } +  		if (!input["body"].has("agent-id") ||  			!input["body"].has("sim-ip-and-port") ||  			!input["body"].has("seed-capability")) diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index eda9739976..0f790bf26a 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -807,6 +807,14 @@           function="Inventory.DoToSelected"           parameter="save_as" />      </menu_item_call> +  <menu_item_call + label="Save Selected As" + layout="topleft" + name="Save Selected As"> +    <menu_item_call.on_click +     function="Inventory.DoToSelected" +     parameter="save_selected_as" /> +  </menu_item_call>      <menu_item_separator       layout="topleft"        name="Wearable And Object Separator"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index 8794e3bf95..864223e616 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -259,6 +259,15 @@      <combo_box.commit_callback       function="Pref.ClickActionChange"/>    </combo_box> +  <check_box +   control_name="EnableCollisionSounds" +   height="20" +   label="Play sound on collisions" +   layout="topleft" +   left="83" +   name="sound_on_collisions" +   top_pad="10" +   width="200" />    <button     height="23"     label="Other Devices" diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index f9abc8b25d..8d1956957c 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -308,6 +308,10 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)  	memcpy(unique_id, gMACAddress, len);  	return 1;  } +S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len) +{ +    return 0; +}  //-----------------------------------------------------------------------------  // misc  std::string xml_escape_string(const std::string& in) diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index e5d226a2a4..02185316b2 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -121,6 +121,10 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)  	memcpy(unique_id, gMACAddress, len);  	return 1;  } +S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len) +{ +    return 0; +}  S32 LLMachineID::init() { return 1; } diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index 267224a79b..0cbe0b0d17 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -498,7 +498,7 @@ bool LLCrashLoggerWindows::frame()  		MSG msg;  		memset(&msg, 0, sizeof(msg)); -		while (!LLApp::isQuitting() && GetMessage(&msg, NULL, 0, 0)) +		while (!LLApp::isExiting() && GetMessage(&msg, NULL, 0, 0))  		{  			TranslateMessage(&msg);  			DispatchMessage(&msg); diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 635227ccf3..a3ddc6d336 100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -2999,6 +2999,16 @@ version 2.0  		RegionInfo3		Variable  		{	RegionFlagsExtended	U64			}  	} +	{ +		RegionInfo5     Variable +		{	ChatWhisperRange	F32 		} +		{	ChatNormalRange		F32 		} +		{	ChatShoutRange		F32 		} +		{	ChatWhisperOffset	F32 		} +		{	ChatNormalOffset	F32 		} +		{	ChatShoutOffset		F32 		} +		{	ChatFlags			U32			} +	}  }  // GodUpdateRegionInfo diff --git a/scripts/template_verifier.py b/scripts/template_verifier.py index b44410cdd8..358931b13e 100755 --- a/scripts/template_verifier.py +++ b/scripts/template_verifier.py @@ -229,7 +229,7 @@ http://wiki.secondlife.com/wiki/Template_verifier.py  """)      parser.add_option(          '-u', '--master_url', type='string', dest='master_url', -        default='http://bitbucket.org/lindenlab/master-message-template/raw/tip/message_template.msg', +        default='https://bitbucket.org/lindenlab/master-message-template-git/raw/master/message_template.msg',          help="""The url of the master message template.""")      parser.add_option(          '-c', '--cache_master', action='store_true', dest='cache_master', | 
