Lslsimcaps

From Second Life Wiki
Jump to navigation Jump to search

Example accessing login and capabilities with LSL. The script posts login parameters to the login server, and in response gets a seed_capability for the simulator it would connect to. The script posts a an LLSD array of desired capabilities to this seed_capability (in this case, only the MapLayer capability is desired) and gets back an LLSD map of capability uri's. Finally, the script posts parameters to its MapLayer capability uri and gets the MapLayer response, which is dumped to chat.

string PARSE_SEED_CAPABILITY = "<member><name>seed_capability</name><value><string>";
string PARSE_MAPLAYER = "<key>MapLayer</key><string>";


string LOGINURI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
string FIRSTNAME = "MrsDay";
string LASTNAME = "Oh";
string PASSWD = "password";
string START = "home";


key http_reqid;
integer http_func;
integer HTTP_FUNC_NONE = 0;
integer HTTP_FUNC_LOGIN = 1;
integer HTTP_FUNC_CAPABILITIES = 2;
integer HTTP_FUNC_MAPLAYER = 3;



//////////////////////////////////////////////////////////////////////////////////////
//
//	UTF-8 MD5
//	Version 1.0 Alpha
//	ESL Compiled: "Dec  2 2007", "02:03:06"
//	Copyright (C) 2007  Strife Onizuka
//	Based on Pseudo-code from http://en.wikipedia.org/wiki/MD5
//	
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public License
//	as published by the Free Software Foundation;
//	version 3 of the License.
//	
//	This library is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Lesser General Public License for more details.
//	
//	You should have received a copy of the GNU Lesser General Public License
//	along with this library.  If not, see <http://www.gnu.org/licenses/>
//	or write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
//	Boston, MA  02111-1307  USA
//	
//////////////////////////////////////////////////////////////////////////////////////

//===================================================//
//                 Combined Library                  //
//             "Dec  2 2007", "02:03:06"             //
//  Copyright (C) 2004-2007, Strife Onizuka (cc-by)  //
//    http://creativecommons.org/licenses/by/3.0/    //
//===================================================//
//{

//Functions marked "Mono Safe" are safe for use in LSLEditor & Mono
//Functions marked "LSO Safe" are safe for use in LSO
//Functions marked "Double Safe" are safe for use in VM's that support doubles (Mono, LSLEditor).
//Mono is the future VM for LSL, LSO is the current VM of LSL.
//To achieve safety, the functions require more bytecode and sacrifice a bit of performance.

string TrimRight(string src, string chrs)//Mono Safe, LSO Safe
{
    integer i = llStringLength(src);
    integer j = i;
    do ; while(~llSubStringIndex(chrs, llGetSubString(src, i = (~-(j = i)), i)) && j);
    return llDeleteSubString(src, j, 0xFFFF);
}

string hexc="0123456789abcdef";

//} Combined Library

list r1 = [7, 12, 17, 22];
list r2 = [5,  9, 14, 20];
list r3 = [4, 11, 16, 23];
list r4 = [6, 10, 15, 21];

list k1 = [
    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821];
list k2 = [
    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a];
list k3 = [
    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665];
list k4 = [
    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391];

string UTF8_MD5(string plain) { 
    integer H1 = 1732584193;
    integer H2 = -271733879;
    integer H3 = -1732584194;
    integer H4 = 271733878;

    //OR on the extra bit.
    integer j = llStringLength(plain) << 3;
    integer b = (~-(((j + 552) & -512) >> 5));
    integer T = llBase64ToInteger((TrimRight(llGetSubString(plain = llStringToBase64(plain), -4, -1),"=")) + "AAAA");
    string buf = "AAA";
    integer i = -5;
    do buf += buf; while((i = -~i));
    if(j)
    {
        i = 0x800000;
        if(T & 0xFF00)
            i = 0x00000080;
        else if(T & 0xFF0000)
            i = 0x00008000;
    }
    else
        T = 0x80000000;//T is corrupt because of https://jira.secondlife.com/browse/SVC-104
//    llOwnerSay(llList2CSV([i,j]));
    plain = llGetSubString( llDeleteSubString(plain, -4, -1) + 
                            llGetSubString(llIntegerToBase64(T | i), 0, 5) + 
                            buf, 0, ((b << 4) / 3) - 7) + 
            llGetSubString(llIntegerToBase64((((j & 0xFF) << 20) | ((j & 0xFF00) << 4) | ((j >> 12) & 0xFF0) | ((j >> 28) & 0xF)) >> ((b % 3) << 1)), 0, 5) + 
            "AAAAAAAA";
    integer S = i = 0;
    list x;
    do
    {
        integer A = H1;
        integer B = H2;
        integer C = H3;
        integer D = H4;
        j = 0;
        x = [];
        do
        {
            T = llBase64ToInteger(buf = llGetSubString(plain, T = ((i + j) << 4) / 3, T+6)) << (S = (((i + j) % 3) << 1));
            if(S)
                T = T | (llBase64ToInteger("A" + (llDeleteSubString(buf, 0, 1))) >> (6 - S));
            x += (T = (((T & 0xFF) << 24) | ((T & 0xFF00) << 8) | ((T >> 8) & 0xFF00) | ((T >> 24) & 0xFF)));

            S = A + llList2Integer(k1, j) + T + (D ^ (B & (C ^ D)));
            T = llList2Integer(r1, j & 3);
            A = D;
            D = C;
            C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
        }
        while(16 > (j = -~j));
        do
        {
            S = A + llList2Integer(k2, j & 15) + (C ^ (D & (B ^ C))) + llList2Integer(x, (5 * j + 1) & 15);
            T = llList2Integer(r2, j & 3);
            A = D;
            D = C;
            C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
        }
        while(32 > (j = -~j));
        do
        {
            S = A + llList2Integer(k3, j & 15) + (B ^ C ^ D) + llList2Integer(x, (3 * j + 5) & 15);
            T = llList2Integer(r3, j & 3);
            A = D;
            D = C;
            C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
        }
        while(48 > (j = -~j));
        do
        {
            T = llList2Integer(r4, j & 3);
            S = A + llList2Integer(k4, j & 15) + (C ^ (B | (~D))) + llList2Integer(x, (7 * j) & 15);
            A = D;
            D = C;
            C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
        }
        while(64 > (j = -~j));
//        llOwnerSay(llList2CSV(x));
        H1 += A;
        H2 += B;
        H3 += C;
        H4 += D;
    }while(b > (i += 16));
    x = [H4, H3, H2, H1];
    i = -4;
    buf = "";
    do
    {
        T = llList2Integer(x,i);
        j = 32;
        do
            buf = llGetSubString(hexc, b = ((T >> (j - 4)) & 0xF), b) + llGetSubString(hexc, b = ((T >> (j - 8)) & 0xF), b) + buf;
        while ((j -= 8));
    }while ((i = -~i));
    return buf;
}

LongStringDump(string str)
{
    string chop;
    while(llStringLength(str) > 1023)
    {
        chop = llGetSubString(str, 0, 1022);
        llOwnerSay(chop);
        str = llGetSubString(str, 1023, -1);
    }
    if(llStringLength(str))
        llOwnerSay(str);
}

key Login(string firstName, string lastName, string passwd, string start)
{
    string xml = "<?xml version=\"1.0\"?>
<methodCall>
    <methodName>login_to_simulator</methodName>
    <params>
        <param>
            <value>
                <struct>
                    <member><name>first</name><value><string>" + firstName + "</string></value></member>
                    <member><name>last</name><value><string>" + lastName + "</string></value></member>
                    <member><name>passwd</name><value><string>" + "$1$" + UTF8_MD5(passwd) + "</string></value></member>
                    <member><name>start</name><value><string>" + start + "</string></value></member>
                    <member><name>major</name><value><string>1</string></value></member>
                    <member><name>minor</name><value><string>18</string></value></member>
                    <member><name>patch</name><value><string>4</string></value></member>
                    <member><name>build</name><value><string>3</string></value></member>
                    <member><name>mac</name><value><string>00:00:00:00:00:00</string></value></member>
                </struct>
            </value>
        </param>
    </params>
</methodCall>";
    return llHTTPRequest(LOGINURI, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "text/xml"], xml);
}



default
{
    touch_start(integer t)
    {
        key owner = llGetOwner();
        integer i;
        for(i = 0; i < t; i++)
        {
            if(llDetectedKey(i) == owner)
            {
                llOwnerSay("Login begins...");
                http_func = HTTP_FUNC_LOGIN;
                http_reqid = Login(FIRSTNAME, LASTNAME, PASSWD, START);
            }
        }
    }

    http_response(key reqid, integer status, list metadata, string body)
    {
        if(reqid != http_reqid)
            return;
            
        llOwnerSay("--- begin ---");
        llOwnerSay("status: " + (string)status);
        llOwnerSay("metadata: " + llList2CSV(metadata));
        LongStringDump(body);
        llOwnerSay("--- end ---");
        
        
        if(http_func == HTTP_FUNC_LOGIN)
        {
            integer index = llSubStringIndex(body, PARSE_SEED_CAPABILITY);
            if(index == -1)
            {
                llOwnerSay("Couldn't parse out seed_capability");
            }
            else
            {
                string buffer = llGetSubString(body, index + llStringLength(PARSE_SEED_CAPABILITY), -1);
                integer index = llSubStringIndex(buffer, "</string>");
                string uri = llGetSubString(buffer, 0, index - 1);
                llOwnerSay("Requesting " + uri);
                http_func = HTTP_FUNC_CAPABILITIES;
                http_reqid = llHTTPRequest(uri, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "text/html"], "<llsd><array><string>MapLayer</string></array></llsd>");
            }
        }
        else if(http_func == HTTP_FUNC_CAPABILITIES)
        {
            integer index = llSubStringIndex(body, PARSE_MAPLAYER);
            if(index == -1)
            {
                llOwnerSay("Couldn't parse out capability for MapLayer");
            }
            else
            {
                string buffer = llGetSubString(body, index + llStringLength(PARSE_MAPLAYER), -1);
                integer index = llSubStringIndex(buffer, "</string>");
                string uri = llGetSubString(buffer, 0, index - 1);
                string llsd = "<llsd><map><key>flags</key><integer>0</integer></map></llsd>";
                llOwnerSay("Requesting " + uri);
                http_func = HTTP_FUNC_MAPLAYER;
                http_reqid = llHTTPRequest(uri, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "text/html"], llsd);
            }
        }
        
    }
}