diff --git a/.hgtags b/.hgtags
index 9b426adee44bfaee8a3357f63ddf25d6a79b86b3..4d2aec76733f6e54253525e9b51ac7c7db8d1719 100755
--- a/.hgtags
+++ b/.hgtags
@@ -485,3 +485,4 @@ a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
 91dae9494b4d147541c7a01902334ba19a7ec05e 3.7.10-release
 64799eb298834073a3e9992cd8d27c3cb9d30b10 3.7.11-release
 3b44ea8988cb902f0dda8429e8d5e4569e304532 3.7.12-release
+d86a7e1bc96d27b683f951d3701d5b7042158c68 3.7.13-release
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 5e1f12996e194d5af557cd35679a8be8890797c9..7f2224870d76eed58cd1931044af54fa91545468 100755
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -477,7 +477,8 @@ void LLToolTipMgr::show(const std::string& msg)
 void LLToolTipMgr::show(const LLToolTip::Params& params)
 {
 	if (!params.styled_message.isProvided() 
-		&& (!params.message.isProvided() || params.message().empty())) return;
+		&& (!params.message.isProvided() || params.message().empty())
+		&& !params.image.isProvided()) return;
 
 	// fill in default tooltip params from tool_tip.xml
 	LLToolTip::Params params_with_defaults(params);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 76f02a1b776a53f35941959bb8cb2a7c7775c341..b81b2aa9cf4a160e414b47264d87eaff8ac522c5 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -238,6 +238,7 @@ set(viewer_SOURCE_FILES
     llfloatergesture.cpp
     llfloatergodtools.cpp
     llfloatergotoline.cpp
+    llfloatergroupbulkban.cpp
     llfloatergroupinvite.cpp
     llfloatergroups.cpp
     llfloaterhandler.cpp
@@ -412,6 +413,8 @@ set(viewer_SOURCE_FILES
     llpanelface.cpp
     llpanelgenerictip.cpp
     llpanelgroup.cpp
+    llpanelgroupbulk.cpp
+    llpanelgroupbulkban.cpp
     llpanelgroupgeneral.cpp
     llpanelgroupinvite.cpp
     llpanelgrouplandmoney.cpp
@@ -839,6 +842,7 @@ set(viewer_HEADER_FILES
     llfloatergesture.h
     llfloatergodtools.h
     llfloatergotoline.h
+    llfloatergroupbulkban.h
     llfloatergroupinvite.h
     llfloatergroups.h
     llfloaterhandler.h
@@ -1006,6 +1010,9 @@ set(viewer_HEADER_FILES
     llpanelface.h
     llpanelgenerictip.h
     llpanelgroup.h
+    llpanelgroupbulk.h
+    llpanelgroupbulkimpl.h
+    llpanelgroupbulkban.h
     llpanelgroupgeneral.h
     llpanelgroupinvite.h
     llpanelgrouplandmoney.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 214b521fe220d3c853d5ed5f5012756c70a56ba2..35c6ac5179bf486944e8f38a19d468a9ad6164e0 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.13
+3.7.14
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 03b953b6cc0e5a3ab9237a5b14f502c1e12eeec4..000362ebfd6657d6340f8e3692bf95149f9f074d 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -6118,16 +6118,16 @@
     <integer>0</integer>
   </map>
   <key>MemoryLogFrequency</key>
-        <map>
-        <key>Comment</key>
-            <string>Seconds between display of Memory in log (0 for never)</string>
-        <key>Persist</key>
-            <integer>1</integer>
-        <key>Type</key>
-            <string>F32</string>
-        <key>Value</key>
-            <real>600.0</real>
-        </map>
+  <map>
+    <key>Comment</key>
+    <string>Seconds between display of Memory in log (0 for never)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>30.0</real>
+  </map>
     <key>MemoryPrivatePoolEnabled</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 74b77f760df0a9824a62a15914cdc3e2e903db57..6e32ce60ecc4667a836d945119d3d75a926210d4 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -51,6 +51,7 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u
 	mConvType(CONV_UNKNOWN),
 	mLastActiveTime(0.0),
 	mDisplayModeratorOptions(false),
+	mDisplayGroupBanOptions(false),
 	mAvatarNameCacheConnection()
 {
 }
@@ -63,6 +64,7 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte
 	mConvType(CONV_UNKNOWN),
 	mLastActiveTime(0.0),
 	mDisplayModeratorOptions(false),
+	mDisplayGroupBanOptions(false),
 	mAvatarNameCacheConnection()
 {
 }
@@ -75,6 +77,7 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod
 	mConvType(CONV_UNKNOWN),
 	mLastActiveTime(0.0),
 	mDisplayModeratorOptions(false),
+	mDisplayGroupBanOptions(false),
 	mAvatarNameCacheConnection()
 {
 }
@@ -159,6 +162,12 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
 			items.push_back(std::string("ModerateVoiceMute"));
 			items.push_back(std::string("ModerateVoiceUnmute"));
 		}
+
+		if ((getType() != CONV_SESSION_1_ON_1) && mDisplayGroupBanOptions)
+		{
+			items.push_back(std::string("Group Ban Separator"));
+			items.push_back(std::string("BanMember"));
+		}
 	}
 }
 
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index dc74506c531b377792827e190397e01e536a5f2b..56e1a267098c3dbc07e01b6a7ea32eddbfb314bb 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -143,6 +143,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon
 	bool mNeedsRefresh;	// Flag signaling to the view that something changed for this item
 	F64  mLastActiveTime;
 	bool mDisplayModeratorOptions;
+	bool mDisplayGroupBanOptions;
 	boost::signals2::connection mAvatarNameCacheConnection;
 };	
 
@@ -206,6 +207,7 @@ class LLConversationItemParticipant : public LLConversationItem
 	void dumpDebugData();
 	void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; }
 	void setDisplayModeratorRole(bool displayRole);
+	void setGroupBanVisible(bool visible) { mDisplayGroupBanOptions = visible; }
 
 private:
 	void onAvatarNameCache(const LLAvatarName& av_name);	// callback used by fetchAvatarName
diff --git a/indra/newview/llfloatergroupbulkban.cpp b/indra/newview/llfloatergroupbulkban.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..54a2283b1325d1ca356baf15e93ba30ecaa9640c
--- /dev/null
+++ b/indra/newview/llfloatergroupbulkban.cpp
@@ -0,0 +1,134 @@
+/** 
+* @file llfloatergroupbulkban.cpp
+* @brief Floater to ban Residents from a group.
+* 
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatergroupbulkban.h"
+#include "llpanelgroupbulkban.h"
+#include "lltrans.h"
+#include "lldraghandle.h"
+
+
+class LLFloaterGroupBulkBan::impl
+{
+public:
+	impl(const LLUUID& group_id) : mGroupID(group_id), mBulkBanPanelp(NULL) {}
+	~impl() {}
+
+	static void closeFloater(void* data);
+
+public:
+	LLUUID mGroupID;
+	LLPanelGroupBulkBan* mBulkBanPanelp;
+
+	static std::map<LLUUID, LLFloaterGroupBulkBan*> sInstances;
+};
+
+//
+// Globals
+//
+std::map<LLUUID, LLFloaterGroupBulkBan*> LLFloaterGroupBulkBan::impl::sInstances;
+
+void LLFloaterGroupBulkBan::impl::closeFloater(void* data)
+{
+	LLFloaterGroupBulkBan* floaterp = (LLFloaterGroupBulkBan*)data;
+	if(floaterp)
+		floaterp->closeFloater();
+}
+
+//-----------------------------------------------------------------------------
+// Implementation
+//-----------------------------------------------------------------------------
+LLFloaterGroupBulkBan::LLFloaterGroupBulkBan(const LLUUID& group_id/*=LLUUID::null*/)
+	: LLFloater(group_id)
+{
+	S32 floater_header_size = getHeaderHeight();
+	LLRect contents;
+
+	mImpl = new impl(group_id);
+	mImpl->mBulkBanPanelp = new LLPanelGroupBulkBan(group_id);
+
+	contents = mImpl->mBulkBanPanelp->getRect();
+	contents.mTop -= floater_header_size;
+
+	setTitle(mImpl->mBulkBanPanelp->getString("GroupBulkBan"));
+	mImpl->mBulkBanPanelp->setCloseCallback(impl::closeFloater, this);
+	mImpl->mBulkBanPanelp->setRect(contents);
+
+	addChild(mImpl->mBulkBanPanelp);
+}
+
+LLFloaterGroupBulkBan::~LLFloaterGroupBulkBan()
+{
+	if(mImpl->mGroupID.notNull())
+	{
+		impl::sInstances.erase(mImpl->mGroupID);
+	}
+
+	delete mImpl->mBulkBanPanelp;
+	delete mImpl;
+}
+
+void LLFloaterGroupBulkBan::showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids)
+{
+	const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = floater_params.header_height;
+	LLRect contents;
+
+	// Make sure group_id isn't null
+	if (group_id.isNull())
+	{
+		llwarns << "LLFloaterGroupInvite::showForGroup with null group_id!" << llendl;
+		return;
+	}
+
+	// If we don't have a floater for this group, create one.
+	LLFloaterGroupBulkBan* fgb = get_if_there(impl::sInstances,
+		group_id,
+		(LLFloaterGroupBulkBan*)NULL);
+	if (!fgb)
+	{
+		fgb = new LLFloaterGroupBulkBan(group_id);
+		contents = fgb->mImpl->mBulkBanPanelp->getRect();
+		contents.mTop += floater_header_size;
+		fgb->setRect(contents);
+		fgb->getDragHandle()->setRect(contents);
+		fgb->getDragHandle()->setTitle(fgb->mImpl->mBulkBanPanelp->getString("GroupBulkBan"));
+
+		impl::sInstances[group_id] = fgb;
+
+		fgb->mImpl->mBulkBanPanelp->clear();
+	}
+
+	if (agent_ids != NULL)
+	{
+		fgb->mImpl->mBulkBanPanelp->addUsers(*agent_ids);
+	}
+
+	fgb->center();
+	fgb->openFloater();
+	fgb->mImpl->mBulkBanPanelp->update();
+}
diff --git a/indra/newview/llfloatergroupbulkban.h b/indra/newview/llfloatergroupbulkban.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b680a1ba4969541920a8ae728a62153a6895d6a
--- /dev/null
+++ b/indra/newview/llfloatergroupbulkban.h
@@ -0,0 +1,48 @@
+/** 
+* @file   llfloatergroupbulkban.h
+* @brief  This floater is a wrapper for LLPanelGroupBulkBan, which
+* is used to ban Residents from a specific group.
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLFLOATERGROUPBULKBAN_H
+#define LL_LLFLOATERGROUPBULKBAN_H
+
+#include "llfloater.h"
+#include "lluuid.h"
+
+class LLFloaterGroupBulkBan : public LLFloater
+{
+public:
+	virtual ~LLFloaterGroupBulkBan();
+
+	static void showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids = NULL);
+
+protected:
+	LLFloaterGroupBulkBan(const LLUUID& group_id = LLUUID::null);
+
+	class impl;
+	impl* mImpl;
+};
+
+#endif // LL_LLFLOATERGROUPBULKBAN_H
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index ebb44561da6f2a46c7b7b81df722c62f539d9043..be8195b5ee9b1d7a828617f9dc84135b7771da60 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -532,6 +532,7 @@ void LLFloaterIMContainer::draw()
 		{
 			LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
 			participant_model->setModeratorOptionsVisible(isGroupModerator() && participant_model->getUUID() != gAgentID);
+			participant_model->setGroupBanVisible(haveAbilityToBan() && participant_model->getUUID() != gAgentID);
 
 			current_participant_model++;
 		}
@@ -1150,6 +1151,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
 		{
 			toggleAllowTextChat(userID);
 		}
+		else if ("ban_member" == command)
+		{
+			banSelectedMember(userID);
+		}
 	}
 	else if (selectedIDS.size() > 1)
 	{
@@ -1271,6 +1276,22 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
 	uuid_vec_t uuids;
 	getParticipantUUIDs(uuids);
 
+
+	//If there is group or ad-hoc chat in multiselection, everything needs to be disabled
+	if(uuids.size() > 1)
+	{
+		const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList();
+		LLConversationItem * conversationItem;
+		for(std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+		{
+			conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem());
+			if((conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) || (conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC))
+			{
+				return false;
+			}
+		}
+	}
+
 	if ("conversation_log" == item)
 	{
 		return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
@@ -1375,6 +1396,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
     else if ("can_call" == item)
     {
         return LLAvatarActions::canCall();
+    }
+    else if ("can_open_voice_conversation" == item)
+    {
+    	return is_single_select && LLAvatarActions::canCall();
     }
 	else if ("can_zoom_in" == item)
 	{
@@ -1387,6 +1412,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
     else if ("can_offer_teleport" == item)
     {
 		return LLAvatarActions::canOfferTeleport(uuids);
+    }
+    else if ("can_ban_member" == item)
+    {
+   		return canBanSelectedMember(single_id);
     }
 	else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item))
 	{
@@ -1810,6 +1839,95 @@ bool LLFloaterIMContainer::isGroupModerator()
 	return false;
 }
 
+bool LLFloaterIMContainer::haveAbilityToBan()
+{
+	LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+	if (NULL == speaker_manager)
+	{
+		LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+		return false;
+	}
+	LLUUID group_uuid = speaker_manager->getSessionID();
+
+	return gAgent.isInGroup(group_uuid) && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS);
+}
+
+bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)
+{
+	LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+	if (NULL == speaker_manager)
+	{
+		LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+		return false;
+	}
+	LLUUID group_uuid = speaker_manager->getSessionID();
+	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(group_uuid);
+	if(!gdatap)
+	{
+		LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
+		return false;
+	}
+
+	if (!gdatap->mMembers.size())
+	{
+		return false;
+	}
+
+	LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
+	if (mi == gdatap->mMembers.end())
+	{
+		return false;
+	}
+
+	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;
+	}
+
+	return false;
+}
+
+void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
+{
+	LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+	if (NULL == speaker_manager)
+	{
+		LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+		return;
+	}
+
+	LLUUID group_uuid = speaker_manager->getSessionID();
+	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(group_uuid);
+	if(!gdatap)
+	{
+		LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
+		return;
+	}
+	std::vector<LLUUID> ids;
+	ids.push_back(participant_uuid);
+
+	LLGroupBanData ban_data;
+	gdatap->createBanEntry(participant_uuid, ban_data);
+	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids);
+	LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids);
+	LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid);
+	LLSD args;
+	std::string name;
+	gCacheName->getFullName(participant_uuid, name);
+	args["AVATAR_NAME"] = name;
+	args["GROUP_NAME"] = gdatap->mName;
+	LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
+
+}
+
 void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID)
 {
 	if (!gAgent.getRegion()) return;
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index f6d973b9b3be5f7646d3be62b25106d62bc39549..5ea9fd399bb08f59b2b2241d797cde836b117a86 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -167,12 +167,16 @@ class LLFloaterIMContainer
 	LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp);
 	LLSpeakerMgr * getSpeakerMgrForSelectedParticipant();
 	bool isGroupModerator();
+	bool haveAbilityToBan();
+	bool canBanSelectedMember(const LLUUID& participant_uuid);
+	LLUUID getGroupUIIDForSelectedParticipant();
 	bool isMuted(const LLUUID& avatar_id);
 	void moderateVoice(const std::string& command, const LLUUID& userID);
 	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/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index f514729aa1ed19de00f82abe9da064a357d7f920..913efd643426aa50e727377a6d9987095cd206ae 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -149,7 +149,7 @@ class LLFetchGroupMemberData : public LLGroupMgrObserver
 
 	void changed(LLGroupChange gc)
 	{
-		if (gc == GC_MEMBER_DATA && !mRequestProcessed)
+		if (gc == GC_PROPERTIES && !mRequestProcessed)
 		{
 			LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
 			if (!gdatap)
@@ -159,9 +159,6 @@ class LLFetchGroupMemberData : public LLGroupMgrObserver
 			else if (!gdatap->isMemberDataComplete())
 			{
 				LL_WARNS() << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << LL_ENDL;
-			}
-			else
-			{
 				processGroupData();
 				mRequestProcessed = true;
 			}
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index d5b817ce765140615a7d4add736ace865c36fd59..56e671d902e44fb380640e13d7514718ea8a7a6c 100755
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -234,11 +234,11 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :
 	mMemberCount(0),
 	mRoleCount(0),
 	mReceivedRoleMemberPairs(0),
-	mMemberDataComplete(FALSE),
-	mRoleDataComplete(FALSE),
-	mRoleMemberDataComplete(FALSE),
-	mGroupPropertiesDataComplete(FALSE),
-	mPendingRoleMemberRequest(FALSE),
+	mMemberDataComplete(false),
+	mRoleDataComplete(false),
+	mRoleMemberDataComplete(false),
+	mGroupPropertiesDataComplete(false),
+	mPendingRoleMemberRequest(false),
 	mAccessTime(0.0f)
 {
 	mMemberVersion.generate();
@@ -427,7 +427,7 @@ void LLGroupMgrGroupData::removeMemberData()
 		delete mi->second;
 	}
 	mMembers.clear();
-	mMemberDataComplete = FALSE;
+	mMemberDataComplete = false;
 	mMemberVersion.generate();
 }
 
@@ -449,8 +449,8 @@ void LLGroupMgrGroupData::removeRoleData()
 	}
 	mRoles.clear();
 	mReceivedRoleMemberPairs = 0;
-	mRoleDataComplete = FALSE;
-	mRoleMemberDataComplete = FALSE;
+	mRoleDataComplete = false;
+	mRoleMemberDataComplete= false;
 }
 
 void LLGroupMgrGroupData::removeRoleMemberData()
@@ -474,7 +474,7 @@ void LLGroupMgrGroupData::removeRoleMemberData()
 	}
 
 	mReceivedRoleMemberPairs = 0;
-	mRoleMemberDataComplete = FALSE;
+	mRoleMemberDataComplete= false;
 }
 
 LLGroupMgrGroupData::~LLGroupMgrGroupData()
@@ -750,6 +750,20 @@ void LLGroupMgrGroupData::cancelRoleChanges()
 	// Clear out all changes!
 	mRoleChanges.clear();
 }
+
+void LLGroupMgrGroupData::createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data)
+{ 
+	mBanList[ban_id] = ban_data;
+}
+
+void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
+{
+	mBanList.erase(ban_id);
+}
+
+
+
+
 //
 // LLGroupMgr
 //
@@ -959,12 +973,12 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
 
 	if (group_datap->mMembers.size() ==  (U32)group_datap->mMemberCount)
 	{
-		group_datap->mMemberDataComplete = TRUE;
+		group_datap->mMemberDataComplete = true;
 		group_datap->mMemberRequestID.setNull();
 		// We don't want to make role-member data requests until we have all the members
 		if (group_datap->mPendingRoleMemberRequest)
 		{
-			group_datap->mPendingRoleMemberRequest = FALSE;
+			group_datap->mPendingRoleMemberRequest = false;
 			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
 		}
 	}
@@ -1034,7 +1048,7 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
 	group_datap->mMemberCount = num_group_members;
 	group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role.
 	
-	group_datap->mGroupPropertiesDataComplete = TRUE;
+	group_datap->mGroupPropertiesDataComplete = true;
 	group_datap->mChanged = TRUE;
 
 	LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
@@ -1111,12 +1125,12 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
 
 	if (group_datap->mRoles.size() == (U32)group_datap->mRoleCount)
 	{
-		group_datap->mRoleDataComplete = TRUE;
+		group_datap->mRoleDataComplete = true;
 		group_datap->mRoleDataRequestID.setNull();
 		// We don't want to make role-member data requests until we have all the role data
 		if (group_datap->mPendingRoleMemberRequest)
 		{
-			group_datap->mPendingRoleMemberRequest = FALSE;
+			group_datap->mPendingRoleMemberRequest = false;
 			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
 		}
 	}
@@ -1225,7 +1239,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
 			}
 		}
 		
-        group_datap->mRoleMemberDataComplete = TRUE;
+        group_datap->mRoleMemberDataComplete= true;
 		group_datap->mRoleMembersRequestID.setNull();
 	}
 
@@ -1848,6 +1862,138 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
 }
 
 
+// Responder class for capability group management
+class GroupBanDataResponder : public LLHTTPClient::Responder
+{
+public:
+	GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh=false);
+	virtual ~GroupBanDataResponder() {}
+	virtual void httpSuccess();
+	virtual void httpFailure();
+private:
+	LLUUID mGroupID;
+	BOOL mForceRefresh;
+};
+
+GroupBanDataResponder::GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh) :
+	mGroupID(gropup_id),
+	mForceRefresh(force_refresh)
+{}
+
+void GroupBanDataResponder::httpFailure()
+{
+	LL_WARNS("GrpMgr") << "Error receiving group member data [status:" 
+		<< mStatus << "]: " << mContent << LL_ENDL;
+}
+
+void GroupBanDataResponder::httpSuccess()
+{
+	if (mContent.has("ban_list"))
+	{
+		// group ban data received
+		LLGroupMgr::processGroupBanRequest(mContent);
+	}
+	else if (mForceRefresh)
+	{
+		// no ban data received, refreshing data after successful operation 
+		LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+	}
+}
+
+void LLGroupMgr::sendGroupBanRequest(	EBanRequestType request_type, 
+										const LLUUID& group_id, 
+										U32 ban_action, /* = BAN_NO_ACTION */
+										const std::vector<LLUUID> ban_list) /* = std::vector<LLUUID>() */
+{
+	LLViewerRegion* currentRegion = gAgent.getRegion();
+	if(!currentRegion)
+	{
+		LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL;
+		return;
+	}
+
+	// Check to make sure we have our capabilities
+	if(!currentRegion->capabilitiesReceived())
+	{
+		LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL;
+		return;
+	}
+
+	// Get our capability
+	std::string cap_url =  currentRegion->getCapability("GroupAPIv1");
+	if(cap_url.empty())
+	{
+		return;
+	}
+	cap_url += "?group_id=" + group_id.asString();
+
+	LLSD body = LLSD::emptyMap();
+	body["ban_action"]  = (LLSD::Integer)(ban_action & ~BAN_UPDATE);
+	// Add our list of potential banned residents to the list
+	body["ban_ids"]	= LLSD::emptyArray();
+	LLSD ban_entry;
+
+	uuid_vec_t::const_iterator iter = ban_list.begin();
+	for(;iter != ban_list.end(); ++iter)
+	{
+		ban_entry = (*iter);
+		body["ban_ids"].append(ban_entry);
+	}
+
+	LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(group_id, ban_action & BAN_UPDATE);
+	switch(request_type)
+	{
+	case REQUEST_GET:
+		LLHTTPClient::get(cap_url, grp_ban_responder);
+		break;
+	case REQUEST_POST:
+		LLHTTPClient::post(cap_url, body, grp_ban_responder);
+		break;
+	case REQUEST_PUT:
+	case REQUEST_DEL:
+		break;
+	}
+}
+
+
+void LLGroupMgr::processGroupBanRequest(const LLSD& content)
+{
+	// Did we get anything in content?
+	if(!content.size())
+	{
+		LL_WARNS("GrpMgr") << "No group member data received." << LL_ENDL;
+		return;
+	}
+
+	LLUUID group_id = content["group_id"].asUUID();
+	
+	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+	if (!gdatap)
+		return;
+	
+	LLSD::map_const_iterator i		= content["ban_list"].beginMap();
+	LLSD::map_const_iterator iEnd	= content["ban_list"].endMap();
+	for(;i != iEnd; ++i)
+	{
+		const LLUUID ban_id(i->first);
+		LLSD ban_entry(i->second);
+		
+		LLGroupBanData ban_data;
+		if(ban_entry.has("ban_date"))
+		{
+			ban_data.mBanDate = ban_entry["ban_date"].asDate();
+			// TODO: Ban Reason
+		}
+
+		gdatap->createBanEntry(ban_id, ban_data);
+	}
+
+	gdatap->mChanged = TRUE;
+	LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);
+}
+
+
+
 // Responder class for capability group management
 class GroupMemberDataResponder : public LLHTTPClient::Responder
 {
@@ -1941,7 +2087,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 	if(num_members < 1)
 		return;
 	
-	LLUUID	group_id = content["group_id"].asUUID();
+	LLUUID group_id = content["group_id"].asUUID();
 
 	LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
 	if(!group_datap)
@@ -2008,6 +2154,22 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 			online_status,
 			is_owner);
 
+		LLGroupMemberData* member_old = group_datap->mMembers[member_id];
+		if (member_old && group_datap->mRoleMemberDataComplete)
+		{
+			LLGroupMemberData::role_list_t::iterator rit = member_old->roleBegin();
+			LLGroupMemberData::role_list_t::iterator end = member_old->roleEnd();
+
+			for ( ; rit != end; ++rit)
+			{
+				data->addRole((*rit).first,(*rit).second);
+			}
+		}
+		else
+		{
+			group_datap->mRoleMemberDataComplete = false;
+		}
+
 		group_datap->mMembers[member_id] = data;
 	}
 
@@ -2024,12 +2186,12 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 		LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
 
 
-	group_datap->mMemberDataComplete = TRUE;
+	group_datap->mMemberDataComplete = true;
 	group_datap->mMemberRequestID.setNull();
 	// Make the role-member data request
-	if (group_datap->mPendingRoleMemberRequest)
+	if (group_datap->mPendingRoleMemberRequest || !group_datap->mRoleMemberDataComplete)
 	{
-		group_datap->mPendingRoleMemberRequest = FALSE;
+		group_datap->mPendingRoleMemberRequest = false;
 		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id);
 	}
 
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index 9b62ecac48d0289f88cb0c7a5b9585ec9d89947b..2e94e8d9a0d359484f6b50658f434ecbc8b828c0 100755
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -33,8 +33,10 @@
 #include <string>
 #include <map>
 
+// Forward Declarations
 class LLMessageSystem;
-
+class LLGroupRoleData;
+class LLGroupMgr;
 
 enum LLGroupChange
 {
@@ -43,9 +45,12 @@ enum LLGroupChange
 	GC_ROLE_DATA,
 	GC_ROLE_MEMBER_DATA,
 	GC_TITLES,
+	GC_BANLIST,
 	GC_ALL
 };
 
+const U32 GB_MAX_BANNED_AGENTS = 500;
+
 class LLGroupMgrObserver
 {
 public:
@@ -65,8 +70,6 @@ class LLParticularGroupObserver
 	virtual void changed(const LLUUID& group_id, LLGroupChange gc) = 0;
 };
 
-class LLGroupRoleData;
-
 class LLGroupMemberData
 {
 friend class LLGroupMgrGroupData;
@@ -201,6 +204,17 @@ struct lluuid_pair_less
 	}
 };
 
+
+struct LLGroupBanData
+{
+	LLGroupBanData(): mBanDate()	{}
+	~LLGroupBanData()	{}
+	
+	LLDate mBanDate;
+	// TODO: std:string ban_reason;
+};
+
+
 struct LLGroupTitle
 {
 	std::string mTitle;
@@ -208,8 +222,6 @@ struct LLGroupTitle
 	BOOL		mSelected;
 };
 
-class LLGroupMgr;
-
 class LLGroupMgrGroupData
 {
 friend class LLGroupMgr;
@@ -239,11 +251,11 @@ friend class LLGroupMgr;
 	void recalcAllAgentPowers();
 	void recalcAgentPowers(const LLUUID& agent_id);
 
-	BOOL isMemberDataComplete() { return mMemberDataComplete; }
-	BOOL isRoleDataComplete() { return mRoleDataComplete; }
-	BOOL isRoleMemberDataComplete() { return mRoleMemberDataComplete; }
-	BOOL isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }
-	
+	bool isMemberDataComplete() { return mMemberDataComplete; }
+	bool isRoleDataComplete() { return mRoleDataComplete; }
+	bool isRoleMemberDataComplete() { return mRoleMemberDataComplete; }
+	bool isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }
+
 	bool isSingleMemberNotOwner();
 
 	F32 getAccessTime() const { return mAccessTime; }
@@ -251,17 +263,26 @@ friend class LLGroupMgr;
 
 	const LLUUID& getMemberVersion() const { return mMemberVersion; }
 
+	void clearBanList() { mBanList.clear(); }
+	void getBanList(const LLUUID& group_id, LLGroupBanData& ban_data);
+	const LLGroupBanData& getBanEntry(const LLUUID& ban_id) { return mBanList[ban_id]; }
+	
+	void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData());
+	void removeBanEntry(const LLUUID& ban_id);
+	
+
 public:
 	typedef	std::map<LLUUID,LLGroupMemberData*> member_list_t;
 	typedef	std::map<LLUUID,LLGroupRoleData*> role_list_t;
 	typedef std::map<lluuid_pair,LLRoleMemberChange,lluuid_pair_less> change_map_t;
 	typedef std::map<LLUUID,LLRoleData> role_data_map_t;
+	typedef std::map<LLUUID,LLGroupBanData> ban_list_t;
+
 	member_list_t		mMembers;
 	role_list_t			mRoles;
-
-	
 	change_map_t		mRoleMemberChanges;
 	role_data_map_t		mRoleChanges;
+	ban_list_t			mBanList;
 
 	std::vector<LLGroupTitle> mTitles;
 
@@ -292,12 +313,12 @@ friend class LLGroupMgr;
 	LLUUID				mTitlesRequestID;
 	U32					mReceivedRoleMemberPairs;
 
-	BOOL				mMemberDataComplete;
-	BOOL				mRoleDataComplete;
-	BOOL				mRoleMemberDataComplete;
-	BOOL				mGroupPropertiesDataComplete;
+	bool				mMemberDataComplete;
+	bool				mRoleDataComplete;
+	bool				mRoleMemberDataComplete;
+	bool				mGroupPropertiesDataComplete;
 
-	BOOL				mPendingRoleMemberRequest;
+	bool				mPendingRoleMemberRequest;
 	F32					mAccessTime;
 
 	// Generate a new ID every time mMembers
@@ -324,6 +345,23 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 {
 	LOG_CLASS(LLGroupMgr);
 	
+public:
+	enum EBanRequestType
+	{
+		REQUEST_GET = 0,
+		REQUEST_POST,
+		REQUEST_PUT,
+		REQUEST_DEL
+	};
+
+	enum EBanRequestAction
+	{
+		BAN_NO_ACTION	= 0,
+		BAN_CREATE		= 1,
+		BAN_DELETE		= 2,
+		BAN_UPDATE		= 4
+	};
+
 public:
 	LLGroupMgr();
 	~LLGroupMgr();
@@ -357,8 +395,14 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 	static void sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& role_member_pairs);
 	static void sendGroupMemberEjects(const LLUUID& group_id,
 									  uuid_vec_t& member_ids);
+	
+	static void sendGroupBanRequest(EBanRequestType request_type, 
+									const LLUUID& group_id,	
+									U32 ban_action = BAN_NO_ACTION,
+									const uuid_vec_t ban_list = uuid_vec_t());
+
+	static void processGroupBanRequest(const LLSD& content);
 
-	// BAKER
 	void sendCapGroupMembersRequest(const LLUUID& group_id);
 	static void processCapGroupMembersRequest(const LLSD& content);
 
@@ -403,4 +447,3 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 
 
 #endif
-
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 91866e5ca29a7ec80707653843800db1e9752f07..54e4c6c1dac19444f68f0120e1331040b7be7b72 100755
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -64,7 +64,8 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
 	mNameColumnIndex(p.name_column.column_index),
 	mNameColumn(p.name_column.column_name),
 	mAllowCallingCardDrop(p.allow_calling_card_drop),
-	mShortNames(p.short_names)
+	mShortNames(p.short_names),
+	mPendingLookupsRemaining(0)
 {}
 
 // public
@@ -337,6 +338,17 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
 					mAvatarNameCacheConnections.erase(it);
 				}
 				mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, item->getHandle()));
+
+				if(mPendingLookupsRemaining <= 0)
+				{
+					// BAKER TODO:
+					// We might get into a state where mPendingLookupsRemaining might
+					//	go negative.  So just reset it right now and figure out if it's
+					//	possible later :)
+					mPendingLookupsRemaining = 0;
+					mNameListCompleteSignal(false);
+				}
+				mPendingLookupsRemaining++;
 			}
 			break;
 		}
@@ -388,6 +400,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
 	{
 		selectNthItem(idx); // not sure whether this is needed, taken from previous implementation
 		deleteSingleItem(idx);
+
+		mPendingLookupsRemaining--;
 	}
 }
 
@@ -429,6 +443,23 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
 		}
 	}
 	
+	//////////////////////////////////////////////////////////////////////////
+	// BAKER - FIX NameListCtrl
+ 	//if (mPendingLookupsRemaining <= 0)
+ 	{
+ 		// We might get into a state where mPendingLookupsRemaining might
+ 		//	go negative.  So just reset it right now and figure out if it's
+ 		//	possible later :)
+ 		//mPendingLookupsRemaining = 0;
+		
+ 		mNameListCompleteSignal(true);
+ 	}
+ 	//else
+ 	{
+ 	//	mPendingLookupsRemaining--;
+ 	}
+	//////////////////////////////////////////////////////////////////////////
+
 	dirtyColumns();
 }
 
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 4ed260d84759f15f4004bbb24f13884bba4e0839..2c40eeaacace69fef2b50a6c7527587b7c9511f7 100755
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -67,6 +67,7 @@ class LLNameListCtrl
 :	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>
 {
 public:
+	typedef boost::signals2::signal<void(bool)> namelist_complete_signal_t;
 
 	typedef enum e_name_type
 	{
@@ -156,7 +157,7 @@ class LLNameListCtrl
 
 	/*virtual*/ void updateColumns(bool force_update);
 
-	/*virtual*/ void	mouseOverHighlightNthItem( S32 index );
+	/*virtual*/ void mouseOverHighlightNthItem( S32 index );
 private:
 	void showInspector(const LLUUID& avatar_id, bool is_group);
 	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item);
@@ -168,6 +169,16 @@ class LLNameListCtrl
 	bool			mShortNames;  // display name only, no SLID
 	typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
 	avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
+
+	S32 mPendingLookupsRemaining;
+	namelist_complete_signal_t mNameListCompleteSignal;
+	
+public:
+	boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback) 
+	{ 
+		return mNameListCompleteSignal.connect(onNameListCompleteCallback); 
+	}
+
 };
 
 
diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1eafc5bd6467ebf06958f6259b2d358ca9b27710
--- /dev/null
+++ b/indra/newview/llpanelgroupbulk.cpp
@@ -0,0 +1,421 @@
+/** 
+* @file llpanelgroupbulk.cpp
+* @brief Implementation of llpanelgroupbulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelgroupbulk.h"
+#include "llpanelgroupbulkimpl.h"
+
+#include "llagent.h"
+#include "llavatarnamecache.h"
+#include "llfloateravatarpicker.h"
+#include "llbutton.h"
+#include "llcallingcard.h"
+#include "llcombobox.h"
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+// Implementation of llpanelgroupbulkimpl.h functions
+//////////////////////////////////////////////////////////////////////////
+LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
+	mGroupID(group_id),
+	mBulkAgentList(NULL),
+	mOKButton(NULL),
+	mRemoveButton(NULL),
+	mGroupName(NULL),
+	mLoadingText(),
+	mTooManySelected(),
+	mCloseCallback(NULL),
+	mCloseCallbackUserData(NULL),
+	mAvatarNameCacheConnection(),
+	mRoleNames(NULL),
+	mOwnerWarning(),
+	mAlreadyInGroup(),
+	mConfirmedOwnerInvite(false),
+	mListFullNotificationSent(false)
+{}
+
+LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl()
+{
+	if(mAvatarNameCacheConnection.connected())
+	{
+		mAvatarNameCacheConnection.disconnect();
+	}
+}
+
+void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata)
+{
+	LLPanelGroupBulk* panelp = (LLPanelGroupBulk*)userdata;
+
+	if(panelp)
+	{
+		//Right now this is hard coded with some knowledge that it is part
+		//of a floater since the avatar picker needs to be added as a dependent
+		//floater to the parent floater.
+		//Soon the avatar picker will be embedded into this panel
+		//instead of being it's own separate floater.  But that is next week.
+		//This will do for now. -jwolk May 10, 2006
+		LLView* button = panelp->findChild<LLButton>("add_button");
+		LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
+		LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(
+			boost::bind(callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button);
+		if(picker)
+		{
+			root_floater->addDependentFloater(picker);
+		}
+	}
+}
+
+void LLPanelGroupBulkImpl::callbackClickRemove(void* userdata)
+{
+	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+	if (selfp) 
+		selfp->handleRemove();
+}
+
+void LLPanelGroupBulkImpl::callbackClickCancel(void* userdata)
+{
+	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+	if(selfp) 
+		(*(selfp->mCloseCallback))(selfp->mCloseCallbackUserData);
+}
+
+void LLPanelGroupBulkImpl::callbackSelect(LLUICtrl* ctrl, void* userdata)
+{
+	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+	if (selfp) 
+		selfp->handleSelection();
+}
+
+void LLPanelGroupBulkImpl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data)
+{
+	std::vector<std::string> names;
+	for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+	{
+		LLAvatarName av_name;
+		if (LLAvatarNameCache::get(agent_ids[i], &av_name))
+		{
+			onAvatarNameCache(agent_ids[i], av_name, user_data);
+		}
+		else 
+		{
+			LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data;
+			if (selfp)
+			{
+				if (selfp->mAvatarNameCacheConnection.connected())
+				{
+					selfp->mAvatarNameCacheConnection.disconnect();
+				}
+				// *TODO : Add a callback per avatar name being fetched.
+				selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(onAvatarNameCache, _1, _2, user_data));
+			}
+		}
+	}
+}
+
+void LLPanelGroupBulkImpl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data)
+{
+	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data;
+
+	if (selfp)
+	{
+		if (selfp->mAvatarNameCacheConnection.connected())
+		{
+			selfp->mAvatarNameCacheConnection.disconnect();
+		}
+		std::vector<std::string> names;
+		uuid_vec_t agent_ids;
+		agent_ids.push_back(agent_id);
+		names.push_back(av_name.getCompleteName());
+
+		selfp->addUsers(names, agent_ids);
+	}
+}
+
+void LLPanelGroupBulkImpl::handleRemove()
+{
+	std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected();
+	if (selection.empty()) 
+		return;
+
+	std::vector<LLScrollListItem*>::iterator iter;
+	for(iter = selection.begin(); iter != selection.end(); ++iter)
+	{
+		mInviteeIDs.erase((*iter)->getUUID());
+	}
+
+	mBulkAgentList->deleteSelectedItems();
+	mRemoveButton->setEnabled(FALSE);
+
+	if(	mOKButton && mOKButton->getEnabled() &&
+		mBulkAgentList->isEmpty())
+	{
+		mOKButton->setEnabled(FALSE);
+	}
+}
+
+void LLPanelGroupBulkImpl::handleSelection()
+{
+	std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected();
+	if (selection.empty())
+		mRemoveButton->setEnabled(FALSE);
+	else
+		mRemoveButton->setEnabled(TRUE);
+}
+
+void LLPanelGroupBulkImpl::addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids)
+{
+	std::string name;
+	LLUUID id;
+
+	if(mListFullNotificationSent)
+	{	
+		return;
+	}
+
+	if(	!mListFullNotificationSent &&
+		(names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES))
+	{
+		mListFullNotificationSent = true;
+
+		// Fail! Show a warning and don't add any names.
+		LLSD msg;
+		msg["MESSAGE"] = mTooManySelected;
+		LLNotificationsUtil::add("GenericAlert", msg);
+		return;
+	}
+
+	for (S32 i = 0; i < (S32)names.size(); ++i)
+	{
+		name = names[i];
+		id = agent_ids[i];
+
+		if(mInviteeIDs.find(id) != mInviteeIDs.end())
+		{
+			continue;
+		}
+
+		//add the name to the names list
+		LLSD row;
+		row["id"] = id;
+		row["columns"][0]["value"] = name;
+
+		mBulkAgentList->addElement(row);
+		mInviteeIDs.insert(id);
+
+		// We've successfully added someone to the list.
+		if(mOKButton && !mOKButton->getEnabled())
+			mOKButton->setEnabled(TRUE);
+	}
+}
+
+void LLPanelGroupBulkImpl::setGroupName(std::string name)
+{
+	if(mGroupName)
+		mGroupName->setText(name);
+}
+
+
+LLPanelGroupBulk::LLPanelGroupBulk(const LLUUID& group_id) : 
+	LLPanel(),
+	mImplementation(new LLPanelGroupBulkImpl(group_id)),
+	mPendingGroupPropertiesUpdate(false),
+	mPendingRoleDataUpdate(false),
+	mPendingMemberDataUpdate(false)
+{}
+
+LLPanelGroupBulk::~LLPanelGroupBulk()
+{
+	delete mImplementation;
+}
+
+void LLPanelGroupBulk::clear()
+{
+	mImplementation->mInviteeIDs.clear();
+
+	if(mImplementation->mBulkAgentList)
+		mImplementation->mBulkAgentList->deleteAllItems();
+	
+	if(mImplementation->mOKButton)
+		mImplementation->mOKButton->setEnabled(FALSE);
+}
+
+void LLPanelGroupBulk::update()
+{
+	updateGroupName();
+	updateGroupData();
+}
+
+void LLPanelGroupBulk::draw()
+{
+	LLPanel::draw();
+	update();
+}
+
+void LLPanelGroupBulk::updateGroupName()
+{
+	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+
+	if(	gdatap &&
+		gdatap->isGroupPropertiesDataComplete())
+	{
+		// Only do work if the current group name differs
+		if(mImplementation->mGroupName->getText().compare(gdatap->mName) != 0)
+			mImplementation->setGroupName(gdatap->mName);
+	}
+	else
+	{
+		mImplementation->setGroupName(mImplementation->mLoadingText);
+	}
+}
+
+void LLPanelGroupBulk::updateGroupData()
+{
+	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+	if(gdatap && gdatap->isGroupPropertiesDataComplete())
+	{
+		mPendingGroupPropertiesUpdate = false;
+	}
+	else
+	{
+		if(!mPendingGroupPropertiesUpdate)
+		{
+			mPendingGroupPropertiesUpdate = true;
+			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
+		}
+	}
+
+	if(gdatap && gdatap->isRoleDataComplete())
+	{
+		mPendingRoleDataUpdate = false;
+	}
+	else
+	{
+		if(!mPendingRoleDataUpdate)
+		{
+			mPendingRoleDataUpdate = true;
+			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
+		}
+	}
+
+	if(gdatap && gdatap->isMemberDataComplete())
+	{
+		mPendingMemberDataUpdate = false;
+	}
+	else
+	{
+		if(!mPendingMemberDataUpdate)
+		{
+			mPendingMemberDataUpdate = true;
+			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
+		}
+	}
+}
+
+void LLPanelGroupBulk::addUserCallback(const LLUUID& id, const LLAvatarName& av_name)
+{
+	std::vector<std::string> names;
+	uuid_vec_t agent_ids;
+	agent_ids.push_back(id);
+	names.push_back(av_name.getAccountName());
+
+	mImplementation->addUsers(names, agent_ids);
+}
+
+void LLPanelGroupBulk::setCloseCallback(void (*close_callback)(void*), void* data)
+{
+	mImplementation->mCloseCallback         = close_callback;
+	mImplementation->mCloseCallbackUserData = data;
+}
+
+void LLPanelGroupBulk::addUsers(uuid_vec_t& agent_ids)
+{
+	std::vector<std::string> names;
+	for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+	{
+		std::string fullname;
+		LLUUID agent_id = agent_ids[i];
+		LLViewerObject* dest = gObjectList.findObject(agent_id);
+		if(dest && dest->isAvatar())
+		{
+			LLNameValue* nvfirst = dest->getNVPair("FirstName");
+			LLNameValue* nvlast = dest->getNVPair("LastName");
+			if(nvfirst && nvlast)
+			{
+				fullname = LLCacheName::buildFullName(
+					nvfirst->getString(), nvlast->getString());
+
+			}
+			if (!fullname.empty())
+			{
+				names.push_back(fullname);
+			} 
+			else 
+			{
+				llwarns << "llPanelGroupBulk: Selected avatar has no name: " << dest->getID() << llendl;
+				names.push_back("(Unknown)");
+			}
+		}
+		else
+		{
+			//looks like user try to invite offline friend
+			//for offline avatar_id gObjectList.findObject() will return null
+			//so we need to do this additional search in avatar tracker, see EXT-4732
+			if (LLAvatarTracker::instance().isBuddy(agent_id))
+			{
+				LLAvatarName av_name;
+				if (!LLAvatarNameCache::get(agent_id, &av_name))
+				{
+					// actually it should happen, just in case
+					LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupBulk::addUserCallback, this, _1, _2));
+					// for this special case!
+					//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence
+					// removed id will be added in callback
+					agent_ids.erase(agent_ids.begin() + i);
+				}
+				else
+				{
+					names.push_back(av_name.getAccountName());
+				}
+			}
+		}
+	}
+	mImplementation->mListFullNotificationSent = false;
+	mImplementation->addUsers(names, agent_ids);
+}
+
diff --git a/indra/newview/llpanelgroupbulk.h b/indra/newview/llpanelgroupbulk.h
new file mode 100644
index 0000000000000000000000000000000000000000..25ae71ab86f0bf6e559b10cbda712d6f23704a51
--- /dev/null
+++ b/indra/newview/llpanelgroupbulk.h
@@ -0,0 +1,74 @@
+/** 
+* @file   llpanelgroupbulk.h
+* @brief  Header file for llpanelgroupbulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLPANELGROUPBULK_H
+#define LL_LLPANELGROUPBULK_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLAvatarName;
+class LLGroupMgrGroupData;
+class LLPanelGroupBulkImpl;
+
+// Base panel class for bulk group invite / ban floaters
+class LLPanelGroupBulk : public LLPanel
+{
+public:
+	LLPanelGroupBulk(const LLUUID& group_id);
+	/*virtual*/ ~LLPanelGroupBulk();
+
+public:	
+	static void callbackClickSubmit(void* userdata) {}
+	virtual void submit() = 0;
+
+public:
+	virtual void clear();
+	virtual void update();
+	virtual void draw();
+
+protected:
+	virtual void updateGroupName();
+	virtual void updateGroupData();
+
+public:
+	// this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers().
+	virtual void addUserCallback(const LLUUID& id, const LLAvatarName& av_name);
+	virtual void setCloseCallback(void (*close_callback)(void*), void* data);
+
+	virtual void addUsers(uuid_vec_t& agent_ids);
+
+public:
+	LLPanelGroupBulkImpl* mImplementation;
+
+protected:
+	bool mPendingGroupPropertiesUpdate;
+	bool mPendingRoleDataUpdate;
+	bool mPendingMemberDataUpdate;
+};
+
+#endif // LL_LLPANELGROUPBULK_H
+
diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cf1f0bc32f0222bdaa1c6d465e00524a9bb65a24
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkban.cpp
@@ -0,0 +1,259 @@
+/** 
+* @file llpanelgroupbulkban.cpp
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelgroupbulkban.h"
+#include "llpanelgroupbulk.h"
+#include "llpanelgroupbulkimpl.h"
+
+#include "llagent.h"
+#include "llavatarnamecache.h"
+#include "llavataractions.h"
+#include "llfloateravatarpicker.h"
+#include "llbutton.h"
+#include "llcallingcard.h"
+#include "llcombobox.h"
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
+#include "llslurl.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+
+#include <boost/foreach.hpp>
+
+LLPanelGroupBulkBan::LLPanelGroupBulkBan(const LLUUID& group_id) : LLPanelGroupBulk(group_id)
+{
+	// Pass on construction of this panel to the control factory.
+	buildFromFile( "panel_group_bulk_ban.xml");
+}
+
+BOOL LLPanelGroupBulkBan::postBuild()
+{
+	BOOL recurse = TRUE;
+
+	mImplementation->mLoadingText = getString("loading");
+	mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse);
+	mImplementation->mBulkAgentList = getChild<LLNameListCtrl>("banned_agent_list", recurse);
+	if ( mImplementation->mBulkAgentList )
+	{
+		mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE);
+		mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation);
+	}
+
+	LLButton* button = getChild<LLButton>("add_button", recurse);
+	if ( button )
+	{
+		// default to opening avatarpicker automatically
+		// (*impl::callbackClickAdd)((void*)this);
+		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this);
+	}
+
+	mImplementation->mRemoveButton = 
+		getChild<LLButton>("remove_button", recurse);
+	if ( mImplementation->mRemoveButton )
+	{
+		mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation);
+		mImplementation->mRemoveButton->setEnabled(FALSE);
+	}
+
+	mImplementation->mOKButton = 
+		getChild<LLButton>("ban_button", recurse);
+	if ( mImplementation->mOKButton )
+	{
+		mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this);
+		mImplementation->mOKButton->setEnabled(FALSE);
+	}
+
+	button = getChild<LLButton>("cancel_button", recurse);
+	if ( button )
+	{
+		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation);
+	}
+
+	mImplementation->mTooManySelected = getString("ban_selection_too_large");
+	mImplementation->mBanNotPermitted = getString("ban_not_permitted");
+	mImplementation->mBanLimitFail = getString("ban_limit_fail");
+	mImplementation->mCannotBanYourself = getString("cant_ban_yourself");
+
+	update();
+	return TRUE;
+}
+
+// TODO: Refactor the shitty callback functions with void* -- just use boost::bind to call submit() instead.
+void LLPanelGroupBulkBan::callbackClickSubmit(void* userdata)
+{
+	LLPanelGroupBulkBan* selfp = (LLPanelGroupBulkBan*)userdata;
+
+	if(selfp)
+		selfp->submit();
+}
+
+
+void LLPanelGroupBulkBan::submit()
+{
+	if (!gAgent.hasPowerInGroup(mImplementation->mGroupID, GP_GROUP_BAN_ACCESS))
+	{
+		// Fail! Agent no longer have ban rights. Permissions could have changed after button was pressed.
+		LLSD msg;
+		msg["MESSAGE"] = mImplementation->mBanNotPermitted;
+		LLNotificationsUtil::add("GenericAlert", msg);
+		(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+		return;
+	}
+	LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+	if (group_datap && group_datap->mBanList.size() >= GB_MAX_BANNED_AGENTS)
+	{
+		// Fail! Size limit exceeded. List could have updated after button was pressed.
+		LLSD msg;
+		msg["MESSAGE"] = mImplementation->mBanLimitFail;
+		LLNotificationsUtil::add("GenericAlert", msg);
+		(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+		return;
+	}
+	std::vector<LLUUID> banned_agent_list;	
+	std::vector<LLScrollListItem*> agents = mImplementation->mBulkAgentList->getAllData();
+	std::vector<LLScrollListItem*>::iterator iter = agents.begin();
+	for(;iter != agents.end(); ++iter)
+	{
+		LLScrollListItem* agent = *iter;
+		banned_agent_list.push_back(agent->getUUID());
+	}
+
+	const S32 MAX_BANS_PER_REQUEST = 100; // Max bans per request. 100 to match server cap.
+	if (banned_agent_list.size() > MAX_BANS_PER_REQUEST)
+	{
+		// Fail!
+		LLSD msg;
+		msg["MESSAGE"] = mImplementation->mTooManySelected;
+		LLNotificationsUtil::add("GenericAlert", msg);
+		(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+		return;
+	}
+
+	// remove already banned users and yourself from request.
+	std::vector<LLAvatarName> banned_avatar_names;
+	std::vector<LLAvatarName> out_of_limit_names;
+	bool banning_self = FALSE;
+	std::vector<LLUUID>::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID());
+	if (conflict != banned_agent_list.end())
+	{
+		banned_agent_list.erase(conflict);
+		banning_self = TRUE;
+	}
+	if (group_datap)
+	{
+		BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList)
+		{
+			const LLUUID& group_ban_agent_id = group_ban_pair.first;
+			std::vector<LLUUID>::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id);
+			if (conflict != banned_agent_list.end())
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(group_ban_agent_id, &av_name);
+				banned_avatar_names.push_back(av_name);
+
+				banned_agent_list.erase(conflict);
+				if (banned_agent_list.size() == 0)
+				{
+					break;
+				}
+			}
+		}
+		// this check should always be the last one before we send the request.
+		// Otherwise we have a possibility of cutting more then we need to.
+		if (banned_agent_list.size() > GB_MAX_BANNED_AGENTS - group_datap->mBanList.size())
+		{
+			std::vector<LLUUID>::iterator exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size();
+			for (std::vector<LLUUID>::iterator itor = exeedes_limit ; 
+				itor != banned_agent_list.end(); ++itor)
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(*itor, &av_name);
+				out_of_limit_names.push_back(av_name);
+			}
+			banned_agent_list.erase(exeedes_limit,banned_agent_list.end());
+		}
+	}
+
+	// sending request and ejecting members
+	if (banned_agent_list.size() != 0)
+	{
+		LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list);
+		LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list);
+	}
+
+	// building notification
+	if (banned_avatar_names.size() > 0 || banning_self || out_of_limit_names.size() > 0)
+	{
+		std::string reasons;
+		if(banned_avatar_names.size() > 0)
+		{
+			reasons = "\n " + buildResidentsArgument(banned_avatar_names, "residents_already_banned");
+		}
+
+		if(banning_self)
+		{
+			reasons += "\n " + mImplementation->mCannotBanYourself;
+		}
+
+		if(out_of_limit_names.size() > 0)
+		{
+			reasons += "\n " + buildResidentsArgument(out_of_limit_names, "ban_limit_reached");
+		}
+
+		LLStringUtil::format_map_t msg_args;
+		msg_args["[REASONS]"] = reasons;
+		LLSD msg;
+		if (banned_agent_list.size() == 0)
+		{
+			msg["MESSAGE"] = getString("ban_failed", msg_args);
+		}
+		else
+		{
+			msg["MESSAGE"] = getString("partial_ban", msg_args);
+		}
+		LLNotificationsUtil::add("GenericAlert", msg);
+	}
+	
+	//then close
+	(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+}
+
+std::string LLPanelGroupBulkBan::buildResidentsArgument(std::vector<LLAvatarName> avatar_names, const std::string &format)
+{
+	std::string names_string;
+	LLAvatarActions::buildResidentsString(avatar_names, names_string);
+	LLStringUtil::format_map_t args;
+	args["[RESIDENTS]"] = names_string;
+	return getString(format, args);
+}
diff --git a/indra/newview/llpanelgroupbulkban.h b/indra/newview/llpanelgroupbulkban.h
new file mode 100644
index 0000000000000000000000000000000000000000..9060d275f97973dc1f232534e0d52121072ce25a
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkban.h
@@ -0,0 +1,49 @@
+/** 
+* @file   llpanelgroupbulkban.h
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLPANELGROUPBULKBAN_H
+#define LL_LLPANELGROUPBULKBAN_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+#include "llpanelgroupbulk.h"
+
+class LLAvatarName;
+
+class LLPanelGroupBulkBan : public LLPanelGroupBulk
+{
+public:
+	LLPanelGroupBulkBan(const LLUUID& group_id);
+	~LLPanelGroupBulkBan() {}
+
+	virtual BOOL postBuild();
+
+	static void callbackClickSubmit(void* userdata);
+	virtual void submit();
+private:
+	std::string buildResidentsArgument(std::vector<LLAvatarName> avatar_names, const std::string &format);
+};
+
+#endif // LL_LLPANELGROUPBULKBAN_H
diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3a48e5a9a3fb462c4df5eb8d16bcb32d94d3952
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkimpl.h
@@ -0,0 +1,99 @@
+/** 
+* @file   llpanelgroupbulkimpl.h
+* @brief  Class definition for implementation class of LLPanelGroupBulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLPANELGROUPBULKIMPL_H
+#define LL_LLPANELGROUPBULKIMPL_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLAvatarName;
+class LLNameListCtrl;
+class LLTextBox;
+class LLComboBox;
+
+//////////////////////////////////////////////////////////////////////////
+//	Implementation found in llpanelgroupbulk.cpp
+//////////////////////////////////////////////////////////////////////////
+class LLPanelGroupBulkImpl
+{
+public:
+	LLPanelGroupBulkImpl(const LLUUID& group_id);
+	~LLPanelGroupBulkImpl();
+
+	static void callbackClickAdd(void* userdata);
+	static void callbackClickRemove(void* userdata);
+
+	static void callbackClickCancel(void* userdata);
+
+	static void callbackSelect(LLUICtrl* ctrl, void* userdata);
+	static void callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data);
+
+	static void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data);
+
+	void handleRemove();
+	void handleSelection();
+
+	void addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids);
+	void setGroupName(std::string name);
+
+
+public:
+	static const S32 MAX_GROUP_INVITES = 100;	// Max invites per request. 100 to match server cap.
+	
+
+	LLUUID				mGroupID;
+
+	LLNameListCtrl*		mBulkAgentList;
+	LLButton*			mOKButton;
+	LLButton*			mRemoveButton;
+	LLTextBox*			mGroupName;
+
+	std::string			mLoadingText; 
+	std::string			mTooManySelected;
+	std::string			mBanNotPermitted;
+	std::string			mBanLimitFail;
+	std::string			mCannotBanYourself;
+
+	std::set<LLUUID>	mInviteeIDs;
+
+	void (*mCloseCallback)(void* data);
+	void* mCloseCallbackUserData;
+	boost::signals2::connection mAvatarNameCacheConnection;
+
+	// The following are for the LLPanelGroupInvite subclass only.  
+	// These aren't needed for LLPanelGroupBulkBan, but if we have to add another 
+	// group bulk floater for some reason, we'll have these objects too.
+public:
+	LLComboBox*		mRoleNames;
+	std::string		mOwnerWarning;
+	std::string		mAlreadyInGroup;
+	bool			mConfirmedOwnerInvite;
+	bool			mListFullNotificationSent;
+};
+
+#endif // LL_LLPANELGROUPBULKIMPL_H
+
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index dd13e8abf4b48b36a68f9574a5241ddc618e2dca..236ad861a5cc9eb2f838df7ab5ff57de101753f3 100755
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -260,7 +260,7 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)
 			//else if they have the limited add to roles power
 			//we add every role the user is in
 			//else we just add to everyone
-			bool is_owner   = member_data->isInRole(gdatap->mOwnerRole);
+			bool is_owner   = member_data->isOwner();
 			bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
 												 GP_ROLE_ASSIGN_MEMBER);
 			bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
@@ -492,7 +492,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
 			} 
 			else 
 			{
-				LL_WARNS() << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << LL_ENDL;
+				llwarns << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << llendl;
 				names.push_back("(Unknown)");
 			}
 		}
@@ -579,7 +579,7 @@ void LLPanelGroupInvite::updateLists()
 		{
 			waiting = true;
 		}
-		if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete()) 
+		if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete()) 
 		{
 			if ( mImplementation->mRoleNames )
 			{
@@ -607,6 +607,7 @@ void LLPanelGroupInvite::updateLists()
 		{
 			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
 			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
+			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
 			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
 		}
 		mPendingUpdate = TRUE;
@@ -654,7 +655,7 @@ BOOL LLPanelGroupInvite::postBuild()
 	}
 
 	mImplementation->mOKButton = 
-		getChild<LLButton>("ok_button", recurse);
+		getChild<LLButton>("invite_button", recurse);
 	if ( mImplementation->mOKButton )
  	{
 		mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation);
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 9ca3d7e96e4000976b8245f9065354b53aa1158a..1d7ba4d741196a25556692146f0c2375d9d64a6a 100755
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file llpanelgrouproles.cpp
  * @brief Panel for roles information about a particular group.
  *
@@ -32,6 +32,7 @@
 #include "llavatarnamecache.h"
 #include "llbutton.h"
 #include "llfiltereditor.h"
+#include "llfloatergroupbulkban.h"
 #include "llfloatergroupinvite.h"
 #include "llavataractions.h"
 #include "lliconctrl.h"
@@ -109,8 +110,10 @@ bool agentCanAddToRole(const LLUUID& group_id,
 	return false;
 }
 
-// static
 
+// LLPanelGroupRoles /////////////////////////////////////////////////////
+
+// static
 LLPanelGroupRoles::LLPanelGroupRoles()
 :	LLPanelGroupTab(),
 	mCurrentTab(NULL),
@@ -297,7 +300,6 @@ bool LLPanelGroupRoles::onModalClose(const LLSD& notification, const LLSD& respo
 	return false;
 }
 
-
 bool LLPanelGroupRoles::apply(std::string& mesg)
 {
 	// Pass this along to the currently visible sub tab.
@@ -334,7 +336,6 @@ void LLPanelGroupRoles::update(LLGroupChange gc)
 {
 	if (mGroupID.isNull()) return;
 	
-	
 	LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
 	if (panelp)
 	{
@@ -351,39 +352,33 @@ void LLPanelGroupRoles::activate()
 {
 	// Start requesting member and role data if needed.
 	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
-	//if (!gdatap || mFirstUse)
+	if (!gdatap || !gdatap->isMemberDataComplete() )
 	{
-		// Check member data.
-		
-		if (!gdatap || !gdatap->isMemberDataComplete() )
-		{
-			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
-		}
-
-		// Check role data.
-		if (!gdatap || !gdatap->isRoleDataComplete() )
-		{
-			// Mildly hackish - clear all pending changes
-			cancel();
+		LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
+	}
 
-			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
-		}
+	if (!gdatap || !gdatap->isRoleDataComplete() )
+	{
+		// Mildly hackish - clear all pending changes
+		cancel();
 
-		// Check role-member mapping data.
-		if (!gdatap || !gdatap->isRoleMemberDataComplete() )
-		{
-			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
-		}
+		LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
+	}
 
-		// Need this to get base group member powers
-		if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
-		{
-			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
-		}
+	// Check role-member mapping data.
+	if (!gdatap || !gdatap->isRoleMemberDataComplete() )
+	{
+		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+	}
 
-		mFirstUse = FALSE;
+	// Need this to get base group member powers
+	if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
+	{
+		LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
 	}
 
+	mFirstUse = FALSE;
+
 	LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
 	if (panelp) panelp->activate();
 }
@@ -412,15 +407,38 @@ BOOL LLPanelGroupRoles::hasModal()
 	return panelp->hasModal();
 }
 
+void LLPanelGroupRoles::setGroupID(const LLUUID& id)
+{
+	LLPanelGroupTab::setGroupID(id);
+
+	LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab");
+	LLPanelGroupRolesSubTab*  group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab");
+	LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab");
+	LLPanelGroupBanListSubTab* group_ban_tab = findChild<LLPanelGroupBanListSubTab>("banlist_sub_tab");
+
+	if(group_members_tab) group_members_tab->setGroupID(id);
+	if(group_roles_tab) group_roles_tab->setGroupID(id);
+	if(group_actions_tab) group_actions_tab->setGroupID(id);
+	if(group_ban_tab) group_ban_tab->setGroupID(id);
+
+	LLButton* button = getChild<LLButton>("member_invite");
+	if ( button )
+		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+
+	if(mSubTabContainer)
+		mSubTabContainer->selectTab(1);
+	group_roles_tab->mFirstOpen = TRUE;
+	activate();
+}
+
 
-////////////////////////////
-// LLPanelGroupSubTab
-////////////////////////////
+// LLPanelGroupSubTab ////////////////////////////////////////////////////
 LLPanelGroupSubTab::LLPanelGroupSubTab()
 :	LLPanelGroupTab(),
 	mHeader(NULL),
 	mFooter(NULL),
 	mActivated(false),
+	mHasGroupBanPower(false),
 	mSearchEditor(NULL)
 {
 }
@@ -542,9 +560,10 @@ void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
 		return;
 	}
 
+	mHasGroupBanPower = false;
+
 	std::vector<LLRoleActionSet*>::iterator ras_it = LLGroupMgr::getInstance()->mRoleActionSets.begin();
 	std::vector<LLRoleActionSet*>::iterator ras_end = LLGroupMgr::getInstance()->mRoleActionSets.end();
-
 	for ( ; ras_it != ras_end; ++ras_it)
 	{
 		buildActionCategory(ctrl,
@@ -674,6 +693,31 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
 			row["columns"][column_index]["value"] = (*ra_it)->mDescription;
 			row["columns"][column_index]["font"] = "SANSSERIF_SMALL";
 
+			if(mHasGroupBanPower)
+			{
+				// The ban ability is being set. Prevent these abilities from being manipulated
+				if((*ra_it)->mPowerBit == GP_MEMBER_EJECT)
+				{
+					row["enabled"] = false;
+				}
+				else if((*ra_it)->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+				{
+					row["enabled"] = false;
+				}
+			}
+			else
+			{
+				// The ban ability is not set. Allow these abilities to be manipulated
+				if((*ra_it)->mPowerBit == GP_MEMBER_EJECT)
+				{
+					row["enabled"] = true;
+				}
+				else if((*ra_it)->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+				{
+					row["enabled"] = true;
+				}
+			}
+
 			LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
 
 			if (-1 != check_box_index)
@@ -709,6 +753,15 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
 						check->setTentative(TRUE);
 					}
 				}
+
+				// Regardless of whether or not this ability is allowed by all or some, we want to prevent
+				// the group managers from accidentally disabling either of the two additional abilities
+				// tied with GP_GROUP_BAN_ACCESS.
+				if(	(allowed_by_all & GP_GROUP_BAN_ACCESS) == GP_GROUP_BAN_ACCESS ||
+					(allowed_by_some & GP_GROUP_BAN_ACCESS) == GP_GROUP_BAN_ACCESS)
+				{
+					mHasGroupBanPower = true;
+				}
 			}
 		}
 
@@ -728,11 +781,8 @@ void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
 	}
 }
 
-////////////////////////////
-// LLPanelGroupMembersSubTab
-////////////////////////////
-
 
+// LLPanelGroupMembersSubTab /////////////////////////////////////////////
 static LLPanelInjector<LLPanelGroupMembersSubTab> t_panel_group_members_subtab("panel_group_members_subtab");
 
 LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
@@ -813,6 +863,13 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
 		mEjectBtn->setEnabled(FALSE);
 	}
 
+	mBanBtn = parent->getChild<LLButton>("member_ban", recurse);
+	if(mBanBtn)
+	{
+		mBanBtn->setClickedCallback(onBanMember, this);
+		mBanBtn->setEnabled(FALSE);
+	}
+
 	return TRUE;
 }
 
@@ -826,34 +883,6 @@ void LLPanelGroupMembersSubTab::setGroupID(const LLUUID& id)
 	LLPanelGroupSubTab::setGroupID(id);
 }
 
-void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id)
-{
-	if(mRolesList) mRolesList->deleteAllItems();
-	if(mAssignedMembersList) mAssignedMembersList->deleteAllItems();
-	if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
-
-	if(mRoleName) mRoleName->clear();
-	if(mRoleDescription) mRoleDescription->clear();
-	if(mRoleTitle) mRoleTitle->clear();
-
-	mHasRoleChange = FALSE;
-
-	setFooterEnabled(FALSE);
-
-	LLPanelGroupSubTab::setGroupID(id);
-}
-void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)
-{
-	if(mActionList) mActionList->deleteAllItems();
-	if(mActionRoles) mActionRoles->deleteAllItems();
-	if(mActionMembers) mActionMembers->deleteAllItems();
-
-	if(mActionDescription) mActionDescription->clear();
-
-	LLPanelGroupSubTab::setGroupID(id);
-}
-
-
 // static
 void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
 {
@@ -882,7 +911,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 
 	// Build a vector of all selected members, and gather allowed actions.
 	uuid_vec_t selected_members;
-	U64 allowed_by_all = 0xffffffffffffLL;
+	U64 allowed_by_all = GP_ALL_POWERS; //0xFFFFffffFFFFffffLL;
 	U64 allowed_by_some = 0;
 
 	std::vector<LLScrollListItem*>::iterator itor;
@@ -919,8 +948,8 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 	LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin();
 	LLGroupMgrGroupData::role_list_t::iterator end  = gdatap->mRoles.end();
 
-	BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
-													GP_MEMBER_EJECT);
+	BOOL can_ban_members = gAgent.hasPowerInGroup(mGroupID,	GP_GROUP_BAN_ACCESS);
+	BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_EJECT);
 	BOOL member_is_owner = FALSE;
 	
 	for( ; iter != end; ++iter)
@@ -967,6 +996,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 					{
 						// Can't remove other owners.
 						cb_enable = FALSE;
+						can_ban_members = FALSE;
 						break;
 					}
 				}
@@ -986,14 +1016,14 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 			}
 			
 			// If anyone selected is in any role besides 'Everyone' then they can't be ejected.
-			if (role_id.notNull() && (count > 0))
-			{
+ 			if (role_id.notNull() && (count > 0))
+ 			{
 				can_eject_members = FALSE;
-				if (role_id == gdatap->mOwnerRole)
-				{
-					member_is_owner = TRUE;
-				}
-			}
+ 				if (role_id == gdatap->mOwnerRole)
+ 				{
+ 					member_is_owner = TRUE;
+ 				}
+ 			}
 
 			LLRoleData rd;
 			if (gdatap->getRoleData(role_id,rd))
@@ -1050,7 +1080,10 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 	mAssignedRolesList->setEnabled(TRUE);
 
 	if (gAgent.isGodlike())
+	{
 		can_eject_members = TRUE;
+	//	can_ban_members = TRUE;
+	}
 
 	if (!can_eject_members && !member_is_owner)
 	{
@@ -1063,10 +1096,41 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 			if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
 			{
 				can_eject_members = TRUE;
+				//can_ban_members = TRUE;
 			}
 		}
+
+	}
+
+	// ... or we can eject them because we have all the requisite powers...
+	if(	gAgent.hasPowerInGroup(mGroupID, GP_ROLE_REMOVE_MEMBER) &&
+		!member_is_owner)
+	{
+		if( gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_EJECT))
+		{
+			can_eject_members = TRUE;
+		}
+		
+		if( gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+		{
+			can_ban_members = TRUE;
+		}
 	}
 
+
+	uuid_vec_t::const_iterator member_iter = selected_members.begin();
+	uuid_vec_t::const_iterator member_end = selected_members.end();
+	for ( ; member_iter != member_end; ++member_iter)
+	{
+		// Don't count the agent.
+		if ((*member_iter) == gAgent.getID())
+		{
+			can_eject_members = FALSE;
+			can_ban_members = FALSE;
+		}
+	}
+
+	mBanBtn->setEnabled(can_ban_members);
 	mEjectBtn->setEnabled(can_eject_members);
 }
 
@@ -1104,61 +1168,26 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
 }
 
 void LLPanelGroupMembersSubTab::handleEjectMembers()
-{	
+{
+	//send down an eject message
+	uuid_vec_t selected_members;
+
 	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
 	if (selection.empty()) return;
-	
-	S32 selection_count = selection.size();
-	if (selection_count == 1)
-	{
-		LLSD args;
-		LLUUID selected_avatar = mMembersList->getValue().asUUID();
-		std::string fullname = LLSLURL("agent", selected_avatar, "inspect").getSLURLString();
-		args["AVATAR_NAME"] = fullname;
-		LLSD payload;
-		LLNotificationsUtil::add("EjectGroupMemberWarning",
-								 args,
-								 payload,
-								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
-	}
-	else
-	{
-		LLSD args;
-		args["COUNT"] = llformat("%d", selection_count);
-		LLSD payload;
-		LLNotificationsUtil::add("EjectGroupMembersWarning",
-								 args,
-								 payload,
-								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
-	}
-}
 
-bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option) // Eject button
+	std::vector<LLScrollListItem*>::iterator itor;
+	for (itor = selection.begin() ; 
+		 itor != selection.end(); ++itor)
 	{
-		//send down an eject message
-		uuid_vec_t selected_members;
-		
-		std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
-		if (selection.empty()) return false;
-		
-		std::vector<LLScrollListItem*>::iterator itor;
-		for (itor = selection.begin() ;
-			 itor != selection.end(); ++itor)
-		{
-			LLUUID member_id = (*itor)->getUUID();
-			selected_members.push_back( member_id );
-		}
-		
-		mMembersList->deleteSelectedItems();
-		
-		sendEjectNotifications(mGroupID, selected_members);
-		
-		LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
+		LLUUID member_id = (*itor)->getUUID();
+		selected_members.push_back( member_id );
 	}
-	return false;
+
+	mMembersList->deleteSelectedItems();
+
+	sendEjectNotifications(mGroupID, selected_members);
+
+	LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
 }
 
 void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
@@ -1186,12 +1215,11 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
 
 	//add that the user is requesting to change the roles for selected
 	//members
-	U64 powers_all_have  = 0xffffffffffffLL;
+	U64 powers_all_have  = GP_ALL_POWERS;
 	U64 powers_some_have = 0;
 
 	BOOL   is_owner_role = ( gdatap->mOwnerRole == role_id );
 	LLUUID member_id;
-	
 
 	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
 	if (selection.empty())
@@ -1202,7 +1230,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
 	for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ; 
 		 itor != selection.end(); ++itor)
 	{
-
 		member_id = (*itor)->getUUID();
 
 		//see if we requested a change for this member before
@@ -1268,7 +1295,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
 					 FALSE);
 }
 
-
 // static 
 void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
 {
@@ -1307,6 +1333,15 @@ void LLPanelGroupMembersSubTab::activate()
 		update(GC_ALL);
 		mActivated = true;
 	}
+	else
+	{
+		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+		// Members can be removed outside of this tab, checking changes
+		if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount()))
+		{
+			update(GC_MEMBER_DATA);
+		}
+	}
 }
 
 void LLPanelGroupMembersSubTab::deactivate()
@@ -1701,13 +1736,12 @@ void LLPanelGroupMembersSubTab::updateMembers()
 		return;
 	}
 
-	//cleanup list only for first iretation
+	//cleanup list only for first iteration
 	if(mMemberProgress == gdatap->mMembers.begin())
 	{
 		mMembersList->deleteAllItems();
 	}
 
-
 	LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
 
 	LLTimer update_time;
@@ -1764,12 +1798,44 @@ void LLPanelGroupMembersSubTab::updateMembers()
 	handleMemberSelect();
 }
 
+void LLPanelGroupMembersSubTab::onBanMember(void* user_data)
+{
+	LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
+	self->handleBanMember();
+}
 
+void LLPanelGroupMembersSubTab::handleBanMember()
+{
+	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(mGroupID);
+	if(!gdatap) 
+	{
+		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+		return;
+	}
 
-////////////////////////////
-// LLPanelGroupRolesSubTab
-////////////////////////////
+	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+	if(selection.empty())
+	{
+		return;
+	}
 
+	uuid_vec_t ban_ids;
+	std::vector<LLScrollListItem*>::iterator itor;
+	for(itor = selection.begin(); itor != selection.end(); ++itor)
+	{
+		LLUUID ban_id = (*itor)->getUUID();
+		ban_ids.push_back(ban_id);
+		
+		LLGroupBanData ban_data;
+		gdatap->createBanEntry(ban_id, ban_data);
+	}	
+
+	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_CREATE, ban_ids);
+	handleEjectMembers();
+}
+
+
+// LLPanelGroupRolesSubTab ///////////////////////////////////////////////
 static LLPanelInjector<LLPanelGroupRolesSubTab> t_panel_group_roles_subtab("panel_group_roles_subtab");
 
 LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
@@ -1783,7 +1849,7 @@ LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
 	mMemberVisibleCheck(NULL),
 	mDeleteRoleButton(NULL),
 	mCreateRoleButton(NULL),
-
+	mFirstOpen(TRUE),
 	mHasRoleChange(FALSE)
 {
 }
@@ -1885,6 +1951,7 @@ void LLPanelGroupRolesSubTab::deactivate()
 	LL_DEBUGS() << "LLPanelGroupRolesSubTab::deactivate()" << LL_ENDL;
 
 	LLPanelGroupSubTab::deactivate();
+	mFirstOpen = FALSE;
 }
 
 bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg)
@@ -1892,6 +1959,12 @@ bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg)
 	LL_DEBUGS() << "LLPanelGroupRolesSubTab::needsApply()" << LL_ENDL;
 
 	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+	if(!gdatap)
+	{
+		llwarns << "Unable to get group data for group " << mGroupID << llendl;
+		return false;
+	}
+
 
 	return (mHasRoleChange								// Text changed in current role
 			|| (gdatap && gdatap->pendingRoleChanges()));	// Pending role changes in the group
@@ -1902,7 +1975,7 @@ bool LLPanelGroupRolesSubTab::apply(std::string& mesg)
 	LL_DEBUGS() << "LLPanelGroupRolesSubTab::apply()" << LL_ENDL;
 
 	saveRoleChanges(true);
-
+	mFirstOpen = FALSE;
 	LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID);
 
 	notifyObservers();
@@ -2039,14 +2112,17 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
 		}
 	}
 
-	if (!gdatap || !gdatap->isMemberDataComplete())
+	if(!mFirstOpen)
 	{
-		LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
-	}
-	
-	if (!gdatap || !gdatap->isRoleMemberDataComplete())
-	{
-		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+		if (!gdatap || !gdatap->isMemberDataComplete())
+		{
+			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
+		}
+
+		if (!gdatap || !gdatap->isRoleMemberDataComplete())
+		{
+			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+		}
 	}
 
 	if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
@@ -2062,6 +2138,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
 void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
 {
 	LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+	if (!self) 
+		return;
+
 	self->handleRoleSelect();
 }
 
@@ -2241,40 +2320,115 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
 	LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
 	U64 power = rap->mPowerBit;
 
-	if (check->get())
+	bool isEnablingAbility = check->get();
+	LLRoleData rd;
+	LLSD args;
+
+	if (isEnablingAbility &&
+		!force && 
+		((GP_ROLE_ASSIGN_MEMBER == power) || (GP_ROLE_CHANGE_ACTIONS == power) ))
 	{
-		if (!force && (    (GP_ROLE_ASSIGN_MEMBER == power)
-						|| (GP_ROLE_CHANGE_ACTIONS == power) ))
-		{
-			// Uncheck the item, for now.  It will be
-			// checked if they click 'Yes', below.
-			check->set(FALSE);
+		// Uncheck the item, for now.  It will be
+		// checked if they click 'Yes', below.
+		check->set(FALSE);
 
-			LLRoleData rd;
-			LLSD args;
+		LLRoleData rd;
+		LLSD args;
 
-			if ( gdatap->getRoleData(role_id, rd) )
+		if ( gdatap->getRoleData(role_id, rd) )
+		{
+			args["ACTION_NAME"] = rap->mDescription;
+			args["ROLE_NAME"] = rd.mRoleName;
+			mHasModal = TRUE;
+			std::string warning = "AssignDangerousActionWarning";
+			if (GP_ROLE_CHANGE_ACTIONS == power)
 			{
-				args["ACTION_NAME"] = rap->mDescription;
-				args["ROLE_NAME"] = rd.mRoleName;
-				mHasModal = TRUE;
-				std::string warning = "AssignDangerousActionWarning";
-				if (GP_ROLE_CHANGE_ACTIONS == power)
-				{
-					warning = "AssignDangerousAbilityWarning";
-				}
-				LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
+				warning = "AssignDangerousAbilityWarning";
 			}
-			else
-			{
+			LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
+		}
+		else
+		{
 				LL_WARNS() << "Unable to look up role information for role id: "
 						<< role_id << LL_ENDL;
+		}
+	}
+
+	if(GP_GROUP_BAN_ACCESS == power)
+	{
+		std::string warning = isEnablingAbility ? "AssignBanAbilityWarning" : "RemoveBanAbilityWarning";
+
+		//////////////////////////////////////////////////////////////////////////
+		// Get role data for both GP_ROLE_REMOVE_MEMBER and GP_MEMBER_EJECT
+		// Add description and role name to LLSD
+		// Pop up dialog saying "Yo, you also granted these other abilities when you did this!"
+		if ( gdatap->getRoleData(role_id, rd) )
+		{
+			args["ACTION_NAME"] = rap->mDescription;
+			args["ROLE_NAME"] = rd.mRoleName;
+			mHasModal = TRUE;
+			
+			std::vector<LLScrollListItem*> all_data = mAllowedActionsList->getAllData();
+			std::vector<LLScrollListItem*>::iterator ad_it = all_data.begin();
+			std::vector<LLScrollListItem*>::iterator ad_end = all_data.end();
+			LLRoleAction* adp;
+			for( ; ad_it != ad_end; ++ad_it)
+			{
+				adp = (LLRoleAction*)(*ad_it)->getUserdata();
+				if(adp->mPowerBit == GP_MEMBER_EJECT)
+				{
+					args["ACTION_NAME_2"] = adp->mDescription;
+				}
+				else if(adp->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+				{
+					args["ACTION_NAME_3"] = adp->mDescription;
+				}
 			}
+		
+			LLNotificationsUtil::add(warning, args);
 		}
 		else
 		{
-			gdatap->addRolePower(role_id,power);
+			llwarns << "Unable to look up role information for role id: "
+				<< role_id << llendl;
+		}
+		
+		//////////////////////////////////////////////////////////////////////////
+
+		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);
+		}
+
+		if(isEnablingAbility)
+		{
+			power |= (GP_ROLE_REMOVE_MEMBER | GP_MEMBER_EJECT);
+			current_role_powers |= power;
 		}
+		else
+		{
+			current_role_powers &= ~GP_GROUP_BAN_ACCESS;
+		}
+
+		mAllowedActionsList->deleteAllItems();
+		buildActionsList(	mAllowedActionsList,
+			current_role_powers,
+			current_role_powers,				
+			boost::bind(&LLPanelGroupRolesSubTab::handleActionCheck, this, _1, false),
+			TRUE,
+			FALSE,
+			FALSE);
+
+	}
+	
+	//////////////////////////////////////////////////////////////////////////
+	// Adding non-specific ability to role
+	//////////////////////////////////////////////////////////////////////////
+	if(isEnablingAbility)
+	{
+		gdatap->addRolePower(role_id, power);
 	}
 	else
 	{
@@ -2283,6 +2437,7 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
 
 	mHasRoleChange = TRUE;
 	notifyObservers();
+
 }
 
 bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check)
@@ -2302,7 +2457,6 @@ bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD&
 	return false;
 }
 
-
 // static
 void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
 {
@@ -2480,13 +2634,28 @@ void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role)
 		mHasRoleChange = FALSE;
 	}
 }
-////////////////////////////
-// LLPanelGroupActionsSubTab
-////////////////////////////
 
-static LLPanelInjector<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
+void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id)
+{
+	if(mRolesList) mRolesList->deleteAllItems();
+	if(mAssignedMembersList) mAssignedMembersList->deleteAllItems();
+	if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
+
+	if(mRoleName) mRoleName->clear();
+	if(mRoleDescription) mRoleDescription->clear();
+	if(mRoleTitle) mRoleTitle->clear();
+
+	mHasRoleChange = FALSE;
+
+	setFooterEnabled(FALSE);
+
+	LLPanelGroupSubTab::setGroupID(id);
+}
 
 
+// LLPanelGroupActionsSubTab /////////////////////////////////////////////
+static LLPanelInjector<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
+
 LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab()
 : LLPanelGroupSubTab()
 {
@@ -2659,26 +2828,298 @@ void LLPanelGroupActionsSubTab::handleActionSelect()
 	}
 }
 
-void LLPanelGroupRoles::setGroupID(const LLUUID& id)
+void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)
 {
-	LLPanelGroupTab::setGroupID(id);
+	if(mActionList) mActionList->deleteAllItems();
+	if(mActionRoles) mActionRoles->deleteAllItems();
+	if(mActionMembers) mActionMembers->deleteAllItems();
+
+	if(mActionDescription) mActionDescription->clear();
+
+	LLPanelGroupSubTab::setGroupID(id);
+}
+
+
+// LLPanelGroupBanListSubTab /////////////////////////////////////////////
+static LLPanelInjector<LLPanelGroupBanListSubTab> t_panel_group_ban_subtab("panel_group_banlist_subtab");
+
+LLPanelGroupBanListSubTab::LLPanelGroupBanListSubTab()
+	: LLPanelGroupSubTab(),
+	  mBanList(NULL),
+	  mCreateBanButton(NULL),
+	  mDeleteBanButton(NULL)
+{}
+
+BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root)
+{
+	LLPanelGroupSubTab::postBuildSubTab(root);
+
+	// Upcast parent so we can ask it for sibling controls.
+	LLPanelGroupRoles* parent = (LLPanelGroupRoles*)root;
+
+	// Look recursively from the parent to find all our widgets.
+	bool recurse = true;
 	
-	LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab");
-	LLPanelGroupRolesSubTab*  group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab");
-	LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab");
+	mHeader	= parent->getChild<LLPanel>("banlist_header", recurse);
+	mFooter	= parent->getChild<LLPanel>("banlist_footer", recurse);
+	
+	mBanList = parent->getChild<LLNameListCtrl>("ban_list", recurse);
+	
+	mCreateBanButton		= parent->getChild<LLButton>("ban_create", recurse);
+	mDeleteBanButton		= parent->getChild<LLButton>("ban_delete", recurse);
+	mRefreshBanListButton	= parent->getChild<LLButton>("ban_refresh", recurse);
+	mBanCountText			= parent->getChild<LLTextBase>("ban_count", recurse);
 
-	if(group_members_tab) group_members_tab->setGroupID(id);
-	if(group_roles_tab) group_roles_tab->setGroupID(id);
-	if(group_actions_tab) group_actions_tab->setGroupID(id);
+	if(!mBanList || !mCreateBanButton || !mDeleteBanButton || !mRefreshBanListButton || !mBanCountText)
+		return FALSE;
 
-	LLButton* button = getChild<LLButton>("member_invite");
-	if ( button )
-		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+	mBanList->setCommitOnSelectionChange(TRUE);
+	mBanList->setCommitCallback(onBanEntrySelect, this);
 
-	if(mSubTabContainer)
-		mSubTabContainer->selectTab(1);
+	mCreateBanButton->setClickedCallback(onCreateBanEntry, this);
+	mCreateBanButton->setEnabled(FALSE);
 
-	activate();
+	mDeleteBanButton->setClickedCallback(onDeleteBanEntry, this);
+	mDeleteBanButton->setEnabled(FALSE);
+	
+	mRefreshBanListButton->setClickedCallback(onRefreshBanList, this);
+	mRefreshBanListButton->setEnabled(FALSE);
+
+	setBanCount(0);
+
+	mBanList->setOnNameListCompleteCallback(boost::bind(&LLPanelGroupBanListSubTab::onBanListCompleted, this, _1));
+	
+	populateBanList();
+
+	setFooterEnabled(FALSE);
+	return TRUE;
 }
 
+void LLPanelGroupBanListSubTab::activate()
+{
+	LLPanelGroupSubTab::activate();
+
+	mBanList->deselectAllItems();
+	mDeleteBanButton->setEnabled(FALSE);
 
+	LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+	if (group_datap)
+	{
+		mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) &&
+									 group_datap->mBanList.size() < GB_MAX_BANNED_AGENTS);
+		setBanCount(group_datap->mBanList.size());
+	}
+	else
+	{
+		mCreateBanButton->setEnabled(FALSE);
+		setBanCount(0);
+	}
+
+	// BAKER: Should I really request everytime activate() is called?
+	//		  Perhaps I should only do it on a force refresh, or if an action on the list happens...
+	//		  Because it's not going to live-update the list anyway... You'd have to refresh if you 
+	//		  wanted to see someone else's additions anyway...
+	//		  
+	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+
+	setFooterEnabled(FALSE);
+	update(GC_ALL);
+}
+
+void LLPanelGroupBanListSubTab::update(LLGroupChange gc)
+{
+	populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::draw()
+{
+	LLPanelGroupSubTab::draw();
+
+	// BAKER: Might be good to put it here instead of update, maybe.. See how often draw gets hit.
+	//if(
+	//	populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::onBanEntrySelect(LLUICtrl* ctrl, void* user_data)
+{
+	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+	if (!self) 
+		return;
+
+	self->handleBanEntrySelect();
+}
+
+void LLPanelGroupBanListSubTab::handleBanEntrySelect()
+{
+	if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+	{
+		mDeleteBanButton->setEnabled(TRUE);
+	}
+}
+
+void LLPanelGroupBanListSubTab::onCreateBanEntry(void* user_data)
+{
+	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+	if (!self) 
+		return;
+
+	self->handleCreateBanEntry();
+}
+
+void LLPanelGroupBanListSubTab::handleCreateBanEntry()
+{
+	LLFloaterGroupBulkBan::showForGroup(mGroupID);
+	//populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::onDeleteBanEntry(void* user_data)
+{
+	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+	if (!self) 
+		return;
+
+	self->handleDeleteBanEntry();
+}
+
+void LLPanelGroupBanListSubTab::handleDeleteBanEntry()
+{
+	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(mGroupID);
+	if(!gdatap) 
+	{
+		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+		return;
+	}
+
+	std::vector<LLScrollListItem*> selection = mBanList->getAllSelected();
+	if(selection.empty())
+	{
+		return;
+	}
+
+	bool can_ban_members = false;
+	if (gAgent.isGodlike() ||
+		gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+	{
+		can_ban_members	= true;
+	}
+	
+	// Owners can ban anyone in the group.
+	LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
+	if (mi != gdatap->mMembers.end())
+	{
+		LLGroupMemberData* member_data = (*mi).second;
+		if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
+		{
+			can_ban_members	= true;
+		}
+	}
+		
+	if(!can_ban_members)
+		return;
+
+	std::vector<LLUUID> ban_ids;
+	std::vector<LLScrollListItem*>::iterator itor;
+	for(itor = selection.begin(); itor != selection.end(); ++itor)
+	{
+		LLUUID ban_id = (*itor)->getUUID();
+		ban_ids.push_back(ban_id);
+		
+		gdatap->removeBanEntry(ban_id);
+		mBanList->removeNameItem(ban_id);
+	
+		// Removing an item removes the selection, we shouldn't be able to click
+		// the button anymore until we reselect another entry.
+		mDeleteBanButton->setEnabled(FALSE);
+	}
+
+	// update ban-count related elements
+	mCreateBanButton->setEnabled(TRUE);
+	setBanCount(gdatap->mBanList.size());
+	
+	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_DELETE, ban_ids);
+}
+
+void LLPanelGroupBanListSubTab::onRefreshBanList(void* user_data)
+{
+	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+	if (!self) 
+		return;
+
+	self->handleRefreshBanList();
+}
+
+void LLPanelGroupBanListSubTab::handleRefreshBanList()
+{
+	mRefreshBanListButton->setEnabled(FALSE);
+	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+}
+
+void LLPanelGroupBanListSubTab::onBanListCompleted(bool isComplete)
+{
+	if(isComplete)
+	{
+		mRefreshBanListButton->setEnabled(TRUE);
+		populateBanList();
+	}
+}
+
+void LLPanelGroupBanListSubTab::setBanCount(U32 ban_count)
+{
+	LLStringUtil::format_map_t args;
+	args["[COUNT]"] = llformat("%d", ban_count);
+	args["[LIMIT]"] = llformat("%d", GB_MAX_BANNED_AGENTS);
+	mBanCountText->setText(getString("ban_count_template", args));
+}
+
+void LLPanelGroupBanListSubTab::populateBanList()
+{
+	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+	if(!gdatap) 
+	{
+		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+		return;
+	}
+
+	mBanList->deleteAllItems();
+	std::map<LLUUID,LLGroupBanData>::const_iterator entry = gdatap->mBanList.begin();
+	for(; entry != gdatap->mBanList.end(); entry++)
+	{
+		LLNameListCtrl::NameItem ban_entry;
+		ban_entry.value = entry->first;
+		LLGroupBanData bd = entry->second;
+		
+		ban_entry.columns.add().column("name").font.name("SANSSERIF_SMALL").style("NORMAL");
+
+		// Baker TODO: MAINT-
+		// Check out utc_to_pacific_time()
+
+		std::string ban_date_str = bd.mBanDate.toHTTPDateString("%Y/%m/%d");
+// 		time_t utc_time;
+// 		utc_time = time_corrected();
+// 		LLSD substitution;
+// 		substitution["datetime"] = (S32) utc_time;
+// 		LLStringUtil::format (ban_date_str, substitution);
+
+		//LL_INFOS("BAKER") << "[BAKER] BAN_DATE: " << bd.mBanDate.toHTTPDateString("%Y/%m/%d") << LL_ENDL;
+		//LL_INFOS("BAKER") << "[BAKER] BAN_DATE_MODIFIED: " << ban_date_str << LL_ENDL;
+
+		//ban_entry.columns.add().column("ban_date").value(ban_date_str.font.name("SANSSERIF_SMALL").style("NORMAL");
+		ban_entry.columns.add().column("ban_date").value(bd.mBanDate.toHTTPDateString("%Y/%m/%d")).font.name("SANSSERIF_SMALL").style("NORMAL");
+
+		mBanList->addNameItemRow(ban_entry);
+	}
+	 
+	mRefreshBanListButton->setEnabled(TRUE);
+	mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) &&
+								 gdatap->mBanList.size() < GB_MAX_BANNED_AGENTS);
+	setBanCount(gdatap->mBanList.size());
+}
+
+void LLPanelGroupBanListSubTab::setGroupID(const LLUUID& id)
+{
+	if(mBanList)
+		mBanList->deleteAllItems();
+
+	setFooterEnabled(FALSE);
+	LLPanelGroupSubTab::setGroupID(id); 
+}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index baa2d40c7ec501c5cc6977055fd633fb8423c432..540b24ada6421cd5490cde75edf763452f5a109c 100755
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -39,11 +39,9 @@ class LLScrollListCtrl;
 class LLScrollListItem;
 class LLTextEditor;
 
-// Forward declare for friend usage.
-//virtual BOOL LLPanelGroupSubTab::postBuildSubTab(LLView*);
-
 typedef std::map<std::string,std::string> icon_map_t;
 
+
 class LLPanelGroupRoles : public LLPanelGroupTab
 {
 public:
@@ -92,6 +90,7 @@ class LLPanelGroupRoles : public LLPanelGroupTab
 	std::string				mWantApplyMesg;
 };
 
+
 class LLPanelGroupSubTab : public LLPanelGroupTab
 {
 public:
@@ -143,10 +142,14 @@ class LLPanelGroupSubTab : public LLPanelGroupTab
 	icon_map_t	mActionIcons;
 
 	bool mActivated;
-
+	
+	bool mHasGroupBanPower; // Used to communicate between action sets due to the dependency between
+							// GP_GROUP_BAN_ACCESS and GP_EJECT_MEMBER and GP_ROLE_REMOVE_MEMBER
+	
 	void setOthersVisible(BOOL b);
 };
 
+
 class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
 {
 public:
@@ -173,6 +176,10 @@ class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
 	void handleRoleCheck(const LLUUID& role_id,
 						 LLRoleMemberChangeType type);
 
+	static void onBanMember(void* user_data);
+	void handleBanMember();
+
+
 	void applyMemberChanges();
 	bool addOwnerCB(const LLSD& notification, const LLSD& response);
 
@@ -206,6 +213,7 @@ class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
 	LLScrollListCtrl*	mAssignedRolesList;
 	LLScrollListCtrl*	mAllowedActionsList;
 	LLButton*           mEjectBtn;
+	LLButton*			mBanBtn;
 
 	BOOL mChanged;
 	BOOL mPendingMemberUpdate;
@@ -219,6 +227,7 @@ class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
 	avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
 };
 
+
 class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
 {
 public:
@@ -241,7 +250,7 @@ class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
 
 	static void onActionCheck(LLUICtrl*, void*);
 	bool addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check);
-
+	
 	static void onPropertiesKey(LLLineEditor*, void*);
 
 	void onDescriptionKeyStroke(LLTextEditor* caller);
@@ -260,6 +269,9 @@ class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
 	void saveRoleChanges(bool select_saved_role);
 
 	virtual void setGroupID(const LLUUID& id);
+
+	BOOL	mFirstOpen;
+
 protected:
 	void handleActionCheck(LLUICtrl* ctrl, bool force);
 	LLSD createRoleItem(const LLUUID& role_id, std::string name, std::string title, S32 members);
@@ -281,6 +293,7 @@ class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
 	std::string mRemoveEveryoneTxt;
 };
 
+
 class LLPanelGroupActionsSubTab : public LLPanelGroupSubTab
 {
 public:
@@ -308,4 +321,46 @@ class LLPanelGroupActionsSubTab : public LLPanelGroupSubTab
 };
 
 
+class LLPanelGroupBanListSubTab : public LLPanelGroupSubTab
+{
+public:
+	LLPanelGroupBanListSubTab();
+	virtual ~LLPanelGroupBanListSubTab() {}
+
+	virtual BOOL postBuildSubTab(LLView* root);
+
+	virtual void activate();
+	virtual void update(LLGroupChange gc);
+	virtual void draw();
+
+	static void onBanEntrySelect(LLUICtrl* ctrl, void* user_data);
+	void handleBanEntrySelect();
+	
+	static void onCreateBanEntry(void* user_data);
+	void handleCreateBanEntry();
+	
+	static void onDeleteBanEntry(void* user_data);
+	void handleDeleteBanEntry();
+
+	static void onRefreshBanList(void* user_data);
+	void handleRefreshBanList();
+
+	void onBanListCompleted(bool isComplete);
+
+protected:
+	void setBanCount(U32 ban_count);
+	void populateBanList();
+
+public:
+	virtual void setGroupID(const LLUUID& id);
+
+protected:
+	LLNameListCtrl* mBanList;
+	LLButton* mCreateBanButton;
+	LLButton* mDeleteBanButton;
+	LLButton* mRefreshBanListButton;
+	LLTextBase* mBanCountText;
+
+};
+
 #endif // LL_LLPANELGROUPROLES_H
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 0817b677bc31065383344ff3f317bb0a5ae92296..ed91d277ddd60d9236d169ae6f567386aa654aee 100755
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -488,8 +488,9 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
 				gCacheName->getGroup(parcel->getGroupID(),
 								boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
 
-				gCacheName->getGroup(parcel->getGroupID(),
-								boost::bind(&LLPanelPlaceInfo::onNameCache, mParcelOwner, _2));
+				std::string owner =
+					LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString();
+				mParcelOwner->setText(owner);
 			}
 			else
 			{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 673913c4f27438d14e7b72f2f79bc0bc4a0588c1..cd5f64b9caca893fe18c5787b73ee322d97d07f4 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2708,6 +2708,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("GetObjectCost");
 	capabilityNames.append("GetObjectPhysicsData");
 	capabilityNames.append("GetTexture");
+	capabilityNames.append("GroupAPIv1");
 	capabilityNames.append("GroupMemberData");
 	capabilityNames.append("GroupProposalBallot");
 	capabilityNames.append("HomeLocation");
diff --git a/indra/newview/roles_constants.h b/indra/newview/roles_constants.h
old mode 100755
new mode 100644
index effd15ea72e33b820ceec239a8d5aa69870143c7..8fd7978fa16c53220760445e449ec1a9f51cb438
--- a/indra/newview/roles_constants.h
+++ b/indra/newview/roles_constants.h
@@ -53,98 +53,100 @@ enum LLRoleChangeType
 
 // KNOWN HOLES: use these for any single bit powers you need
 // bit 0x1 << 46
-// bit 0x1 << 49 and above
+// bit 0x1 << 52 and above
 
 // These powers were removed to make group roles simpler
 // bit 0x1 << 41 (GP_ACCOUNTING_VIEW)
 // bit 0x1 << 46 (GP_PROPOSAL_VIEW)
 
 const U64 GP_NO_POWERS = 0x0;
-const U64 GP_ALL_POWERS = 0xFFFFFFFFFFFFFFFFLL;
+const U64 GP_ALL_POWERS = 0xFFFFffffFFFFffffLL;
 
 // Membership
-const U64 GP_MEMBER_INVITE		= 0x1 << 1;		// Invite member
-const U64 GP_MEMBER_EJECT			= 0x1 << 2;		// Eject member from group
-const U64 GP_MEMBER_OPTIONS		= 0x1 << 3;		// Toggle "Open enrollment" and change "Signup Fee"
-const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47;
+const U64 GP_MEMBER_INVITE				= 0x1LL << 1;	// Invite member
+const U64 GP_MEMBER_EJECT				= 0x1LL << 2;	// Eject member from group
+const U64 GP_MEMBER_OPTIONS				= 0x1LL << 3;	// Toggle "Open enrollment" and change "Signup Fee"
+const U64 GP_MEMBER_VISIBLE_IN_DIR		= 0x1LL << 47;
 
 // Roles
-const U64 GP_ROLE_CREATE			= 0x1 << 4;		// Create new roles
-const U64 GP_ROLE_DELETE			= 0x1 << 5;		// Delete roles
-const U64 GP_ROLE_PROPERTIES		= 0x1 << 6;		// Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
-const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1 << 7; // Assign Member to a Role that the assigner is in
-const U64 GP_ROLE_ASSIGN_MEMBER	= 0x1 << 8;		// Assign Member to Role
-const U64 GP_ROLE_REMOVE_MEMBER	= 0x1 << 9;		// Remove Member from Role
-const U64 GP_ROLE_CHANGE_ACTIONS	= 0x1 << 10;	// Change actions a role can perform
+const U64 GP_ROLE_CREATE				= 0x1LL << 4;	// Create new roles
+const U64 GP_ROLE_DELETE				= 0x1LL << 5;	// Delete roles
+const U64 GP_ROLE_PROPERTIES			= 0x1LL << 6;	// Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
+const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED	= 0x1LL << 7;	// Assign Member to a Role that the assigner is in
+const U64 GP_ROLE_ASSIGN_MEMBER			= 0x1LL << 8;	// Assign Member to Role
+const U64 GP_ROLE_REMOVE_MEMBER			= 0x1LL << 9;	// Remove Member from Role
+const U64 GP_ROLE_CHANGE_ACTIONS		= 0x1LL << 10;	// Change actions a role can perform
 
 // Group Identity
-const U64 GP_GROUP_CHANGE_IDENTITY = 0x1 << 11;	// Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
+const U64 GP_GROUP_CHANGE_IDENTITY		= 0x1LL << 11;	// Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
 
 // Parcel Management
-const U64 GP_LAND_DEED			= 0x1 << 12;	// Deed Land and Buy Land for Group
-const U64 GP_LAND_RELEASE			= 0x1 << 13;	// Release Land (to Gov. Linden)
-const U64 GP_LAND_SET_SALE_INFO	= 0x1 << 14;	// Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
-const U64 GP_LAND_DIVIDE_JOIN		= 0x1 << 15;	// Divide and Join Parcels
+const U64 GP_LAND_DEED					= 0x1LL << 12;	// Deed Land and Buy Land for Group
+const U64 GP_LAND_RELEASE				= 0x1LL << 13;	// Release Land (to Gov. Linden)
+const U64 GP_LAND_SET_SALE_INFO			= 0x1LL << 14;	// Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
+const U64 GP_LAND_DIVIDE_JOIN			= 0x1LL << 15;	// Divide and Join Parcels
 
 // Parcel Identity
-const U64 GP_LAND_FIND_PLACES		= 0x1 << 17;	// Toggle "Show in Find Places" and Set Category.
-const U64 GP_LAND_CHANGE_IDENTITY = 0x1 << 18;	// Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
-const U64 GP_LAND_SET_LANDING_POINT = 0x1 << 19;	// Set Landing Point
+const U64 GP_LAND_FIND_PLACES			= 0x1LL << 17;	// Toggle "Show in Find Places" and Set Category.
+const U64 GP_LAND_CHANGE_IDENTITY		= 0x1LL << 18;	// Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
+const U64 GP_LAND_SET_LANDING_POINT		= 0x1LL << 19;	// Set Landing Point
 
 // Parcel Settings
-const U64 GP_LAND_CHANGE_MEDIA	= 0x1 << 20;	// Change Media Settings
-const U64 GP_LAND_EDIT			= 0x1 << 21;	// Toggle Edit Land
-const U64 GP_LAND_OPTIONS			= 0x1 << 22;	// Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
+const U64 GP_LAND_CHANGE_MEDIA			= 0x1LL << 20;	// Change Media Settings
+const U64 GP_LAND_EDIT					= 0x1LL << 21;	// Toggle Edit Land
+const U64 GP_LAND_OPTIONS				= 0x1LL << 22;	// Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
 
 // Parcel Powers
-const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1 << 23;	// Bypass Edit Land Restriction
-const U64 GP_LAND_ALLOW_FLY		= 0x1 << 24;	// Bypass Fly Restriction
-const U64 GP_LAND_ALLOW_CREATE	= 0x1 << 25;	// Bypass Create/Edit Objects Restriction
-const U64 GP_LAND_ALLOW_LANDMARK	= 0x1 << 26;	// Bypass Landmark Restriction
-const U64 GP_LAND_ALLOW_SET_HOME	= 0x1 << 28;	// Bypass Set Home Point Restriction
-const U64 GP_LAND_ALLOW_HOLD_EVENT	= 0x1LL << 41;	// Allowed to hold events on group-owned land
-
+const U64 GP_LAND_ALLOW_EDIT_LAND		= 0x1LL << 23;	// Bypass Edit Land Restriction
+const U64 GP_LAND_ALLOW_FLY				= 0x1LL << 24;	// Bypass Fly Restriction
+const U64 GP_LAND_ALLOW_CREATE			= 0x1LL << 25;	// Bypass Create/Edit Objects Restriction
+const U64 GP_LAND_ALLOW_LANDMARK		= 0x1LL << 26;	// Bypass Landmark Restriction
+const U64 GP_LAND_ALLOW_SET_HOME		= 0x1LL << 28;	// Bypass Set Home Point Restriction
+const U64 GP_LAND_ALLOW_HOLD_EVENT		= 0x1LL << 41;	// Allowed to hold events on group-owned land
 
 // Parcel Access
-const U64 GP_LAND_MANAGE_ALLOWED	= 0x1 << 29;	// Manage Allowed List
-const U64 GP_LAND_MANAGE_BANNED	= 0x1 << 30;	// Manage Banned List
-const U64 GP_LAND_MANAGE_PASSES	= 0x1LL << 31;	// Change Sell Pass Settings
-const U64 GP_LAND_ADMIN			= 0x1LL << 32;	// Eject and Freeze Users on the land
+const U64 GP_LAND_MANAGE_ALLOWED		= 0x1LL << 29;	// Manage Allowed List
+const U64 GP_LAND_MANAGE_BANNED			= 0x1LL << 30;	// Manage Banned List
+const U64 GP_LAND_MANAGE_PASSES			= 0x1LL << 31;	// Change Sell Pass Settings
+const U64 GP_LAND_ADMIN					= 0x1LL << 32;	// Eject and Freeze Users on the land
 
 // Parcel Content
-const U64 GP_LAND_RETURN_GROUP_SET	= 0x1LL << 33;	// Return objects on parcel that are set to group
-const U64 GP_LAND_RETURN_NON_GROUP	= 0x1LL << 34;	// Return objects on parcel that are not set to group
-const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48;	// Return objects on parcel that are owned by the group
+const U64 GP_LAND_RETURN_GROUP_SET		= 0x1LL << 33;	// Return objects on parcel that are set to group
+const U64 GP_LAND_RETURN_NON_GROUP		= 0x1LL << 34;	// Return objects on parcel that are not set to group
+const U64 GP_LAND_RETURN_GROUP_OWNED	= 0x1LL << 48;	// Return objects on parcel that are owned by the group
 
 // Select a power-bit based on an object's relationship to a parcel.
 const U64 GP_LAND_RETURN		= GP_LAND_RETURN_GROUP_OWNED 
 								| GP_LAND_RETURN_GROUP_SET	
 								| GP_LAND_RETURN_NON_GROUP;
 
-const U64 GP_LAND_GARDENING		= 0x1LL << 35;	// Parcel Gardening - plant and move linden trees
+const U64 GP_LAND_GARDENING				= 0x1LL << 35;	// Parcel Gardening - plant and move linden trees
 
 // Object Management
-const U64 GP_OBJECT_DEED			= 0x1LL << 36;	// Deed Object
-const U64 GP_OBJECT_MANIPULATE		= 0x1LL << 38;	// Manipulate Group Owned Objects (Move, Copy, Mod)
-const U64 GP_OBJECT_SET_SALE		= 0x1LL << 39;	// Set Group Owned Object for Sale
+const U64 GP_OBJECT_DEED				= 0x1LL << 36;	// Deed Object
+const U64 GP_OBJECT_MANIPULATE			= 0x1LL << 38;	// Manipulate Group Owned Objects (Move, Copy, Mod)
+const U64 GP_OBJECT_SET_SALE			= 0x1LL << 39;	// Set Group Owned Object for Sale
 
 // Accounting
-const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40;	// Pay Group Liabilities and Receive Group Dividends
+const U64 GP_ACCOUNTING_ACCOUNTABLE		= 0x1LL << 40;	// Pay Group Liabilities and Receive Group Dividends
 
 // Notices
-const U64 GP_NOTICES_SEND			= 0x1LL << 42;	// Send Notices
-const U64 GP_NOTICES_RECEIVE		= 0x1LL << 43;	// Receive Notices and View Notice History
+const U64 GP_NOTICES_SEND				= 0x1LL << 42;	// Send Notices
+const U64 GP_NOTICES_RECEIVE			= 0x1LL << 43;	// Receive Notices and View Notice History
 
 // Proposals
 // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_START		= 0x1LL << 44;	// Start Proposal
+const U64 GP_PROPOSAL_START				= 0x1LL << 44;	// Start Proposal
 // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_VOTE		= 0x1LL << 45;	// Vote on Proposal
+const U64 GP_PROPOSAL_VOTE				= 0x1LL << 45;	// Vote on Proposal
 
 // Group chat moderation related
-const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
-const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
-const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
+const U64 GP_SESSION_JOIN				= 0x1LL << 16;	//can join session
+const U64 GP_SESSION_VOICE				= 0x1LL << 27;	//can hear/talk
+const U64 GP_SESSION_MODERATOR			= 0x1LL << 37;	//can mute people's session
+
+// Group Banning
+const U64 GP_GROUP_BAN_ACCESS			= 0x1LL << 51;	// Allows access to ban / un-ban agents from a group.
 
 const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE
 								| GP_LAND_ALLOW_SET_HOME
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 9668cfa526e6157c88bab138272c675e9b3dd078..ef2f158a864440f8c33d7c59c4edfc85c439f19f 100755
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -72,7 +72,7 @@ Second Life is brought to you by the Lindens:
        top_pad="10"
        width="435"
        word_wrap="true">
-Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase
+Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase, Baker
       </text_editor>
       <text
           follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index 31b1d091eef1be5d8e80b57883ab7695790ec6bc..ed362b36e54ec2310581d0e90e9ef81e4d1fac36 100755
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -17,6 +17,7 @@
      layout="topleft"
      name="open_voice_conversation">
         <on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/>
+        <on_enable function="Avatar.EnableItem" parameter="can_open_voice_conversation"/>
      </menu_item_call>	
      <menu_item_call
      label="Disconnect from voice"
@@ -213,4 +214,12 @@
 			<on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
 		</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="Avatar.DoToSelected" parameter="ban_member" />
+			<on_enable function="Avatar.EnableItem" parameter="can_ban_member" />
+	</menu_item_call>		
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f49f300868a29ace9cefef6fcbea03da846e414c..772d81c4489e64b3b2a37b1884a29fa398228e46 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -506,7 +506,35 @@ Add this Ability to &apos;[ROLE_NAME]&apos;?
      notext="No"
      yestext="Yes"/>
   </notification>
-  
+
+  <notification
+    icon="alertmodal.tga"
+    name="AssignBanAbilityWarning"
+    type="alertmodal">
+You are about to add the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+Any Member in a Role with this Ability will also be granted the Abilities &apos;[ACTION_NAME_2]&apos; and &apos;[ACTION_NAME_3]&apos;
+    <usetemplate
+      name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+  icon="alertmodal.tga"
+  name="RemoveBanAbilityWarning"
+  type="alertmodal">
+You are removing the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+Removing this ability will NOT remove the Abilities &apos;[ACTION_NAME_2]&apos; and &apos;[ACTION_NAME_3]&apos;.
+ 
+If you no longer wish to have these abilities granted to this role, disable them immediately!
+    <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
   <notification
     icon="alertmodal.tga"
     name="EjectGroupMemberWarning"
@@ -3746,6 +3774,28 @@ Leave Group?
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="aler.tga"
+   name="GroupDepartError"
+   type="alert">
+Unable to leave group: [reason].
+      <tag>reason</tag>
+      <usetemplate
+       name="okbutton"
+       yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alert.tga"
+   name="GroupDepart"
+   type="alert">
+You have left the group [group_name].
+      <tag>group_name</tag>
+      <usetemplate
+       name="okbutton"
+       yestext="OK"/>
+  </notification>
+
   <notification
    icon="alert.tga"
    name="ConfirmKick"
diff --git a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml
new file mode 100644
index 0000000000000000000000000000000000000000..509dcf354ea311abb0a3179f97e12149ed48cef6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="330"
+ label="Ban Residents"
+ layout="topleft"
+ left="0"
+ name="bulk_ban_panel"
+ top="330"
+ width="210">
+  <panel.string
+   name="loading">
+    (loading...)
+  </panel.string>
+  <panel.string
+     name="ban_selection_too_large">
+    Group bans not sent: too many Residents selected. Group bans are limited to 100 per request.
+  </panel.string>
+  <panel.string
+     name="ban_not_permitted">
+    Group ban not sent: you do not have 'Manage ban list' ability.
+  </panel.string>
+  <panel.string
+     name="ban_limit_fail">
+    Group ban not sent: your group have reached limit of allowed ban records.
+  </panel.string>
+  <panel.string
+     name="partial_ban">
+    Some group bans were not sent:
+[REASONS]
+  </panel.string>
+  <panel.string
+     name="ban_failed">
+    Group bans were not sent:
+[REASONS]
+  </panel.string>
+  <panel.string
+     name="residents_already_banned">
+    - The following resident(s) are already banned: [RESIDENTS].
+  </panel.string>
+  <panel.string
+     name="ban_limit_reached">
+    - Ban limit reached, following agents not banned: [RESIDENTS].
+  </panel.string>
+  <panel.string
+     name="cant_ban_yourself">
+    - You cannot ban yourself from a group.
+  </panel.string>
+  <text
+   type="string"
+   length="1"
+   height="54"
+   layout="topleft"
+   left="7"
+   name="help_text"
+   top="28"
+   word_wrap="true"
+   width="200">
+    You can select multiple Residents to ban from your group. Click &apos;Open Resident Chooser&apos; to start.
+  </text>
+  <button
+   height="20"
+   label="Open Resident Chooser"
+   layout="topleft"
+   left_delta="-2"
+   name="add_button"
+   top_delta="44"
+   width="200" />
+  <name_list
+   allow_calling_card_drop="true"
+   column_padding="0"
+   height="174"
+   layout="topleft"
+   left_delta="0"
+   multi_select="true"
+   name="banned_agent_list"
+   tool_tip="Hold the Ctrl key and click Resident names to multi-select"
+   top_pad="4"
+   width="200" />
+  <button
+   height="20"
+   label="Remove Selected from List"
+   layout="topleft"
+   left_delta="0"
+   name="remove_button"
+   tool_tip="Removes the Residents selected above from the ban list"
+   top_pad="4"
+   width="200" />
+  <button
+   height="20"
+   label="Ban Residents"
+   layout="topleft"
+   left="4"
+   name="ban_button"
+   top_delta="30"
+   width="135" />
+  <button
+   height="20"
+   label="Cancel"
+   layout="topleft"
+   left_pad="2"
+   name="cancel_button"
+   top_delta="0"
+   width="65" />
+  <string
+  name="GroupBulkBan">
+    Group Ban
+  </string>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml
index 124c0596c3d4857827b4ac3e55bbf776bfaa9598..ebb460deb0cb452e1e0567f3fa83b3c4c93785ac 100755
--- a/indra/newview/skins/default/xui/en/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml
@@ -76,7 +76,7 @@
         Choose what Role to assign them to:
     </text>
     <combo_box
-     height="16"
+     height="20"
      layout="topleft"
      left_delta="0"
      name="role_name"
@@ -88,7 +88,7 @@
      label="Send Invitations"
      layout="topleft"
      left="4"
-     name="ok_button"
+     name="invite_button"
      top="356"
      width="135" />
     <button
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 9ac5b8800ed833e19c4eb9553ec30a81dccfa1b7..dac4371a383565db7053ef0463f744c0c574dd52 100755
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -118,6 +118,13 @@ clicking on their names.
              left_pad="10"
              name="member_eject"
              width="100" />
+      <button
+       height="23"
+       label="Ban Member(s)"
+       follows="top|left"
+       left_pad="10"
+       name="member_ban"
+       width="100" />
         </panel>
         <panel
          border="false"
@@ -138,454 +145,535 @@ clicking on their names.
              right="-5"
              name="show_all_button"
              width="100" />-->
-            <panel.string
-             name="help_text">
-                Roles have a title and an allowed list of Abilities
-that Members can perform. Members can belong to
-one or more Roles. A group can have up to 10 Roles,
-including the Everyone and Owner Roles.
-            </panel.string>
-            <panel.string
-             name="cant_delete_role">
-                The &apos;Everyone&apos; and &apos;Owners&apos; Roles are special and can't be deleted.
-            </panel.string>
-            <panel.string
-             name="power_folder_icon" translate="false">
-                Inv_FolderClosed
-            </panel.string>
-            <panel.string
-             name="power_all_have_icon" translate="false">
-                Checkbox_On
-            </panel.string>
-            <panel.string
-             name="power_partial_icon" translate="false">
-                Checkbox_Off
-            </panel.string>
-         <filter_editor
-         layout="topleft"
-         top="5"
-         left="5"
-         right="-5"
-         height="22"
-         search_button_visible="false"
-         follows="left|top|right"
-         label="Filter Roles"
-         name="filter_input" />
-            <scroll_list
-             column_padding="0"
-             draw_heading="true"
-             draw_stripes="false"
-             heading_height="23"
-             height="132"
-             layout="topleft"
-             search_column="1"
-             left="0"
-             follows="left|top|right"
-             right="-1"
-             name="role_list"
-             top_pad="2"
-             width="310">
-                <scroll_list.columns
-                 label="Role"
-                 name="name"
-               relative_width="0.45"  />
-                <scroll_list.columns
-                 label="Title"
-                 name="title"
-               relative_width="0.45"  />
-                <scroll_list.columns
-                 label="#"
-                 name="members"
-               relative_width="0.15"  />
-            </scroll_list>
-            <button
-            follows="top|left"
-             height="23"
-             label="New Role"
-             layout="topleft"
-             left="0"
-             name="role_create"
-             width="120" />
-            <button
-             height="23"
-             follows="top|left"
-             label="Delete Role"
-             layout="topleft"
-             left_pad="10"
-             name="role_delete"
-             width="120" />
-        </panel>
-        <panel
-         border="false"
-         height="303"
-         label="ABILITIES"
-         layout="topleft"
-         left="0"
-         right="-1"
-         help_topic="roles_actions_tab"
-         name="actions_sub_tab"
-         class="panel_group_actions_subtab"
-         tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
-         width="310">
-            <panel.string
-             name="help_text">
-                Abilities allow Members in Roles to do specific
-things in this group. There&apos;s a broad variety of Abilities.
-            </panel.string>
-            <panel.string
-             name="power_folder_icon" translate="false">
-                Inv_FolderClosed
-            </panel.string>
-            <panel.string
-             name="power_all_have_icon" translate="false">
-                Checkbox_On
-            </panel.string>
-            <panel.string
-             name="power_partial_icon" translate="false">
-                Checkbox_Off
-            </panel.string>
-         <filter_editor
-         layout="topleft"
-         top="5"
-         left="5"
-         right="-5"
-         height="22"
-         search_button_visible="false"
-         follows="left|top|right"
-         label="Filter Abilities"
-         name="filter_input" />
-        <scroll_list
-         column_padding="0"
-         draw_stripes="true"
-         height="200"
-         follows="left|top|right"
-         layout="topleft"
-         left="0"
-         right="-1"
-         name="action_list"
-         search_column="2"
-         tool_tip="Select an Ability to view more details"
-         top_pad="5"
-         width="300">
-            <scroll_list.columns
-             label=""
-             name="icon"
-             width="2" />
-            <scroll_list.columns
-             label=""
-             name="checkbox"
-             width="20" />
-            <scroll_list.columns
-             label=""
-             name="action"
-             width="270" />
-        </scroll_list>
-        </panel>
-    </tab_container>
+      <panel.string
+       name="help_text">
+        Roles have a title and an allowed list of Abilities
+        that Members can perform. Members can belong to
+        one or more Roles. A group can have up to 10 Roles,
+        including the Everyone and Owner Roles.
+      </panel.string>
+      <panel.string
+       name="cant_delete_role">
+        The &apos;Everyone&apos; and &apos;Owners&apos; Roles are special and can't be deleted.
+      </panel.string>
+      <panel.string
+       name="power_folder_icon" translate="false">
+        Inv_FolderClosed
+      </panel.string>
+      <panel.string
+       name="power_all_have_icon" translate="false">
+        Checkbox_On
+      </panel.string>
+      <panel.string
+       name="power_partial_icon" translate="false">
+        Checkbox_Off
+      </panel.string>
+      <filter_editor
+      layout="topleft"
+      top="5"
+      left="5"
+      right="-5"
+      height="22"
+      search_button_visible="false"
+      follows="left|top|right"
+      label="Filter Roles"
+      name="filter_input" />
+      <scroll_list
+       column_padding="0"
+       draw_heading="true"
+       draw_stripes="false"
+       heading_height="23"
+       height="132"
+       layout="topleft"
+       search_column="1"
+       left="0"
+       follows="left|top|right"
+       right="-1"
+       name="role_list"
+       top_pad="2"
+       width="310">
+        <scroll_list.columns
+         label="Role"
+         name="name"
+       relative_width="0.45"  />
+        <scroll_list.columns
+         label="Title"
+         name="title"
+       relative_width="0.45"  />
+        <scroll_list.columns
+         label="#"
+         name="members"
+       relative_width="0.15"  />
+      </scroll_list>
+      <button
+      follows="top|left"
+       height="23"
+       label="New Role"
+       layout="topleft"
+       left="0"
+       name="role_create"
+       width="120" />
+      <button
+       height="23"
+       follows="top|left"
+       label="Delete Role"
+       layout="topleft"
+       left_pad="10"
+       name="role_delete"
+       width="120" />
+    </panel>
     <panel
-     height="350"
-     background_visible="false"
-     bg_alpha_color="FloaterUnfocusBorderColor"
+     border="false"
+     height="303"
+     label="ABILITIES"
      layout="topleft"
-     follows="top|left|right"
      left="0"
      right="-1"
-     width="313"
-     mouse_opaque="false"
-     name="members_footer"
-     top="325"
-     visible="false">
-        <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         top="8"
-         text_color="EmphasisColor"
-         name="static"
-         width="300">
-            Assigned Roles
-        </text>
-        <scroll_list
-         draw_stripes="true"
-        follows="left|top|right"
-         height="150"
-         layout="topleft"
-         left="0"
-         right="-1"
-         name="member_assigned_roles"
-         top_pad="0">
-            <scroll_list.columns
-             label=""
-             name="checkbox"
-             width="20" />
-            <scroll_list.columns
-             label=""
-             name="role"
-             width="270" />
-        </scroll_list>
-          <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         top_pad="5"
-         text_color="EmphasisColor"
-         name="static2"
-         width="285">
-            Allowed Abilities
-        </text>
-        <scroll_list
-         draw_stripes="true"
-             follows="left|top|right"
-         height="150"
-         layout="topleft"
-         left="0"
-         right="-1"
-         name="member_allowed_actions"
-         search_column="2"
-         tool_tip="For details of each allowed ability see the abilities tab"
-         top_pad="0">
-            <scroll_list.columns
-             label=""
-             name="icon"
-             width="2" />
-            <scroll_list.columns
-             label=""
-             name="checkbox"
-             width="20" />
-            <scroll_list.columns
-             label=""
-             name="action"
-             width="270" />
-        </scroll_list>
+     help_topic="roles_actions_tab"
+     name="actions_sub_tab"
+     class="panel_group_actions_subtab"
+     tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
+     width="310">
+      <panel.string
+       name="help_text">
+        Abilities allow Members in Roles to do specific
+        things in this group. There&apos;s a broad variety of Abilities.
+      </panel.string>
+      <panel.string
+       name="power_folder_icon" translate="false">
+        Inv_FolderClosed
+      </panel.string>
+      <panel.string
+       name="power_all_have_icon" translate="false">
+        Checkbox_On
+      </panel.string>
+      <panel.string
+       name="power_partial_icon" translate="false">
+        Checkbox_Off
+      </panel.string>
+      <filter_editor
+      layout="topleft"
+      top="5"
+      left="5"
+      right="-5"
+      height="22"
+      search_button_visible="false"
+      follows="left|top|right"
+      label="Filter Abilities"
+      name="filter_input" />
+      <scroll_list
+       column_padding="0"
+       draw_stripes="true"
+       height="200"
+       follows="left|top|right"
+       layout="topleft"
+       left="0"
+       right="-1"
+       name="action_list"
+       search_column="2"
+       tool_tip="Select an Ability to view more details"
+       top_pad="5"
+       width="300">
+        <scroll_list.columns
+         label=""
+         name="icon"
+         width="2" />
+        <scroll_list.columns
+         label=""
+         name="checkbox"
+         width="20" />
+        <scroll_list.columns
+         label=""
+         name="action"
+         width="270" />
+      </scroll_list>
     </panel>
     <panel
-     height="550"
-     background_visible="false"
-     bg_alpha_color="FloaterUnfocusBorderColor"
+     border="false"
+     height="303"
+     label="BANNED RESIDENTS"
      layout="topleft"
-     follows="top|left|right"
      left="0"
      right="-1"
-     width="313"
-     mouse_opaque="false"
-     name="roles_footer"
-     top_delta="0"
-     top="209"
-     visible="false">
-        <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         top="5"
-         name="static"
-         width="300">
-           Role Name
-        </text>
-        <line_editor
-         type="string"
-         height="20"
-         layout="topleft"
-         left="0"
-         follows="left|top|right"
-         right="-1"
-         max_length_bytes="20"
-         name="role_name"
-         top_pad="0"
-         width="300">
-        </line_editor>
-        <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         name="static3"
-         top_pad="5"
-         width="300">
-           Role Title
-        </text>
-        <line_editor
-         type="string"
-         height="20"
-         layout="topleft"
-         left="0"
-         follows="left|top|right"
-         right="-1"
-         max_length_bytes="20"
-         name="role_title"
-         top_pad="0"
-         width="300">
-        </line_editor>
-               <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         name="static2"
-         top_pad="5"
-         width="200">
-            Description
-        </text>
-        <text_editor
-         type="string"
-         layout="topleft"
-         left="0"
-         follows="left|top|right"
-         right="-1"
-         max_length="295"
-         height="35"
-         name="role_description"
-         top_pad="0"
-         width="300"
-         word_wrap="true">
-        </text_editor>
-        <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         text_color="EmphasisColor"
-         name="static4"
-         top_pad="5"
-         width="300">
-            Assigned Members
-        </text>
-        <name_list
-         draw_stripes="true"
-         height="128"
-         layout="topleft"
-         left="0"
-         follows="left|top|right"
-         right="-1"
-         name="role_assigned_members"
-         top_pad="0"
-         width="300" />
-        <check_box
-         height="15"
-         label="Reveal members"
-         left="5"
-         layout="topleft"
-         name="role_visible_in_list"
-         tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
-         top_pad="4"
-         width="300" />
-         <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         text_color="EmphasisColor"
-         name="static5"
-         top_pad="2"
-         width="300">
-            Allowed Abilities
-        </text>
-        <scroll_list
-         draw_stripes="true"
-         height="140"
-         layout="topleft"
-         left="0"
-         follows="left|top|right"
-         right="-1"
-         name="role_allowed_actions"
-         search_column="2"
-         tool_tip="For details of each allowed ability see the abilities tab"
-         top_pad="0"
-         width="300">
-            <scroll_list.columns
-             label=""
-             name="icon"
-             width="2" />
-            <scroll_list.columns
-             label=""
-             name="checkbox"
-             width="20" />
-            <scroll_list.columns
-             label=""
-             name="action"
-             width="270" />
-        </scroll_list>
+     help_topic="roles_banlist_tab"
+     name="banlist_sub_tab"
+     class="panel_group_banlist_subtab"
+     tool_tip="View the banned residents from this group."
+     width="310">
+      <panel.string
+       name="help_text">
+        Any resident on the ban list will be unable to join the group.
+      </panel.string>
+      <panel.string
+       name="ban_count_template">
+        Ban count: [COUNT]/[LIMIT]
+      </panel.string>
+      <name_list
+           column_padding="0"
+           draw_heading="true"
+           height="400"
+           follows="left|top|right"
+           layout="topleft"
+           left="0"
+           right="-1"
+           multi_select="true"
+           name="ban_list"
+           short_names="false"
+           top_pad="5">
+        <name_list.columns
+         label="Resident"
+         name="name"
+         font.name="SANSSERIF_SMALL"
+         font.style="NORMAL"
+         relative_width="0.7" />
+        <name_list.columns
+         label="Date Banned"
+         name="ban_date"
+         relative_width="0.3" />
+      </name_list>
+      <button
+        follows="top|left"
+        height="23"
+        label="Ban Resident(s)"
+        layout="topleft"
+        left="3"
+        name="ban_create"
+        tool_tip="Ban residents from your group"
+        width="120" />
+      <button
+        follows="top|left"
+        height="23"
+        label="Remove Ban(s)"
+        layout="topleft"
+        left_pad="5"
+        name="ban_delete"
+        tool_tip="Unban selected residents from your group"
+        width="120" />
+      <button
+        follows="top|left"
+        height="23"
+        width="23"
+        image_overlay="Refresh_Off"
+        layout="topleft"
+        left_pad="5"
+        name="ban_refresh"
+        tool_tip="Refresh the ban list"
+        />
+      <text
+        type="string"
+        height="18"
+        left_pad="5"
+        follows="top|left"
+        layout="topleft"
+        name="ban_count"
+        width="100">
+      </text>
     </panel>
-   <panel
-     height="424"
-     background_visible="false"
-     bg_alpha_color="FloaterUnfocusBorderColor"
+  </tab_container>
+  <panel
+   height="350"
+   background_visible="false"
+   bg_alpha_color="FloaterUnfocusBorderColor"
+   layout="topleft"
+   follows="top|left|right"
+   left="0"
+   right="-1"
+   width="313"
+   mouse_opaque="false"
+   name="members_footer"
+   top="325"
+   visible="false">
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     top="8"
+     text_color="EmphasisColor"
+     name="static"
+     width="300">
+      Assigned Roles
+    </text>
+    <scroll_list
+     draw_stripes="true"
+    follows="left|top|right"
+     height="150"
      layout="topleft"
-     follows="top|left|right"
      left="0"
      right="-1"
-     width="313"
-     mouse_opaque="false"
-     name="actions_footer"
-     top_delta="0"
-     top="255"
-     visible="false">
-        <text_editor
-       bg_readonly_color="Transparent"
-       text_readonly_color="EmphasisColor"
-       font="SansSerifSmall"
-         type="string"
-         enabled="false"
-         halign="left"
-         layout="topleft"
+     name="member_assigned_roles"
+     top_pad="0">
+      <scroll_list.columns
+       label=""
+       name="checkbox"
+       width="20" />
+      <scroll_list.columns
+       label=""
+       name="role"
+       width="270" />
+    </scroll_list>
+    <text
+   type="string"
+   height="16"
+   layout="topleft"
+   follows="left|top"
+   left="5"
+   top_pad="5"
+   text_color="EmphasisColor"
+   name="static2"
+   width="285">
+      Allowed Abilities
+    </text>
+    <scroll_list
+     draw_stripes="true"
          follows="left|top|right"
-         left="0"
-         right="-1"
-         height="90"
-         max_length="512"
-         name="action_description"
-         top="0"
-         word_wrap="true">
-            This Ability is &apos;Eject Members from this Group&apos;. Only an Owner can eject another Owner.
-        </text_editor>
-        <text
+     height="150"
+     layout="topleft"
+     left="0"
+     right="-1"
+     name="member_allowed_actions"
+     search_column="2"
+     tool_tip="For details of each allowed ability see the abilities tab"
+     top_pad="0">
+      <scroll_list.columns
+       label=""
+       name="icon"
+       width="2" />
+      <scroll_list.columns
+       label=""
+       name="checkbox"
+       width="20" />
+      <scroll_list.columns
+       label=""
+       name="action"
+       width="270" />
+    </scroll_list>
+  </panel>
+  <panel
+   height="550"
+   background_visible="false"
+   bg_alpha_color="FloaterUnfocusBorderColor"
+   layout="topleft"
+   follows="top|left|right"
+   left="0"
+   right="-1"
+   width="313"
+   mouse_opaque="false"
+   name="roles_footer"
+   top_delta="0"
+   top="209"
+   visible="false">
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     top="5"
+     name="static"
+     width="300">
+      Role Name
+    </text>
+    <line_editor
+     type="string"
+     height="20"
+     layout="topleft"
+     left="0"
+     follows="left|top|right"
+     right="-1"
+     max_length_bytes="20"
+     name="role_name"
+     top_pad="0"
+     width="300">
+    </line_editor>
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     name="static3"
+     top_pad="5"
+     width="300">
+      Role Title
+    </text>
+    <line_editor
+     type="string"
+     height="20"
+     layout="topleft"
+     left="0"
+     follows="left|top|right"
+     right="-1"
+     max_length_bytes="20"
+     name="role_title"
+     top_pad="0"
+     width="300">
+    </line_editor>
+    <text
          type="string"
          height="16"
          layout="topleft"
          follows="left|top"
          left="5"
          name="static2"
-         top_pad="1"
-         width="300">
-            Roles with this ability
-        </text>
-        <scroll_list
-         height="172"
-         layout="topleft"
-         follows="left|top|right"
-         left="5"
-         right="-1"
-         name="action_roles"
-         top_pad="0"
-         width="300" />
-        <text
-         type="string"
-         height="16"
-         layout="topleft"
-         follows="left|top"
-         left="5"
-         name="static3"
          top_pad="5"
-         width="300">
-            Members with this ability
-        </text>
-        <name_list
-         height="122"
-         follows="left|top|right"
-         layout="topleft"
-         left="5"
-         right="-1"
-         name="action_members"
-         top_pad="0"
-         width="300" />
-    </panel>
+         width="200">
+      Description
+    </text>
+    <text_editor
+     type="string"
+     layout="topleft"
+     left="0"
+     follows="left|top|right"
+     right="-1"
+     max_length="295"
+     height="35"
+     name="role_description"
+     top_pad="0"
+     width="300"
+     word_wrap="true">
+    </text_editor>
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     text_color="EmphasisColor"
+     name="static4"
+     top_pad="5"
+     width="300">
+      Assigned Members
+    </text>
+    <name_list
+     draw_stripes="true"
+     height="128"
+     layout="topleft"
+     left="0"
+     follows="left|top|right"
+     right="-1"
+     name="role_assigned_members"
+     top_pad="0"
+     width="300" />
+    <check_box
+     height="15"
+     label="Reveal members"
+     left="5"
+     layout="topleft"
+     name="role_visible_in_list"
+     tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
+     top_pad="4"
+     width="300" />
+    <text
+    type="string"
+    height="16"
+    layout="topleft"
+    follows="left|top"
+    left="5"
+    text_color="EmphasisColor"
+    name="static5"
+    top_pad="2"
+    width="300">
+      Allowed Abilities
+    </text>
+    <scroll_list
+     draw_stripes="true"
+     height="140"
+     layout="topleft"
+     left="0"
+     follows="left|top|right"
+     right="-1"
+     name="role_allowed_actions"
+     search_column="2"
+     tool_tip="For details of each allowed ability see the abilities tab"
+     top_pad="0"
+     width="300">
+      <scroll_list.columns
+       label=""
+       name="icon"
+       width="2" />
+      <scroll_list.columns
+       label=""
+       name="checkbox"
+       width="20" />
+      <scroll_list.columns
+       label=""
+       name="action"
+       width="270" />
+    </scroll_list>
+  </panel>
+  <panel
+    height="424"
+    background_visible="false"
+    bg_alpha_color="FloaterUnfocusBorderColor"
+    layout="topleft"
+    follows="top|left|right"
+    left="0"
+    right="-1"
+    width="313"
+    mouse_opaque="false"
+    name="actions_footer"
+    top_delta="0"
+    top="255"
+    visible="false">
+    <text_editor
+   bg_readonly_color="Transparent"
+   text_readonly_color="EmphasisColor"
+   font="SansSerifSmall"
+     type="string"
+     enabled="false"
+     halign="left"
+     layout="topleft"
+     follows="left|top|right"
+     left="0"
+     right="-1"
+     height="90"
+     max_length="512"
+     name="action_description"
+     top="0"
+     word_wrap="true">
+      This Ability is &apos;Eject Members from this Group&apos;. Only an Owner can eject another Owner.
+    </text_editor>
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     name="static2"
+     top_pad="1"
+     width="300">
+      Roles with this ability
+    </text>
+    <scroll_list
+     height="172"
+     layout="topleft"
+     follows="left|top|right"
+     left="5"
+     right="-1"
+     name="action_roles"
+     top_pad="0"
+     width="300" />
+    <text
+     type="string"
+     height="16"
+     layout="topleft"
+     follows="left|top"
+     left="5"
+     name="static3"
+     top_pad="5"
+     width="300">
+      Members with this ability
+    </text>
+    <name_list
+     height="122"
+     follows="left|top|right"
+     layout="topleft"
+     left="5"
+     right="-1"
+     name="action_members"
+     top_pad="0"
+     width="300" />
+  </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
index 0eeccbeac516983fcf523daae0cf7685a0f481a1..1044cbfd2e1d24a5b15ab1db6958b38c4f374e5b 100755
--- a/indra/newview/skins/default/xui/en/role_actions.xml
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -9,7 +9,10 @@
 		<action description="Eject Members from this Group"
 		     longdescription="Eject Members from this Group using the &apos;Eject&apos; button in the Roles section &gt; Members tab. An Owner can eject anyone except another Owner. If you&apos;re not an Owner, a Member can be ejected from a group if, and only if, they&apos;re only in the Everyone Role, and NO other Roles. To remove Members from Roles, you need to have the &apos;Remove Members from Roles&apos; Ability."
 		     name="member eject" value="2" />
-		<action
+    <action description="Manage ban list"
+         longdescription="Allows the group member to ban / un-ban Residents from this group."
+         name="allow ban" value="51" />
+    <action
 		     description="Toggle &apos;Open Enrollment&apos; and change &apos;Enrollment fee&apos;"
 		     longdescription="Toggle &apos;Open Enrollment&apos; to let new Members join without an invitation, and change the &apos;Enrollment fee&apos; in the General section."
 		     name="member options" value="3" />
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ba95d701ab753e1867601f4259f868397e787a74..5fbc539a0638d0a8513b0549ce905391513d35b5 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3775,6 +3775,7 @@ Abuse Report</string>
   <string name="LocalEstimateUSD">US$ [AMOUNT]</string>
 
   <!-- Group Profile roles and powers -->
+  <string name="Group Ban">Group Ban</string>
   <string name="Membership">Membership</string>
   <string name="Roles">Roles</string>
   <string name="Group Identity">Group Identity</string>