[sldev] Patch to Address Debit Permission Spoofing

Able Whitman able.whitman at gmail.com
Mon May 28 21:20:37 PDT 2007


Skipped content of type multipart/alternative-------------- next part --------------
A non-text attachment was scrubbed...
Name: perm-debit2-prompt1.PNG
Type: image/png
Size: 30495 bytes
Desc: not available
Url : http://lists.secondlife.com/pipermail/sldev/attachments/20070529/c5c0c7af/perm-debit2-prompt1-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: perm-debit2-prompt2.PNG
Type: image/png
Size: 27847 bytes
Desc: not available
Url : http://lists.secondlife.com/pipermail/sldev/attachments/20070529/c5c0c7af/perm-debit2-prompt2-0001.png
-------------- next part --------------
diff -ur -X diff-excludes.txt linden-base/indra/newview/app_settings/colors_base.xml linden/indra/newview/app_settings/colors_base.xml
--- linden-base/indra/newview/app_settings/colors_base.xml	2007-05-23 11:56:00.000000000 -0400
+++ linden/indra/newview/app_settings/colors_base.xml	2007-05-28 20:06:29.859375000 -0400
@@ -10,8 +10,10 @@
 <!--  usually be left as opaque white. -->
 <ButtonColor value="255, 255, 255, 255"/>
 <ButtonImageColor value="255, 255, 255, 255"/>
+<!--  This will shade the blue dialog buttons so they appear redish in a caution dialog, more or less -->
+<ButtonCautionImageColor value="127, 127,  127, 191"/>
 
-<!--  Text labels for buttons, like the "OK" text -->
+  <!--  Text labels for buttons, like the "OK" text -->
 <ButtonLabelColor value="220, 220, 220, 255"/>
 <ButtonLabelSelectedColor value="220, 220, 220, 255"/>
 <ButtonLabelDisabledColor value="147, 169, 213, 200"/>
@@ -95,6 +97,10 @@
 <!--  top-right of the screen. -->
 <NotifyBoxColor value="58, 147, 242, 255"/>
 <NotifyTextColor value="0, 0, 0, 255"/>
+  <!-- the background color of caution permissions prompts -->
+<NotifyCautionBoxColor value="242, 58, 73, 255"/>
+  <!-- the foreground color of the special title in caution permissions prompts -->
+<NotifyCautionWarnColor value="255, 255, 255, 255"/>
 <!--  Background color of focused floaters -->
 <FocusBackgroundColor value="62, 62, 62, 255"/>
 <GroupNotifyBoxColor value="70, 170, 255, 255"/>
diff -ur -X diff-excludes.txt linden-base/indra/newview/llcontroldef.cpp linden/indra/newview/llcontroldef.cpp
--- linden-base/indra/newview/llcontroldef.cpp	2007-05-23 11:56:00.000000000 -0400
+++ linden/indra/newview/llcontroldef.cpp	2007-05-27 18:41:58.156250000 -0400
@@ -240,6 +240,10 @@
 	// Other....
 	//------------------------------------------------------------------------
 
+	gSavedSettings.declareBOOL("PermissionsCautionEnabled", TRUE, "When enabled, changes the handling of script permission requests to help avoid accidental granting of certain permissions, such as the debit permission", NO_PERSIST);
+	gSavedSettings.declareBOOL("PermissionsCautionAutoDecline", FALSE, "Automatically decline permission requests from scripts that ask for permissions that would raise a caution, such as the debit permission");
+	gSavedSettings.declareS32("PermissionsCautionNotifyBoxHeight", 312, "Height of caution-style notification messages", NO_PERSIST);
+
 	gSavedSettings.declareBOOL("ScriptHelpFollowsCursor", FALSE, "Scripting help window updates contents based on script editor contents under text cursor");
 
 	gSavedSettings.declareS32("LastFeatureVersion", 0, "[DO NOT MODIFY] Version number for tracking hardware changes", TRUE);
diff -ur -X diff-excludes.txt linden-base/indra/newview/llnotify.cpp linden/indra/newview/llnotify.cpp
--- linden-base/indra/newview/llnotify.cpp	2007-05-23 11:56:00.000000000 -0400
+++ linden/indra/newview/llnotify.cpp	2007-05-28 22:28:14.421875000 -0400
@@ -71,6 +71,16 @@
 	return showXml(xml_desc, LLString::format_map_t(), callback, user_data);
 }
 
+
+//static
+void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution,
+						   notify_callback_t callback, void *user_data)
+{
+	// for script permission prompts
+	LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, is_caution);
+	gNotifyBoxView->addChild(notify);
+}
+
 //static
 void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
 						   notify_callback_t callback, void *user_data)
@@ -85,19 +95,20 @@
 						   const option_list_t& options,
 						   BOOL layout_script_dialog)
 {
-	LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, options, layout_script_dialog);
+	LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, FALSE, options, layout_script_dialog);
 	gNotifyBoxView->addChild(notify);
 }
 
 //---------------------------------------------------------------------------
 
 LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& args,
-						 notify_callback_t callback, void* user_data,
+						 notify_callback_t callback, void* user_data, BOOL is_caution,
 						 const option_list_t& extra_options,
 						 BOOL layout_script_dialog)
 	: LLPanel("notify", LLRect(), BORDER_NO),
 	  LLEventTimer(gSavedSettings.getF32("NotifyTipDuration")),
 	  mIsTip(FALSE),
+	  mIsCaution(FALSE),
 	  mAnimating(TRUE),
 	  mTimer(),
 	  mNextBtn(NULL),
@@ -141,9 +152,19 @@
 	options.insert(options.end(), extra_options.begin(), extra_options.end());
 
 	// initialize
-	
+
 	mIsTip = xml_template->mIsTip;
 	mIsFocusRoot = !mIsTip;
+
+	// caution flag can be set explicitly by specifying it in the
+	// call to the c'tor, or it can be set implicitly if the
+	// notify xml template specifies that it is a caution
+	//
+	// (but a tip-style notification cannot be a caution notification,
+	// since the rendering of the additional top textbox doesn't 
+	// account for the special layout of a tip notification)
+	mIsCaution = ((xml_template->mIsCaution | is_caution) && (!mIsTip));
+
 	mAnimating = TRUE;
 	mCallback = callback;
 	mData = user_data;
@@ -151,7 +172,7 @@
 	mDefaultOption = xml_template->mDefaultOption;
 		  
 	LLRect rect = mIsTip ? getNotifyTipRect(message)
-		   		  		 : getNotifyRect(mNumOptions, layout_script_dialog);
+		   		  		 : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution);
 	setRect(rect);
 	setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
 	setBackgroundVisible(FALSE);
@@ -160,18 +181,42 @@
 	LLIconCtrl* icon;
 	LLTextEditor* text;
 
-	S32 x = HPAD + HPAD;
 	const S32 TOP = mRect.getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
 	const S32 BOTTOM = (S32)sFont->getLineHeight();
+	S32 x = HPAD + HPAD;
+	S32 y = TOP;
 
 	icon = new LLIconCtrl("icon",
-						  LLRect(x, TOP, x+32, TOP-32),
+						  LLRect(x, y, x+32, TOP-32),
 						  mIsTip ? "notify_tip_icon.tga" : "notify_box_icon.tga");
 	icon->setMouseOpaque(FALSE);
 	addChild(icon);
 
 	x += HPAD + HPAD + 32;
 
+	// add a caution textbox at the top of a caution notification
+	LLTextBox* caution_box = NULL;
+	if (mIsCaution)
+	{
+		caution_box = new LLTextBox(
+			"caution_box", 
+			LLRect(x, y, mRect.getWidth() - 2, (S32)sFont->getLineHeight()), 
+			LLNotifyBox::getTemplateMessage("ScriptQuestionCautionWarn"), 
+			sFont, 
+			FALSE);
+
+		caution_box->setFontStyle(LLFontGL::BOLD);
+		caution_box->setColor(gColors.getColor("NotifyCautionWarnColor"));
+		caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor"));
+		caution_box->setBorderVisible(FALSE);
+		
+		addChild(caution_box);
+
+		// adjust the vertical position of the next control so that 
+		// it appears below the caution textbox
+		y = y - HPAD - (S32)sFont->getLineHeight();
+	}
+
 	const S32 BOTTOM_PAD = VPAD * 3;
 	const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
 
@@ -183,7 +228,7 @@
 		DB_INV_ITEM_NAME_BUF_SIZE;  // For script dialogs: add space for title.
 
 	text = new LLTextEditor("box",
-							LLRect(x, TOP, mRect.getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16),
+							LLRect(x, y, mRect.getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16),
 							MAX_LENGTH,
 							message,
 							sFont,
@@ -224,7 +269,9 @@
 		addChild(btn);
 		mNextBtn = btn;
 
-		S32 btn_width = 90;
+		// make caution notification buttons slightly narrower
+		// so that 3 of them can fit without overlapping the "next" button
+		S32 btn_width = mIsCaution? 84 : 90;
 		LLRect btn_rect;
 
 		for (S32 i = 0; i < mNumOptions; i++)
@@ -260,6 +307,13 @@
 
 			btn = new LLButton(options[i], btn_rect, "", onClickButton, userdata);
 			btn->setFont(font);
+
+			if (mIsCaution)
+			{
+				btn->setImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor"));
+				btn->setDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor"));
+			}
+
 			addChild(btn, -1);
 
 			if (i == mDefaultOption)
@@ -363,7 +417,8 @@
 	{
 		LLGLSTexture texture_enabled;
 		LLViewerImage::bindTexture(imagep);
-		LLColor4 color = gColors.getColor("NotifyBoxColor");
+		// set proper background color depending on whether notify box is a caution or not
+		LLColor4 color = mIsCaution? gColors.getColor("NotifyCautionBoxColor") : gColors.getColor("NotifyBoxColor");
 		if(gFocusMgr.childHasKeyboardFocus( this ))
 		{
 			const S32 focus_width = 2;
@@ -376,7 +431,7 @@
 			color = gColors.getColor("ColorDropShadow");
 			glColor4fv(color.mV);
 			gl_segmented_rect_2d_tex(0, mRect.getHeight(), mRect.getWidth(), 0, imagep->getWidth(), imagep->getHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
-			color = gColors.getColor("NotifyBoxColor");
+			color = mIsCaution? gColors.getColor("NotifyCautionBoxColor") : gColors.getColor("NotifyBoxColor");
 			glColor4fv(color.mV);
 			gl_segmented_rect_2d_tex(1, mRect.getHeight()-1, mRect.getWidth()-1, 1, imagep->getWidth(), imagep->getHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
 		}
@@ -456,9 +511,17 @@
 
 
 // static
-LLRect LLNotifyBox::getNotifyRect(S32 num_options, BOOL layout_script_dialog)
+LLRect LLNotifyBox::getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution)
 {
 	S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
+	if (is_caution)
+	{
+		// make caution-style dialog taller to accomodate extra text,
+		// as well as causing the accept/decline buttons to be drawn
+		// in a different position, to help prevent "quick-click-through"
+		// of many permissions prompts
+		notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight");
+	}
 	const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
 
 	const S32 TOP = gNotifyBoxView->getRect().getHeight();
@@ -577,6 +640,17 @@
 	LLNotifyBox* self = self_and_button->mSelf;
 	S32 button = self_and_button->mButton;
 
+	// for caution notifications, check if the last button in the prompt was clicked
+	// unless it is the only button, in which case it will just be an "OK" button
+	if ((self->mIsCaution) && (button > 0) && (button == (self->mNumOptions - 1)))
+	{
+		// show an alert dialog containing more explanation about the debit permission
+		LLAlertDialog::showXml("DebitPermissionDetails");
+
+		// keep this notification open
+		return;
+	}
+
 	if (self->mCallback)
 	{
 		self->mCallback(button, self->mData);
@@ -609,6 +683,20 @@
 	}
 }
 
+// method to check whether a given notify template show as a caution or not
+const BOOL LLNotifyBox::getTemplateIsCaution(const LLString& xml_desc)
+{
+	BOOL is_caution = FALSE;
+
+	template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
+	if (iter != sNotifyTemplates.end())
+	{
+		is_caution = iter->second->mIsCaution;
+	}
+
+	return is_caution;
+}
+
 //static
 bool LLNotifyBox::parseNotify(const LLString& xml_filename)
 {
@@ -656,6 +744,18 @@
 				xml_template->mIsTip = tip;
 			}
 		}
+
+		// parse a bool attribute named "caution" to determine
+		// whether this notification gets cautionary special handling
+		BOOL caution = FALSE;
+		if (notify->getAttributeBOOL("caution", caution))
+		{
+			if (xml_template)
+			{
+				xml_template->mIsCaution = caution;
+			}
+		}
+		
 				
 		S32 btn_idx = 0;
 		for (LLXMLNode* child = notify->getFirstChild();
diff -ur -X diff-excludes.txt linden-base/indra/newview/llnotify.h linden/indra/newview/llnotify.h
--- linden-base/indra/newview/llnotify.h	2007-05-23 11:56:00.000000000 -0400
+++ linden/indra/newview/llnotify.h	2007-05-27 19:17:25.187500000 -0400
@@ -46,7 +46,8 @@
 
 	static void showXml( const LLString& xml_desc,
 						 notify_callback_t callback = NULL, void *user_data = NULL);
-	
+	static void showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution,
+						 notify_callback_t callback = NULL, void *user_data = NULL);
 	static void showXml( const LLString& xml_desc, const LLString::format_map_t& args,
 						 notify_callback_t callback = NULL, void *user_data = NULL);
 	// For script notifications:
@@ -57,13 +58,16 @@
 
 	static bool parseNotify(const LLString& xml_filename);
 	static const LLString& getTemplateMessage(const LLString& xml_desc);
+	static const BOOL LLNotifyBox::getTemplateIsCaution(const LLString& xml_desc);
 	
 	BOOL isTip() const { return mIsTip; }
+	BOOL isCaution() const { return mIsCaution; }
 	/*virtual*/ void setVisible(BOOL visible);
 
 protected:
 	LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& args,
 							 notify_callback_t callback, void* user_data,
+							 BOOL is_caution = FALSE,
 							 const option_list_t& extra_options = option_list_t(),
 							 BOOL layout_script_dialog = FALSE);
 	/*virtual*/ ~LLNotifyBox();
@@ -81,7 +85,7 @@
 
 	// Returns the rect, relative to gNotifyView, where this
 	// notify box should be placed.
-	static LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog);
+	static LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution);
 	static LLRect getNotifyTipRect(const LLString &message);
 
 	// internal handler for button being clicked
@@ -95,6 +99,7 @@
 
 protected:
 	BOOL mIsTip;
+	BOOL mIsCaution; // is this a caution notification?
 	BOOL mAnimating; // Are we sliding onscreen?
 
 	// Time since this notification was displayed.
@@ -142,7 +147,7 @@
 class LLNotifyBoxTemplate : public LLRefCount
 {
 public:
-	LLNotifyBoxTemplate() : mIsTip(FALSE), mDefaultOption(0) {}
+	LLNotifyBoxTemplate() : mIsTip(FALSE), mIsCaution(FALSE), mDefaultOption(0) {}
 
 	void setMessage(const LLString& message)
 	{
@@ -162,6 +167,9 @@
 	LLString mLabel;			// Handle for access from code, etc
 	LLString mMessage;			// Message to display
 	BOOL mIsTip;
+	// flag whether to use special caution dialog when a script permission
+	// request includes a notification marked as a caution in notify.xml
+	BOOL mIsCaution;				
 	LLNotifyBox::option_list_t mOptions;
 	S32 mDefaultOption;
 };
diff -ur -X diff-excludes.txt linden-base/indra/newview/llviewermessage.cpp linden/indra/newview/llviewermessage.cpp
--- linden-base/indra/newview/llviewermessage.cpp	2007-05-23 11:56:00.000000000 -0400
+++ linden/indra/newview/llviewermessage.cpp	2007-05-28 22:04:55.328125000 -0400
@@ -154,6 +154,22 @@
 const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period
 const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds
 
+//script permissions
+const LLString SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = 
+	{ 
+		"ScriptTakeMoney",
+		"ActOnControlInputs",
+		"RemapControlInputs",
+		"AnimateYourAvatar",
+		"AttachToYourAvatar",
+		"ReleaseOwnership",
+		"LinkAndDelink",
+		"AddAndRemoveJoints",
+		"ChangePermissions",
+		"TrackYourCamera",
+		"ControlYourCamera"
+	};
+
 struct LLFriendshipOffer
 {
 	LLUUID mFromID;
@@ -4273,8 +4289,8 @@
 class LLScriptQuestionCBData
 {
 public:
-	LLScriptQuestionCBData(const LLUUID &taskid, const LLUUID &itemid, const LLHost &sender, S32 questions)
-		: mTaskID(taskid), mItemID(itemid), mSender(sender), mQuestions(questions)
+	LLScriptQuestionCBData(const LLUUID &taskid, const LLUUID &itemid, const LLHost &sender, S32 questions, const char *object_name, const char *owner_name)
+		: mTaskID(taskid), mItemID(itemid), mSender(sender), mQuestions(questions), mObjectName(object_name), mOwnerName(owner_name)
 	{
 	}
 
@@ -4282,17 +4298,135 @@
 	LLUUID mItemID;
 	LLHost mSender;
 	S32	   mQuestions;
+	LLString mObjectName;
+	LLString mOwnerName;
 };
 
+void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_questions, BOOL allowed)
+{
+	// only continue if at least some permissions were requested
+	if (orig_questions)
+	{
+		// always include the object name and owner name 
+		LLString notice("'");
+		notice.append(cbdata->mObjectName);
+		notice.append("', an object owned by '");
+		notice.append(cbdata->mOwnerName);
+		notice.append("', ");
+
+		// try to lookup viewerobject that corresponds to the object that
+		// requested permissions (here, taskid->requesting object id)
+		LLViewerObject* tllvo = gObjectList.findObject(cbdata->mTaskID);
+		if (tllvo)
+		{
+			// found the viewerobject, get it's position in its region
+			LLVector3 tpos(tllvo->getPosition());
+			
+			// try to lookup the name of the region the object is in
+			LLViewerRegion* tllvr = tllvo->getRegion();
+			if (tllvr)
+			{
+				// got the region, so include the region and 3d coordinates of the object
+				LLString tname(tllvr->getName());
+
+				notice.append("located in ");
+				notice.append(tname);
+				notice.append(" at ");
+				
+				notice.append(llformat("%.1f, %.1f,%.1f ", tpos[VX], tpos[VY], tpos[VZ]));
+			}
+		}
+
+		if (allowed)
+		{
+			notice.append("has been granted permission to: ");
+		}
+		else
+		{
+			notice.append("has been denied permission to: ");
+		}
+
+		// check each permission that was requested, and list each 
+		// permission that has been flagged as a caution permission
+		BOOL caution = FALSE;
+		S32 count = 0;
+		for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
+		{
+			if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && LLNotifyBox::getTemplateIsCaution(SCRIPT_QUESTIONS[i]))
+			{
+				count++;
+				caution = TRUE;
+
+				if ((count > 1) && (i < SCRIPT_PERMISSION_EOF))
+				{
+					notice.append(", ");
+				}
+
+				notice.append(LLNotifyBox::getTemplateMessage(SCRIPT_QUESTIONS[i]));
+			}
+		}
+
+		notice.append(".");
+
+		// log a chat message as long as at least one requested permission
+		// is a caution permission
+		if (caution)
+		{
+			LLChat chat(notice);
+			LLFloaterChat::addChat(chat, FALSE, FALSE);
+		}
+	}
+}
+
+void script_question_decline_cb(S32 option, void* user_data)
+{
+	LLMessageSystem *msg = gMessageSystem;
+	LLScriptQuestionCBData *cbdata = (LLScriptQuestionCBData *)user_data;
+	
+	// remember the permissions requested so they can be checked
+	// when it comes time to log a chat message
+	S32 orig = cbdata->mQuestions;
+
+	// this callback will always decline all permissions requested
+	// (any question flags set in the ScriptAnswerYes message
+	// will be interpreted as having been granted, so clearing all
+	// the bits will deny every permission)
+	cbdata->mQuestions = 0;
+
+	// respond with the permissions denial
+	msg->newMessageFast(_PREHASH_ScriptAnswerYes);
+	msg->nextBlockFast(_PREHASH_AgentData);
+	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+	msg->nextBlockFast(_PREHASH_Data);
+	msg->addUUIDFast(_PREHASH_TaskID, cbdata->mTaskID);
+	msg->addUUIDFast(_PREHASH_ItemID, cbdata->mItemID);
+	msg->addS32Fast(_PREHASH_Questions, cbdata->mQuestions);
+	msg->sendReliable(cbdata->mSender);
+
+	// log a chat message, if appropriate
+	notify_cautioned_script_question(cbdata, orig, FALSE);
+
+	delete cbdata;
+}
 
 void script_question_cb(S32 option, void* user_data)
 {
 	LLMessageSystem *msg = gMessageSystem;
 	LLScriptQuestionCBData *cbdata = (LLScriptQuestionCBData *)user_data;
+	S32 orig = cbdata->mQuestions;
+
+	// check whether permissions were granted or denied
+	BOOL allowed = TRUE;
+	// the "yes/accept" button is the first button in the template, making it button 0
+	// if any other button was clicked, the permissions were denied
 	if (option != 0)
 	{
 		cbdata->mQuestions = 0;
-	}
+		allowed = FALSE;
+	}	
+
+	// reply with the permissions granted or denied
 	msg->newMessageFast(_PREHASH_ScriptAnswerYes);
 	msg->nextBlockFast(_PREHASH_AgentData);
 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -4302,27 +4436,20 @@
 	msg->addUUIDFast(_PREHASH_ItemID, cbdata->mItemID);
 	msg->addS32Fast(_PREHASH_Questions, cbdata->mQuestions);
 	msg->sendReliable(cbdata->mSender);
+
+	// only log a chat message if caution prompts are enabled
+	if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
+	{
+		// log a chat message, if appropriate
+		notify_cautioned_script_question(cbdata, orig, allowed);
+	}
+
 	delete cbdata;
 }
 
-
 void process_script_question(LLMessageSystem *msg, void **user_data)
 {
 	// XUI:translate owner name -> [FIRST] [LAST]
-	const LLString script_questions[SCRIPT_PERMISSION_EOF] = 
-	{ 
-		"ScriptTakeMoney",
-		"ActOnControlInputs",
-		"RemapControlInputs",
-		"AnimateYourAvatar",
-		"AttachToYourAvatar",
-		"ReleaseOwnership",
-		"LinkAndDelink",
-		"AddAndRemoveJoints",
-		"ChangePermissions",
-		"TrackYourCamera",
-		"ControlYourCamera"
-	};
 
 	LLHost sender = msg->getSender();
 
@@ -4332,7 +4459,9 @@
 	char object_name[255];		/* Flawfinder: ignore */
 	char owner_name[DB_FULL_NAME_BUF_SIZE];		/* Flawfinder: ignore */
 
+	// taskid -> object key of object requesting permissions
 	msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid );
+	// itemid -> script asset key of script requesting permissions
 	msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid );
 	msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectName, 255, object_name);
 	msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectOwner, DB_FULL_NAME_BUF_SIZE, owner_name);
@@ -4341,23 +4470,53 @@
 	LLString script_question;
 	if (questions)
 	{
+		BOOL caution = FALSE;
 		S32 count = 0;
 		LLString::format_map_t args;
 		args["[OBJECTNAME]"] = object_name;
 		args["[NAME]"] = owner_name;
+
+		// check the received permission flags against each permission
 		for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
 		{
 			if (questions & LSCRIPTRunTimePermissionBits[i])
 			{
 				count++;
-				script_question += "    " + LLNotifyBox::getTemplateMessage(script_questions[i]) + "\n";
+				script_question += "    " + LLNotifyBox::getTemplateMessage(SCRIPT_QUESTIONS[i]) + "\n";
+
+				// check whether permission question should cause special caution dialog
+				caution |= LLNotifyBox::getTemplateIsCaution(SCRIPT_QUESTIONS[i]);
 			}
 		}
 		args["[QUESTIONS]"] = script_question;
 
-		LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions);
+		LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name);
+
+		// check whether cautions are even enabled or not
+		if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
+		{
+			if (caution && gSavedSettings.getBOOL("PermissionsCautionAutoDecline"))
+			{
+				// automatically decline the request for permissions that would otherwise raise a caution prompt
+				LLNotifyBox::showXml("ScriptQuestionDecline", args, TRUE, script_question_decline_cb, cbdata);
+			}
+			else if (caution)
+			{
+				// display the caution permissions prompt
+				LLNotifyBox::showXml("ScriptQuestionCaution", args, TRUE, script_question_cb, cbdata);
+			}
+			else
+			{
+				// display the permissions request normally
+				LLNotifyBox::showXml("ScriptQuestion", args, FALSE, script_question_cb, cbdata);
+			}
+		}
+		else
+		{
+			// fall back to default behavior if cautions are entirely disabled
+			LLNotifyBox::showXml("ScriptQuestion", args, FALSE, script_question_cb, cbdata);
+		}
 
-		LLNotifyBox::showXml("ScriptQuestion", args, script_question_cb, cbdata);
 	}
 }
 
diff -ur -X diff-excludes.txt linden-base/indra/newview/skins/xui/en-us/alerts.xml linden/indra/newview/skins/xui/en-us/alerts.xml
--- linden-base/indra/newview/skins/xui/en-us/alerts.xml	2007-05-23 11:56:02.000000000 -0400
+++ linden/indra/newview/skins/xui/en-us/alerts.xml	2007-05-28 22:56:20.796875000 -0400
@@ -4298,5 +4298,17 @@
 			they are part of an attachment.
 		</message>
 	</alert>
+  <!-- alert for more information about the debit permission -->
+  <alert modal="true" name="DebitPermissionDetails">
+    <message name="message">
+      You should be careful about granting an object permission to take Linden dollars (L$) from your account.
 
+      Some objects, such as vendors, legitimately require this permission in order to function properly, but unless you trust both the object and its creator, you should generally deny it permission to debit money from you.
+
+      Once you have granted this permission to an object, it will be allowed to automatically debit money from your account without additional prompting. The only way to revoke this permission is to delete the object or to reset the scripts in the object.
+    </message>
+    <option default="true" name="OK">
+      OK
+    </option>
+  </alert>
 </alerts>
diff -ur -X diff-excludes.txt linden-base/indra/newview/skins/xui/en-us/notify.xml linden/indra/newview/skins/xui/en-us/notify.xml
--- linden-base/indra/newview/skins/xui/en-us/notify.xml	2007-05-23 11:56:02.000000000 -0400
+++ linden/indra/newview/skins/xui/en-us/notify.xml	2007-05-28 22:12:49.937500000 -0400
@@ -634,7 +634,8 @@
 			Failed to find [TYPE] named [DESC] in database.
 		</message>
 	</notify>
-	<notify name="ScriptTakeMoney" tip="false">
+  <!-- flag the debit permission as causing a caution permissions prompt -->
+  <notify name="ScriptTakeMoney" tip="false" caution="true">
 		<message name="message">
 			Take Linden dollars (L$) from you
 		</message>
@@ -689,6 +690,7 @@
 			Control your camera
 		</message>
 	</notify>
+  <!-- the normal permissions prompt -->
 	<notify name="ScriptQuestion" tip="false">
 		<message name="message">
 			&apos;[OBJECTNAME]&apos;, an object owned by &apos;[NAME]&apos;, would like to:
@@ -703,7 +705,50 @@
 			No
 		</option>
 	</notify>
-	<notify name="ScriptDialog" tip="false">
+  <!-- the special title to display at the top of a caution permissions prompt -->
+  <notify name="ScriptQuestionCautionWarn" tip="false">
+    <message name="message">Debit Permission Warning</message>
+  </notify>
+  <!-- the caution permssions prompt, when auto-deny is disabled -->
+  <notify name="ScriptQuestionCaution" tip="false" caution="true">
+    <message name="message">
+      &apos;[OBJECTNAME]&apos;, an object owned by &apos;[NAME]&apos;, would like to:
+ 
+[QUESTIONS]
+Accepting this request will give the object ongoing permission to take L$ from your account without further prompting. For additional information, click the Details button.
+
+Do you wish to accept this request?
+    </message>
+    <option name="Accept">
+      Accept
+    </option>
+    <option name="Decline" default="true">
+      Decline
+    </option>
+    <!-- details button MUST be the last button -->
+    <option name="Details">
+      Details...
+    </option>
+  </notify>
+  <!-- the caution permissions prompt, when auto-deny is enabled -->
+  <notify name="ScriptQuestionDecline" tip="false" caution="true">
+    <message name="message">
+      &apos;[OBJECTNAME]&apos;, an object owned by &apos;[NAME]&apos;, would like to:
+ 
+[QUESTIONS]
+This request will be automatically declined.
+
+If you trust this object and its creator, and wish to grant it debit permission, you can turn off the "Always decline" setting in the Popups section of Preferences.
+    </message>
+    <option name="OK" default="true">
+      OK
+    </option>
+    <!-- details button MUST be the last button -->
+    <option name="Details">
+      Details...
+    </option>
+  </notify>
+  <notify name="ScriptDialog" tip="false">
 		<message name="message">
 			[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
 [MESSAGE]
diff -ur -X diff-excludes.txt linden-base/indra/newview/skins/xui/en-us/panel_settings_msgbox.xml linden/indra/newview/skins/xui/en-us/panel_settings_msgbox.xml
--- linden-base/indra/newview/skins/xui/en-us/panel_settings_msgbox.xml	2007-05-23 11:56:02.000000000 -0400
+++ linden/indra/newview/skins/xui/en-us/panel_settings_msgbox.xml	2007-05-28 21:54:26.781250000 -0400
@@ -11,7 +11,13 @@
 		Show popups:
 	</text>
 	<scroll_list follows="top|left" height="100" left="12" name="enabled_popups" width="480" />
-	<button bottom_delta="-45" follows="top|left" height="20"
+  <button bottom_delta="-45" follows="top|left" height="20"
 	     label="Reset &apos;Show next time&apos; Dialogs..." left="12"
 	     name="reset_dialogs_btn" width="210" />
+  <text bottom_delta="-40" follows="top|left" left="12" width="200">
+    Script Permissions:
+  </text>
+  <check_box follows="top|left" height="16" name="caution_auto_decline" width="480" left="12" 
+        control_name="PermissionsCautionAutoDecline" initial_value="false"
+        label="Always decline script requests for permission to take money (L$) from your account" />
 </panel>
-------------- next part --------------
[[ Second Life Viewer Patch to Address Debit Permission Spoofing ]]
Revision 2

Purpose
=======
The purpose of this patch is to alter the client's handling of script permission requests so as to make requests for the debit permission more readily apparent to the user. 

Background
==========
A script can ask an agent to grant it certain permissions, such as the ability to animate the avatar, or to attach itself to the avatar. Almost all of these permissions grant a script the ability to perform actions that are revocable--animations can be stopped, and controls can be regained, attachments can be detached.

The one exception to this is the debit permission, where a script asks for an agent's permission to "Take Linden Dollars (L$) from you". Worse, not only are the actions performed with this permission not revocable, once an object is granted such permission, that permission itself is irrevocable until the object itself is reset.

When the user is prompted to grant an object various permissions, the prompt is the visually the same regardless of what permissions are requested. Maliciously-scripted objects have taken advantage of this fact to trick users into granting seemingly-innocuous objects permission to take their money, an action for which they have no recourse. See, for example:

> Animator that steals your cash?
> http://www.secondlifeinsider.com/2007/05/15/animator-that-steals-your-cash/

> Can objects really steal your $L?
> http://forums.secondlife.com/showthread.php?t=184519

Rationale
=========
It is good that the client requires scripts to ask for explicit permission to perform these various actions. The fact that the debit permission is given essentially the same visual "weight" as other permissions, however, can lead to users to make inappropriate trust decisions. Where a user might trust a random object from a stranger to animate his avatar, it's unlikely that he will trust the same object to debit money from his account.

Bugs Addressed
==============
This patch nominally addresses the following JIRA issue:

> VWR-650: making permission debit red
> https://jira.secondlife.com/browse/VWR-650

Other related issues include VWR-767, MISC-228, and MISC-109. In addition, this patch addresses some of the same issues around the debit permission that the following JIRA issue deals with:

> SVC-232: Create a second tier for debit permissions for vendor refunds
> https://jira.secondlife.com/browse/SVC-232

Functional Specification
======================
This patch modifies the client's behavior when it handles script permission requests. 

== Permissions Requests Other than Debit ==

- Goals -
1. Leave the behavior for permission requests that do not include the debit permission unchanged

- Non-Goals -
1. Do not introduce any additional "noise" into the permissions UI  

- Details -

When the client receives a script permissions request, it examines all of the permissions being requested. If the debit permission is not requested, the permissions request proceeds normally. 

- Scenarios -

Scenario 1: A user interacts with a new or and existing object that requests permissions that do not include the debit permission.

Result 1: The prompt for permissions is displayed and behaves exactly as it would have without this patch.

- Examples -

The user will see a prompt similar to that in "debit-perm-normal-prompt.PNG", as they expect.

== Permissions Requests for Debit ==

- Goals -
1. Make it very clear to the user that an object is requesting the debit permission
2. More clearly explain the implications of granting an object debit permission
3. Make it more difficult for a user to accidentally grant an unwanted permission
4. Make it more difficult for a maliciously-written script to lure a user into unknowingly granting an unwanted permission
5. Make the UI changes clear and readily apparent to all users

- Non-Goals -
1. Do not attempt to make it impossible for scripts to be granted the debit permission
2. Do not make UI changes which are onerous or annoying

- Details -

If the debit permission is requested (regardless of what other permissions are also requested), the client alters the appearance of the permissions request prompt. The changes are intended to increase the "visual weight" of a prompt for debit permissions, so that the user doesn't click straight through by accident. The modified version of the permissions prompt incorporates the following changes:

* The background of the prompt box is changed to red, instead of blue
* The buttons are shaded to be reddish-purple, instead of blue
* The button labels are changed to "Accept" and "Decline"
* The default button is "Decline"
* The height of the prompt box is increased by at least 25%
* An additional warning message will appear at the top of the modified prompt
* Additional wording at the bottom of the prompt will be added to more clearly explain the implications of granting an object debit permission
* An additional button "Details?" will be added which, when clicked, displays a modal alert containing details about the debit permission, when to grant it, and how to revoke it.

- Scenarios -

Scenario 1: The user interacts with a new or existing object, which then requests the debit permission.

Result 1: The user sees the new, expanded debit permissions dialog. Noting that it appears significantly different from the one he was expecting, he hesitates long enough to examine the dialog more closely before making a decision about whether to grant the debit permission or not.

Scenario 2: The user interacts with a new or existing object, which then requests the debit permission, along with other permissions.

Result 2: The user behaves as in Result 1, with the understanding that accepting or denying the request will act on all of the listed permissions, not just the debit permission. In this way, the new modified prompt behaves functionally the same as the standard permissions prompt.

- Examples -

The user will see a caution prompt similar to that in "debit-perm-caution-prompt.PNG". 

== Chat Messages after Accepting or Declining a Debit Permission Request ==

- Goals -
1. Provide the user with additional feedback after making a debit permissions decision
2. Leave behind an artifact from the permissions decision that can be logged and recovered in the future

- Non-Goals -
1. Do not report on permissions decisions other than those involving the debit permission
2. Do not spam the user with extraneous or distracting information 

- Details -

When the user makes a decision to accept or decline a request for the debit permission, a chat message is echoed to his chat window giving the following information:
* The name of the object requesting the debit permission
* The name of the owner of the requesting object 
* The location (region name and coordinates) of the object
* Whether the debit permission was granted or declined

This provides an additional visual cue to the user that something out of the ordinary has happened and, if the client has chat logging enabled, this provides a searchable record of objects and owners to which he has granted or denied debit permission.

- Scenarios -

Scenario 1: The user chooses either to accept or deny a request to grant an object the debit permission (and possibly other permissions).

Result 1: The user sees a message in his Chat window that contains additional information about the object that requested the permission, and whether he accepted or declined the request for the debit permission only. 

Scenario 2: The user chooses to accept or deny a request to grant an object a permission or set of permissions that does not include the debit permission.

Result 2: The user does not see any messages logged to his Chat window.

- Examples -

The chat messaged that is logged will be similar to the one in "debit-perm-deny-chat.PNG".


== Automatic Denial of Debit Permission Requests ==

- Goals -
1. Provide users with an additional layer of defense against maliciously-scripted objects
2. Make the additional protection easy to understand and easy to use

- Non-Goals -
1. Do not irreversibly prevent users from conducting transactions in-world, whether they be buying or selling items

- Details -

The UI cues alone should help users to make more informed trust decisions about the permissions they grant to objects. 

In addition to these cues, this patch introduces a new Preferences setting called "Always decline requests for permission to take money (L$) from your account" which will appear as a checkbox on the Popups page of the Preferences dialog. This option is disabled by default, and persists across client sessions. When it is enabled, any permissions requests that include a request for the debit permission will automatically be denied. This denial will apply to all of the requested permissions, not just the debit permission. This setting will not affect permissions requests that do not include the debit permission.

When an automatic denial occurs, the user will see a prompt explaining which object was requesting the permission, and a list of permissions it requested. There will also be a message logged to the user's chat window indicating the object name and the name of its owner, just as when automatic denial is disabled. 

- Examples -

The informational prompt will look similar to the one in "debit-perm-deny-prompt.PNG".

The preference to enable automatic denial will look similar to the preference in "debit-perm-debit-autodeny-pref.PNG".

- Further Information -

The reasoning behind the auto-deny feature is as follows:

1. The frequency with which users will need to legitimately grant an object debit permission is relatively quite rare. Users who are setting up vendors will need to grant this permission rarely, perhaps only once. Users do not need to grant this permission to Pay an object or to Pay other users, so it will not interfere with normal consumer transactions.

2. In the event that a user has auto-deny enabled and needs to legitimately grant an object debit permission, they can simply turn auto-deny off, grant the permission, and re-enable it. For example, someone setting up a vendor who has auto-deny enabled will most likely find that, if they accidentally auto-deny the vendor permission to debit, the vendor will have a mechanism to re-prompt them. Failing that, they can always reset the vendor object to force it to re-request the permission. (Vendor objects always must be owned by the person using them in order to grant them debit permission, and thus users will always have the ability to reset the objects.)

3. On balance, the value of the auto-deny feature is outweighed by the possible hassles around an accidental auto-denial. The effects of wrongly denying the debit permission are always reversible. The effects of wrongly *granting* the debit permission are never reversible. This fundamental asymmetry makes it worth treating the debit permission with a stigma. (In any event, auto-deny is disabled by default.)

== Temporary Opt-out of Caution Permissions Prompts ==

If the user wishes to disable the changes this patch makes to the behavior of permissions handling, he can use the Debug Settings menu to change the "PermissionsCautionEnabled " setting to False.

This setting is set to True by default, and acts as a "kill switch" for the behavior changes made by this patch. When set to False, all permissions prompts behave as they would without this patch, regardless of the permissions set requested.

The act of disabling the caution permissions prompts does *not* persist across client sessions, so that the caution prompts will be re-enabled the next time the user logs in.

Technical Discussion
====================
The diff patch provided is derived from a copy of the 1.16.0.5 client source that was modified to build under Microsoft Visual Studio 2005. The patch itself is fairly straightforward, but there are a few details worth mentioning specifically.

== Marking Which Permissions and Templates Cause a Caution Prompt ==

In the processing of "notify.xml", notifications are examined for an optional Boolean property called Caution on each Notify element. If this property is not present, or is set to False, the template specified by that Notify element is treated normally.

If the Caution property is set to True, then any permissions request that include a permission whose Notify element is flagged, or the use of any notification template that is flagged will trigger a caution prompt. In the case of script permissions with the Caution property set, an automatic denial will be triggered if enabled.

Currently, the only permission notification entry that is marked as a Caution is "ScriptTakeMoney", the entry that corresponds to the debit permission. There is no reason that special handling could be applied to other permissions as well, although this would significantly dilute the effectiveness of the cautionary prompts, and would require changes to the wording of the prompts. This kind of change is not recommended.

== Changes to the Mechanism for Processing Script Requests ==

In "llviewermessage.cpp", the "process_script_question()" method has been modified to include logic to allow it to evaluate whether the requested permissions should trigger an automatic denial or not. In the event of an automatic denial, a new callback named "script_question_decline_cb" is used which always denies permissions requests.

In addition, the "LLScriptQuestionCBData" class was modified to include the name of the object requesting permissions, and the name of its owner, so that this information can be used in both callbacks to log a chat message, if appropriate.

== Changes to the Mechanism for Displaying Notifications ==

In "llnotify.cpp", the LLNotifyBox constructor was modified to accept an additional Boolean parameter that indicates whether the notification is a caution or not. Additional logic was added to the constructor to adjust the size and layout of the notification for caution notifications. The drawBackground() method has been modified to paint a red background for caution notifications.

== Changes to Settings and Configuration ==

In "llcontroldef.cpp":
* Added Boolean "PermissionsCautionEnabled", which controls whether caution notifications are shown (True, default), or not (False). Setting doest not persist.
* Added Boolean "PermissionsCautionAutoDecline", which controls whether script requests for debit permission are automatically declined (True) or not (False, default). Setting persists.
* Added integer "PermissionsCautionNotifyBoxHeight" which determines the height of a caution notification window (312, default). Setting does not persist.

In "panel_settings_msgbox.xml":
* Added a text box and a check box that wire up the "PermissionsCautionAutoDecline" setting to the Popups section of the Preferences dialog.

In "notify.xml":
* Flagged the "ScriptTakeMoney" element as a caution.
* Added the "ScriptQuestionCautionWarn" element, which contains the text to display at the top of the caution warning window.
* Added the "ScriptQuestionCaution" element, which is used instead of "ScriptQuestion" to render a caution notification.
* Added the "ScriptQuestionDecline" element, which is used instead of "ScriptQuestion" when auto-deny is enabled.

In "alerts.xml":
* Added the "DebitPermissionDetails" element, which contains the text that is shown as the "Details" message for debit permission prompts.

In "colors_base.xml":
* Added entry "ButtonCautionImageColor", which defines the shading applied to caution notification buttons.
* Added entry "NotifyCautionBoxColor", which defines the background color for caution notifications.
* Added entry "NotifyCautionWarnColor", which defines the foreground color of the bold title in caution notifications.

Known Bugs
==========

== Notification default button issue ==

The LLNotifyBox class doesn't properly respect the default button settings specified in the "notify.xml" entries, if the notification has fewer than 3 buttons specified. The "default" button specifier is correctly parsed and passed along to the instance of LLNotifyBox, and the drawing code seems to respect the setting when adding buttons to the panel. At runtime though, the first button added to the panel always becomes the default button when the window is given keyboard focus, if there are only 1 or 2 buttons in the notification.

I am still investigating this issue.

== Localization Issue ==

I have only provided English (en-us) entries for the changes made to the notifications, chat messages, and preference settings that were added for this patch.

Localized translations of these resources will be necessary in order for the patch to function properly in non-English clients.

Improvements
============

It is certainly possible that the wording or terminology I have used could be improved upon.

It would also be possible to fundamentally change the style and semantics of a prompt for permissions that includes a debit permission request. For example, the prompt could be changed to become a modal dialog that is centered in the client. My preference is to keep the debit permission prompt in the same overall style of the standard permission prompt. I think that, combined with the visual cues the patch makes, this will strike a reasonable balance between making the debit prompt more visible while not getting too "in-your-face" about the issue.

Questions
=========

If you have any questions, comments, or concerns about this patch, please IM me in-world or email me at able.whitman at gmail.com.

-------------- next part --------------
[[ Second Life Viewer Patch to Address Debit Permission Spoofing ]]
Revision 2

Test Plan
=========
This patch modifies the code paths that generate a variety of notifications in the client, including script permission prompts, script dialogs, region restart notifications, Linden-sent notifications, money transaction confirmations, sent inventory notifications, friend presence popups, etc.

Since this code path is used frequently, testing of this patch must verify that the behavior of existing notifications do not change. The test plan includes several regression test cases to cover these notifications.

Test Cases
==========
There are 14 test cases defined below. They cover all of the major code paths that have been changed as part of this patch, but they may not cover all of the possible interactions between the LLNotifyBox implementation and all other areas of the client.

== TestTipFriendSelf ==

Purpose: Tests whether existing tip notifications work.
Repro Steps:
1. Try to add yourself as a friend.
Expected Results:
* Client should display a normal tip notification in the lower-right of the window that says "You cannot add yourself as a friend." that disappears on its own after a few seconds.

== TestTipFriendPresence ==

Purpose: Tests whether friend presence tip notification work.
Repro Steps:
1. Have a friend who is offline log in.
2. After they have logged in, wait for a minute, and then have the friend log off.
Expected Results:
* When the friend logs in, the client should display a tip notification in the lower-right of the window that says "FirstName LastName is Online" that disappears on its own after a few seconds.
* When the friend logs off, he client should display a tip notification in the lower-right of the window that says "FirstName LastName is Offline" that disappears on its own after a few seconds.

== TestGivenInventoryNotification ==

Purpose: Tests whether notifications about inventory a user is given work.
Repro Steps:
1. Have a friend give you an item from their inventory by dropping it on your profile.
2. Repeat this test for each of the following:
a. Accept the inventory item.
b. Decline the inventory item.
Expected Results:
* The client should display a standard notification in the upper-right of the window that says "ResidentName has given you a ObjectType named 'ObjectName'." The notification should have 3 buttons: Keep, Discard, and Mute.
* When the item is accepted, it should appear in your inventory. 
* When the item is declined, it should not appear in your inventory. 

== TestDialogOnly ==

Purpose: Tests whether simple script dialogs are displayed correctly.
Repro Steps:
1. Create a new box prim and drop the "TestDialogOnly" script onto it.
2. Touch the prim.
3. In the script dialog that appears, click the OK button.
Expected Results:
* After touching the prim, the client should display a script dialog with the text "Test message" in it, along with a button labeled "OK" and a smaller button labeled "Ignore".
* Clicking the OK button should cause the prim to owner-say "Got menu." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several dialogs to be displayed stacked on top of each other.
o Each of the dialogs should be identical, and clicking OK on any of them should have the same effect as above.
* Repeat the test with the auto-deny feature enabled.
o The results should be unchanged from when the auto-deny feature is disabled.

Script:

// start script
integer chan = -19099;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        llSetText("Dialog only", <1.0,1.0,1.0>, 1.0);
        llSetColor(<0.0,1.0,0.0>, ALL_SIDES);
        llListen(chan, "", NULL_KEY, "OK");
    }

    touch_start(integer total_number)
    {
        llDialog(llDetectedKey(0), "Test message", [ "OK" ], chan);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        llOwnerSay("Got menu.");
        if (channel == chan) llResetScript();
    }

}
// end script

== TestNoDebitOnly ==

Purpose: Tests whether a permissions prompt for a single non-debit permission works properly, and behaves the same as it did before this patch.
Repro Steps:
1. Create a new box prim and drop the "TestNoDebitOnly" script onto it.
2. Touch the prim.
3. Repeat this test, and click the Yes button and then the No button.
Expected Results:
* After touching the prim, the client should display a permission prompt asking for just the animation permission. 
* The prompt should be the normal blue color, and should have two buttons, Yes and No.
* Clicking the Yes button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the No button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Yes or No on any of them should have the same effect as above.
* Repeat the test with the auto-deny feature enabled.
o The results should be unchanged from when the auto-deny feature is disabled.

Script:

// start script
integer askfor = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        askfor = PERMISSION_TRIGGER_ANIMATION;
        llSetText("No Debit", <1.0,1.0,1.0>, 1.0);
        llSetColor(<0.0,0.0,1.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        llRequestPermissions(llDetectedKey(0), askfor);
    }
    
    run_time_permissions(integer perm)
    {
        if ((perm & askfor) == askfor)
        {
            llOwnerSay("Granted.");
        }
        else
        {
            llOwnerSay("Denied.");
        }
        
        llResetScript();
    }
}
// end script

== TestAllNoDebit ==

Purpose: Tests whether a permissions prompt for many non-debit permissions works properly, and behaves the same as it did before this patch.
Repro Steps:
1. Create a new box prim and drop the "TestAllNoDebit" script onto it.
2. Touch the prim.
3. Repeat this test, and click the Yes button and then the No button.
Expected Results:
* After touching the prim, the client should display a permission prompt asking for all permissions except for the control camera and debit permissions. 
* The prompt should be the normal blue color, and should have two buttons, Yes and No.
* The prompt should list each permission being requested individually.
* Clicking the Yes button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the No button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Yes or No on any of them should have the same effect as above.

== TestAllNoDebitAutoDeny ==

Purpose: Tests whether a permissions prompt for many non-debit permissions works properly, and behaves the same as it did before this patch, when the auto-deny feature is enabled.
Repro Steps:
1. Enable the auto-deny feature.
2. Create a new box prim and drop the "TestAllNoDebit" script onto it.
3. Touch the prim.
4. Repeat this test, and click the Yes button and then the No button.
Expected Results:
* After touching the prim, the client should display a permission prompt asking for all permissions except for the control camera and debit permissions. 
* The prompt should be the normal blue color, and should have two buttons, Yes and No.
* The prompt should list each permission being requested individually.
* Clicking the Yes button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the No button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Yes or No on any of them should have the same effect as above.

Script:

// start script
integer askfor = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        // all except for control_camera and debit
        askfor = PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION | PERMISSION_ATTACH | PERMISSION_CHANGE_LINKS | PERMISSION_TRACK_CAMERA ;
        llSetText("AllNoDebit", <1.0,1.0,1.0>, 1.0);
        llSetColor(<0.0,0.0,1.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        llRequestPermissions(llDetectedKey(0), askfor);
    }
    
    run_time_permissions(integer perm)
    {
        if ((perm & askfor) == askfor)
        {
            llOwnerSay("Granted.");
        }
        else
        {
            llOwnerSay("Denied.");
        }
        
        llResetScript();
    }
}
// end script

== TestDebitOnly ==

Purpose: Tests whether a permissions prompt for just the debit permission works properly, and displays the new caution-style prompt.
Repro Steps:
1. Make sure the Auto-Deny feature is disabled.
2. Create a new box prim and drop the "TestDebitOnly" script onto it.
3. Touch the prim.
4. Click the Details? button.
5. Repeat this test, and click the Accept button and then the Decline button.
Expected Results:
* After touching the prim, the client should display a caution permission prompt asking for the debit permission. 
* The prompt should be the cautionary red color, should have a bold white title, and should include additional explanation about the effects of the debit permission.
* The prompt should have two buttons, Accept and decline.
* When clicking the Details? button, make sure that the alert detailing the debit permission appears correctly, and that the alert window is modal.
* Clicking the Accept button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the Decline button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Accept or Decline on any of them should have the same effect as above.

== TestDebitOnlyAutoDeny ==

Purpose: Tests whether a permissions prompt for just the debit permission works properly when the auto-deny feature is enabled, and displays the new caution-style prompt.
Repro Steps:
1. Enable the Auto-Deny feature
2. Create a new box prim and drop the "TestDebitOnly" script onto it.
3. Touch the prim.
4. Click the Details? button.
5. Click the OK button.
Expected Results:
* After touching the prim, the client should display a caution permission prompt asking for the debit permission. 
* The prompt should be the cautionary red color, should have a bold white title, and should include additional explanation about the effects of the debit permission.
* With auto-deny enabled, the permissions prompt should only have one button labeled OK.
* The auto-deny prompt should explain that the permission request will automatically be declined.
* When clicking the Details? button, make sure that the alert detailing the debit permission appears correctly, and that the alert window is modal.
* When clicking the OK button, the script should owner-say "Denied" and then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking OK on any of them should have the same effect as above.

Script:

// start script
integer askfor = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        askfor = PERMISSION_DEBIT;
        llSetText("Debit only", <1.0,1.0,1.0>, 1.0);
        llSetColor(<1.0,0.0,0.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        llRequestPermissions(llDetectedKey(0), askfor);
    }
    
    run_time_permissions(integer perm)
    {
        if ((perm & askfor) == askfor)
        {
            llOwnerSay("Granted.");
        }
        else
        {
            llOwnerSay("Denied.");
        }
        
        llResetScript();
    }
}
// end script

== TestDebitAndUnlink ==

Purpose: Tests whether a permissions prompt for the debit permission and an additional permission works properly, and displays the new caution-style prompt.
Repro Steps:
1. Make sure the Auto-Deny feature is disabled.
2. Create a new box prim and drop the "TestDebitAndUnlink" script onto it.
3. Touch the prim.
4. Repeat this test, and click the Accept button and then the Decline button.
Expected Results:
* After touching the prim, the client should display a caution permission prompt asking for the debit permission and the unlink permission. 
* The prompt window should be tall enough the display the entire message without needing a vertical scroll bar.
* The prompt should be the cautionary red color, should have a bold white title, and should include additional explanation about the effects of the debit permission.
* The prompt should have two buttons, Accept and decline.
* Clicking the Accept button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the Decline button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Accept or Decline on any of them should have the same effect as above.

Script:

// start script
integer askfor = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        askfor = PERMISSION_DEBIT | PERMISSION_CHANGE_LINKS;
        llSetText("Debit + Link", <1.0,1.0,1.0>, 1.0);
        llSetColor(<1.0,0.0,0.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        llRequestPermissions(llDetectedKey(0), askfor);
    }
    
    run_time_permissions(integer perm)
    {
        if ((perm & askfor) == askfor)
        {
            llOwnerSay("Granted.");
        }
        else
        {
            llOwnerSay("Denied.");
        }
        
        llResetScript();
    }
}
// end script

== TestDebitAndAll ==

Purpose: Tests whether a permissions prompt for the debit permission and many other permissions works properly, and displays the new caution-style prompt.
Repro Steps:
1. Make sure the Auto-Deny feature is disabled.
2. Create a new box prim and drop the "TestDebitAndAll" script onto it.
3. Touch the prim.
4. Repeat this test, and click the Accept button and then the Decline button.
Expected Results:
* After touching the prim, the client should display a caution permission prompt asking for the debit permission along with every other permission except for the control camera permission. 
* The text should be too long to display in the prompt, and there should be a vertical scroll bar visible to allow the user to scroll though the entire message.
* The prompt should be the cautionary red color, should have a bold white title, and should include additional explanation about the effects of the debit permission.
* The prompt should have two buttons, Accept and decline.
* Clicking the Accept button should cause the prim to owner-say "Granted." The script should then reset itself.
* Clicking the Decline button should cause the prim to owner-say "Denied." The script should then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking Accept or Decline on any of them should have the same effect as above.

== TestDebitAndAllAutoDeny ==

Purpose: Tests whether a permissions prompt for the debit permission and many other permissions works properly when the auto-deny feature is enabled, and displays the new caution-style prompt.
Repro Steps:
1. Enable the Auto-Deny feature.
2. Create a new box prim and drop the "TestDebitAndAll" script onto it.
3. Touch the prim.
4. Click the OK button.
Expected Results:
* After touching the prim, the client should display a caution permission prompt asking for the debit permission along with every other permission except for the control camera permission. 
* The text should be too long to display in the prompt, and there should be a vertical scroll bar visible to allow the user to scroll though the entire message.
* The prompt should be the cautionary red color, should have a bold white title, and should include additional explanation about the effects of the debit permission.
* With auto-deny enabled, the permissions prompt should only have one button labeled OK.
* The auto-deny prompt should explain that the permission request will automatically be declined.
* When clicking the OK button, the script should owner-say "Denied" and then reset itself.

Further Tests:
* Repeat the test, but touch the prim several times in a row instead of just once.
o This should cause several permission prompts to be displayed stacked on top of each other.
o Each of the prompts should be identical, and clicking OK on any of them should have the same effect as above.

Script:

// start script
integer askfor = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        // all except control_camera
        askfor = PERMISSION_DEBIT | PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION | PERMISSION_ATTACH | PERMISSION_CHANGE_LINKS | PERMISSION_TRACK_CAMERA ;
        llSetText("Debit + All", <1.0,1.0,1.0>, 1.0);
        llSetColor(<1.0,0.0,0.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        llRequestPermissions(llDetectedKey(0), askfor);
    }
    
    run_time_permissions(integer perm)
    {
        if ((perm & askfor) == askfor)
        {
            llOwnerSay("Granted.");
        }
        else
        {
            llOwnerSay("Denied.");
        }
        
        llResetScript();
    }
}
// end script

== TestDebitAndUnlinkMulti ==

Purpose: Tests whether having several permissions prompts display in rapid succession (some asking for the debit permission and some for another single permission) works properly, displays the new caution-style prompt, and helps mitigate the "rapid click-through-and-grant" for many overlapping permissions prompts.
Repro Steps:
1. Make sure the Auto-Deny feature is disabled.
2. Create a new box prim and drop the "TestDebitAndUnlinkMulti" script onto it.
3. Touch the prim.
Expected Results:
* After touching the prim, the client should display a series of 9 permissions prompts in rapid succession.
* Each permission prompt should request a single permission: either the debit permission (about 30% of the time), or the unlink permission (about 70% of the time). 
* The prompts for the unlink permission should all be the normal blue permission prompts.
* The prompts for the debit permission should all be the red caution prompts.
* Being able to rapidly click on more than one permission dialog in a row should be more difficult when a caution prompt appears, since the buttons are not in the same place on the screen.

Further Tests:
* Repeat this test 3 or more times, since each time the prim is touched, a different random combination of permissions dialogs will appear.

== TestDebitAndUnlinkMultiAutoDeny ==

Purpose: Tests whether having several permissions prompts display in rapid succession (some asking for the debit permission and some for another single permission) works properly, displays the new auto-denial prompt when the auto-deny feature is enabled, and helps mitigate the "rapid click-through-and-grant" for many overlapping permissions prompts.
Repro Steps:
1. Enable the auto-deny feature.
2. Create a new box prim and drop the "TestDebitAndUnlinkMulti" script onto it.
3. Touch the prim.
Expected Results:
* After touching the prim, the client should display a series of 9 permissions prompts in rapid succession.
* Each permission prompt should request a single permission: either the debit permission (about 30% of the time), or the unlink permission (about 70% of the time). 
* The prompts for the unlink permission should all be the normal blue permission prompts.
* The prompts for the debit permission should all be the red caution prompts, and all should indicate that the request for the debit permission has been automatically denied.
* Being able to rapidly click on more than one permission dialog in a row should be more difficult when a caution prompt appears, since the buttons are not in the same place on the screen.

Further Tests:
* Repeat this test 3 or more times, since each time the prim is touched, a different random combination of permissions dialogs will appear.


Script:

// start script
integer askfor1 = 0;
integer askfor2 = 0;
integer total = 9;
integer count = 0;

default
{
    state_entry()
    {
        llOwnerSay("Start.");
        askfor1 = PERMISSION_DEBIT;
        askfor2 = PERMISSION_CHANGE_LINKS;
        llSetText("Debit / Link\nmulti, rand", <1.0,1.0,1.0>, 1.0);
        llSetColor(<1.0,0.0,0.0>, ALL_SIDES);
    }

    touch_start(integer total_number)
    {
        count = 0;
        
        integer i;
        for (i = 0; i < total; ++i)
        {
            if (llFrand(1.0) < 0.3)
            {
                llRequestPermissions(llDetectedKey(0), askfor1);
            }
            else
            {
                llRequestPermissions(llDetectedKey(0), askfor2);
            }
        }
    }
    
    run_time_permissions(integer perm)
    {
        if (perm == 0)
        {
            llOwnerSay("Denied either 1 or 2.");
        }
        else if ((perm | askfor1) == askfor1)
        {
            llOwnerSay("Granted 1.");
        }
        else if ((perm | askfor2) == askfor2)
        {
            llOwnerSay("Granted 2.");
        }

        ++count;
        if (count == total) llResetScript();
    }
}
// end script



More information about the SLDev mailing list