From e72c120e9eb1691abdcf0a3c6e650be68a15b6bb Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Wed, 17 May 2017 22:34:50 +0300
Subject: MAINT-6805 Fixed Right-click menus in the right and left panes of the
 Conversations windows are different

---
 indra/newview/llavataractions.cpp                  |  12 +-
 indra/newview/llavataractions.h                    |   5 +
 indra/newview/llchathistory.cpp                    | 264 +++++++++++++++++++--
 indra/newview/llfloaterimcontainer.cpp             |  22 +-
 indra/newview/llfloaterimcontainer.h               |   1 -
 .../skins/default/xui/en/menu_avatar_icon.xml      |  44 +++-
 6 files changed, 306 insertions(+), 42 deletions(-)

diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 219d9da01f..8fe684ad79 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -1005,7 +1005,7 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)
 }
 
 // static
-void LLAvatarActions::toggleMuteVoice(const LLUUID& id)
+void LLAvatarActions::toggleMute(const LLUUID& id, U32 flags)
 {
 	LLAvatarName av_name;
 	LLAvatarNameCache::get(id, &av_name);
@@ -1016,14 +1016,20 @@ void LLAvatarActions::toggleMuteVoice(const LLUUID& id)
 	LLMute mute(id, av_name.getUserName(), LLMute::AGENT);
 	if (!is_muted)
 	{
-		mute_list->add(mute, LLMute::flagVoiceChat);
+		mute_list->add(mute, flags);
 	}
 	else
 	{
-		mute_list->remove(mute, LLMute::flagVoiceChat);
+		mute_list->remove(mute, flags);
 	}
 }
 
+// static
+void LLAvatarActions::toggleMuteVoice(const LLUUID& id)
+{
+	toggleMute(id, LLMute::flagVoiceChat);
+}
+
 // static
 bool LLAvatarActions::canOfferTeleport(const LLUUID& id)
 {
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 256d44d820..b56d5b0fb9 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -130,6 +130,11 @@ public:
 	 */
 	static void toggleBlock(const LLUUID& id);
 
+	/**
+	 * Mute/unmute avatar.
+	 */
+	static void toggleMute(const LLUUID& id, U32 flags);
+
 	/**
 	 * Block/unblock the avatar voice.
 	 */
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 9798ef3529..5748eeec47 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -38,10 +38,14 @@
 #include "llpanel.h"
 #include "lluictrlfactory.h"
 #include "llscrollcontainer.h"
-#include "llavatariconctrl.h"
-#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagent.h"
 #include "llagentdata.h"
 #include "llavataractions.h"
+#include "llavatariconctrl.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llspeakers.h" //for LLIMSpeakerMgr
 #include "lltrans.h"
 #include "llfloaterreg.h"
 #include "llfloatersidepanelcontainer.h"
@@ -49,7 +53,6 @@
 #include "llstylemap.h"
 #include "llslurl.h"
 #include "lllayoutstack.h"
-#include "llagent.h"
 #include "llnotificationsutil.h"
 #include "lltoastnotifypanel.h"
 #include "lltooltip.h"
@@ -61,7 +64,6 @@
 #include "llurlaction.h"
 #include "llviewercontrol.h"
 #include "llviewerobjectlist.h"
-#include "llmutelist.h"
 
 static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
 
@@ -187,6 +189,161 @@ public:
         return false;
     }
 
+	void banGroupMember(const LLUUID& participant_uuid)
+	{
+		LLUUID group_uuid = mSessionID;
+		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid);
+		if (!gdatap)
+		{
+			// Not a group
+			return;
+		}
+
+		gdatap->banMemberById(participant_uuid);
+	}
+
+	bool canBanInGroup()
+	{
+		LLUUID group_uuid = mSessionID;
+		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid);
+		if (!gdatap)
+		{
+			// Not a group
+			return false;
+		}
+
+		if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER)
+			&& gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS))
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	bool canBanGroupMember(const LLUUID& participant_uuid)
+	{
+		LLUUID group_uuid = mSessionID;
+		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid);
+		if (!gdatap)
+		{
+			// Not a group
+			return false;
+		}
+
+		if (gdatap->mPendingBanRequest)
+		{
+			return false;
+		}
+
+		if (gAgentID == getAvatarId())
+		{
+			//Don't ban self
+			return false;
+		}
+
+		if (gdatap->isRoleMemberDataComplete())
+		{
+			if (gdatap->mMembers.size())
+			{
+				LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(participant_uuid);
+				if (mi != gdatap->mMembers.end())
+				{
+					LLGroupMemberData* member_data = (*mi).second;
+					// Is the member an owner?
+					if (member_data && member_data->isInRole(gdatap->mOwnerRole))
+					{
+						return false;
+					}
+
+					if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER)
+						&& gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS))
+					{
+						return true;
+					}
+				}
+			}
+		}
+
+		LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+		if (speaker_mgr)
+		{
+			LLSpeaker * speakerp = speaker_mgr->findSpeaker(participant_uuid).get();
+
+			if (speakerp
+				&& gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER)
+				&& gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS))
+			{
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	bool isGroupModerator()
+	{
+		LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+		if (!speaker_mgr)
+		{
+			LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+			return false;
+		}
+
+		// Is session a group call/chat?
+		if(gAgent.isInGroup(mSessionID))
+		{
+			LLSpeaker * speakerp = speaker_mgr->findSpeaker(gAgentID).get();
+
+			// Is agent a moderator?
+			return speakerp && speakerp->mIsModerator;
+		}
+
+		return false;
+	}
+
+	bool canModerate(const std::string& userdata)
+	{
+		// only group moderators can perform actions related to this "enable callback"
+		if (!isGroupModerator() || gAgentID == getAvatarId())
+		{
+			return false;
+		}
+
+		LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+		if (!speaker_mgr)
+		{
+			return false;
+		}
+
+		LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get();
+		if (!speakerp)
+		{
+			return false;
+		}
+
+		bool voice_channel = speakerp->isInVoiceChannel();
+
+		if ("can_moderate_voice" == userdata)
+		{
+			return voice_channel;
+		}
+		else if ("can_mute" == userdata)
+		{
+			return voice_channel && (speakerp->mStatus != LLSpeaker::STATUS_MUTED);
+		}
+		else if ("can_unmute" == userdata)
+		{
+			return speakerp->mStatus == LLSpeaker::STATUS_MUTED;
+		}
+		else if ("can_allow_text_chat" == userdata)
+		{
+			return true;
+		}
+
+		return false;
+	}
+
 	void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
 	{
 		std::string level = userdata.asString();
@@ -245,11 +402,36 @@ public:
 		}
 		else if(level == "block_unblock")
 		{
-			mute(getAvatarId(), LLMute::flagVoiceChat);
+			LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagVoiceChat);
 		}
 		else if(level == "mute_unmute")
 		{
-			mute(getAvatarId(), LLMute::flagTextChat);
+			LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagTextChat);
+		}
+		else if(level == "toggle_allow_text_chat")
+		{
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			speaker_mgr->toggleAllowTextChat(getAvatarId());
+		}
+		else if(level == "group_mute")
+		{
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if (speaker_mgr)
+			{
+				speaker_mgr->moderateVoiceParticipant(getAvatarId(), false);
+			}
+		}
+		else if(level == "group_unmute")
+		{
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if (speaker_mgr)
+			{
+				speaker_mgr->moderateVoiceParticipant(getAvatarId(), true);
+			}
+		}
+		else if(level == "ban_member")
+		{
+			banGroupMember(getAvatarId());
 		}
 	}
 
@@ -265,24 +447,69 @@ public:
 		{
 			return LLMuteList::getInstance()->isMuted(getAvatarId(), LLMute::flagTextChat);
 		}
+		else if (level == "is_allowed_text_chat")
+		{
+			if (gAgent.isInGroup(mSessionID))
+			{
+				LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+				const LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId());
+
+				if (NULL != speakerp)
+				{
+					return !speakerp->mModeratorMutedText;
+				}
+			}
+			return false;
+		}
 		return false;
 	}
 
-	void mute(const LLUUID& participant_id, U32 flags)
+	bool onAvatarIconContextMenuItemEnabled(const LLSD& userdata)
 	{
-		BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags);
-		LLAvatarName av_name;
-		LLAvatarNameCache::get(participant_id, &av_name);
-		LLMute mute(participant_id, av_name.getUserName(), LLMute::AGENT);
+		std::string level = userdata.asString();
 
-		if (!is_muted)
+		if (level == "can_allow_text_chat" || level == "can_mute" || level == "can_unmute")
 		{
-			LLMuteList::getInstance()->add(mute, flags);
+			return canModerate(userdata);
 		}
-		else
+		else if (level == "can_ban_member")
 		{
-			LLMuteList::getInstance()->remove(mute, flags);
+			return canBanGroupMember(getAvatarId());
 		}
+		return false;
+	}
+
+	bool onAvatarIconContextMenuItemVisible(const LLSD& userdata)
+	{
+		std::string level = userdata.asString();
+
+		if (level == "show_mute")
+		{
+			LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if (speaker_mgr)
+			{
+				LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get();
+				if (speakerp)
+				{
+					return speakerp->isInVoiceChannel() && speakerp->mStatus != LLSpeaker::STATUS_MUTED;
+				}
+			}
+			return false;
+		}
+		else if (level == "show_unmute")
+		{
+			LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if (speaker_mgr)
+			{
+				LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get();
+				if (speakerp)
+				{
+					return speakerp->mStatus == LLSpeaker::STATUS_MUTED;
+				}
+			}
+			return false;
+		}
+		return false;
 	}
 
 	BOOL postBuild()
@@ -292,6 +519,8 @@ public:
 
 		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
 		registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
+		registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
+		registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
 		registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
 		registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
 
@@ -567,9 +796,14 @@ protected:
 		if(menu)
 		{
 			bool is_friend = LLAvatarActions::isFriend(mAvatarID);
+			bool is_group_session = gAgent.isInGroup(mSessionID);
 			
 			menu->setItemEnabled("Add Friend", !is_friend);
 			menu->setItemEnabled("Remove Friend", is_friend);
+			menu->setItemVisible("Moderator Options Separator", is_group_session && isGroupModerator());
+			menu->setItemVisible("Moderator Options", is_group_session && isGroupModerator());
+			menu->setItemVisible("Group Ban Separator", is_group_session && canBanInGroup());
+			menu->setItemVisible("BanMember", is_group_session && canBanInGroup());
 
 			if(gAgentID == mAvatarID)
 			{
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 3522932d03..333765f99f 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -1150,11 +1150,11 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
 		}
 		else if ("block_unblock" == command)
 		{
-			toggleMute(userID, LLMute::flagVoiceChat);
+			LLAvatarActions::toggleMute(userID, LLMute::flagVoiceChat);
 		}
 		else if ("mute_unmute" == command)
 		{
-			toggleMute(userID, LLMute::flagTextChat);
+			LLAvatarActions::toggleMute(userID, LLMute::flagTextChat);
 		}
 		else if ("selected" == command || "mute_all" == command || "unmute_all" == command)
 		{
@@ -2096,24 +2096,6 @@ void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid)
 	}
 }
 
-void LLFloaterIMContainer::toggleMute(const LLUUID& participant_id, U32 flags)
-{
-        BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags);
-
-        LLAvatarName av_name;
-        LLAvatarNameCache::get(participant_id, &av_name);
-        LLMute mute(participant_id, av_name.getUserName(), LLMute::AGENT);
-
-        if (!is_muted)
-        {
-                LLMuteList::getInstance()->add(mute, flags);
-        }
-        else
-        {
-                LLMuteList::getInstance()->remove(mute, flags);
-        }
-}
-
 void LLFloaterIMContainer::openNearbyChat()
 {
 	// If there's only one conversation in the container and that conversation is the nearby chat
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 60cef83d9a..90fc0c2bdd 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -176,7 +176,6 @@ private:
 	void moderateVoiceAllParticipants(bool unmute);
 	void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
 	void toggleAllowTextChat(const LLUUID& participant_uuid);
-	void toggleMute(const LLUUID& participant_id, U32 flags);
 	void banSelectedMember(const LLUUID& participant_uuid);
 	void openNearbyChat();
 	bool isParticipantListExpanded();
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
index 410caa7290..05ab4d35a0 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
  height="101"
  layout="topleft"
  left="100"
@@ -109,5 +109,43 @@
      name="Mute Text">
        <on_click function="AvatarIcon.Action" parameter="mute_unmute" />
        <on_check function="AvatarIcon.Check" parameter="is_muted" />   
-  </menu_item_check>
-</menu>
+    </menu_item_check>
+    <menu_item_separator layout="topleft" name="Moderator Options Separator"/>
+    <context_menu
+     label="Moderator Options"
+     layout="topleft"
+     name="Moderator Options">
+      <menu_item_check
+       label="Allow text chat"
+       layout="topleft"
+       name="AllowTextChat">
+        <on_check function="AvatarIcon.Check" parameter="is_allowed_text_chat" />
+        <on_click function="AvatarIcon.Action" parameter="toggle_allow_text_chat" />
+        <on_enable function="AvatarIcon.Enable" parameter="can_allow_text_chat" />
+      </menu_item_check>
+      <menu_item_call
+       label="Mute this participant"
+       layout="topleft"
+       name="ModerateVoiceMuteSelected">
+        <on_click function="AvatarIcon.Action" parameter="group_mute" />
+        <on_enable function="AvatarIcon.Enable" parameter="can_mute" />
+        <on_visible function="AvatarIcon.Visible" parameter="show_mute" />
+      </menu_item_call>
+      <menu_item_call
+       label="Unmute this participant"
+       layout="topleft"
+       name="ModerateVoiceUnMuteSelected">
+        <on_click function="AvatarIcon.Action" parameter="group_unmute" />
+        <on_enable function="AvatarIcon.Enable" parameter="can_unmute" />
+        <on_visible function="AvatarIcon.Visible" parameter="show_unmute" />
+      </menu_item_call>
+    </context_menu>
+    <menu_item_separator layout="topleft" name="Group Ban Separator"/>
+    <menu_item_call
+     label="Ban member"
+     layout="topleft"
+     name="BanMember">
+      <on_click function="AvatarIcon.Action" parameter="ban_member" />
+      <on_enable function="AvatarIcon.Enable" parameter="can_ban_member" />
+    </menu_item_call>
+</toggleable_menu>
-- 
cgit v1.2.3


From c7d7728e4a4caadac1875856d77b752bc36a2f56 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 19 May 2017 17:46:08 +0300
Subject: MAINT-7417 FIXED Confirmation is not shown when removing your own
 object inworld

---
 indra/newview/llviewermessage.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 507087d1ae..2dc219a769 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1222,6 +1222,11 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
 		const LLUUID& obj_id = (*obj_iter);
 		if(!highlight_offered_object(obj_id))
 		{
+			const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(obj_id);
+			if (parent && (parent->getPreferredType() == LLFolderType::FT_TRASH))
+			{
+				gInventory.checkTrashOverflow();
+			}
 			continue;
 		}
 
-- 
cgit v1.2.3


From ed249c13af3509645089b280d3a594c29c216f68 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 19 May 2017 17:50:17 +0300
Subject: MAINT-7383 Show correct number of items including folder descendants

---
 indra/newview/llinventorymodel.h   |  1 -
 indra/newview/llinventorypanel.cpp | 11 ++++++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index c558c0803b..da78a057b5 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -265,7 +265,6 @@ public:
 	// Follow parent chain to the top.
 	bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
 
-private:
 	U32 getDescendentsCountRecursive(const LLUUID& id, U32 max_item_limit);
 	
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 4b117941a0..5a7881fe49 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1217,7 +1217,16 @@ void LLInventoryPanel::purgeSelectedItems()
     const std::set<LLFolderViewItem*> inventory_selected = mFolderRoot.get()->getSelectionList();
     if (inventory_selected.empty()) return;
     LLSD args;
-    args["COUNT"] = (S32)inventory_selected.size();
+    S32 count = inventory_selected.size();
+    static const U32 trash_max_capacity = gSavedSettings.getU32("InventoryTrashMaxCapacity");
+    for (std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(), end_it = inventory_selected.end();
+        it != end_it;
+        ++it)
+    {
+        LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();
+        count += gInventory.getDescendentsCountRecursive(item_id, trash_max_capacity);
+    }
+    args["COUNT"] = count;
     LLNotificationsUtil::add("PurgeSelectedItems", args, LLSD(), boost::bind(&LLInventoryPanel::callbackPurgeSelectedItems, this, _1, _2));
 }
 
-- 
cgit v1.2.3


From c7dde30435c578b8fd4606135193e3ec8d31bd76 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Fri, 19 May 2017 18:47:20 +0300
Subject: MAINT-7424 Fixed number of items in the Trash not calculating
 correctly

---
 indra/newview/llinventorymodel.cpp | 38 ++++++++++++++++++--------------------
 indra/newview/llinventorymodel.h   |  2 --
 indra/newview/llinventorypanel.cpp |  5 ++++-
 3 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index e5fd126d53..7ee41140f0 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -799,22 +799,6 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 	}
 }
 
-U32 LLInventoryModel::getDescendentsCountRecursive(const LLUUID& id, U32 max_item_limit)
-{
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
-	gInventory.collectDescendents(id, cats, items, LLInventoryModel::INCLUDE_TRASH);
-
-	U32 items_found = items.size() + cats.size();
-
-	for (U32 i = 0; i < cats.size() && items_found <= max_item_limit; ++i)
-	{
-		items_found += getDescendentsCountRecursive(cats[i]->getUUID(), max_item_limit - items_found);
-	}
-
-	return items_found;
-}
-
 void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
 {
 	const LLInventoryObject *obj = getObject(object_id);
@@ -3321,9 +3305,12 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT
 		LLSD args;
 		if(LLFolderType::FT_TRASH == preferred_type)
 		{
-			static const U32 trash_max_capacity = gSavedSettings.getU32("InventoryTrashMaxCapacity");
+			LLInventoryModel::cat_array_t cats;
+			LLInventoryModel::item_array_t items;
 			const LLUUID trash_id = findCategoryUUIDForType(preferred_type);
-			args["COUNT"] = (S32)getDescendentsCountRecursive(trash_id, trash_max_capacity);
+			gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH); //All descendants
+			S32 item_count = items.size() + cats.size();
+			args["COUNT"] = item_count;
 		}
 		LLNotificationsUtil::add(notification, args, LLSD(),
 										boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type));
@@ -3433,9 +3420,20 @@ bool callback_preview_trash_folder(const LLSD& notification, const LLSD& respons
 
 void  LLInventoryModel::checkTrashOverflow()
 {
-	static const U32 trash_max_capacity = gSavedSettings.getU32("InventoryTrashMaxCapacity");
+	static LLCachedControl<U32> trash_max_capacity(gSavedSettings, "InventoryTrashMaxCapacity");
+
+	// Collect all descendants including those in subfolders.
+	//
+	// Note: Do we really need content of subfolders?
+	// This was made to prevent download of trash folder timeouting
+	// viewer and sub-folders are supposed to download independently.
+	LLInventoryModel::cat_array_t cats;
+	LLInventoryModel::item_array_t items;
 	const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
-	if (getDescendentsCountRecursive(trash_id, trash_max_capacity) >= trash_max_capacity)
+	gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
+	S32 item_count = items.size() + cats.size();
+
+	if (item_count >= trash_max_capacity)
 	{
 		if (LLFloaterPreviewTrash::isVisible())
 		{
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index da78a057b5..01e0ed7e9b 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -265,8 +265,6 @@ public:
 	// Follow parent chain to the top.
 	bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
 
-	U32 getDescendentsCountRecursive(const LLUUID& id, U32 max_item_limit);
-	
 	//--------------------------------------------------------------------
 	// Find
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 5a7881fe49..ba2dce1f98 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1224,7 +1224,10 @@ void LLInventoryPanel::purgeSelectedItems()
         ++it)
     {
         LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();
-        count += gInventory.getDescendentsCountRecursive(item_id, trash_max_capacity);
+        LLInventoryModel::cat_array_t cats;
+        LLInventoryModel::item_array_t items;
+        gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
+        count += items.size() + cats.size();
     }
     args["COUNT"] = count;
     LLNotificationsUtil::add("PurgeSelectedItems", args, LLSD(), boost::bind(&LLInventoryPanel::callbackPurgeSelectedItems, this, _1, _2));
-- 
cgit v1.2.3


From c9f9e93889ae7400f242db6cc3b01469532c1def Mon Sep 17 00:00:00 2001
From: username = daianakproductengine <daianakproductengine@lindenlab.com>
Date: Fri, 19 May 2017 20:28:59 +0300
Subject: MAINT-2060 Fixed Double Freeze when clicking on Help>About Second
 Life

---
 indra/llwindow/lldxhardware.cpp | 155 ++++++++++++++++++++++++++++++++++++++++
 indra/llwindow/lldxhardware.h   |   2 +
 indra/newview/llappviewer.cpp   |  15 +++-
 3 files changed, 169 insertions(+), 3 deletions(-)

diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index e7afef63f8..d4790f9f29 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -35,6 +35,7 @@
 #undef INITGUID
 
 #include <wbemidl.h>
+#include <comdef.h>
 
 #include <boost/tokenizer.hpp>
 
@@ -206,6 +207,160 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
         return E_FAIL;
 }
 
+//Getting the version of graphics controller driver via WMI
+std::string LLDXHardware::getDriverVersionWMI()
+{
+	std::string mDriverVersion;
+	HRESULT hrCoInitialize = S_OK;
+	HRESULT hres;
+	hrCoInitialize = CoInitialize(0);
+	IWbemLocator *pLoc = NULL;
+
+	hres = CoCreateInstance(
+		CLSID_WbemLocator,
+		0,
+		CLSCTX_INPROC_SERVER,
+		IID_IWbemLocator, (LPVOID *)&pLoc);
+	
+	if (FAILED(hres))
+	{
+		LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hres << LL_ENDL;
+		return std::string();                  // Program has failed.
+	}
+
+	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" << hres << LL_ENDL;
+		pLoc->Release();
+		CoUninitialize();
+		return std::string();                // Program has failed.
+	}
+
+	LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL;
+
+	// Set security levels on the proxy -------------------------
+	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 
+		);
+
+	if (FAILED(hres))
+	{
+		LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hres << LL_ENDL;
+		pSvc->Release();
+		pLoc->Release();
+		CoUninitialize();
+		return std::string();               // Program has failed.
+	}
+	IEnumWbemClassObject* pEnumerator = NULL;
+
+	// Get the data from the query
+	ULONG uReturn = 0;
+	hres = pSvc->ExecQuery( 
+		bstr_t("WQL"),
+		bstr_t("SELECT * FROM Win32_VideoController"), //Consider using Availability to filter out disabled controllers
+		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" << hres << LL_ENDL;
+		pSvc->Release();
+		pLoc->Release();
+		CoUninitialize();
+		return std::string();               // Program has failed.
+	}
+
+	while (pEnumerator)
+	{
+		IWbemClassObject *pclsObj = NULL;
+		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
+			&pclsObj, &uReturn);
+
+		if (0 == uReturn)
+		{
+			break;               // If quantity less then 1.
+		}
+
+		VARIANT vtProp;
+
+		// Get the value of the Name property
+		hr = pclsObj->Get(L"DriverVersion", 0, &vtProp, 0, 0);
+
+		if (FAILED(hr))
+		{
+			LL_WARNS("AppInit") << "Query for name property failed." << " Error code = 0x" << hr << LL_ENDL;
+			pSvc->Release();
+			pLoc->Release();
+			CoUninitialize();
+			return std::string();               // Program has failed.
+		}
+
+		// use characters in the returned driver version
+		BSTR driverVersion(vtProp.bstrVal);
+
+		//convert BSTR to std::string
+		std::wstring ws(driverVersion, SysStringLen(driverVersion));
+		std::string str(ws.begin(), ws.end());
+		LL_INFOS("AppInit") << " DriverVersion : " << str << LL_ENDL;
+
+		if (mDriverVersion.empty())
+		{
+			mDriverVersion = str;
+		}
+		else if (mDriverVersion != str)
+		{
+			LL_WARNS("DriverVersion") << "Different versions of drivers. Version of second driver : " << str << LL_ENDL;
+		}
+
+		VariantClear(&vtProp);
+		pclsObj->Release();
+	}
+
+	// Cleanup
+	// ========
+	if (pSvc)
+	{
+		pSvc->Release();
+	}
+	if (pLoc)
+	{
+		pLoc->Release();
+	}
+	if (pEnumerator)
+	{
+		pEnumerator->Release();
+	}
+	if (SUCCEEDED(hrCoInitialize))
+	{
+		CoUninitialize();
+	}
+	return mDriverVersion;
+}
+
 void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize)
 {
 	HRESULT hr;
diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h
index 61a32bf0fb..cf33db8b37 100644
--- a/indra/llwindow/lldxhardware.h
+++ b/indra/llwindow/lldxhardware.h
@@ -88,6 +88,8 @@ public:
 	// vram_only TRUE does a "light" probe.
 	BOOL getInfo(BOOL vram_only);
 
+	std::string getDriverVersionWMI();
+
 	S32 getVRAM() const { return mVRAM; }
 
 	LLSD getDisplayInfo();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f53ba01d37..4095f1c8ef 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3347,10 +3347,19 @@ LLSD LLAppViewer::getViewerInfo() const
 	info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
 
 #if LL_WINDOWS
-	LLSD driver_info = gDXHardware.getDisplayInfo();
-	if (driver_info.has("DriverVersion"))
+	std::string drvinfo = gDXHardware.getDriverVersionWMI();
+	if (!drvinfo.empty())
 	{
-		info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
+		info["GRAPHICS_DRIVER_VERSION"] = drvinfo;
+	}
+	else
+	{
+		LL_WARNS("Driver version")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
+		LLSD driver_info = gDXHardware.getDisplayInfo();
+		if (driver_info.has("DriverVersion"))
+		{
+			info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
+		}
 	}
 #endif
 
-- 
cgit v1.2.3


From f5e0a536c1e6de34b6bffc871d1fef1efd963fdf Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Mon, 22 May 2017 03:29:01 +0300
Subject: MAINT-7431 Fixed crash in LLAccordionCtrlTab::showAndFocusHeader()

---
 indra/llui/llaccordionctrltab.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index f8ef5289db..eaf1284237 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -823,6 +823,11 @@ BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
 
 void LLAccordionCtrlTab::showAndFocusHeader()
 {
+	if (!mHeader)
+	{
+		return;
+	}
+
 	mHeader->setFocus(true);
 	mHeader->setSelected(mSelectionEnabled);
 
-- 
cgit v1.2.3


From c102bcf0adc45f855f103831542b019ad60702e7 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 22 May 2017 11:44:41 +0300
Subject: build fix

---
 indra/newview/llinventorypanel.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index ba2dce1f98..f9c91312ee 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1218,7 +1218,6 @@ void LLInventoryPanel::purgeSelectedItems()
     if (inventory_selected.empty()) return;
     LLSD args;
     S32 count = inventory_selected.size();
-    static const U32 trash_max_capacity = gSavedSettings.getU32("InventoryTrashMaxCapacity");
     for (std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(), end_it = inventory_selected.end();
         it != end_it;
         ++it)
-- 
cgit v1.2.3


From f34bee596641318d7480acf624e04af7d8bc8bfc Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 22 May 2017 16:45:33 +0300
Subject: MAINT-1094 FIXED after triggering a menu with control-F10, clicking
 in-world should move keyboard focus in-world

---
 indra/llui/llmenugl.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 022f814bbc..0d42f726fa 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3331,6 +3331,7 @@ BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask)
 		if (getHighlightedItem())
 		{
 			clearHoverItem();
+			LLMenuGL::setKeyboardMode(FALSE);
 		}
 		else
 		{
@@ -3777,10 +3778,10 @@ BOOL LLMenuHolderGL::hideMenus()
 	{
 		return FALSE;
 	}
+	LLMenuGL::setKeyboardMode(FALSE);
 	BOOL menu_visible = hasVisibleMenu();
 	if (menu_visible)
 	{
-		LLMenuGL::setKeyboardMode(FALSE);
 		// clicked off of menu, hide them all
 		for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
 		{
-- 
cgit v1.2.3


From c33fb844ab87c85d8989ea909423b559d417b250 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Tue, 23 May 2017 06:36:16 +0300
Subject: MAINT-7396 [JigglyPuff] Agent that is not estate owner or estate
 manager shouldn't be able to toggle estate access settings.

---
 indra/newview/llfloaterregioninfo.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index c33dee5fb4..1af2c10a33 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -2296,7 +2296,7 @@ BOOL LLPanelEstateInfo::postBuild()
 void LLPanelEstateInfo::refresh()
 {
 	// Disable access restriction controls if they make no sense.
-	bool public_access = getChild<LLRadioGroup>("externally_visible_radio")->getSelectedIndex();
+	bool public_access = ("estate_public_access" == getChild<LLUICtrl>("externally_visible_radio")->getValue().asString());
 
 	getChildView("Only Allow")->setEnabled(public_access);
 	getChildView("limit_payment")->setEnabled(public_access);
@@ -2317,7 +2317,7 @@ void LLPanelEstateInfo::refreshFromEstate()
 	getChild<LLUICtrl>("estate_name")->setValue(estate_info.getName());
 	setOwnerName(LLSLURL("agent", estate_info.getOwnerID(), "inspect").getSLURLString());
 
-	getChild<LLRadioGroup>("externally_visible_radio")->setSelectedIndex(estate_info.getIsExternallyVisible() ? 1 : 0);
+	getChild<LLUICtrl>("externally_visible_radio")->setValue(estate_info.getIsExternallyVisible() ? "estate_public_access" : "estate_restricted_access");
 	getChild<LLUICtrl>("voice_chat_check")->setValue(estate_info.getAllowVoiceChat());
 	getChild<LLUICtrl>("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport());
 	getChild<LLUICtrl>("limit_payment")->setValue(estate_info.getDenyAnonymous());
@@ -2360,7 +2360,7 @@ bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, con
 
 			// update model
 			estate_info.setUseFixedSun(false); // we don't support fixed sun estates anymore
-			estate_info.setIsExternallyVisible(getChild<LLRadioGroup>("externally_visible_radio")->getSelectedIndex());
+			estate_info.setIsExternallyVisible("estate_public_access" == getChild<LLUICtrl>("externally_visible_radio")->getValue().asString());
 			estate_info.setAllowDirectTeleport(getChild<LLUICtrl>("allow_direct_teleport")->getValue().asBoolean());
 			estate_info.setDenyAnonymous(getChild<LLUICtrl>("limit_payment")->getValue().asBoolean());
 			estate_info.setDenyAgeUnverified(getChild<LLUICtrl>("limit_age_verified")->getValue().asBoolean());
-- 
cgit v1.2.3


From b4e54352171f6b95714270909cda99dc1c5ad3f0 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 24 May 2017 11:06:21 +0300
Subject: MAINT-7434 FIXED SLURL instead of username appears in "have said
 something new" text for some messages

---
 indra/newview/llnotificationhandler.h       |  2 ++
 indra/newview/llnotificationhandlerutil.cpp | 14 ++++++++++++++
 indra/newview/llnotificationtiphandler.cpp  |  2 +-
 indra/newview/llviewermessage.cpp           |  1 +
 4 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 7a183cb298..52c5234137 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -322,6 +322,8 @@ public:
 	 */
 	static std::string getSubstitutionName(const LLNotificationPtr& notification);
 
+	static std::string getSubstitutionOriginalName(const LLNotificationPtr& notification);
+
 	/**
 	 * Adds notification panel to the IM floater.
 	 */
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
index 4a3923ef6e..6a58196760 100644
--- a/indra/newview/llnotificationhandlerutil.cpp
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -241,6 +241,20 @@ std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notifica
 	return res;
 }
 
+// static
+std::string LLHandlerUtil::getSubstitutionOriginalName(const LLNotificationPtr& notification)
+{
+	if(notification->getSubstitutions().has("ORIGINAL_NAME"))
+	{
+		std::string name = notification->getSubstitutions()["ORIGINAL_NAME"];
+		if(!name.empty())
+		{
+			return name;
+		}
+	}
+	return LLHandlerUtil::getSubstitutionName(notification);
+}
+
 // static
 void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification)
 {
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 596327e8f1..a6ef130cd0 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -86,7 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)
 	}
 
 	std::string session_name = notification->getPayload()["SESSION_NAME"];
-	const std::string name = notification->getSubstitutions()["NAME"];
+	const std::string name = LLHandlerUtil::getSubstitutionOriginalName(notification);
 	if (session_name.empty())
 	{
 		session_name = name;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 2dc219a769..06f868dc08 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2841,6 +2841,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 	case IM_INVENTORY_ACCEPTED:
 	{
 		args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
+		args["ORIGINAL_NAME"] = original_name;
 		LLSD payload;
 		payload["from_id"] = from_id;
 		// Passing the "SESSION_NAME" to use it for IM notification logging
-- 
cgit v1.2.3


From 5db0af5327e1aa21f607c51cf9e69e3733395350 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Mon, 22 May 2017 20:24:45 +0300
Subject: MAINT-7419 Workaround for some purge and trash issues, stuck
 descendants count

---
 indra/newview/llaisapi.cpp                | 45 ++++++++++++++++++++++++++++++-
 indra/newview/llinventorybridge.cpp       |  8 +++++-
 indra/newview/llpanelmaininventory.cpp    |  4 +--
 indra/newview/llplacesinventorybridge.cpp |  2 +-
 indra/newview/llviewerinventory.cpp       |  8 ++++++
 5 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 648212177b..ee49125711 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -394,6 +394,40 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
         {
             status = LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents");
         }
+        else if (status.getType() == 410) //GONE
+        {
+            // Item does not exist or was already deleted from server.
+            // parent folder is out of sync
+            if (type == REMOVECATEGORY)
+            {
+                LLViewerInventoryCategory *cat = gInventory.getCategory(targetId);
+                if (cat)
+                {
+                    LL_WARNS("Inventory") << "Purge failed for '" << cat->getName()
+                        << "' local version:" << cat->getVersion()
+                        << " since folder no longer exists at server. Descendent count: server == " << cat->getDescendentCount()
+                        << ", viewer == " << cat->getViewerDescendentCount()
+                        << LL_ENDL;
+                    gInventory.fetchDescendentsOf(cat->getParentUUID());
+                    // Note: don't delete folder here - contained items will be deparented (or deleted)
+                    // and since we are clearly out of sync we can't be sure we won't get rid of something we need.
+                    // For example folder could have been moved or renamed with items intact, let it fetch first.
+                }
+            }
+            else if (type == REMOVEITEM)
+            {
+                LLViewerInventoryItem *item = gInventory.getItem(targetId);
+                if (item)
+                {
+                    LL_WARNS("Inventory") << "Purge failed for '" << item->getName()
+                        << "' since item no longer exists at server." << LL_ENDL;
+                    gInventory.fetchDescendentsOf(item->getParentUUID());
+                    // since item not on the server and exists at viewer, so it needs an update at the least,
+                    // so delete it, in worst case item will be refetched with new params.
+                    gInventory.onObjectDeletedFromServer(targetId);
+                }
+            }
+        }
         LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL;
         LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL;
     }
@@ -970,7 +1004,16 @@ void AISUpdate::doUpdate()
             // inventory COF is maintained on the viewer through calls to 
             // LLInventoryModel::accountForUpdate when a changing operation 
             // is performed.  This occasionally gets out of sync however.
-            cat->setVersion(version);
+            if (version != LLViewerInventoryCategory::VERSION_UNKNOWN)
+            {
+                cat->setVersion(version);
+            }
+            else
+            {
+                // We do not account for update if version is UNKNOWN, so we shouldn't rise version
+                // either or viewer will get stuck on descendants count -1, try to refetch folder instead
+                cat->fetch();
+            }
 		}
 	}
 
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1b32fc9dfe..c8a20c9d97 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3884,8 +3884,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		LLInventoryModel::cat_array_t* cat_array;
 		LLInventoryModel::item_array_t* item_array;
 		gInventory.getDirectDescendentsOf(mUUID, cat_array, item_array);
+		LLViewerInventoryCategory *trash = getCategory();
 		// Enable Empty menu item only when there is something to act upon.
-		if ((0 == cat_array->size() && 0 == item_array->size()) || is_recent_panel)
+		// Also don't enable menu if folder isn't fully fetched
+		if ((0 == cat_array->size() && 0 == item_array->size())
+			|| is_recent_panel
+			|| !trash
+			|| trash->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN
+			|| trash->getDescendentCount() == LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
 			disabled_items.push_back(std::string("Empty Trash"));
 		}
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 3db9500de0..dd75ae9c06 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1287,13 +1287,13 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 	{
 		const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
 		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id);
-		return children != LLInventoryModel::CHILDREN_NO;
+		return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id);
 	}
 	if (command_name == "empty_lostnfound")
 	{
 		const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id);
-		return children != LLInventoryModel::CHILDREN_NO;
+		return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id);
 	}
 
 	return TRUE;
diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp
index 55cb7d616b..471e1c24f3 100644
--- a/indra/newview/llplacesinventorybridge.cpp
+++ b/indra/newview/llplacesinventorybridge.cpp
@@ -62,7 +62,7 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	if(isItemInTrash())
 	{
 		items.push_back(std::string("Purge Item"));
-		if (!isItemRemovable())
+		if (!isItemRemovable() || (gInventory.getCategory(mUUID) && !gInventory.isCategoryComplete(mUUID)))
 		{
 			disabled_items.push_back(std::string("Purge Item"));
 		}
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index bf79a0595c..da6b18bb77 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1463,6 +1463,10 @@ void remove_inventory_category(
 	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
 	if(obj)
 	{
+		if (!gInventory.isCategoryComplete(cat_id))
+		{
+			LL_WARNS() << "Removing (purging) incomplete category " << obj->getName() << LL_ENDL;
+		}
 		if(LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
 		{
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
@@ -1540,6 +1544,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		{
             if (AISAPI::isAvailable())
 			{
+				if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+				{
+					LL_WARNS() << "Purging not fetched folder: " << cat->getName() << LL_ENDL;
+				}
                 AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
                 AISAPI::PurgeDescendents(id, cr);
 			}
-- 
cgit v1.2.3


From 7021f95b5b09951d834cfb757b3b842313f27d49 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 24 May 2017 17:28:30 +0300
Subject: MAINT-7436 FIXED [viewer-neko] Crash occurs when trying to highlight
 non-existent(or removed item) using SLURI

---
 indra/newview/llinventorymodel.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 7ee41140f0..0ccaa1992d 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -221,7 +221,11 @@ BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
 const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(const LLUUID& obj_id) const
 {
 	const LLInventoryObject* obj = getObject(obj_id);
-
+	if(!obj)
+	{
+		LL_WARNS(LOG_INV) << "Non-existent object [ id: " << obj_id << " ] " << LL_ENDL;
+		return NULL;
+	}
 	// Search up the parent chain until we get to root or an acceptable folder.
 	// This assumes there are no cycles in the tree else we'll get a hang.
 	LLUUID parent_id = obj->getParentUUID();
-- 
cgit v1.2.3


From 561cee12d8d3c456d71efae3b711dbf5115c66f5 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 25 May 2017 16:51:45 +0300
Subject: MAINT-2585 Make permission request notifications permanent until
 action taken

---
 indra/llui/llnotifications.cpp                       | 6 ++++++
 indra/llui/llnotifications.h                         | 1 +
 indra/llui/llnotificationtemplate.h                  | 3 +++
 indra/newview/llnotificationofferhandler.cpp         | 1 +
 indra/newview/llnotificationscripthandler.cpp        | 1 +
 indra/newview/skins/default/xui/en/notifications.xml | 3 +++
 6 files changed, 15 insertions(+)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 604092d536..c364c4d5ae 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -426,6 +426,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
 	mLogToChat(p.log_to_chat),
 	mLogToIM(p.log_to_im),
 	mShowToast(p.show_toast),
+	mFadeToast(p.fade_toast),
     mSoundName("")
 {
 	if (p.sound.isProvided()
@@ -942,6 +943,11 @@ bool LLNotification::canShowToast() const
 	return mTemplatep->mShowToast;
 }
 
+bool LLNotification::canFadeToast() const
+{
+	return mTemplatep->mFadeToast;
+}
+
 bool LLNotification::hasFormElements() const
 {
 	return mTemplatep->mForm->getNumElements() != 0;
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 024332ee65..4a701d0ca7 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -558,6 +558,7 @@ public:
 	bool canLogToChat() const;
 	bool canLogToIM() const;
 	bool canShowToast() const;
+	bool canFadeToast() const;
 	bool hasFormElements() const;
     void playSound();
 
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index bed29254d8..20cbc89ede 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -177,6 +177,7 @@ struct LLNotificationTemplate
 		Optional<bool>					persist,
 										log_to_im,
 										show_toast,
+										fade_toast,
 										log_to_chat,
 										force_urls_external;
 		Optional<std::string>			functor,
@@ -199,6 +200,7 @@ struct LLNotificationTemplate
 		Params()
 		:	name("name"),
 			persist("persist", false),
+			fade_toast("fade_toast", true),
 			log_to_im("log_to_im", false),
 			show_toast("show_toast", true),
 			log_to_chat("log_to_chat", true),
@@ -316,6 +318,7 @@ struct LLNotificationTemplate
 	bool mLogToChat;
 	bool mLogToIM;
 	bool mShowToast;
+	bool mFadeToast;
 };
 
 #endif //LL_LLNOTIFICATION_TEMPLATE_H
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 63ab88da42..14d25d8158 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -131,6 +131,7 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)
 			// we not save offer notifications to the syswell floater that should be added to the IM floater
 			p.can_be_stored = !add_notif_to_im;
 			p.force_show = notification->getOfferFromAgent();
+			p.can_fade = notification->canFadeToast();
 
 			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
 			if(channel)
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 7acb2f9e90..fef0631fa6 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -77,6 +77,7 @@ void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notifica
 	p.notification = notification;
 	p.panel = notify_box;
 	p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1);
+	p.can_fade = notification->canFadeToast();
 	if(gAgent.isDoNotDisturb())
 	{ 
 		p.force_show = notification->getName() == "SystemMessage" 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 8620c09f9a..91f3b7456f 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7527,6 +7527,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
    name="TeleportOffered"
    log_to_im="true"
    log_to_chat="false"
+   fade_toast="false"
    type="offer"
    sound="UISndNewIncomingIMSession">
 [NAME_SLURL] has offered to teleport you to their location:
@@ -7602,6 +7603,7 @@ However, this region contains content accessible to adults only.
    icon="notify.tga"
    name="TeleportRequest"
    log_to_im="true"
+   fade_toast="false"
    type="offer">
 [NAME_SLURL] is requesting to be teleported to your location.
 [MESSAGE]
@@ -7958,6 +7960,7 @@ Other Key Experiences may be available.
    icon="notify.tga"
    name="ScriptQuestionExperience"
    persist="false"
+   fade_toast="false"
    type="notify">
 &apos;&lt;nolink&gt;[OBJECTNAME]&lt;/nolink&gt;&apos;, an object owned by &apos;[NAME]&apos;, requests your participation in the [GRID_WIDE] experience:
 
-- 
cgit v1.2.3


From bb8609fa9408f206142b5c67983c7d0fd1876b19 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 25 May 2017 18:09:52 +0300
Subject: MAINT-5100 Fixed viewer not finding sky files at login

---
 indra/llvfs/lldiriterator.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp
index 76296ff877..3eb64e69d9 100644
--- a/indra/llvfs/lldiriterator.cpp
+++ b/indra/llvfs/lldiriterator.cpp
@@ -51,7 +51,11 @@ private:
 LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
 	: mIsValid(false)
 {
+#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
+	fs::path dir_path(utf8str_to_utf16str(dirname));
+#else
 	fs::path dir_path(dirname);
+#endif
 
 	bool is_dir = false;
 
-- 
cgit v1.2.3


From fe49c1e8a5b3ebbb8fddeb23d32d4de68558fa37 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Fri, 26 May 2017 15:11:37 +0300
Subject: MAINT-1139 Catch Windows crash on Saving snapshot

---
 indra/newview/llfilepicker.cpp | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index a7236d1778..7e92643b93 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -544,11 +544,18 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 	send_agent_pause();
 	{
 		// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
-		success = GetSaveFileName(&mOFN);
-		if (success)
+		try
 		{
-			std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
-			mFiles.push_back(filename);
+			success = GetSaveFileName(&mOFN);
+			if (success)
+			{
+				std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+				mFiles.push_back(filename);
+			}
+		}
+		catch (...)
+		{
+			LOG_UNHANDLED_EXCEPTION("");
 		}
 		gKeyboard->resetKeys();
 	}
-- 
cgit v1.2.3


From e62444c0e73e6d89ab6a11e1e03047c83fe756f9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 29 May 2017 11:30:07 +0300
Subject: MAINT-7443 FIXED Able to Block a user with Lastname Linden

---
 indra/newview/llmutelist.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 5b53a05274..bf1716e18c 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -48,6 +48,7 @@
 
 #include <boost/tokenizer.hpp>
 #include <boost/bind.hpp>
+#include <boost/algorithm/string/replace.hpp>
 
 #include "lldispatcher.h"
 #include "llxfermanager.h"
@@ -180,9 +181,10 @@ LLMuteList::~LLMuteList()
 
 BOOL LLMuteList::isLinden(const std::string& name) const
 {
+	std::string username = boost::replace_all_copy(name, ".", " ");
 	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
 	boost::char_separator<char> sep(" ");
-	tokenizer tokens(name, sep);
+	tokenizer tokens(username, sep);
 	tokenizer::iterator token_iter = tokens.begin();
 	
 	if (token_iter == tokens.end()) return FALSE;
@@ -190,7 +192,8 @@ BOOL LLMuteList::isLinden(const std::string& name) const
 	if (token_iter == tokens.end()) return FALSE;
 	
 	std::string last_name = *token_iter;
-	return last_name == "Linden";
+	LLStringUtil::toLower(last_name);
+	return last_name == "linden";
 }
 
 static LLVOAvatar* find_avatar(const LLUUID& id)
-- 
cgit v1.2.3


From a6cda1ee06ee422d39b8bc9ba9369e14ec3f1251 Mon Sep 17 00:00:00 2001
From: Cinder <cinder@sdf.org>
Date: Thu, 15 Dec 2016 09:34:04 -0600
Subject: STORM-2144 - Guard against null pointers when LLPanelOutfitEdit gets
 called before postBuild() on login.

---
 doc/contributions.txt               | 1 +
 indra/newview/llpaneloutfitedit.cpp | 8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index eb012ee318..e4b24b3abe 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -362,6 +362,7 @@ Cinder Roxley
     STORM-2053
     STORM-2113
     STORM-2127
+    STORM-2144
 Clara Young
 Coaldust Numbers
     VWR-1095
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 3f6bdde127..5973b08183 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -1285,7 +1285,7 @@ void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type
 	showWearablesListView();
 
 	//e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE
-	applyListViewFilter((EListViewItemType) (LVIT_SHAPE + type));
+	applyListViewFilter(static_cast<EListViewItemType>(LVIT_SHAPE + type));
 }
 
 static void update_status_widget_rect(LLView * widget, S32 right_border)
@@ -1305,8 +1305,10 @@ void LLPanelOutfitEdit::onOutfitChanging(bool started)
 	S32 delta = started ? indicator_delta : 0;
 	S32 right_border = status_panel->getRect().getWidth() - delta;
 
-	update_status_widget_rect(mCurrentOutfitName, right_border);
-	update_status_widget_rect(mStatus, right_border);
+	if (mCurrentOutfitName)
+		update_status_widget_rect(mCurrentOutfitName, right_border);
+	if (mStatus)
+		update_status_widget_rect(mStatus, right_border);
 
 	indicator->setVisible(started);
 }
-- 
cgit v1.2.3


From f82785a9b275b78b47cdebaf2ccfc8aa9407c405 Mon Sep 17 00:00:00 2001
From: daianakproductengine <daianakproductengine@lindenlab.com>
Date: Wed, 24 May 2017 16:33:39 +0300
Subject: MAINT-4375 Viewer saves an empty snapshots if disk is full

---
 indra/newview/llpanelsnapshotlocal.cpp             |  1 +
 indra/newview/llsnapshotlivepreview.cpp            | 38 +++++++++++++++++++++-
 indra/newview/llsnapshotlivepreview.h              |  1 +
 indra/newview/llviewermenufile.cpp                 |  2 +-
 indra/newview/llviewerwindow.cpp                   | 11 +++++++
 indra/newview/llviewerwindow.h                     |  1 +
 .../newview/skins/default/xui/en/notifications.xml |  5 +++
 7 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp
index 51ec964ace..77378f8092 100644
--- a/indra/newview/llpanelsnapshotlocal.cpp
+++ b/indra/newview/llpanelsnapshotlocal.cpp
@@ -172,6 +172,7 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
 	}
 	else
 	{
+		cancel();
 		floater->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local")));
 	}
 }
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 58e48480c1..c6f8c414fa 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -45,6 +45,7 @@
 #include "llimagepng.h"
 #include "lllandmarkactions.h"
 #include "lllocalcliprect.h"
+#include "llresmgr.h"
 #include "llnotificationsutil.h"
 #include "llslurl.h"
 #include "llsnapshotlivepreview.h"
@@ -56,6 +57,7 @@
 #include "llvfs.h"
 #include "llwindow.h"
 #include "llworld.h"
+#include <boost/filesystem.hpp>
 
 const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
 
@@ -1069,7 +1071,7 @@ BOOL LLSnapshotLivePreview::saveLocal()
     getFormattedImage();
     
     // Save the formatted image
-	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
+	BOOL success = saveLocal(mFormattedImage);
 
 	if(success)
 	{
@@ -1078,3 +1080,37 @@ BOOL LLSnapshotLivePreview::saveLocal()
 	return success;
 }
 
+//Check if failed due to insuficient memory
+BOOL LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> mFormattedImage)
+{
+	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
+
+	if (!success)
+	{
+		std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir();
+
+#ifdef LL_WINDOWS
+		boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir));
+#else
+		boost::filesystem::path b_path(lastSnapshotDir);
+#endif
+		boost::filesystem::space_info b_space = boost::filesystem::space(b_path);
+		if (b_space.free < mFormattedImage->getDataSize())
+		{
+			LLSD args;
+			args["PATH"] = lastSnapshotDir;
+
+			std::string needM_bytes_string;
+			LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (mFormattedImage->getDataSize()) >> 10);
+			args["NEED_MEMORY"] = needM_bytes_string;
+
+			std::string freeM_bytes_string;
+			LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10);
+			args["FREE_MEMORY"] = freeM_bytes_string;
+
+			LLNotificationsUtil::add("SnapshotToComputerFailed", args);
+			return false;
+		}
+	}
+	return success;
+}
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index b689c50320..4ea8d25a5a 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -41,6 +41,7 @@ class LLSnapshotLivePreview : public LLView
 	LOG_CLASS(LLSnapshotLivePreview);
 public:
 
+	static BOOL saveLocal(LLPointer<LLImageFormatted>);
 	struct Params : public LLInitParam::Block<Params, LLView::Params>
 	{
 		Params()
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index d46bb0199b..8d0c5af314 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -583,7 +583,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
 			formatted->enableOverSize() ;
 			formatted->encode(raw, 0);
 			formatted->disableOverSize() ;
-			gViewerWindow->saveImageNumbered(formatted);
+			LLSnapshotLivePreview::saveLocal(formatted);
 		}
 		return true;
 	}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2d3b48bab3..45ea0f8e02 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -33,6 +33,7 @@
 #include <iostream>
 #include <fstream>
 #include <algorithm>
+#include <boost/filesystem.hpp>
 #include <boost/lambda/core.hpp>
 #include <boost/regex.hpp>
 
@@ -4398,6 +4399,16 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke
 		LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
 	}
 
+// Check if there is enough free space to save snapshot
+#ifdef LL_WINDOWS
+	boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(sSnapshotDir));
+#else
+	boost::filesystem::space_info b_space = boost::filesystem::space(sSnapshotDir);
+#endif
+	if (b_space.free < image->getDataSize())
+	{
+		return FALSE;
+	}
 	// Look for an unused file name
 	std::string filepath;
 	S32 i = 1;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index a134dfaaa9..5d7076178a 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -419,6 +419,7 @@ public:
 
 	bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; }
 	static void showSystemUIScaleFactorChanged();
+	static std::string getLastSnapshotDir() { return sSnapshotDir; }
 
 private:
 	bool                    shouldShowToolTipFor(LLMouseHandler *mh);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 91f3b7456f..b413720bc9 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8533,6 +8533,11 @@ Appearance has been saved to XML to [PATH]
 Failed to save appearance to XML.
   </notification>
 
+  <notification icon="notifytip.tga"
+    name="SnapshotToComputerFailed" type="notifytip">
+Failed to save snapshot to [PATH]: Not enough memory. [NEED_MEMORY]KB is required but only [FREE_MEMORY]KB is free.
+  </notification>
+
   <notification
     icon="notifytip.tga"
     name="PresetNotSaved"
-- 
cgit v1.2.3


From c6fbc55c6910b010ea805f77ff9d536890830abd Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 29 May 2017 17:53:20 +0300
Subject: MAINT-7438 FIXED Always allow 'create landmark' allows group teleport
 routing override, however was removed.

---
 indra/newview/skins/default/xui/en/role_actions.xml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
index 4d20ecb9b6..8d058b0b53 100644
--- a/indra/newview/skins/default/xui/en/role_actions.xml
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -105,6 +105,9 @@
 		<action description="Always allow &apos;Create Objects&apos;"
 		     longdescription="Members in a Role with this Ability can create objects on a group-owned parcel, even if it&apos;s turned off in About Land &gt; Options tab."
 		     name="land allow create" value="25" />
+		<action description="Ignore landing point"
+		     longdescription="Members in a Role with this Ability can direct teleport to a group-owned parcel, even if a landing point is set in About Land &gt; Options tab."
+		     name="land allow direct teleport" value="26" />
 		<action description="Allow &apos;Set Home to Here&apos; on group land"
 		     longdescription="Members in a Role with this Ability can use World menu &gt; Landmarks &gt; Set Home to Here on a parcel deeded to this group."
 		     name="land allow set home" value="28" />
-- 
cgit v1.2.3


From d65db1f16c75a8d5f54c9e6f52c3755d29b39b3e Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 31 May 2017 11:27:36 +0300
Subject: MAINT-7455 Update Viewer Login error message

---
 indra/newview/skins/default/xui/en/strings.xml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c9be141427..439560031e 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -150,8 +150,7 @@ support@secondlife.com.</string>
 	<string name="LoginFailedAcountSuspended">Your account is not accessible until
 [TIME] Pacific Time.</string>
 	<string name="LoginFailedAccountDisabled">We are unable to complete your request at this time.
-Please contact Second Life support for assistance at http://secondlife.com/support.
-If you are unable to change your password, please call (866) 476-9763.</string>
+Please contact Second Life support for assistance at http://support.secondlife.com.</string>
 	<string name="LoginFailedTransformError">Data inconsistency found during login.
 Please contact support@secondlife.com.</string>
 	<string name="LoginFailedAccountMaintenance">Your account is undergoing minor maintenance.
-- 
cgit v1.2.3


From 735ae02583558544a4a3b65f72cdf52fe7d27677 Mon Sep 17 00:00:00 2001
From: pavelkproductengine <pavelkproductengine@lindenlab.com>
Date: Tue, 30 May 2017 20:35:05 +0300
Subject: MAINT-7356 Feature - Force item delete warning to prompt once per
 session

---
 indra/newview/llinventoryfunctions.cpp | 29 +++++++++++++++++++++++++++++
 indra/newview/llinventoryfunctions.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index bccc654fbf..2bb6fb853c 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -92,6 +92,8 @@ BOOL LLInventoryState::sWearNewClothing = FALSE;
 LLUUID LLInventoryState::sWearNewClothingTransactionID;
 std::list<LLUUID> LLInventoryAction::sMarketplaceFolders;
 
+const int LLInventoryAction::sConfirmOnDeleteItemsNumber = 5;
+
 // Helper function : callback to update a folder after inventory action happened in the background
 void update_folder_cb(const LLUUID& dest_folder)
 {
@@ -2297,6 +2299,33 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 	{
 		LLSD args;
 		args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" :  "DeleteItem");
+		static bool sDisplayedAtSession = false;
+		std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin();
+		LLFolderViewModelItemInventory * viewModel = NULL;
+		bool has_folder_items = false;
+		for (; set_iter != selected_items.end(); ++set_iter)
+		{
+			viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem());
+			if (viewModel && viewModel->hasChildren())
+			{
+				has_folder_items = true;
+				break;
+			}
+		}
+		if (root->getSelectedCount() >= sConfirmOnDeleteItemsNumber || has_folder_items)
+		{
+			bool ignore = !(LLUI::sSettingGroups["ignores"]->getBOOL("DeleteItems"));
+			if (ignore)
+			{
+
+				if (!sDisplayedAtSession)
+				{
+					LLUI::sSettingGroups["ignores"]->setBOOL("DeleteItems", TRUE);
+					sDisplayedAtSession = true;
+				}
+
+			}
+		}
 		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
         // Note: marketplace listings will be updated in the callback if delete confirmed
 		return;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 649db4032d..d454d7e00b 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -460,6 +460,8 @@ struct LLInventoryAction
 	static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);
 	static void removeItemFromDND(LLFolderView* root);
 
+	static const int sConfirmOnDeleteItemsNumber;
+
 private:
 	static void buildMarketplaceFolders(LLFolderView* root);
 	static void updateMarketplaceFolders();
-- 
cgit v1.2.3


From 54d3e2634d66f3d32eef91ee81688276aeebd8ad Mon Sep 17 00:00:00 2001
From: daianakproductengine <daianakproductengine@lindenlab.com>
Date: Wed, 24 May 2017 16:33:39 +0300
Subject: MAINT-4375 Viewer saves an empty snapshots if disk is full

---
 indra/newview/skins/default/xui/en/notifications.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index b413720bc9..16bf0e344d 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8535,7 +8535,7 @@ Failed to save appearance to XML.
 
   <notification icon="notifytip.tga"
     name="SnapshotToComputerFailed" type="notifytip">
-Failed to save snapshot to [PATH]: Not enough memory. [NEED_MEMORY]KB is required but only [FREE_MEMORY]KB is free.
+Failed to save snapshot to [PATH]: Disk is full. [NEED_MEMORY]KB is required but only [FREE_MEMORY]KB is free.
   </notification>
 
   <notification
-- 
cgit v1.2.3


From 8c393b49930d695529ffee48864bb5aae5e71693 Mon Sep 17 00:00:00 2001
From: daianakproductengine <daianakproductengine@lindenlab.com>
Date: Wed, 31 May 2017 19:55:38 +0300
Subject: MAINT-321 If Spin option is turned on, user cannot lift an object
 using Ctrl button + Mouse

---
 indra/newview/llfloatertools.cpp | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index b14b9b7578..5b7cfb242e 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -638,20 +638,22 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
 
 	// HACK - highlight buttons for next click
 	mRadioGroupMove->setVisible(move_visible);
-	if (!gGrabBtnSpin && 
-		!gGrabBtnVertical &&
-		!(mask == MASK_VERTICAL) && 
-		!(mask == MASK_SPIN) )
+	if (!(gGrabBtnSpin || 
+		gGrabBtnVertical || 
+		(mask == MASK_VERTICAL) || 
+		(mask == MASK_SPIN)))
 	{
 		mRadioGroupMove->setValue("radio move");
 	}
-	else if (gGrabBtnVertical || 
-			 (mask == MASK_VERTICAL) )
+	else if ((mask == MASK_VERTICAL) ||
+			gGrabBtnVertical && 
+			(mask != MASK_SPIN))
 	{
 		mRadioGroupMove->setValue("radio lift");
 	}
-	else if (gGrabBtnSpin || 
-			 (mask == MASK_SPIN) )
+	else if ((mask == MASK_SPIN) || 
+			gGrabBtnSpin && 
+			(mask != MASK_VERTICAL))
 	{
 		mRadioGroupMove->setValue("radio spin");
 	}
-- 
cgit v1.2.3


From 19c3f47e00e348739eaf31685c8ea804704a08e5 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Wed, 31 May 2017 21:24:04 +0300
Subject: MAINT-7325 Fixed issue of images being marked as missing due to
 uninitialized discard level

---
 indra/newview/llviewertexture.cpp | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 6abd6f7b64..c162af371f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1462,9 +1462,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
 	}
 
 	bool size_okay = true;
-	
-	U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel;
-	U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel;
+
+	S32 discard_level = mRawDiscardLevel;
+	if (mRawDiscardLevel < 0)
+	{
+		LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL;
+		discard_level = 0;
+	}
+
+	U32 raw_width = mRawImage->getWidth() << discard_level;
+	U32 raw_height = mRawImage->getHeight() << discard_level;
+
 	if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
 	{
 		LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL;
-- 
cgit v1.2.3


From 13cddfdfdd8c42367af8a197e1f2deefc986495b Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Thu, 1 Jun 2017 15:30:49 +0300
Subject: Mac buildfix

---
 indra/newview/llfloatertools.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 5b7cfb242e..2869256d09 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -646,14 +646,12 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
 		mRadioGroupMove->setValue("radio move");
 	}
 	else if ((mask == MASK_VERTICAL) ||
-			gGrabBtnVertical && 
-			(mask != MASK_SPIN))
+			 (gGrabBtnVertical && (mask != MASK_SPIN)))
 	{
 		mRadioGroupMove->setValue("radio lift");
 	}
 	else if ((mask == MASK_SPIN) || 
-			gGrabBtnSpin && 
-			(mask != MASK_VERTICAL))
+			 (gGrabBtnSpin && (mask != MASK_VERTICAL)))
 	{
 		mRadioGroupMove->setValue("radio spin");
 	}
-- 
cgit v1.2.3


From a8fffc7d172d3a786904e6d8e7e7c2943e6d54fc Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Tue, 30 May 2017 16:28:07 +0300
Subject: MAINT-731 Fixed Images Do Not Show at Proper Proportions

---
 indra/newview/llpreviewtexture.cpp | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 645a77e42a..54eeebda28 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -52,6 +52,8 @@
 #include "llviewerwindow.h"
 #include "lllineeditor.h"
 
+#include <boost/lexical_cast.hpp>
+
 const S32 CLIENT_RECT_VPAD = 4;
 
 const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
@@ -579,7 +581,11 @@ void LLPreviewTexture::adjustAspectRatio()
 			std::vector<std::string>::const_iterator found = std::find(mRatiosList.begin(), mRatiosList.end(), ratio.str());
 			if (found == mRatiosList.end())
 			{
-				combo->setCurrentByIndex(0);
+				// No existing ratio found, create an element that will show image at original ratio
+				std::string ratio = boost::lexical_cast<std::string>(num)+":" + boost::lexical_cast<std::string>(denom);
+				mRatiosList.push_back(ratio);
+				combo->add(ratio);
+				combo->setCurrentByIndex(mRatiosList.size()- 1);
 			}
 			else
 			{
@@ -587,6 +593,15 @@ void LLPreviewTexture::adjustAspectRatio()
 			}
 		}
 	}
+	else
+	{
+		// Aspect ratio was set to unconstrained or was clamped
+		LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+		if (combo)
+		{
+			combo->setCurrentByIndex(0); //unconstrained
+		}
+	}
 
 	mUpdateDimensions = TRUE;
 }
-- 
cgit v1.2.3


From 045eebbccd7bb49021ddd17bdfb6967e2812d749 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Fri, 2 Jun 2017 19:38:04 +0300
Subject: MAINT-7459 Fixed incorrect 'Parcel owners can be more restrictive'
 checkbox focus behavior

---
 indra/newview/llfloaterregioninfo.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 1af2c10a33..c330c2ae47 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -2290,6 +2290,8 @@ BOOL LLPanelEstateInfo::postBuild()
 
 	getChild<LLUICtrl>("parcel_access_override")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAccessOverride, this));
 
+	getChild<LLUICtrl>("externally_visible_radio")->setFocus(TRUE);
+
 	return LLPanelRegionInfo::postBuild();
 }
 
-- 
cgit v1.2.3


From 81f4da646800e2a1b7218397290183144f6aed92 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 6 Jun 2017 12:47:51 +0300
Subject: MAINT-7447 FIXED Selecting a group ability refreshes the list and
 deselects your choice

---
 indra/llui/llscrolllistctrl.cpp     | 15 +++++++++++++++
 indra/llui/llscrolllistctrl.h       |  2 ++
 indra/newview/llpanelgrouproles.cpp | 28 ++++++++++++++++++----------
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 0afa8d43f1..7c1f4a4dca 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -345,6 +345,21 @@ S32 LLScrollListCtrl::getItemCount() const
 	return mItemList.size();
 }
 
+BOOL LLScrollListCtrl::hasSelectedItem() const
+{
+	item_list::iterator iter;
+	for (iter = mItemList.begin(); iter < mItemList.end(); )
+	{
+		LLScrollListItem* itemp = *iter;
+		if (itemp && itemp->getSelected())
+		{
+			return TRUE;
+		}
+		iter++;
+	}
+	return FALSE;
+}
+
 // virtual LLScrolListInterface function (was deleteAllItems)
 void LLScrollListCtrl::clearRows()
 {
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 8343750a54..699a8744e1 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -201,6 +201,8 @@ public:
 
 	virtual BOOL	isSelected(const LLSD& value) const;
 
+	BOOL 			hasSelectedItem() const;
+
 	BOOL			handleClick(S32 x, S32 y, MASK mask);
 	BOOL			selectFirstItem();
 	BOOL			selectNthItem( S32 index );
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 8440e9ee50..473451bdb6 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -2775,6 +2775,16 @@ void LLPanelGroupActionsSubTab::activate()
 	LLPanelGroupSubTab::activate();
 
 	update(GC_ALL);
+	mActionDescription->clear();
+	mActionList->deselectAllItems();
+	mActionList->deleteAllItems();
+	buildActionsList(mActionList,
+					 GP_ALL_POWERS,
+					 GP_ALL_POWERS,
+					 NULL,
+					 FALSE,
+					 TRUE,
+					 FALSE);
 }
 
 void LLPanelGroupActionsSubTab::deactivate()
@@ -2803,19 +2813,17 @@ void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
 
 	if (mGroupID.isNull()) return;
 
-	mActionList->deselectAllItems();
 	mActionMembers->deleteAllItems();
 	mActionRoles->deleteAllItems();
-	mActionDescription->clear();
 
-	mActionList->deleteAllItems();
-	buildActionsList(mActionList,
-					 GP_ALL_POWERS,
-					 GP_ALL_POWERS,
-					 NULL,
-					 FALSE,
-					 TRUE,
-					 FALSE);
+	if(mActionList->hasSelectedItem())
+	{
+		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+		if (gdatap && gdatap->isMemberDataComplete() && gdatap->isRoleDataComplete())
+		{
+			handleActionSelect();
+		}
+	}
 }
 
 void LLPanelGroupActionsSubTab::handleActionSelect()
-- 
cgit v1.2.3


From d700552b449f3c2bcaee46f61fe3290f57e58fe9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 6 Jun 2017 12:51:16 +0300
Subject: MAINT-7458 FIXED Release notes opens every time after any problem
 with logining, until viewer will be relaunched.

---
 indra/newview/llstartup.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 33b6352bf5..1a480b1838 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2268,13 +2268,15 @@ void login_callback(S32 option, void *userdata)
 */
 void show_release_notes_if_required()
 {
-    if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion
+    static bool release_notes_shown = false;
+    if (!release_notes_shown && (LLVersionInfo::getChannelAndVersion() != gLastRunVersion)
         && LLVersionInfo::getViewerMaturity() != LLVersionInfo::TEST_VIEWER // don't show Release Notes for the test builds
         && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")
         && !gSavedSettings.getBOOL("FirstLoginThisInstall"))
     {
         LLSD info(LLAppViewer::instance()->getViewerInfo());
         LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]);
+        release_notes_shown = true;
     }
 }
 
-- 
cgit v1.2.3


From d3a1c4cda49cc1b113abbdb175c557456581efac Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Tue, 6 Jun 2017 16:06:28 +0300
Subject: MAINT-7462 check pointer to avoid allocation crash in
 llpluginclassmedia

---
 indra/llplugin/llpluginclassmedia.cpp |  9 ++++++++-
 indra/newview/llviewermedia.cpp       | 29 ++++++++++++++++-------------
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index f1b6fe0a12..680017204c 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -224,7 +224,14 @@ void LLPluginClassMedia::idle(void)
 				void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
 
 				// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
-				memset( addr, 0x00, newsize );
+				if (addr)
+				{
+					memset( addr, 0x00, newsize );
+				}
+				else
+				{
+					LL_WARNS("Plugin") << "Failed to get previously created shared memory address: " << mTextureSharedMemoryName << " size: " << mTextureSharedMemorySize << LL_ENDL;
+				}
 
 				// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
 				// so it may not be worthwhile.
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 9f05ee61bd..01b0dd0077 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -3052,20 +3052,23 @@ void LLViewerMediaImpl::update()
 					data = mMediaSource->getBitsData();
 				}
 
-				// Offset the pixels pointer to match x_pos and y_pos
-				data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
-				data += ( y_pos * mMediaSource->getTextureDepth() );
-
+				if(data != NULL)
 				{
-					LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE);
-					placeholder_image->setSubImage(
-							data,
-							mMediaSource->getBitsWidth(),
-							mMediaSource->getBitsHeight(),
-							x_pos,
-							y_pos,
-							width,
-							height);
+					// Offset the pixels pointer to match x_pos and y_pos
+					data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
+					data += ( y_pos * mMediaSource->getTextureDepth() );
+
+					{
+						LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE);
+									placeholder_image->setSubImage(
+									data,
+									mMediaSource->getBitsWidth(),
+									mMediaSource->getBitsHeight(),
+									x_pos,
+									y_pos,
+									width,
+									height);
+					}
 				}
 
 			}
-- 
cgit v1.2.3


From 95d0da56fda169a7cce34e07f8ae76f86dce42c0 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <none@none>
Date: Wed, 7 Jun 2017 18:56:24 +0300
Subject: MAINT-7447 restore filter functionality in Abilities tab

---
 indra/newview/llpanelgroup.h        |  2 ++
 indra/newview/llpanelgrouproles.cpp | 15 +++++++++++++++
 indra/newview/llpanelgrouproles.h   |  1 +
 3 files changed, 18 insertions(+)

diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 0e6f5b8924..05be4b5aee 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -164,6 +164,8 @@ public:
 
 	virtual void setupCtrls	(LLPanel* parent) {};
 
+	virtual void onFilterChanged() { }
+
 protected:
 	LLUUID	mGroupID;
 	BOOL mAllowEdit;
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 473451bdb6..78270c20bb 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -494,6 +494,7 @@ void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
 	mSearchFilter = filter;
 	LLStringUtil::toLower(mSearchFilter);
 	update(GC_ALL);
+	onFilterChanged();
 }
 
 void LLPanelGroupSubTab::activate()
@@ -2826,6 +2827,20 @@ void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
 	}
 }
 
+void LLPanelGroupActionsSubTab::onFilterChanged()
+{
+	mActionDescription->clear();
+	mActionList->deselectAllItems();
+	mActionList->deleteAllItems();
+	buildActionsList(mActionList,
+		GP_ALL_POWERS,
+		GP_ALL_POWERS,
+		NULL,
+		FALSE,
+		TRUE,
+		FALSE);
+}
+
 void LLPanelGroupActionsSubTab::handleActionSelect()
 {
 	mActionMembers->deleteAllItems();
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 9a696124a8..1d1d69e0ae 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -311,6 +311,7 @@ public:
 	virtual bool needsApply(std::string& mesg);
 	virtual bool apply(std::string& mesg);
 	virtual void update(LLGroupChange gc);
+	virtual void onFilterChanged();
 
 	void handleActionSelect();
 
-- 
cgit v1.2.3


From 47ae78f8cfc9ca71bf9837b06618d34737b07fc4 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Wed, 7 Jun 2017 16:21:40 +0300
Subject: MAINT-7461 Fixed images not showing at correct proportions when
 opened for the first time

---
 indra/newview/llpreviewtexture.cpp | 64 ++++++++++++++++++++++++--------------
 indra/newview/llpreviewtexture.h   |  1 +
 2 files changed, 42 insertions(+), 23 deletions(-)

diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 54eeebda28..12bcd89cb0 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -100,6 +100,29 @@ LLPreviewTexture::~LLPreviewTexture()
 	}
 }
 
+void LLPreviewTexture::populateRatioList()
+{
+	// Fill in ratios list with common aspect ratio values
+	mRatiosList.clear();
+	mRatiosList.push_back(LLTrans::getString("Unconstrained"));
+	mRatiosList.push_back("1:1");
+	mRatiosList.push_back("4:3");
+	mRatiosList.push_back("10:7");
+	mRatiosList.push_back("3:2");
+	mRatiosList.push_back("16:10");
+	mRatiosList.push_back("16:9");
+	mRatiosList.push_back("2:1");
+	
+	// Now fill combo box with provided list
+	LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+	combo->removeall();
+
+	for (std::vector<std::string>::const_iterator it = mRatiosList.begin(); it != mRatiosList.end(); ++it)
+	{
+		combo->add(*it);
+	}
+}
+
 // virtual
 BOOL LLPreviewTexture::postBuild()
 {
@@ -140,27 +163,12 @@ BOOL LLPreviewTexture::postBuild()
         }
     }
 
-	// Fill in ratios list with common aspect ratio values
-	mRatiosList.clear();
-	mRatiosList.push_back(LLTrans::getString("Unconstrained"));
-	mRatiosList.push_back("1:1");
-	mRatiosList.push_back("4:3");
-	mRatiosList.push_back("10:7");
-	mRatiosList.push_back("3:2");
-	mRatiosList.push_back("16:10");
-	mRatiosList.push_back("16:9");
-	mRatiosList.push_back("2:1");
-	
-	// Now fill combo box with provided list
-	LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
-	combo->removeall();
-
-	for (std::vector<std::string>::const_iterator it = mRatiosList.begin(); it != mRatiosList.end(); ++it)
-	{
-		combo->add(*it);
-	}
+	// Fill in ratios list and combo box with common aspect ratio values
+	populateRatioList();
 
 	childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
+
+	LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
 	combo->setCurrentByIndex(0);
 	
 	return LLPreview::postBuild();
@@ -446,16 +454,25 @@ void LLPreviewTexture::updateDimensions()
 		return;
 	}
 
-	if (mAssetStatus != PREVIEW_ASSET_LOADED)
+	S32 img_width = mImage->getFullWidth();
+	S32 img_height = mImage->getFullHeight();
+
+	if (mAssetStatus != PREVIEW_ASSET_LOADED
+		|| mLastWidth != img_width
+		|| mLastHeight != img_height)
 	{
 		mAssetStatus = PREVIEW_ASSET_LOADED;
 		// Asset has been fully loaded, adjust aspect ratio
 		adjustAspectRatio();
 	}
-	
+
+
 	// Update the width/height display every time
-	getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]",  llformat("%d", mImage->getFullWidth()));
-	getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight()));
+	getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]",  llformat("%d", img_width));
+	getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", img_height));
+
+	mLastHeight = img_height;
+	mLastWidth = img_width;
 
 	// Reshape the floater only when required
 	if (mUpdateDimensions)
@@ -582,6 +599,7 @@ void LLPreviewTexture::adjustAspectRatio()
 			if (found == mRatiosList.end())
 			{
 				// No existing ratio found, create an element that will show image at original ratio
+				populateRatioList(); // makes sure previous custom ratio is cleared
 				std::string ratio = boost::lexical_cast<std::string>(num)+":" + boost::lexical_cast<std::string>(denom);
 				mRatiosList.push_back(ratio);
 				combo->add(ratio);
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index b104a91c75..c156c48d0c 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -67,6 +67,7 @@ public:
 	/*virtual*/ void setObjectID(const LLUUID& object_id);
 protected:
 	void				init();
+	void				populateRatioList();
 	/* virtual */ BOOL	postBuild();
 	bool				setAspectRatio(const F32 width, const F32 height);
 	static void			onAspectRatioCommit(LLUICtrl*,void* userdata);
-- 
cgit v1.2.3


From d7edeb2df8b225c39727bf506b4e5126852e2d5d Mon Sep 17 00:00:00 2001
From: Kitty Barnett <develop@catznip.com>
Date: Fri, 2 Jun 2017 16:44:00 +0200
Subject: STORM-2149: Add a warning notification when deleting a folder of
 filtered content

---
 doc/contributions.txt                              |  1 +
 indra/llui/llfolderview.cpp                        | 12 ++++++++
 indra/llui/llfolderview.h                          | 12 ++++++++
 indra/llui/llfolderviewitem.cpp                    |  5 ++++
 indra/llui/llnotifications.cpp                     |  6 ++++
 indra/llui/llnotifications.h                       |  2 ++
 indra/newview/llinventoryfunctions.cpp             | 33 ++++++++++++++++------
 .../newview/skins/default/xui/en/notifications.xml | 16 +++++++++++
 8 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index e4b24b3abe..1d591e2ec2 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -822,6 +822,7 @@ Kitty Barnett
 	MAINT-6153
 	MAINT-6154
 	MAINT-6568
+	STORM-2149
 Kolor Fall
 Komiko Okamoto
 Korvel Noh
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index f9664e0658..895753aeae 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -102,6 +102,18 @@ void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder)
 void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
 { }
 
+//---------------------------------------------------------------------------
+
+void LLAllDescendentsPassedFilter::doFolder(LLFolderViewFolder* folder)
+{
+	mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter());
+}
+
+void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item)
+{
+	mAllDescendentsPassedFilter &= (item) && (item->passedFilter());
+}
+
 ///----------------------------------------------------------------------------
 /// Class LLFolderViewScrollContainer
 ///----------------------------------------------------------------------------
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index b5deefd653..2926e160d0 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -400,6 +400,18 @@ public:
 	virtual void doItem(LLFolderViewItem* item);
 };
 
+class LLAllDescendentsPassedFilter : public LLFolderViewFunctor
+{
+public:
+	LLAllDescendentsPassedFilter() : mAllDescendentsPassedFilter(true) {}
+	/*virtual*/ ~LLAllDescendentsPassedFilter() {}
+	/*virtual*/ void doFolder(LLFolderViewFolder* folder);
+	/*virtual*/ void doItem(LLFolderViewItem* item);
+	bool allDescendentsPassedFilter() const { return mAllDescendentsPassedFilter; }
+protected:
+	bool mAllDescendentsPassedFilter;
+};
+
 // Flags for buildContextMenu()
 const U32 SUPPRESS_OPEN_ITEM = 0x1;
 const U32 FIRST_SELECTED_ITEM = 0x2;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 3d618548c4..0510e472c5 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -1176,6 +1176,11 @@ BOOL LLFolderViewFolder::needsArrange()
 	return mLastArrangeGeneration < getRoot()->getArrangeGeneration();
 }
 
+bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation)
+{
+	return getViewModelItem()->descendantsPassedFilter(filter_generation);
+}
+
 // Passes selection information on to children and record selection
 // information if necessary.
 BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem,
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index c364c4d5ae..d40347de13 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1798,6 +1798,12 @@ bool LLNotifications::getIgnoreAllNotifications()
 {
 	return mIgnoreAllNotifications; 
 }
+
+bool LLNotifications::getIgnored(const std::string& name)
+{
+	LLNotificationTemplatePtr templatep = getTemplate(name);
+	return (mIgnoreAllNotifications) || ( (templatep->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) && (templatep->mForm->getIgnored()) );
+}
 													
 bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
 {
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 4a701d0ca7..a7a5490432 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -964,6 +964,8 @@ public:
 	void setIgnoreAllNotifications(bool ignore);
 	bool getIgnoreAllNotifications();
 
+	bool getIgnored(const std::string& name);
+
 	bool isVisibleByRules(LLNotificationPtr pNotification);
 	
 private:
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 2bb6fb853c..90d6e9b8a8 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2297,15 +2297,12 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
     
 	if ("delete" == action)
 	{
-		LLSD args;
-		args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" :  "DeleteItem");
 		static bool sDisplayedAtSession = false;
-		std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin();
-		LLFolderViewModelItemInventory * viewModel = NULL;
+
 		bool has_folder_items = false;
-		for (; set_iter != selected_items.end(); ++set_iter)
+		for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
 		{
-			viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem());
+			LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem());
 			if (viewModel && viewModel->hasChildren())
 			{
 				has_folder_items = true;
@@ -2317,16 +2314,34 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 			bool ignore = !(LLUI::sSettingGroups["ignores"]->getBOOL("DeleteItems"));
 			if (ignore)
 			{
-
 				if (!sDisplayedAtSession)
 				{
 					LLUI::sSettingGroups["ignores"]->setBOOL("DeleteItems", TRUE);
 					sDisplayedAtSession = true;
 				}
-
 			}
 		}
-		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+		
+		LLAllDescendentsPassedFilter f;
+		for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
+		{
+			if (LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(*it))
+			{
+				folder->applyFunctorRecursively(f);
+			}
+		}
+
+		// Fall through to the generic confirmation if the user choose to ignore the specialized one
+		if ( (!f.allDescendentsPassedFilter()) && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
+		{
+			LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+		}
+		else
+		{
+			LLSD args;
+			args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" :  "DeleteItem");
+			LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+		}
         // Note: marketplace listings will be updated in the callback if delete confirmed
 		return;
 	}
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 16bf0e344d..97f614cf62 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6010,6 +6010,22 @@ You cannot undo this action.
      notext="Cancel"
      yestext="OK"/>
   </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="DeleteFilteredItems"
+   type="alertmodal">
+    <unique/>
+    Your inventory is currently filtered and not all of the items you're about to delete are currently visible.
+
+Are you sure you want to delete them?
+    <tag>confirm</tag>
+    <usetemplate
+     ignoretext="Confirm before deleting filtered items"
+     name="okcancelignore"
+     notext="Cancel"
+     yestext="OK"/>
+  </notification>
   
   <notification
      icon="alertmodal.tga"
-- 
cgit v1.2.3


From f2780a93c082e9c9a9557b7b0f6378980632b634 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Wed, 7 Jun 2017 03:16:56 +0300
Subject: MAINT-6697 Added a nullcheck to unzip_llsd()

---
 indra/llcommon/llsdserialize.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 81ba8631c6..41cdb14886 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2175,6 +2175,14 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
 		U32 have = CHUNK-strm.avail_out;
 
 		result = (U8*) realloc(result, cur_size + have);
+		if (result == NULL)
+		{
+			LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
+			inflateEnd(&strm);
+			free(result);
+			delete[] in;
+			return false;
+		}
 		memcpy(result+cur_size, out, have);
 		cur_size += have;
 
-- 
cgit v1.2.3


From d9fe21f17f8c392a602773fa36b0814a0c672761 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Wed, 7 Jun 2017 19:30:32 +0300
Subject: MAINT-6697 More nullchecks for zip/unzip functions

---
 indra/llcommon/llsdserialize.cpp | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 41cdb14886..0568a639a0 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2092,6 +2092,12 @@ std::string zip_llsd(LLSD& data)
 
 			have = CHUNK-strm.avail_out;
 			output = (U8*) realloc(output, cur_size+have);
+			if (output == NULL)
+			{
+				LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
+				deflateEnd(&strm);
+				return std::string();
+			}
 			memcpy(output+cur_size, out, have);
 			cur_size += have;
 		}
@@ -2179,7 +2185,6 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
 		{
 			LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
 			inflateEnd(&strm);
-			free(result);
 			delete[] in;
 			return false;
 		}
@@ -2275,6 +2280,14 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
 		U32 have = CHUNK-strm.avail_out;
 
 		result = (U8*) realloc(result, cur_size + have);
+		if (result == NULL)
+		{
+			LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
+			inflateEnd(&strm);
+			delete[] in;
+			valid = false;
+			return NULL;
+		}
 		memcpy(result+cur_size, out, have);
 		cur_size += have;
 
-- 
cgit v1.2.3


From c1acdb8b261e60999b820ea36171c18d4c298155 Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Wed, 7 Jun 2017 12:51:41 -0700
Subject: FIX MAINT-7456 Viewer Windows installer translation update for 9
 languages

---
 indra/newview/installers/windows/lang_de.nsi    | Bin 8420 -> 9850 bytes
 indra/newview/installers/windows/lang_es.nsi    | Bin 8458 -> 9884 bytes
 indra/newview/installers/windows/lang_fr.nsi    | Bin 8748 -> 10258 bytes
 indra/newview/installers/windows/lang_it.nsi    | Bin 8102 -> 9520 bytes
 indra/newview/installers/windows/lang_ja.nsi    | Bin 6514 -> 7204 bytes
 indra/newview/installers/windows/lang_pt-br.nsi | Bin 8522 -> 9864 bytes
 indra/newview/installers/windows/lang_ru.nsi    | Bin 7898 -> 9190 bytes
 indra/newview/installers/windows/lang_tr.nsi    | Bin 8006 -> 9286 bytes
 indra/newview/installers/windows/lang_zh.nsi    | Bin 6576 -> 6846 bytes
 9 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi
index 866accae99..2a868acc89 100644
Binary files a/indra/newview/installers/windows/lang_de.nsi and b/indra/newview/installers/windows/lang_de.nsi differ
diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi
index f4f0786332..2310346e6e 100644
Binary files a/indra/newview/installers/windows/lang_es.nsi and b/indra/newview/installers/windows/lang_es.nsi differ
diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi
index 1b5dbfc975..bec5835bed 100644
Binary files a/indra/newview/installers/windows/lang_fr.nsi and b/indra/newview/installers/windows/lang_fr.nsi differ
diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi
index a456e6e417..1d2e150525 100644
Binary files a/indra/newview/installers/windows/lang_it.nsi and b/indra/newview/installers/windows/lang_it.nsi differ
diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi
index 5b1c5f4ce9..1bd6526670 100644
Binary files a/indra/newview/installers/windows/lang_ja.nsi and b/indra/newview/installers/windows/lang_ja.nsi differ
diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi
index 9ef252d232..87032fec18 100644
Binary files a/indra/newview/installers/windows/lang_pt-br.nsi and b/indra/newview/installers/windows/lang_pt-br.nsi differ
diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi
index d7c728d3e2..2ac03d7bba 100644
Binary files a/indra/newview/installers/windows/lang_ru.nsi and b/indra/newview/installers/windows/lang_ru.nsi differ
diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi
index 97c602f4fc..1c4e2c2f48 100644
Binary files a/indra/newview/installers/windows/lang_tr.nsi and b/indra/newview/installers/windows/lang_tr.nsi differ
diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi
index 39c005a683..355e01a333 100644
Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ
-- 
cgit v1.2.3


From 7cc9455fe1b8a6194f52062c90761fffa6ae6fdc Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Wed, 7 Jun 2017 23:05:37 +0300
Subject: MAINT-6697 Correct pointer freeing

---
 indra/llcommon/llsdserialize.cpp | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 0568a639a0..3a219eb998 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2091,13 +2091,18 @@ std::string zip_llsd(LLSD& data)
 			}
 
 			have = CHUNK-strm.avail_out;
-			output = (U8*) realloc(output, cur_size+have);
-			if (output == NULL)
+			U8* new_output = (U8*) realloc(output, cur_size+have);
+			if (new_output == NULL)
 			{
 				LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
 				deflateEnd(&strm);
+				if (output)
+				{
+					free(output);
+				}
 				return std::string();
 			}
+			output = new_output;
 			memcpy(output+cur_size, out, have);
 			cur_size += have;
 		}
@@ -2180,14 +2185,19 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
 
 		U32 have = CHUNK-strm.avail_out;
 
-		result = (U8*) realloc(result, cur_size + have);
-		if (result == NULL)
+		U8* new_result = (U8*)realloc(result, cur_size + have);
+		if (new_result == NULL)
 		{
 			LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
 			inflateEnd(&strm);
+			if (result)
+			{
+				free(result);
+			}
 			delete[] in;
 			return false;
 		}
+		result = new_result;
 		memcpy(result+cur_size, out, have);
 		cur_size += have;
 
@@ -2279,15 +2289,20 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
 
 		U32 have = CHUNK-strm.avail_out;
 
-		result = (U8*) realloc(result, cur_size + have);
-		if (result == NULL)
+		U8* new_result = (U8*) realloc(result, cur_size + have);
+		if (new_result == NULL)
 		{
 			LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
 			inflateEnd(&strm);
+			if (result)
+			{
+				free(result);
+			}
 			delete[] in;
 			valid = false;
 			return NULL;
 		}
+		result = new_result;
 		memcpy(result+cur_size, out, have);
 		cur_size += have;
 
-- 
cgit v1.2.3


From 66bcb3bb8b2837a2a7638817a887ca772a4ba735 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 8 Jun 2017 17:17:59 +0300
Subject: MAINT-7460 FIXED Crash in LLPopupView::removePopup()

---
 indra/newview/llexpandabletextbox.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 711a87dc99..d657f04457 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -407,6 +407,7 @@ void LLExpandableTextBox::collapseTextBox()
 	setRect(mCollapsedRect);
 
 	updateTextBoxRect();
+	gViewerWindow->removePopup(this);
 }
 
 void LLExpandableTextBox::onFocusLost()
@@ -434,8 +435,6 @@ void LLExpandableTextBox::reshape(S32 width, S32 height, BOOL called_from_parent
     mExpanded = false;
     LLUICtrl::reshape(width, height, called_from_parent);
     updateTextBoxRect();
-
-    gViewerWindow->removePopup(this);
 }
 
 void LLExpandableTextBox::setValue(const LLSD& value)
-- 
cgit v1.2.3


From c47bf2656fe83b3ed9ab1008d5ea537c74d620fd Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 8 Jun 2017 19:44:26 +0300
Subject: MAINT-5 Fixed url named group names should not display as url links

---
 .../newview/skins/default/xui/en/notifications.xml | 24 +++++++++++-----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 97f614cf62..afdb696cb4 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -869,7 +869,7 @@ Do you wish to proceed?
    icon="alertmodal.tga"
    name="JoinGroupNoCost"
    type="alertmodal">
-You are joining group [NAME].
+You are joining group &lt;nolink&gt;[NAME]&lt;/nolink&gt;.
 Do you wish to proceed?
     <tag>group</tag>
     <tag>confirm</tag>
@@ -960,7 +960,7 @@ Sorry, trial users can't join groups.
    icon="alertmodal.tga"
    name="JoinGroupMaxGroups"
    type="alertmodal">
-You cannot join '[group_name]':
+You cannot join &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;:
 You are already a member of [group_count] groups, the maximum number allowed is [max_groups]
     <tag>success</tag>
     <tag>group_id</tag>
@@ -976,7 +976,7 @@ You are already a member of [group_count] groups, the maximum number allowed is
    icon="alertmodal.tga"
    name="JoinGroupClosedEnrollment"
    type="alertmodal">
-You cannot join '[group_name]':
+You cannot join &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;:
 The group no longer has open enrollment.
     <tag>group_id</tag>
     <tag>success</tag>
@@ -1065,7 +1065,7 @@ Your selling price will be L$[SALE_PRICE] and will be authorized for sale to [NA
    icon="alertmodal.tga"
    name="ReturnObjectsDeededToGroup"
    type="alertmodal">
-Are you sure you want to return all objects shared with the group &apos;[NAME]&apos; on this parcel of land back to their previous owner&apos;s inventory?
+Are you sure you want to return all objects shared with the group &apos;&lt;nolink&gt;[NAME]&lt;/nolink&gt;&apos; on this parcel of land back to their previous owner&apos;s inventory?
 
 *WARNING* This will delete the non-transferable objects deeded to the group!
 
@@ -1168,7 +1168,7 @@ Are you sure you want to disable all objects in this region?
    icon="alertmodal.tga"
    name="ReturnObjectsNotOwnedByGroup"
    type="alertmodal">
-Return the objects on this parcel of land that are NOT shared with the group [NAME] back to their owners?
+Return the objects on this parcel of land that are NOT shared with the group &lt;nolink&gt;[NAME]&lt;/nolink&gt; back to their owners?
 
 Objects: [N]
     <tag>confirm</tag>
@@ -1956,7 +1956,7 @@ Eject [AVATAR_NAME] from your land?
    name="EjectAvatarFromGroup"
    persist="true"
    type="notify">
-You ejected [AVATAR_NAME] from group [GROUP_NAME]
+You ejected [AVATAR_NAME] from group &lt;nolink&gt;[GROUP_NAME]&lt;/nolink&gt;
     <tag>group</tag>
   </notification>
 
@@ -3331,7 +3331,7 @@ Please select a smaller area and try again.
 By deeding this parcel, the group will be required to have and maintain sufficient land use credits.
 The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
 
-Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
+Deed this [AREA] m² of land to the group &apos;&lt;nolink&gt;[GROUP_NAME]&lt;/nolink&gt;&apos;?
     <tag>group</tag>
     <tag>confirm</tag>
     <usetemplate
@@ -3348,7 +3348,7 @@ By deeding this parcel, the group will be required to have and maintain sufficie
 The deed will include a simultaneous land contribution to the group from &apos;[NAME]&apos;.
 The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
 
-Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
+Deed this [AREA] m² of land to the group &apos;&lt;nolink&gt;[GROUP_NAME]&lt;/nolink&gt;&apos;?
     <tag>group</tag>
     <tag>confirm</tag>
     <usetemplate
@@ -4324,7 +4324,7 @@ Leave Group?
    icon="notify.tga"
    name="GroupDepart"
    type="notify">
-You have left the group &apos;[group_name]&apos;.
+You have left the group &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;.
     <tag>group</tag>
   </notification>
 
@@ -7055,7 +7055,7 @@ The objects on the selected parcel of land owned by the Resident &apos;[NAME]&ap
    name="GroupObjectsReturned"
    persist="true"
    type="notify">
-The objects on the selected parcel of land shared with the group [GROUPNAME] have been returned back to their owner&apos;s inventory.
+The objects on the selected parcel of land shared with the group &lt;nolink&gt;[GROUPNAME]&lt;/nolink&gt; have been returned back to their owner&apos;s inventory.
 Transferable deeded objects have been returned to their previous owners.
 Non-transferable objects that are deeded to the group have been deleted.
     <tag>group</tag>
@@ -8086,7 +8086,7 @@ To grant this permission please update your viewer to the latest version from [D
    show_toast="false"
    type="notify">
     <tag>group</tag>
-[GROUPNAME]&apos;s &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
+&lt;nolink&gt;[GROUPNAME]&lt;/nolink&gt;&apos;s &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
 [MESSAGE]
     <form name="form">
       <button
@@ -8217,7 +8217,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
    icon="notify.tga"
    name="VoiceInviteGroup"
    type="notify">
-[NAME] has joined a Voice Chat call with the group [GROUP].
+[NAME] has joined a Voice Chat call with the group &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
     <tag>group</tag>
     <tag>confirm</tag>
-- 
cgit v1.2.3


From 5e905cf80d472c433875452a2baaa179ceb0fe71 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 9 Jun 2017 18:16:58 +0300
Subject: MAINT-7477 FIXED [viewer-neko] Viewer crashes when saving snapshot to
 disk and closing file picker window

---
 indra/newview/llsnapshotlivepreview.cpp | 7 ++++---
 indra/newview/llviewerwindow.cpp        | 5 ++++-
 indra/newview/llviewerwindow.h          | 2 +-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index c6f8c414fa..ee8b2d79c0 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -1080,12 +1080,13 @@ BOOL LLSnapshotLivePreview::saveLocal()
 	return success;
 }
 
-//Check if failed due to insuficient memory
+//Check if failed due to insufficient memory
 BOOL LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> mFormattedImage)
 {
-	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
+	BOOL insufficient_memory;
+	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, FALSE, insufficient_memory);
 
-	if (!success)
+	if (insufficient_memory)
 	{
 		std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir();
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 45ea0f8e02..a2c5fa2630 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4354,8 +4354,10 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d
 }
 
 // Saves an image to the harddrive as "SnapshotX" where X >= 1.
-BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker)
+BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory)
 {
+	insufficient_memory = FALSE;
+
 	if (!image)
 	{
 		LL_WARNS() << "No image to save" << LL_ENDL;
@@ -4407,6 +4409,7 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke
 #endif
 	if (b_space.free < image->getDataSize())
 	{
+		insufficient_memory = TRUE;
 		return FALSE;
 	}
 	// Look for an unused file name
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 5d7076178a..38178fa910 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -352,7 +352,7 @@ public:
 	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
 	BOOL			isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
 	void			resetSnapshotLoc() const { sSnapshotDir.clear(); }
-	BOOL		    saveImageNumbered(LLImageFormatted *image, bool force_picker = false);
+	BOOL			saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory);
 
 	// Reset the directory where snapshots are saved.
 	// Client will open directory picker on next snapshot save.
-- 
cgit v1.2.3


From 5205be0c65bf8dee8b51c112083a4cc8a7cebc49 Mon Sep 17 00:00:00 2001
From: pavelkproductengine <pavelkproductengine@lindenlab.com>
Date: Wed, 31 May 2017 19:28:46 +0300
Subject: STORM-2148 Crash on trying to save texture file(s) to computer from
 inventory

---
 doc/contributions.txt          | 1 +
 indra/llimage/llimagepng.cpp   | 4 ++--
 indra/llimage/llpngwrapper.cpp | 8 +++++++-
 indra/llimage/llpngwrapper.h   | 2 +-
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 1d591e2ec2..6e4cd76d77 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1304,6 +1304,7 @@ Sovereign Engineer
     MAINT-6218
     MAINT-6913
     STORM-2143
+    STORM-2148
 SpacedOut Frye
 	VWR-34
 	VWR-45
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index a299602d79..a4823ed859 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -124,12 +124,12 @@ bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
 
 	// Temporary buffer to hold the encoded image. Note: the final image
 	// size should be much smaller due to compression.
-	U32 bufferSize = getWidth() * getHeight() * getComponents() + 1024;
+	U32 bufferSize = getWidth() * getHeight() * getComponents() + 8192;
     U8* tmpWriteBuffer = new U8[ bufferSize ];
 
 	// Delegate actual encoding work to wrapper
 	LLPngWrapper pngWrapper;
-	if (! pngWrapper.writePng(raw_image, tmpWriteBuffer))
+	if (!pngWrapper.writePng(raw_image, tmpWriteBuffer, bufferSize))
 	{
 		setLastError(pngWrapper.getErrorMessage());
 		delete[] tmpWriteBuffer;
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index da289ea889..b2fa0ed315 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -112,6 +112,11 @@ void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_siz
 void LLPngWrapper::writeDataCallback(png_structp png_ptr, png_bytep src, png_size_t length)
 {
 	PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr);
+	if (dataInfo->mOffset + length > dataInfo->mDataSize)
+	{
+		png_error(png_ptr, "Data write error. Requested data size exceeds available data size.");
+		return;
+	}
 	U8 *dest = &dataInfo->mData[dataInfo->mOffset];
 	memcpy(dest, src, length);
 	dataInfo->mOffset += static_cast<U32>(length);
@@ -272,7 +277,7 @@ void LLPngWrapper::updateMetaData()
 
 // Method to write raw image into PNG at dest. The raw scanline begins
 // at the bottom of the image per SecondLife conventions.
-BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
+BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSize)
 {
 	try
 	{
@@ -313,6 +318,7 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
 		PngDataInfo dataPtr;
 		dataPtr.mData = dest;
 		dataPtr.mOffset = 0;
+		dataPtr.mDataSize = destSize;
 		png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush);
 
 		// Setup image params
diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h
index 27d7df3bef..8d42317b0f 100644
--- a/indra/llimage/llpngwrapper.h
+++ b/indra/llimage/llpngwrapper.h
@@ -45,7 +45,7 @@ public:
 
 	BOOL isValidPng(U8* src);
 	BOOL readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL);
-	BOOL writePng(const LLImageRaw* rawImage, U8* dst);
+	BOOL writePng(const LLImageRaw* rawImage, U8* dst, size_t destSize);
 	U32  getFinalSize();
 	const std::string& getErrorMessage();
 
-- 
cgit v1.2.3


From e4c262ec5e5636c47fe1df4f5f4bf2f1b1e06891 Mon Sep 17 00:00:00 2001
From: daianakproductengine <daianakproductengine@lindenlab.com>
Date: Tue, 6 Jun 2017 20:02:31 +0300
Subject: MAINT-321 Fixed User cannot lift an object using Ctrl button + Mouse
 if Spin option was turned on earlier

---
 indra/newview/lltoolgrab.cpp | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 5623036b91..f3e661e71a 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -477,39 +477,53 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
 		return;
 	}
 
+	//--------------------------------------------------
+	// Determine target mode
+	//--------------------------------------------------
+	bool vertical_dragging = false;
+	bool spin_grabbing = false;
+	if ((mask == MASK_VERTICAL)
+		|| (gGrabBtnVertical && (mask != MASK_SPIN)))
+	{
+		vertical_dragging = TRUE;
+	}
+	else if ((mask == MASK_SPIN)
+			|| (gGrabBtnSpin && (mask != MASK_VERTICAL)))
+	{
+		spin_grabbing = TRUE;
+	}
+
 	//--------------------------------------------------
 	// Toggle spinning
 	//--------------------------------------------------
-	if (mSpinGrabbing && !(mask == MASK_SPIN) && !gGrabBtnSpin)
+	if (mSpinGrabbing && !spin_grabbing)
 	{
-		// user released ALT key, stop spinning
+		// user released or switched mask key(s), stop spinning
 		stopSpin();
 	}
-	else if (!mSpinGrabbing && (mask == MASK_SPIN) )
+	else if (!mSpinGrabbing && spin_grabbing)
 	{
-		// user pressed ALT key, start spinning
+		// user pressed mask key(s), start spinning
 		startSpin();
 	}
+	mSpinGrabbing = spin_grabbing;
 
 	//--------------------------------------------------
 	// Toggle vertical dragging
 	//--------------------------------------------------
-	if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
+	if (mVerticalDragging && !vertical_dragging)
 	{
 		// ...switch to horizontal dragging
-		mVerticalDragging = FALSE;
-
 		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
 		mDragStartFromCamera = mDragStartPointGlobal - gAgentCamera.getCameraPositionGlobal();
 	}
-	else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
+	else if (!mVerticalDragging && vertical_dragging)
 	{
 		// ...switch to vertical dragging
-		mVerticalDragging = TRUE;
-
 		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
 		mDragStartFromCamera = mDragStartPointGlobal - gAgentCamera.getCameraPositionGlobal();
 	}
+	mVerticalDragging = vertical_dragging;
 
 	const F32 RADIANS_PER_PIXEL_X = 0.01f;
 	const F32 RADIANS_PER_PIXEL_Y = 0.01f;
@@ -755,12 +769,13 @@ void LLToolGrabBase::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
 		//--------------------------------------------------
 		// Toggle vertical dragging
 		//--------------------------------------------------
-		if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
+		if (!(mask == MASK_VERTICAL) && !gGrabBtnVertical)
 		{
 			mVerticalDragging = FALSE;
 		}
 	
-		else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
+		else if ((gGrabBtnVertical && (mask != MASK_SPIN)) 
+				|| (mask == MASK_VERTICAL))
 		{
 			mVerticalDragging = TRUE;
 		}
-- 
cgit v1.2.3


From 99b203d4e8e0ec530d0ee8b0627e5fa3cf0c59db Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 9 Jun 2017 14:06:04 +0100
Subject: MAINT-7482 - continue running with a warning on receipt of unknown
 message

---
 indra/llmessage/lltemplatemessagereader.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 406afadd2f..4e0c53c37e 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -499,9 +499,10 @@ BOOL LLTemplateMessageReader::decodeTemplate(
 	}
 	else
 	{
-		LL_WARNS() << "Message #" << std::hex << num << std::dec
-			<< " received but not registered!" << LL_ENDL;
-		gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
+        // MAINT-7482 - make viewer more tolerant of unknown messages.
+		LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
+                        << " received but not registered!" << LL_ENDL;
+		//gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
 		return(FALSE);
 	}
 
-- 
cgit v1.2.3


From d15e8577773b9afb92c232c757b89343c93d56bf Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Fri, 9 Jun 2017 12:32:29 -0700
Subject: FIX MAINT-7456 Corrected translation errors in Russian and Spanish.

---
 indra/newview/installers/windows/lang_es.nsi | Bin 9884 -> 9872 bytes
 indra/newview/installers/windows/lang_ru.nsi | Bin 9190 -> 9188 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi
index 2310346e6e..1ecf254ffb 100644
Binary files a/indra/newview/installers/windows/lang_es.nsi and b/indra/newview/installers/windows/lang_es.nsi differ
diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi
index 2ac03d7bba..019c66123c 100644
Binary files a/indra/newview/installers/windows/lang_ru.nsi and b/indra/newview/installers/windows/lang_ru.nsi differ
-- 
cgit v1.2.3


From 34cfd3714b8c8f14effd55001191b0519861e2b0 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Fri, 9 Jun 2017 22:02:42 +0300
Subject: MAINT-7478 Fixed "No callback" log spam

---
 indra/newview/llfloaterimnearbychat.cpp | 10 ++++++++++
 indra/newview/llfloaterimsessiontab.cpp |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 7895a5ff48..b2568abb83 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -87,6 +87,10 @@ static LLChatTypeTrigger sChatTypeTriggers[] = {
 	{ "/shout"	, CHAT_TYPE_SHOUT}
 };
 
+bool cb_do_nothing()
+{
+	return false;
+}
 
 LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd)
 :	LLFloaterIMSessionTab(LLSD(LLUUID::null)),
@@ -97,6 +101,12 @@ LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd)
     mIsP2PChat = false;
 	mIsNearbyChat = true;
 	mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
+
+	// Required by LLFloaterIMSessionTab::mGearBtn
+	// But nearby floater has no 'per agent' menu items, 
+	mEnableCallbackRegistrar.add("Avatar.EnableGearItem", boost::bind(&cb_do_nothing));
+	mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&cb_do_nothing));
+	mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&cb_do_nothing));
 }
 
 //static
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 2cd94c592a..e8dbd2598e 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -46,6 +46,10 @@
 
 const F32 REFRESH_INTERVAL = 1.0f;
 
+void cb_do_nothing()
+{
+}
+
 LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
 :	LLTransientDockableFloater(NULL, false, session_id),
 	mIsP2PChat(false),
@@ -82,6 +86,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
     mEnableCallbackRegistrar.add("Avatar.CheckItem",  boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem,	this, _2));
     mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2));
     mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2));
+    mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_do_nothing));
 }
 
 LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
-- 
cgit v1.2.3


From 3d8dc8cd6dd4ea59ff226f91b114a3298f8f096f Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Mon, 12 Jun 2017 15:26:10 +0300
Subject: Fixed line endings for llpngwrapper.cpp

---
 indra/llimage/llpngwrapper.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index b2fa0ed315..eb70b78a36 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -112,10 +112,10 @@ void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_siz
 void LLPngWrapper::writeDataCallback(png_structp png_ptr, png_bytep src, png_size_t length)
 {
 	PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr);
-	if (dataInfo->mOffset + length > dataInfo->mDataSize)
-	{
-		png_error(png_ptr, "Data write error. Requested data size exceeds available data size.");
-		return;
+	if (dataInfo->mOffset + length > dataInfo->mDataSize)
+	{
+		png_error(png_ptr, "Data write error. Requested data size exceeds available data size.");
+		return;
 	}
 	U8 *dest = &dataInfo->mData[dataInfo->mOffset];
 	memcpy(dest, src, length);
-- 
cgit v1.2.3


From 52a964376b6aabd1abadfb7329004c2e58b7b97a Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Mon, 12 Jun 2017 16:28:53 +0300
Subject: MAINT-7478 Build fix, boost function doesn't like 'reuse' of
 cb_do_nothing

---
 indra/newview/llfloaterimsessiontab.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index e8dbd2598e..3aee08482b 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -46,7 +46,7 @@
 
 const F32 REFRESH_INTERVAL = 1.0f;
 
-void cb_do_nothing()
+void cb_group_do_nothing()
 {
 }
 
@@ -86,7 +86,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
     mEnableCallbackRegistrar.add("Avatar.CheckItem",  boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem,	this, _2));
     mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2));
     mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2));
-    mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_do_nothing));
+    mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing));
 }
 
 LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
-- 
cgit v1.2.3


From 515db9c3e6acf30d0adb58868ac0acfe684c4166 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Mon, 12 Jun 2017 20:17:55 +0300
Subject: MAINT-7325 Fixed empty cached image being used instead of fetching

---
 indra/newview/llviewertexture.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c162af371f..cd8dd54fa6 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2089,7 +2089,9 @@ bool LLViewerFetchedTexture::updateFetch()
 	{
 		make_request = false;
 	}
-	else if(mCachedRawImage.notNull() && (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
+	else if(mCachedRawImage.notNull() // can be empty
+			&& mCachedRawImageReady
+			&& (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
 	{
 		make_request = false;
 		switchToCachedImage(); //use the cached raw data first
-- 
cgit v1.2.3


From bbfe5ec2a9a9da9f9863e61ec0da681c0eea109a Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 13 Jun 2017 17:47:38 +0300
Subject: MAINT-7491 FIXED "Remove from current outfit" option is missing for
 all system folders including COF

---
 indra/newview/llinventorybridge.cpp | 38 ++++++++++++++++---------------------
 1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c8a20c9d97..2751631a59 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4066,8 +4066,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 	LLFolderType::EType type = category->getPreferredType();
 	const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
 	// BAP change once we're no longer treating regular categories as ensembles.
-	const bool is_ensemble = (type == LLFolderType::FT_NONE ||
-		LLFolderType::lookupIsEnsembleType(type));
 	const bool is_agent_inventory = isAgentInventory();
 
 	// Only enable calling-card related options for non-system folders.
@@ -4110,30 +4108,26 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 			}
 
 			items.push_back(std::string("Replace Outfit"));
-
-			if (is_agent_inventory)
+		}
+		if (is_agent_inventory)
+		{
+			items.push_back(std::string("Folder Wearables Separator"));
+			items.push_back(std::string("Remove From Outfit"));
+			if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
 			{
-				items.push_back(std::string("Folder Wearables Separator"));
-				if (is_ensemble)
-				{
-					items.push_back(std::string("Wear As Ensemble"));
-				}
-				items.push_back(std::string("Remove From Outfit"));
-				if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
-				{
 					disabled_items.push_back(std::string("Remove From Outfit"));
-				}
-			}
-			if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
-			{
-				disabled_items.push_back(std::string("Replace Outfit"));
-			}
-			if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID))
-			{
-				disabled_items.push_back(std::string("Add To Outfit"));
 			}
-			items.push_back(std::string("Outfit Separator"));
 		}
+		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
+		{
+			disabled_items.push_back(std::string("Replace Outfit"));
+		}
+		if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID))
+		{
+			disabled_items.push_back(std::string("Add To Outfit"));
+		}
+		items.push_back(std::string("Outfit Separator"));
+
 	}
 }
 
-- 
cgit v1.2.3


From c2363c3ae95c38a6ed175375d5af638d64acef22 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 14 Jun 2017 11:29:30 +0300
Subject: MAINT-7489 FIXED Viewer may silently empty trash without the users
 request under obscure inventory folder states

---
 indra/newview/llinventorymodel.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0ccaa1992d..dc75e09ad9 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -462,12 +462,8 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E
         }
         
         // Purge the emptied folder
-        // Note: we'd like to use purgeObject() but it doesn't cleanly eliminate the folder
-        // which leads to issues further down the road when the folder is found again
-        //purgeObject(folder_id);
-        // We remove the folder and empty the trash instead which seems to work
-		removeCategory(folder_id);
-        gInventory.emptyFolderType("", LLFolderType::FT_TRASH);
+        removeCategory(folder_id);
+        remove_inventory_category(folder_id, NULL);
 	}
 }
 
-- 
cgit v1.2.3


From 341ecb2324d7895977a29e11afa9657a27da5912 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 15 Jun 2017 16:45:57 +0300
Subject: MAINT-7483 Fixed inability to drag a folder into object contents

---
 indra/newview/llinventoryobserver.cpp |  5 +++++
 indra/newview/lltooldraganddrop.cpp   | 13 ++++++++++---
 indra/newview/lltooldraganddrop.h     |  2 +-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 4427f32de9..26d7a7a28a 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -350,6 +350,11 @@ void LLInventoryFetchDescendentsObserver::startFetch()
 		if (!cat) continue;
 		if (!isCategoryComplete(cat))
 		{
+			// CHECK IT: isCategoryComplete() checks both version and descendant count but
+			// fetch() only works for Unknown version and doesn't care about descentants,
+			// as result fetch won't start and folder will potentially get stuck as
+			// incomplete in observer.
+			// Likely either both should use only version or both should check descendants.
 			cat->fetch();		//blindly fetch it without seeing if anything else is fetching it.
 			mIncomplete.push_back(*it);	//Add to list of things being downloaded for this observer.
 		}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 49436ee406..bd68d8c999 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1450,13 +1450,20 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj,
 
 // accessor that looks at permissions, copyability, and names of
 // inventory items to determine if a drop would be ok.
-EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
+EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item, EDragAndDropType type)
 {
 	// check the basics
 	if (!item || !obj) return ACCEPT_NO;
 	// HACK: downcast
 	LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item;
-	if (!vitem->isFinished()) return ACCEPT_NO;
+	if (!vitem->isFinished() && (type != DAD_CATEGORY))
+	{
+		// Note: for DAD_CATEGORY we assume that folder version check passed and folder 
+		// is complete, meaning that items inside are up to date. 
+		// (isFinished() == false) at the moment shows that item was loaded from cache.
+		// Library or agent inventory only.
+		return ACCEPT_NO;
+	}
 	if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links
 
 	// deny attempts to drop from an object onto itself. This is to
@@ -2296,7 +2303,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
 				(*item_iter) = item;
 			}
 			*/
-			rv = willObjectAcceptInventory(root_object, item);
+			rv = willObjectAcceptInventory(root_object, item, DAD_CATEGORY);
 			if (rv < ACCEPT_YES_COPY_SINGLE)
 			{
 				LL_DEBUGS() << "Object will not accept " << item->getUUID() << LL_ENDL;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 766046785b..2d99de2244 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -224,7 +224,7 @@ protected:
 	
 	// accessor that looks at permissions, copyability, and names of
 	// inventory items to determine if a drop would be ok.
-	static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item);
+	static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item, EDragAndDropType type = DAD_NONE);
 
 public:
 	// helper functions
-- 
cgit v1.2.3


From 65208b7741c1d842b5a5c6822a56cb9d34158dea Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 16 Jun 2017 17:46:12 +0300
Subject: MAINT-7488 FIXED [Windows] Viewer crashes when pasting empty string
 from clipboard

---
 indra/llcommon/llstring.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 2255e638c2..abe5fda603 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -1325,6 +1325,10 @@ void LLStringUtilBase<T>::removeCRLF(string_type& string)
 template<class T> 
 void LLStringUtilBase<T>::removeWindowsCR(string_type& string)
 {
+    if (string.empty())
+    {
+        return;
+    }
     const T LF = 10;
     const T CR = 13;
 
-- 
cgit v1.2.3


From 75ee01277432a32178aac03ae606df6909c6c959 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Fri, 16 Jun 2017 18:55:43 +0300
Subject: MAINT-1614 Fixed Object changed its position inworld but value in
 Edit tool was not changed

---
 indra/llui/llspinctrl.cpp | 26 ++++++++++++++++++++++++++
 indra/llui/llspinctrl.h   |  1 +
 2 files changed, 27 insertions(+)

diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index d49e216898..f6831c6d5e 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -130,6 +130,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
 	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
 	mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
 	mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
+	mEditor->setFocusLostCallback( boost::bind(&LLSpinCtrl::onEditorLostFocus, _1, this ));
 	if (p.allow_digits_only)
 	{
 		mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
@@ -239,6 +240,31 @@ void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
 	self->onFocusReceived();
 }
 
+// static
+void LLSpinCtrl::onEditorLostFocus( LLFocusableElement* caller, void *userdata )
+{
+	LLSpinCtrl* self = (LLSpinCtrl*) userdata;
+	llassert( caller == self->mEditor );
+
+	self->onFocusLost();
+
+	std::string text = self->mEditor->getText();
+
+	LLLocale locale(LLLocale::USER_LOCALE);
+	F32 val = (F32)atof(text.c_str());
+
+	F32 saved_val = self->getValueF32();
+	if (saved_val != val && !self->mEditor->isDirty())
+	{
+		// Editor was focused when value update arrived, string
+		// in editor is different from one in spin control.
+		// Since editor is not dirty, it won't commit, so either
+		// attempt to commit value from editor or revert to a more
+		// recent value from spin control
+		self->updateEditor();
+	}
+}
+
 void LLSpinCtrl::setValue(const LLSD& value )
 {
 	F32 v = (F32)value.asReal();
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index e34add879d..cab99c35bd 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -93,6 +93,7 @@ public:
 
 	void			onEditorCommit(const LLSD& data);
 	static void		onEditorGainFocus(LLFocusableElement* caller, void *userdata);
+	static void		onEditorLostFocus(LLFocusableElement* caller, void *userdata);
 	static void		onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
 
 	void			onUpBtn(const LLSD& data);
-- 
cgit v1.2.3


From b959a156bafd83355b6b7350318500cdc14420f3 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 20 Jun 2017 17:14:18 +0300
Subject: MAINT-7507 FIXED When assigning abilities to a group role, ticking
 "Manage ban list" causes other selected abilities to untick

---
 indra/newview/llpanelgrouproles.cpp | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 78270c20bb..66a0a1d4ad 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -2472,12 +2472,7 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
 		
 		//////////////////////////////////////////////////////////////////////////
 
-		LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.find(role_id);
-		U64 current_role_powers = GP_NO_POWERS;
-		if (rit != gdatap->mRoles.end())
-		{
-			current_role_powers = ((*rit).second->getRoleData().mRolePowers);
-		}
+		U64 current_role_powers = gdatap->getRolePowers(role_id);
 
 		if(isEnablingAbility)
 		{
-- 
cgit v1.2.3


From c55d9a59a25cbc311c63ca8bfee0189b090ff99a Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 18 Jul 2017 16:17:59 +0300
Subject: MAINT-7607 FIXED Viewer crashes when double clicking on scroll bar
 arrow in Outfit Gallery tab

---
 indra/newview/lloutfitgallery.cpp | 25 ++++++++++++-------------
 indra/newview/lloutfitgallery.h   |  7 ++++---
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 31e89c0ed0..5518656f3f 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -344,7 +344,7 @@ void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item)
     mItemPanels.pop_back();
 }
 
-LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name)
+LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name, LLUUID outfit_id)
 {
     LLOutfitGalleryItem::Params giparams;
     LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams);
@@ -353,6 +353,7 @@ LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name)
     gitem->setFollowsLeft();
     gitem->setFollowsTop();
     gitem->setOutfitName(name);
+    gitem->setUUID(outfit_id);
     return gitem;
 }
 
@@ -511,7 +512,7 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
     if (!cat) return;
 
     std::string name = cat->getName();
-    LLOutfitGalleryItem* item = buildGalleryItem(name);
+    LLOutfitGalleryItem* item = buildGalleryItem(name, cat_id);
     mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item));
     item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
         _1, _2, _3, cat_id));
@@ -661,7 +662,8 @@ LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p)
     mSelected(false),
     mWorn(false),
     mDefaultImage(true),
-    mOutfitName("")
+    mOutfitName(""),
+    mUUID(LLUUID())
 {
     buildFromFile("panel_outfit_gallery_item.xml");
 }
@@ -745,23 +747,20 @@ BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
     return LLUICtrl::handleRightMouseDown(x, y, mask);
 }
 
-BOOL LLOutfitGallery::handleDoubleClick(S32 x, S32 y, MASK mask)
+BOOL LLOutfitGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
     LLTabContainer* appearence_tabs = LLPanelOutfitsInventory::findInstance()->getChild<LLTabContainer>("appearance_tabs");
-    LLPanel* panel = NULL;
-    LLAccordionCtrl* accordion = NULL;
-    if (appearence_tabs != NULL)
+    if (appearence_tabs && (mUUID != LLUUID()))
     {
         appearence_tabs->selectTabByName("outfitslist_tab");
-        panel = appearence_tabs->getCurrentPanel();
-        if (panel != NULL)
+        LLPanel* panel = appearence_tabs->getCurrentPanel();
+        if (panel)
         {
-            accordion = panel->getChild<LLAccordionCtrl>("outfits_accordion");
+            LLAccordionCtrl* accordion = panel->getChild<LLAccordionCtrl>("outfits_accordion");
             LLOutfitsList* outfit_list = dynamic_cast<LLOutfitsList*>(panel);
             if (accordion != NULL && outfit_list != NULL)
             {
-                LLUUID item_id = getSelectedOutfitUUID();
-                outfit_list->setSelectedOutfitByUUID(item_id);
+                outfit_list->setSelectedOutfitByUUID(mUUID);
                 LLAccordionCtrlTab* tab = accordion->getSelectedTab();
                 tab->showAndFocusHeader();
                 return TRUE;
@@ -769,7 +768,7 @@ BOOL LLOutfitGallery::handleDoubleClick(S32 x, S32 y, MASK mask)
         }
     }
 
-	return LLUICtrl::handleDoubleClick(x, y, mask);
+    return LLPanel::handleDoubleClick(x, y, mask);
 }
 
 void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id)
diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h
index 37e75f1109..2566247072 100644
--- a/indra/newview/lloutfitgallery.h
+++ b/indra/newview/lloutfitgallery.h
@@ -115,8 +115,6 @@ public:
     void onBeforeOutfitSnapshotSave();
     void onAfterOutfitSnapshotSave();
 
-    /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
-
 protected:
     /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
     /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
@@ -150,7 +148,7 @@ private:
     void updateRowsIfNeeded();
     void updateGalleryWidth();
 
-    LLOutfitGalleryItem* buildGalleryItem(std::string name);
+    LLOutfitGalleryItem* buildGalleryItem(std::string name, LLUUID outfit_id);
 
     void onTextureSelectionChanged(LLInventoryItem* itemp);
 
@@ -258,6 +256,7 @@ public:
     /*virtual*/ void draw();
     /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
     /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+    /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
 
     void setDefaultImage();
     void setImageAssetId(LLUUID asset_id);
@@ -265,6 +264,7 @@ public:
     void setOutfitName(std::string name);
     void setOutfitWorn(bool value);
     void setSelected(bool value);
+    void setUUID(LLUUID outfit_id) {mUUID = outfit_id;}
     
     std::string getItemName() {return mOutfitName;}
     bool isDefaultImage() {return mDefaultImage;}
@@ -274,6 +274,7 @@ public:
     
 private:
     LLPointer<LLViewerFetchedTexture> mTexturep;
+    LLUUID mUUID;
     LLUUID mImageAssetId;
     LLTextBox* mOutfitNameText;
     LLTextBox* mOutfitWornText;
-- 
cgit v1.2.3


From 2efa40fa6089dabbaccc228d331679c8c92f797f Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Fri, 21 Jul 2017 05:29:51 +0300
Subject: MAINT-7356 Logic fix and cleanup

---
 indra/llui/llnotifications.cpp         |  6 ++++++
 indra/llui/llnotifications.h           |  1 +
 indra/newview/llinventoryfunctions.cpp | 32 ++++++--------------------------
 3 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index d40347de13..6710e9993d 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1799,6 +1799,12 @@ bool LLNotifications::getIgnoreAllNotifications()
 	return mIgnoreAllNotifications; 
 }
 
+void LLNotifications::setIgnored(const std::string& name, bool ignored)
+{
+	LLNotificationTemplatePtr templatep = getTemplate(name);
+	templatep->mForm->setIgnored(ignored);
+}
+
 bool LLNotifications::getIgnored(const std::string& name)
 {
 	LLNotificationTemplatePtr templatep = getTemplate(name);
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index a7a5490432..b06d7cbf4c 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -964,6 +964,7 @@ public:
 	void setIgnoreAllNotifications(bool ignore);
 	bool getIgnoreAllNotifications();
 
+	void setIgnored(const std::string& name, bool ignored);
 	bool getIgnored(const std::string& name);
 
 	bool isVisibleByRules(LLNotificationPtr pNotification);
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 90d6e9b8a8..d282240bfb 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -92,8 +92,6 @@ BOOL LLInventoryState::sWearNewClothing = FALSE;
 LLUUID LLInventoryState::sWearNewClothingTransactionID;
 std::list<LLUUID> LLInventoryAction::sMarketplaceFolders;
 
-const int LLInventoryAction::sConfirmOnDeleteItemsNumber = 5;
-
 // Helper function : callback to update a folder after inventory action happened in the background
 void update_folder_cb(const LLUUID& dest_folder)
 {
@@ -2298,29 +2296,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 	if ("delete" == action)
 	{
 		static bool sDisplayedAtSession = false;
-
-		bool has_folder_items = false;
-		for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
-		{
-			LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem());
-			if (viewModel && viewModel->hasChildren())
-			{
-				has_folder_items = true;
-				break;
-			}
-		}
-		if (root->getSelectedCount() >= sConfirmOnDeleteItemsNumber || has_folder_items)
-		{
-			bool ignore = !(LLUI::sSettingGroups["ignores"]->getBOOL("DeleteItems"));
-			if (ignore)
-			{
-				if (!sDisplayedAtSession)
-				{
-					LLUI::sSettingGroups["ignores"]->setBOOL("DeleteItems", TRUE);
-					sDisplayedAtSession = true;
-				}
-			}
-		}
 		
 		LLAllDescendentsPassedFilter f;
 		for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
@@ -2330,7 +2305,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 				folder->applyFunctorRecursively(f);
 			}
 		}
-
 		// Fall through to the generic confirmation if the user choose to ignore the specialized one
 		if ( (!f.allDescendentsPassedFilter()) && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
 		{
@@ -2338,6 +2312,12 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 		}
 		else
 		{
+			if (!sDisplayedAtSession) // ask for the confirmation at least once per session
+			{
+				LLNotifications::instance().setIgnored("DeleteItems", false);
+				sDisplayedAtSession = true;
+			}
+
 			LLSD args;
 			args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" :  "DeleteItem");
 			LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
-- 
cgit v1.2.3


From dcb6a850aae7692f66ffe156637264b910007b14 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Tue, 25 Jul 2017 03:18:59 +0300
Subject: MAINT-7356 Improved the notification appearance

---
 indra/llui/llnotifications.cpp                     |  6 ++++--
 indra/llui/llnotifications.h                       |  4 +++-
 indra/newview/lltoastalertpanel.cpp                |  4 ++++
 .../newview/skins/default/xui/en/notifications.xml | 24 +++++++++++++++++-----
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 6710e9993d..7bafd711cb 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -67,7 +67,8 @@ LLNotificationForm::FormIgnore::FormIgnore()
 :	text("text"),
 	control("control"),
 	invert_control("invert_control", false),
-	save_option("save_option", false)
+	save_option("save_option", false),
+	session_only("session_only", false)
 {}
 
 LLNotificationForm::FormButton::FormButton()
@@ -125,6 +126,7 @@ bool handleIgnoredNotification(const LLSD& payload)
 		switch(form->getIgnoreType())
 		{
 		case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE:
+		case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY:
 			response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON);
 			break;
 		case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE:
@@ -197,7 +199,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
 
 		if (!p.ignore.save_option)
 		{
-			mIgnore = IGNORE_WITH_DEFAULT_RESPONSE;
+			mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE;
 		}
 		else
 		{
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index b06d7cbf4c..ccdfb90054 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -179,6 +179,7 @@ public:
 		Optional<bool>			save_option;
 		Optional<std::string>	control;
 		Optional<bool>			invert_control;
+		Optional<bool>			session_only;
 
 		FormIgnore();
 	};
@@ -232,7 +233,8 @@ public:
 	typedef enum e_ignore_type
 	{ 
 		IGNORE_NO,
-		IGNORE_WITH_DEFAULT_RESPONSE, 
+		IGNORE_WITH_DEFAULT_RESPONSE,
+		IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY,
 		IGNORE_WITH_LAST_RESPONSE, 
 		IGNORE_SHOW_AGAIN 
 	} EIgnoreType;
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index bbce717c20..dbf0893e43 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -351,6 +351,10 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 	{
 		setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
 	}
+	if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
+	{
+		setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label);
+	}
 	else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
 	{
 		setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 71b0edb572..3ca7feae17 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4,6 +4,11 @@
 		Don&apos;t show me this again
   </global>
 
+  <global name="skipnexttimesessiononly">
+
+    Don&apos;t show me this again (for this session only)
+  </global>
+
   <global name="alwayschoose">
 
 		Always choose this option
@@ -6004,11 +6009,20 @@ You cannot undo this action.
     <unique/>
     [QUESTION]
     <tag>confirm</tag>
-    <usetemplate
-     ignoretext="Confirm before deleting items"
-     name="okcancelignore"
-     notext="Cancel"
-     yestext="OK"/>
+    <form name="form">
+     <ignore name="ignore"
+      session_only="true"
+      text="Confirm before deleting items"/>
+      <button
+       default="true"
+       index="0"
+       name="Yes"
+       text="OK"/>
+      <button
+       index="1"
+       name="No"
+       text="Cancel"/>
+    </form>
   </notification>
 
   <notification
-- 
cgit v1.2.3


From 5d812b95e8fe600ba3fc4c15f6e06fd5b888f21a Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 11 Jul 2017 14:54:29 +0300
Subject: MAINT-7581 [contribution] Closing the 'Replace links' floater crashes
 the viewer if a replace is in progress

---
 doc/contributions.txt                  |  1 +
 indra/newview/llfloaterlinkreplace.cpp | 22 +++++++++-------------
 indra/newview/llfloaterlinkreplace.h   | 11 +++--------
 3 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 549adaaef7..064639fe72 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -823,6 +823,7 @@ Kitty Barnett
 	MAINT-6154
 	MAINT-6568
 	STORM-2149
+	MAINT-7581
 Kolor Fall
 Komiko Okamoto
 Korvel Noh
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index 3f80d6f1a4..10cce3bd22 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -41,16 +41,13 @@ LLFloaterLinkReplace::LLFloaterLinkReplace(const LLSD& key)
 	mRemainingItems(0),
 	mSourceUUID(LLUUID::null),
 	mTargetUUID(LLUUID::null),
-	mInstance(NULL),
 	mBatchSize(gSavedSettings.getU32("LinkReplaceBatchSize"))
 {
 	mEventTimer.stop();
-	mInstance = this;
 }
 
 LLFloaterLinkReplace::~LLFloaterLinkReplace()
 {
-	mInstance = NULL;
 }
 
 BOOL LLFloaterLinkReplace::postBuild()
@@ -180,11 +177,9 @@ void LLFloaterLinkReplace::onStartClicked()
 	}
 }
 
-void LLFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id,
-												const LLUUID& target_item_id,
-												bool needs_wearable_ordering_update,
-												bool needs_description_update,
-												const LLUUID& outfit_folder_id)
+// static
+void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& old_item_id, const LLUUID& target_item_id,
+												bool needs_wearable_ordering_update, bool needs_description_update, const LLUUID& outfit_folder_id)
 {
 	LL_DEBUGS() << "Inventory link replace:" << LL_NEWLINE
 		<< " - old_item_id = " << old_item_id.asString() << LL_NEWLINE
@@ -239,20 +234,21 @@ void LLFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id,
 		outfit_update_folder = outfit_folder_id;
 	}
 
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, this, outfit_update_folder));
+	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, floater_handle, outfit_update_folder));
 	remove_inventory_object(old_item_id, cb);
 }
 
-void LLFloaterLinkReplace::itemRemovedCallback(const LLUUID& outfit_folder_id)
+// static
+void LLFloaterLinkReplace::itemRemovedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& outfit_folder_id)
 {
 	if (outfit_folder_id.notNull())
 	{
 		LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(outfit_folder_id);
 	}
 
-	if (mInstance)
+	if (!floater_handle.isDead())
 	{
-		decreaseOpenItemCount();
+		floater_handle.get()->decreaseOpenItemCount();
 	}
 }
 
@@ -324,7 +320,7 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items)
 			LLInventoryObject::const_object_list_t obj_array;
 			obj_array.push_back(LLConstPointer<LLInventoryObject>(target_item));
 			LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::linkCreatedCallback,
-																											this,
+																											getDerivedHandle<LLFloaterLinkReplace>(),
 																											source_item->getUUID(),
 																											target_item->getUUID(),
 																											needs_wearable_ordering_update,
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index 377dd1d450..dd5c301206 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -98,12 +98,9 @@ private:
 	void updateFoundLinks();
 	void processBatch(LLInventoryModel::item_array_t items);
 
-	void linkCreatedCallback(const LLUUID& old_item_id,
-								const LLUUID& target_item_id,
-								bool needs_wearable_ordering_update,
-								bool needs_description_update,
-								const LLUUID& outfit_folder_id);
-	void itemRemovedCallback(const LLUUID& outfit_folder_id);
+	static void linkCreatedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& old_item_id, const LLUUID& target_item_id,
+	                                bool needs_wearable_ordering_update, bool needs_description_update, const LLUUID& outfit_folder_id);
+	static void itemRemovedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& outfit_folder_id);
 
 	void onSourceItemDrop(const LLUUID& source_item_id);
 	void onTargetItemDrop(const LLUUID& target_item_id);
@@ -120,8 +117,6 @@ private:
 	U32		mBatchSize;
 
 	LLInventoryModel::item_array_t	mRemainingInventoryItems;
-
-	LLFloaterLinkReplace* mInstance;
 };
 
 #endif // LL_FLOATERLINKREPLACE_H
-- 
cgit v1.2.3


From f9b6b0f50d94c5a8838a00ce4b4013b2a0dead06 Mon Sep 17 00:00:00 2001
From: Mnikolenko ProductEngine <mnikolenko@productengine.com>
Date: Mon, 24 Jul 2017 17:48:55 +0300
Subject: MAINT-7629 FIXED Crash in LLSpeakerMgr::findSpeaker(LLUUID const &)

---
 indra/newview/llchathistory.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 5748eeec47..a9e8e77a0b 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -452,11 +452,13 @@ public:
 			if (gAgent.isInGroup(mSessionID))
 			{
 				LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
-				const LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId());
-
-				if (NULL != speakerp)
+				if(speaker_mgr)
 				{
-					return !speakerp->mModeratorMutedText;
+					const LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId());
+					if (NULL != speakerp)
+					{
+						return !speakerp->mModeratorMutedText;
+					}
 				}
 			}
 			return false;
-- 
cgit v1.2.3


From c3f8eb716162f8cec2b2af2a881807b455c81597 Mon Sep 17 00:00:00 2001
From: Mnikolenko ProductEngine <mnikolenko@productengine.com>
Date: Tue, 25 Jul 2017 17:39:40 +0300
Subject: MAINT-7636 Crash in LLPanelClassifiedInfo::sendClickMessage(..)

---
 indra/newview/llpanelclassified.cpp | 57 ++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 26 deletions(-)

diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 5d1ae4ff10..b9b97f4cce 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -208,19 +208,21 @@ void LLPanelClassifiedInfo::onOpen(const LLSD& key)
 	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
 	gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough);
 
-	// While we're at it let's get the stats from the new table if that
-	// capability exists.
-	std::string url = gAgent.getRegion()->getCapability("SearchStatRequest");
-	if (!url.empty())
+	if (gAgent.getRegion())
 	{
-		LL_INFOS() << "Classified stat request via capability" << LL_ENDL;
-		LLSD body;
-        LLUUID classifiedId = getClassifiedId();
-		body["classified_id"] = classifiedId;
-        LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body,
-            boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1));
+		// While we're at it let's get the stats from the new table if that
+		// capability exists.
+		std::string url = gAgent.getRegion()->getCapability("SearchStatRequest");
+		if (!url.empty())
+		{
+			LL_INFOS() << "Classified stat request via capability" << LL_ENDL;
+			LLSD body;
+			LLUUID classifiedId = getClassifiedId();
+			body["classified_id"] = classifiedId;
+			LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body,
+				boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1));
+		}
 	}
-
 	// Update classified click stats.
 	// *TODO: Should we do this when opening not from search?
 	sendClickMessage("profile");
@@ -540,21 +542,24 @@ void LLPanelClassifiedInfo::sendClickMessage(
 		const LLVector3d& global_pos,
 		const std::string& sim_name)
 {
-	// You're allowed to click on your own ads to reassure yourself
-	// that the system is working.
-	LLSD body;
-	body["type"]			= type;
-	body["from_search"]		= from_search;
-	body["classified_id"]	= classified_id;
-	body["parcel_id"]		= parcel_id;
-	body["dest_pos_global"]	= global_pos.getValue();
-	body["region_name"]		= sim_name;
-
-	std::string url = gAgent.getRegion()->getCapability("SearchStatTracking");
-	LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL;
-	LL_INFOS() << "body: [" << body << "]" << LL_ENDL;
-    LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
-        "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent.");
+	if (gAgent.getRegion())
+	{
+		// You're allowed to click on your own ads to reassure yourself
+		// that the system is working.
+		LLSD body;
+		body["type"]			= type;
+		body["from_search"]		= from_search;
+		body["classified_id"]	= classified_id;
+		body["parcel_id"]		= parcel_id;
+		body["dest_pos_global"]	= global_pos.getValue();
+		body["region_name"]		= sim_name;
+
+		std::string url = gAgent.getRegion()->getCapability("SearchStatTracking");
+		LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL;
+		LL_INFOS() << "body: [" << body << "]" << LL_ENDL;
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
+            "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent.");
+	}
 }
 
 void LLPanelClassifiedInfo::sendClickMessage(const std::string& type)
-- 
cgit v1.2.3


From 304de39ff1b7d7c897adff50a71488e3361442d7 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Fri, 28 Jul 2017 00:41:25 +0300
Subject: MAINT-7632 Crash in LLMeshRepoThread::fetchMeshLOD() - added
 allocation check

---
 indra/newview/llmeshrepository.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index c4d1917567..c2a0393170 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1586,7 +1586,12 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 				LLMeshRepository::sCacheBytesRead += size;
 				++LLMeshRepository::sCacheReads;
 				file.seek(offset);
-				U8* buffer = new U8[size];
+				U8* buffer = new(std::nothrow) U8[size];
+				if (!buffer)
+				{
+					LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh LOD" << LL_ENDL;
+					return false;
+				}
 				file.read(buffer, size);
 
 				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
-- 
cgit v1.2.3


From 9e8464d5d941e1f24d6685f2207fbb28f7ab9ec5 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 28 Jul 2017 17:03:23 +0300
Subject: MAINT-7650 FIXED Crash in LLPreviewLSL::saveIfNeeded(bool)

---
 indra/newview/llpreviewscript.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 5cdc5dfd38..b7fea4e982 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1683,6 +1683,7 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
         mScriptEd->sync();
     }
 
+    if (!gAgent.getRegion()) return;
     const LLInventoryItem *inv_item = getItem();
     // save it out to asset server
     std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
-- 
cgit v1.2.3


From 7e746e9221bf90466644999364b3c3cc16c0af98 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Fri, 28 Jul 2017 08:17:19 +0300
Subject: MAINT-7356 Improved multiline label support for the notification
 toast checkbox

---
 indra/newview/lltoastalertpanel.cpp                  | 11 ++++++++---
 indra/newview/skins/default/xui/en/notifications.xml |  4 ++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index dbf0893e43..495c9c1f44 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -46,6 +46,8 @@
 #include "lltransientfloatermgr.h"
 #include "llviewercontrol.h" // for gSavedSettings
 
+#include <boost/algorithm/string.hpp>
+
 const S32 MAX_ALLOWED_MSG_WIDTH = 400;
 const F32 DEFAULT_BUTTON_DELAY = 0.5f;
 
@@ -389,15 +391,18 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::
 
 	const LLFontGL* font =  mCheck->getFont();
 	const S32 LINE_HEIGHT = font->getLineHeight();
+
+	std::vector<std::string> lines;
+	boost::split(lines, check_title, boost::is_any_of("\n"));
 	
 	// Extend dialog for "check next time"
 	S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
-	S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
+	S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
 	max_msg_width = llmax(max_msg_width, check_width);
 	S32 dialog_width = max_msg_width + 2 * HPAD;
 
 	S32 dialog_height = LLToastPanel::getRect().getHeight();
-	dialog_height += LINE_HEIGHT;
+	dialog_height += LINE_HEIGHT * lines.size();
 	dialog_height += LINE_HEIGHT / 2;
 
 	LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
@@ -406,7 +411,7 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::
 
 	// set check_box's attributes
 	LLRect check_rect;
-	mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT));
+	mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size()));
 	mCheck->setLabel(check_title);
 	mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
 	
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 3ca7feae17..e21674a085 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5,8 +5,8 @@
   </global>
 
   <global name="skipnexttimesessiononly">
-
-    Don&apos;t show me this again (for this session only)
+Don&apos;t show me this again
+(for current session)
   </global>
 
   <global name="alwayschoose">
-- 
cgit v1.2.3


From 5250a86e7b35ca0710b1ae8235500786c0559a7c Mon Sep 17 00:00:00 2001
From: Mnikolenko ProductEngine <mnikolenko@productengine.com>
Date: Thu, 3 Aug 2017 16:30:01 +0300
Subject: MAINT-7653 Crash in LLVOAvatarSelf::updateAvatarRezMetrics(bool)

---
 indra/newview/llvoavatarself.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index aa5d82a096..d62862dfb8 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2246,7 +2246,9 @@ bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send)
 {
 	const F32 AV_METRICS_INTERVAL_QA = 30.0;
 	F32 send_period = 300.0;
-	if (gSavedSettings.getBOOL("QAModeMetrics"))
+
+	static LLCachedControl<bool> qa_mode_metrics(gSavedSettings,"QAModeMetrics");
+	if (qa_mode_metrics)
 	{
 		send_period = AV_METRICS_INTERVAL_QA;
 	}
-- 
cgit v1.2.3


From cf865bb5962a85e2da3414468d6a99ecb5423f97 Mon Sep 17 00:00:00 2001
From: AndreyL ProductEngine <alihatskiy@productengine.com>
Date: Wed, 9 Aug 2017 00:04:25 +0300
Subject: MAINT-7652 Fix for crash in LLVertexBuffer::~LLVertexBuffer()
 destructor

---
 indra/llrender/llvertexbuffer.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 31dffdd545..607bbf3b3b 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -1234,7 +1234,7 @@ void LLVertexBuffer::createGLIndices(U32 size)
 
 void LLVertexBuffer::destroyGLBuffer()
 {
-	if (mGLBuffer)
+	if (mGLBuffer || mMappedData)
 	{
 		if (mMappedDataUsingVBOs)
 		{
@@ -1254,7 +1254,7 @@ void LLVertexBuffer::destroyGLBuffer()
 
 void LLVertexBuffer::destroyGLIndices()
 {
-	if (mGLIndices)
+	if (mGLIndices || mMappedIndexData)
 	{
 		if (mMappedIndexDataUsingVBOs)
 		{
-- 
cgit v1.2.3


From 2368c44a8e2b031e5a8ac199923a016915cfe96a Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 15 Aug 2017 16:31:17 -0400
Subject: DRTVWR-418: Disable another fragile llcorehttp memory-usage check.

---
 indra/llcorehttp/tests/test_httprequest.hpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index a9c192e141..45215ee0f4 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -215,7 +215,8 @@ void HttpRequestTestObjectType::test<1>()
 		HttpRequest::destroyService();
 
 		// make sure we didn't leak any memory
-		ensure("Memory returned", mMemTotal == GetMemTotal());
+		// nat 2017-08-15 don't: requires total stasis in every other subsystem
+//		ensure("Memory returned", mMemTotal == GetMemTotal());
 	}
 	catch (...)
 	{
-- 
cgit v1.2.3


From f5f556fd4629c85aa92ad5d3195842e73b734ae5 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 22 Aug 2017 17:10:02 -0400
Subject: Added tag 5.0.7-release for changeset abcab37e1b29

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 90a21a647f..9cbb192d43 100755
--- a/.hgtags
+++ b/.hgtags
@@ -528,3 +528,4 @@ cea1632c002c065985ebea15eeeb4aac90f50545 5.0.2-release
 022709ef76a331cac1ba6ef1a6da8a5e9ef63f5a 5.0.4-release
 b4d76b5590fdf8bab72c64442353753a527cbc44 5.0.5-release
 3e5035dfd8af49bd4c0009f0a76ef46a15991a45 5.0.6-release
+abcab37e1b29414ab8c03af9ca2ab489d809788a 5.0.7-release
-- 
cgit v1.2.3


From 08cbed55ef5689fcc5a02dfb3b9afde15487036e Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 22 Aug 2017 17:10:02 -0400
Subject: increment viewer version to 5.0.8

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 00433367c8..51e67ba4d0 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-5.0.7
+5.0.8
-- 
cgit v1.2.3