Difference between revisions of "User:Ama Omega/archive/lsl hacks"

From Second Life Wiki
Jump to navigation Jump to search
Line 147: Line 147:
=== The Magic ===
=== The Magic ===
* You can set the script HTTP-In url as the form action to get the results of the form sent back to the script
* You can set the script HTTP-In url as the form action to get the results of the form sent back to the script
// example LSL
<lsl>
string html_base =
"<h1><form action='%url%' method='GET'>
Floating Text:<input type='text' name='text'><br>
<input type='submit' value='Set'>
</form></h1>";
 
string url;
 
integer r;
show(string html)
{
    html = "data:text/html," + llEscapeURL(html) + "<span " + (string)((++r) % 10) + "/>";
   
    llSetPrimMediaParams(0,                                // Side to display the media on.
            [PRIM_MEDIA_AUTO_PLAY,TRUE,      // Show this page immediately
            PRIM_MEDIA_CURRENT_URL,html,    // The url if they hit 'home'
            PRIM_MEDIA_HOME_URL,html,      // The url currently showing
            PRIM_MEDIA_HEIGHT_PIXELS,512,  // Height/width of media texture will be
            PRIM_MEDIA_WIDTH_PIXELS,512]);  //  rounded up to nearest power of 2.
}
 
string replace_all(string src, string target, string replace)
{
    return llDumpList2String(llParseString2List(src,[target],[]),replace);
}
 
string get_query(key id, string name)
{
    string query = llGetHTTPHeader(id,"x-query-string");
    query = replace_all(query,"+"," ");
    query = llUnescapeURL(query);
    list q = llParseString2List(query,["=","&",";"],[]);
    integer i = llListFindList(q,[name]);
    if (i != -1)
    {
        return llList2String(q,i+1);
    }
   
    return "";
}
 
default
{
    state_entry()
    {
        show("<h1>This is a test</h1><h2>This is a test</h2><h3>This is a test</h3>");
        llRequestURL();
    }
   
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            url = body + "/";
           
            show(replace_all(html_base,"%url%",url));
        }
        else if (method == "GET")
        {
            llSetText(get_query(id,"text"),<1,1,0>,1);
            show(replace_all(html_base,"%url%",url));
            llHTTPResponse(id,200,"Loading....");
        }
    }
}
</lsl>
 
=== The Limits ===
=== The Limits ===
* 1024 bytes per url
* 1024 bytes per url

Revision as of 16:25, 26 February 2010

Shared Media and HTTP-In

One step at a time .......

llSetPrimMediaParams

  • Use llSetPrimMediaParams to set the url and various parameters on the face of a prim via LSL.

<lsl> default {

   state_entry()
   {
       llSetPrimMediaParams(0,                             // Side to display the media on.
           [PRIM_MEDIA_AUTO_PLAY,TRUE,      // Show this page immediately
            PRIM_MEDIA_CURRENT_URL,"http://google.com",    // The url if they hit 'home'
            PRIM_MEDIA_HOME_URL,"http://google.com",       // The url currently showing
            PRIM_MEDIA_HEIGHT_PIXELS,512,                  // Height/width of media texture will be
            PRIM_MEDIA_WIDTH_PIXELS,512]);                 //   rounded up to nearest power of 2.
   }

} </lsl>

data: urls

There is a special url type: "data:" that lets you send the html *in the url*. Paste the below into your browser's address bar.

data:text/html,<h1>This is a test</h1><h2>This is a test</h2><h3>This is a test</h3>

llSetPrimMediaParams for data: urls

  • Thus you can build arbitrary html in your LSL script and display it on the face of the prim

<lsl> show(string html) {

   html = "data:text/html," + llEscapeURL(html);
   llSetPrimMediaParams(0,                                 // Side to display the media on.
           [PRIM_MEDIA_AUTO_PLAY,TRUE,      // Show this page immediately
            PRIM_MEDIA_CURRENT_URL,html,    // The url if they hit 'home'
            PRIM_MEDIA_HOME_URL,html,       // The url currently showing
            PRIM_MEDIA_HEIGHT_PIXELS,512,   // Height/width of media texture will be
            PRIM_MEDIA_WIDTH_PIXELS,512]);  //   rounded up to nearest power of 2.

} default {

   state_entry()
   {

show("

This is a test

This is a test

This is a test

");

   }

} </lsl>

HTTP-In

  • Scripts can become web servers via HTTP-In(link)

<lsl> default {

   state_entry()
   {
       llRequestURL();
   }
   
   http_request(key id, string method, string body)
   {
       if (method == URL_REQUEST_GRANTED)
       {
           llSay(0,"URL is: " + body);
       }
       else if (method == "GET")
       {
           llSay(0,"Received page request.");
           llHTTPResponse(id,200,"OK");
       }
   }

} </lsl>

llSetPrimMediaParams for data: urls that link back to HTTP-In

  • Which means you can make web pages that trigger other page views via http-in links

<lsl> show(string html) {

   html = "data:text/html," + llEscapeURL(html);
   llSetPrimMediaParams(0,                                 // Side to display the media on.
           [PRIM_MEDIA_AUTO_PLAY,TRUE,      // Show this page immediately
            PRIM_MEDIA_CURRENT_URL,html,    // The url if they hit 'home'
            PRIM_MEDIA_HOME_URL,html,       // The url currently showing
            PRIM_MEDIA_HEIGHT_PIXELS,512,   // Height/width of media texture will be
            PRIM_MEDIA_WIDTH_PIXELS,512]);  //   rounded up to nearest power of 2.

}

string replace_all(string src, string target, string replace) {

   return llDumpList2String(llParseString2List(src,[target],[]),replace);

}

string get_query(key id, string name) {

   string query = llGetHTTPHeader(id,"x-query-string");
   query = replace_all(query,"+"," ");
   query = llUnescapeURL(query);
   list q = llParseString2List(query,["=","&",";"],[]);
   integer i = llListFindList(q,[name]);
   if (i != -1)
   {
       return llList2String(q,i+1);
   }
   
   return "";

}

default {

   state_entry()
   {

show("

This is a test

This is a test

This is a test

");

       llRequestURL();
   }
   
   http_request(key id, string method, string body)
   {
       if (method == URL_REQUEST_GRANTED)
       {

show("

<a href='" + body + "/?get=owner'>Owner ID</a>

<a href='" + body + "/?get=object'>Object ID</a>

");

       }
       else if (method == "GET")
       {
           string get = get_query(id,"get");
           if (get == "owner")
           {
               llHTTPResponse(id,200,"Owner is: " + (string)llGetOwner());
           }
           else if (get == "object")
           {
               llHTTPResponse(id,200,"Object is: " + (string)llGetKey());
           }
           else
           {            
               llHTTPResponse(id,400,"huh?");
           }
       }
   }

} </lsl>

Forms

  • You can put forms in data: urls
data:text/html,<form action="http://google.com" method="GET">Search:<input type="text" name="search"><input type="submit" value="Submit"></form>

The Magic

  • You can set the script HTTP-In url as the form action to get the results of the form sent back to the script

<lsl> string html_base =

"

<form action='%url%' method='GET'> Floating Text:<input type='text' name='text'>
<input type='submit' value='Set'> </form>

";

string url;

integer r; show(string html) {

   html = "data:text/html," + llEscapeURL(html) + "";
   
   llSetPrimMediaParams(0,                                 // Side to display the media on.
           [PRIM_MEDIA_AUTO_PLAY,TRUE,      // Show this page immediately
            PRIM_MEDIA_CURRENT_URL,html,    // The url if they hit 'home'
            PRIM_MEDIA_HOME_URL,html,       // The url currently showing
            PRIM_MEDIA_HEIGHT_PIXELS,512,   // Height/width of media texture will be
            PRIM_MEDIA_WIDTH_PIXELS,512]);  //   rounded up to nearest power of 2.

}

string replace_all(string src, string target, string replace) {

   return llDumpList2String(llParseString2List(src,[target],[]),replace);

}

string get_query(key id, string name) {

   string query = llGetHTTPHeader(id,"x-query-string");
   query = replace_all(query,"+"," ");
   query = llUnescapeURL(query);
   list q = llParseString2List(query,["=","&",";"],[]);
   integer i = llListFindList(q,[name]);
   if (i != -1)
   {
       return llList2String(q,i+1);
   }
   
   return "";

}

default {

   state_entry()
   {

show("

This is a test

This is a test

This is a test

");

       llRequestURL();
   }
   
   http_request(key id, string method, string body)
   {
       if (method == URL_REQUEST_GRANTED)
       {
           url = body + "/";
           
           show(replace_all(html_base,"%url%",url));
       }
       else if (method == "GET")
       {
           llSetText(get_query(id,"text"),<1,1,0>,1);
           show(replace_all(html_base,"%url%",url));
           llHTTPResponse(id,200,"Loading....");
       }
   }

} </lsl>

The Limits

  • 1024 bytes per url
  • llEscapeURLs means non-alphanumeric characters are 3 bytes (ouch)
  • Must force another page view after form submission since HTTP-In can't generate HTML

The Tricks

  • <base href="<http-in-url>/">
  • Tiny urls