LSL Protocol/Restrained Life Relay/How to Test/Relay Test 05

== Objective ==
Ensure that an attacker cannot force an agent to say an unprefixed text of the attackers choice on any channel)
== Instructions ==
# Rez the object and click it
# Wait
== Code ==
integer CHANNEL_RELAY = -1812221819; // Relay Channel
integer CHANNEL_VIEWER_QUERY = 123;
integer CHANNEL_VIEWER_ATTACK = 124;
integer success;
// converts the first letter into upper case
string upperCaseFirstLetter(string param)
{
 integer length = llStringLength(param);
 if (length <= 1)
 {
 return llToUpper(param);
 }
 return llToUpper(llGetSubString(param, 0, 0)) + llGetSubString(param, 1, -1);
}
// looks for the confirmation of the last command
handleRelayResponse(string message)
{
 list tokens = llParseString2List(message, [","], []);
 string question = llList2String(tokens, 2);
 string response = llList2String(tokens, 3);
 if (response == "")
 {
 return;
 }
 if (question == "@end=n")
 {
 llSay(CHANNEL_RELAY, "relaytest," + (string) llGetOwner() + ",!release");
 }
 else if (question == "!release")
 {
 // wait a little bit after "!release,ok" to take
 // network lag from the viewer into account
 llSetTimerEvent(10);
 }
}
// handles response of additional status messages
handleAvatarQueryResponse(string message)
{
 list tokens = llParseString2List(message, ["/"], []);
 integer count = llGetListLength(tokens);
 integer i;
 for (i = 0; i < count; i++)
 {
 string restriction = llList2String(tokens, i);
 
 if (restriction != "crmwqfxdkjfsakdfh")
 {
 string restrictionUpper = upperCaseFirstLetter(restriction);
 llSay(CHANNEL_RELAY, "relaytest," + (string) llGetOwner() 
 + ",@" + restriction + "=y|@" + restriction + ":=y"
 + "|@" + restrictionUpper + "=y|@" + restrictionUpper + ":=y");
 }
 }
 llSay(CHANNEL_RELAY, "relaytest," + (string) llGetOwner() 
 + ",@getstatus=124|@end=n");
}
// analyse attack response.
handleAvatarAttackResponse(string message)
{
 integer pos = llSubStringIndex(message, "crmwqfxdkjfsakdfh");
 if (pos < 0)
 {
 llSay(0, "FAIL: Pseudo restriction was not part of response (broken test?): " + message);
 success = FALSE;
 } 
 else if (pos < 2)
 {
 llSay(0, "FAIL: Avatar said: " + message);
 success = FALSE;
 } 
}
default
{
 state_entry()
 {
 llListen(CHANNEL_RELAY, "", "", "");
 llListen(CHANNEL_VIEWER_QUERY, "", "", "");
 llListen(CHANNEL_VIEWER_ATTACK, "", "", "");
 }
 on_rez(integer ignored)
 {
 llSetText(llGetObjectName(), <1, 1, 1>, 1);
 }
 listen(integer channel, string name, key id, string message)
 {
 llOwnerSay(name + ": " + message);
 if ((llGetOwnerKey(id) == id) && (channel == CHANNEL_VIEWER_QUERY))
 {
 handleAvatarQueryResponse(message);
 }
 if ((llGetOwnerKey(id) == id) && (channel == CHANNEL_VIEWER_ATTACK))
 {
 handleAvatarAttackResponse(message);
 }
 if ((llGetOwnerKey(id) == llGetOwner()) && (channel == CHANNEL_RELAY))
 {
 handleRelayResponse(message);
 }
 }
 touch_start(integer ignored)
 {
 if (llDetectedKey(0) != llGetOwner())
 {
 llSay(0, "Hey, " + llDetectedName(0) + " don't mess with me!");
 return;
 }
 llSetTimerEvent(0);
 success = TRUE;
 llSay(0, "Trying to cause unprefixed chat on channel 124, please wait...");
 llSay(CHANNEL_RELAY, "relaytest," + (string) llGetOwner() 
 + ",@crmwqfxdkjfsakdfh=n|@getstatus=123");
 }
 timer()
 {
 if (success)
 {
 llSay(0, "PASS: All avatar chat was prefixed.");
 }
 llSetTimerEvent(0);
 }
}