Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Notecard Server with a interpreted language

skidz Tweak
Registered User
Join date: 18 Apr 2006
Posts: 42
07-30-2009 03:14
Hey all..

I tried to post this in script libraries, but I suspect scripts have to be nominated or something to get in there :)

I put this together for fun, and thought I would share it with all. Its a notecard server that allows you to request notecards, and that has an interpreted language built in. What this means is you can place some of what I call NSL (notecard scripting language) into the notecard to change what content is served up.

For Example:
I request the URL /Default?Version=1.0
I could place something anywhere in the notecard "Default" that would redirect the content to be returned to a specific line, like so:
[if ([@Version] > 0.9)] line 10

The if statement can support ==, >=, <=, >, <

It also can place query stings values passed into the notecard. For example, if I request the URL "Default?avatar_name=Skidz Tweak" and I had something like this in the notecard "Welcome [@avatar_name]" it would return "Welcome Skidz Tweak"

I really think there is major potential for something like this, especially for changing configurations on the fly of a product. A Great example of something like this would be, a game. I wish I had time to make a kewl game with this :). It could serve up all the content like.. tasks, and other options.

Limitations:
While this works with multiple request if you were going to use this on any kinda scale you would want to implement some load balancing somehow. This also suffers from all the other HTTPIn problems of the temporary URL. You would need to develop some kind of httpin registry for the URLs. And of course the notecard can not be read if there are object in it, like landmarks, or images. It also can only read the first 256 characters of each line.

Free free to use it in your products, but if you make any real improvements please send me a copy and I will try to keep it updated here.

CODE

//settings
string defaultPage = "default";

integer count;
string url;

list Response = [];
list RequestForm = [];
list Request = [];
list RequestPage = [];
list HTTPRequests = [];
list HTMLReadKey = [];
list HTMLReadLine = [];

string str_replace(string src, string from, string to)
{//replaces all occurrences of 'from' with 'to' in 'src'.
integer len = (~-(llStringLength(from)));
if(~len)
{
string buffer = src;
integer b_pos = -1;
integer to_len = (~-(llStringLength(to)));
@loop;
integer to_pos = ~llSubStringIndex(buffer, from);
if(to_pos)
{
buffer = llGetSubString(src = llInsertString(llDeleteSubString(src, b_pos -= to_pos, b_pos + len), b_pos, to), (-~(b_pos += to_len)), 0x8000);
jump loop;
}
}
return src;
}

default
{
state_entry()
{
//Get the intial URL
llRequestURL();
}

http_request(key id, string method, string body)
{
if (method == URL_REQUEST_GRANTED)
{
//URL granted
llOwnerSay(body);
url = body;
return;
}
//getting the notecard name
string x_path_info = llGetHTTPHeader(id,"x-path-info");
//Trimming off the /
if (llGetSubString(x_path_info,0,0) == "/")
x_path_info = llGetSubString(x_path_info,1,-1);
//Setting the default page if no page was passed
if (x_path_info == "")
x_path_info = defaultPage;

//Check to see if the notecard exists. If it does not throw 404 Error
if (llGetInventoryType(x_path_info) != INVENTORY_NOTECARD)
{
llHTTPResponse(id,404,"The page " + x_path_info + " does not exists.");
return;
}

//adding these values to the list so they can be used in dataserver
RequestPage += [x_path_info];
Response += [""];
RequestForm += [body];
Request += [llGetHTTPHeader(id, "x-query-string")];
HTTPRequests += [id];
HTMLReadLine += [1];
HTMLReadKey += llGetNotecardLine(x_path_info,0);
}

changed(integer change)
{
if (CHANGED_REGION_START & change)
llRequestURL();
}

dataserver(key query_id, string data)
{
integer inQ = llListFindList(HTMLReadKey, [query_id]);
if (inQ > -1)
{
if (data == EOF)
{
//Cleaning up
llHTTPResponse(llList2Key(HTTPRequests,inQ), 200, llList2String(Response,inQ));
Response = llListReplaceList(Response, [], inQ, inQ);
RequestForm = llListReplaceList(RequestForm, [], inQ, inQ);
Request = llListReplaceList(Request, [], inQ, inQ);
HTTPRequests = llListReplaceList(HTTPRequests, [], inQ, inQ);
HTMLReadLine = llListReplaceList(HTMLReadLine, [], inQ, inQ);
HTMLReadKey = llListReplaceList(HTMLReadKey, [], inQ, inQ);
RequestPage = llListReplaceList(RequestPage, [], inQ, inQ);
}
else
{
//reparse the query string and replace [@QUERYSTRING_NAME] with QUERYSTRINGVALUE
list tempRequest = llParseString2List(llList2String(Request,inQ), ["&"], []) + llParseString2List(llList2String(RequestForm,inQ), ["&"], []);
integer requestLength = llGetListLength(tempRequest);integer i = -1;
list formFields = [];
list formValues = [];
while(requestLength > ++i)
{
list tempRequestField = llParseString2List(llList2String(tempRequest,i), ["="], []);
formFields += llList2String(tempRequestField,0);
formValues += llList2String(tempRequestField,1);
data = str_replace(data, "[@" + llUnescapeURL(llList2String(tempRequestField,0)) + "]", llUnescapeURL(llList2String(tempRequestField,1)));
}

string raw = llToUpper(str_replace(data, " ",""));
//Checking to see if this line is an if statement
if (llGetSubString(raw,0,3) == "[IF(")
{
//parseing the if line for details
integer statement = FALSE;
integer close = llSubStringIndex(raw, ")]");
if (close > -1)
{
string test = llGetSubString(raw, 4, close - 1);
if (llSubStringIndex(test, "==") > -1)
{
list tempList = llParseString2List(test, ["=="], []);
if (llList2String(tempList,0) == llList2String(tempList,1))
statement = TRUE;
}
else if (llSubStringIndex(test, ">=") > -1)
{
list tempList = llParseString2List(test, [">="], []);
if (llList2Float(tempList,0) >= llList2Float(tempList,1))
statement = TRUE;
}
else if (llSubStringIndex(test, "<=") > -1)
{
list tempList = llParseString2List(test, ["<="], []);
if (llList2Float(tempList,0) <= llList2Float(tempList,1))
statement = TRUE;
}
else if (llSubStringIndex(test, ">") > -1)
{
list tempList = llParseString2List(test, [">"], []);
if (llList2Float(tempList,0) > llList2Float(tempList,1))
statement = TRUE;
}
else if (llSubStringIndex(test, "<") > -1)
{
list tempList = llParseString2List(test, ["<"], []);
if (llList2Float(tempList,0) < llList2Float(tempList,1))
statement = TRUE;
}
}
if (statement)
{
string toDo = llGetSubString(raw, close + 1, -1);
if (llSubStringIndex(toDo,"LINE=") == 1)
{
HTMLReadLine = llListReplaceList(HTMLReadLine, [llGetSubString(toDo,6,-1)], inQ, inQ);
llOwnerSay(llList2String(HTMLReadLine,inQ));
}
}
data = "";
}
else
{
data += "\n";
}
//Reading the next line in the notecard
Response = llListReplaceList(Response, [llList2String(Response,inQ) + data], inQ, inQ);
HTMLReadKey = llListReplaceList(HTMLReadKey, [llGetNotecardLine(llList2String(RequestPage,inQ),llList2Integer(HTMLReadLine,inQ))],inQ,inQ);
HTMLReadLine = llListReplaceList(HTMLReadLine, [llList2Integer(HTMLReadLine,inQ) + 1], inQ, inQ);
}
}
}
}


Here is a notecard Example:
CODE

Welcome. [@test]
[if ([@test] == HELLO)] Line = 5
a
b
c
d
e
f
g
h
bye
CODE


Just trying to win all your hearts back lol :D
Darien Caldwell
Registered User
Join date: 12 Oct 2006
Posts: 3,127
07-30-2009 09:12
Aww don't worry, Nobody thinks ill of you. Thanks for the code. :)
_____________________
Meade Paravane
Hedgehog
Join date: 21 Nov 2006
Posts: 4,845
07-30-2009 09:34
Neat!
_____________________
Tired of shouting clubs and lucky chairs? Vote for llParcelSay!!!
- Go here: http://jira.secondlife.com/browse/SVC-1224
- If you see "if you were logged in.." on the left, click it and log in
- Click the "Vote for it" link on the left
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
07-30-2009 10:06
For those reading the code who might not understand extreme shorthand "tricks":

~-n is the same as (n-1)
-~n is the same as (n+1)
~n is the same as -(n+1)
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
07-30-2009 10:13
You might want to consider putting a complete recursive-descent parser in that.

I posted one to one of the scripting forums several months ago, but I can't find it now.
_____________________
Argent Stonecutter - http://globalcausalityviolation.blogspot.com/

"And now I'm going to show you something really cool."

Skyhook Station - http://xrl.us/skyhook23
Coonspiracy Store - http://xrl.us/coonstore