From Second Life Wiki
Jump to: navigation, search



LSLurl (domain do not response atm) is a Dynamic DNS service focused primarily on the in-world script event, http_request (Article: LSL_http_server). LSLurl provides an extensively featured and flexible API system and the solution to URL Lifetime Limitations. LSLurl also provides an online dynamic storage database. Domains and their content can be created, updated, and deleted via in-world scripts. Users of LSLurl are provided with numerous options for customizing their domains. Optionally, API keys are provided to utterly secure users' domains from unwanted access.


  • Optional API-key security (Viewing and/or editing)
  • Permanent domains
  • Optional temporary domains (6 hour prune interval)
  • Create, edit, delete, and search domains via in-world scripts
  • Online storage database
  • Automatic URL Parsing ("\n", spaces, ANSII characters, etc.)
  • Web-based control panel & account management
  • Domain types: URL (redirects) and DATA (stores data)
  • Unlimited domains
  • Unlimited subdomains

Future features:

Getting Started

IMPORTANT: Closed beta.

To begin using LSLurl, visit an in-world terminal. By clicking the in-world terminal, you will be given a password to use at LSLurl. Log in with your Second Life username and the password given.

Creating a domain

LSLurl User Stats
To create a domain, you must first be logged in. Click the 'Create a new domain' link as shown in the image.
LSLurl Domain Creation
Creating a domain is essentially direct. Simply fill out the creation form and click 'Create'. Sub-domains created via in-world scripts will inherit the settings as the main domain by default.

Note: API keys are limited to 32 characters, and the characters: 'a-z', '0-9', '-', and '_'.

Domain Types

Domains are either one of the two types: DATA or URL. DATA is used for text storage. The domain will return the text of the domain's value. URL is used for in-world http servers as a static URL proxy (or redirect) and solving the URL Lifetime Limitation.

In-world Usage

The LSLurl API system is composed of two scripts. The LSLurl API script, and the core script that handles all of the HTTP-related functions.

Script API

LSLurl API v0.26 by The Wikifoo <lsl>//LSLurl API v. 0.26 BETA

string MY_DOMAIN = "test"; string MY_APIKEY = ""; string MY_TYPE = ""; //URL or DATA. By leaving this blank you will not update the type.

string lslurl_cmd(string command,string domain,string value,string apikey,string type) {

   response: response acts like a callback identifier which is used to identify the response from your requests
   url:      the domain you're trying to perform an action to. (only the domain name, i.e., 'test' (without the quotes)
             subdomains works too, however, you will have to use, 'test.subdomain' (again, without the quotes)
   value:    whatever value you want to set in your domain
   apikey:   your private apikey - only required if you have "require apikey" in read- or writemode.
   type:     set your urls type to DATA or URL. leaving it blank will not update the type.
   string response = llMD5String((string)llGetUnixTime() + (string)llGetTime() + (string)llFrand(100.0),0);
   if(apikey == "") apikey = MY_APIKEY;
   else if(~llSubStringIndex(domain,".")) apikey = lslurl_sub(domain,apikey);
   return response; }

string lslurl_sub(string subdomain,string apikey) {

   if(~llSubStringIndex(subdomain,".")) subdomain = llGetSubString(subdomain,llSubStringIndex(subdomain,".")+1,-1);
   return llMD5String(apikey+subdomain,0); }

string lslurl(string domain,string subdomain,string apikey) {

   if(apikey != "") apikey = "/" + llEscapeURL(apikey);
   domain = llEscapeURL(domain);
   if(subdomain) domain += "." + llEscapeURL(subdomain);
   return ""+domain+apikey; }

string my_test_callback_string; string my_create_callback_string; string my_update_callback_string;

default {

   state_entry() {
       //This is a dummy test domain; let's try update its value:
       my_test_callback_string = lslurl_cmd("UPDATE_VALUE",MY_DOMAIN,"Hello, world!","",MY_TYPE);
       //Let's create a subdomain too
       my_create_callback_string = lslurl_cmd("CREATE_SUB",MY_DOMAIN+".hello","Have to call update-sub RIGHT after.","",MY_TYPE);
       //Update (ALWAYS call this right after creating a sub (note the MY_APIKEY!)):
       my_update_callback_string = lslurl_cmd("CREATE_SUB",MY_DOMAIN+".hello","Ohai there!",MY_APIKEY,MY_TYPE);
       llOwnerSay("You can view the dummy test domains here: "+lslurl(MY_DOMAIN,"",MY_APIKEY)+" and "+lslurl(MY_DOMAIN,"hello",MY_APIKEY));
   link_message(integer sender,integer num,string str,key id) {
       if(num == 501) {
           string response = (string)id;
           if(response == my_test_callback_string) {
               llOwnerSay("This is the response from the request: "+str);
           else if(response == my_create_callback_string) {
               llOwnerSay("This is the response from the CREATE_SUB: "+str);
           else if(response == my_update_callback_string) {
               llOwnerSay("This is the response from the CREATE_SUB (update): "+str);

}</lsl> LSLurl Core v0.25 by The Wikifoo <lsl>//LSLurl API v. 0.25 BETA

//This shouldn't be edited, really.

integer debug = FALSE;

list cache;

string current_url; string current_key; string current_has; string current_val; string current_typ;

string response;

string mainurl = ""; string seturl = "/s/"; //set string geturl = "/i/"; //get string finurl = "/f/"; //find string delurl = "/d/"; //delete

url_do(string what) { //what being set-, get-, or finurl

   if(current_key != "") current_key = "/" + current_key;
   //if(current_val != "") current_val = "/" + llEscapeURL(current_val);
   if(current_typ != "") current_typ = "TYPE="+llToUpper(current_typ);
   if(current_val != "") { 
       current_val = "VALUE=" + llEscapeURL(current_val); 
       if(current_typ != "") current_val = "&" + current_val;
   http(mainurl + what + llToLower(current_url) + current_key); // + current_val);


http(string url) {

   if(debug) llOwnerSay("DEBUG REQUEST: "+url);
   key request = llHTTPRequest(url,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],current_typ+current_val);
   cache += [request, response];


default {

   link_message(integer sender,integer num,string str,key id) {
       if(num == 500) {
           list t = llCSV2List(str);
           response    = llList2String(t,0);
           str         = llList2String(t,1);
           current_url = llList2String(t,2);
           current_val = (string)id;//llList2String(t,3);
           current_key = llList2String(t,4);
           current_has = llList2String(t,5);
           current_typ = llList2String(t,6);
           if(str == "UPDATE_VALUE" || str == "CREATE_SUB") url_do(seturl);
           else if(str == "GET_VALUE")                      url_do(geturl);
           else if(str == "FIND_DOMAIN")                    url_do(finurl);
           else if(str == "DELETE_DOMAIN")                  url_do(delurl);
           llSetTimerEvent(120.0); //reset cache in two minutes, in case the http_response fails
   http_response(key query,integer status,list metadata,string body) {
       integer pos = llListFindList(cache,[query]);
       if(~pos) {
           if(debug) llOwnerSay("DEBUG RESPONSE: "+body);
           cache = llDeleteSubList(cache,pos,pos+1);
           //Current possible error responses (probably forgot to add some.):
           // ---------------------------------
           // cap not found: 'SOME UUID HERE'
           // error: value is write-only, need key
           // error: can't write, data is static
           // error: can't create sub, master is static
           // error: name too long, max length is %MAX LENGTH%
           // error: master value is write-only, need key
           // error: unknown master write-level (%NUM%)
           // error: unknown write-level (%NUM%)
           // error: %NAME% doesn't exist
           // error: invalid name, can't create
           // error: could not find domain
           // error: invalid apikey
           // error: can only delete subs
           // deleted
           // updated
           // created
           // ---------------------------------
   timer() { cache = []; }