Difference between revisions of "Lslsimcaps"

From Second Life Wiki
Jump to navigation Jump to search
(New page: Example accessing login and sim caps with LSL. The script posts login parameters to the login server, and in response gets a seed capability for the simulator it would co...)
 
(Fixed format.)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Example accessing login and sim caps with LSL.  The script posts login parameters to the login server, and in response gets a seed [[Capabilities|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_CAP|MapLayer capability]] is desired) and gets back an LLSD map of capability uri's.  Finally, the script posts parameters to MapLayer capability uri and gets the MapLayer response, which is dumped to chat.
Example accessing [[Current_login_protocols|login]] and [[Capabilities|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_CAP|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.


<pre>string PARSE_SEED_CAPABILITY = "<member><name>seed_capability</name><value><string>";
<source lang="lsl2">string PARSE_SEED_CAPABILITY = "<member><name>seed_capability</name><value><string>";
string PARSE_MAPLAYER = "<key>MapLayer</key><string>";
string PARSE_MAPLAYER = "<key>MapLayer</key><string>";


Line 17: Line 17:
integer HTTP_FUNC_LOGIN = 1;
integer HTTP_FUNC_LOGIN = 1;
integer HTTP_FUNC_CAPABILITIES = 2;
integer HTTP_FUNC_CAPABILITIES = 2;
integer HTTP_FUNC_UPDATENOTECARDAGENTINVENTORY = 3;
integer HTTP_FUNC_MAPLAYER = 3;
integer HTTP_FUNC_MAPLAYER = 4;




string hexc="0123456789abcdef";
string byte2hex(integer x)
{
    return llGetSubString(hexc, x = ((x >> 4) & 0xF), x) + llGetSubString(hexc, (x & 0xF), (x & 0xF));
}
string UnicodeIntegerToUTF8(integer a)
{
    if(a <= 0) return "";//unicode & utf8 only support 2^31 characters, not 2^32; so no negitives.
    integer b = (a >= 0x80) + (a >= 0x800) + (a >= 0x10000) + (a >= 0x200000) + (a >= 0x4000000);
    string c = "%" + byte2hex((a >> (6 * b)) | ((0x7F80 >> b) << !b));
    while(b)
        c += "%" + byte2hex((((a >> (6 * (b=~-b))) | 0x80) & 0xBF));
    return llUnescapeURL(c);
}


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


//===================================================//
//===================================================//
//                Combined Library                  //
//                Combined Library                  //
//            "Nov 25 2007", "20:51:14"            //
//            "Dec  2 2007", "02:03:06"            //
//  Copyright (C) 2004-2007, Strife Onizuka (cc-by)  //
//  Copyright (C) 2004-2007, Strife Onizuka (cc-by)  //
//    http://creativecommons.org/licenses/by/3.0/    //
//    http://creativecommons.org/licenses/by/3.0/    //
Line 83: Line 65:
     integer i = llStringLength(src);
     integer i = llStringLength(src);
     integer j = i;
     integer j = i;
     do;while(~llSubStringIndex(chrs, llGetSubString(src, i = (~-(j = i)), i)) && j);
     do ; while(~llSubStringIndex(chrs, llGetSubString(src, i = (~-(j = i)), i)) && j);
     return llDeleteSubString(src, j, 0xFFFF);
     return llDeleteSubString(src, j, 0xFFFF);
}
}
string hexc="0123456789abcdef";


//} Combined Library
//} Combined Library
list k1 = [ -680876936,  -389564586,  606105819, -1044525330,  -176418897,  1200080426, -1473231341,  -45705983,
            1770035416, -1958414417,      -42063, -1990404162,  1804603682,  -40341101, -1502002290,  1236535329];
list k2 = [ -165796510, -1069501632,  643717713,  -373897302,  -701558691,    38016083,  -660478335,  -405537848,
            568446438, -1019803690,  -187363961,  1163531501, -1444681467,  -51403784,  1735328473, -1926607734];
list k3 = [    -378558, -2022574463,  1839030562,  -35309556, -1530992060,  1272893353,  -155497632, -1094730640,
            681279174,  -358537222,  -722521979,    76029189,  -640364487,  -421815835,  530742520,  -995338651];
list k4 = [ -198630844,  1126891415, -1416354905,  -57434055,  1700485571, -1894986606,    -1051523, -2054922799,
            1873313359,  -30611744, -1560198380,  1309151649,  -145523070, -1120210379,  718787259,  -343485551];


list r1 = [7, 12, 17, 22];
list r1 = [7, 12, 17, 22];
list r2 = [5,  9, 14, 20];
list r2 = [5,  9, 14, 20];
list r3   = [4, 11, 16, 23];
list r3 = [4, 11, 16, 23];
list r4 = [6, 10, 15, 21];
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) {
string UTF8_MD5(string plain) {  
     integer H1 = 1732584193;
     integer H1 = 1732584193;
     integer H2 = -271733879;
     integer H2 = -271733879;
Line 114: Line 100:
     integer j = llStringLength(plain) << 3;
     integer j = llStringLength(plain) << 3;
     integer b = (~-(((j + 552) & -512) >> 5));
     integer b = (~-(((j + 552) & -512) >> 5));
     integer T = llBase64ToInteger(llGetSubString((TrimRight(llGetSubString(plain = llStringToBase64(plain), -4, -1),"=")) + "AAAAAAAA", 0, 7));
     integer T = llBase64ToInteger((TrimRight(llGetSubString(plain = llStringToBase64(plain), -4, -1),"=")) + "AAAA");
     string buf = "AAA";
     string buf = "AAA";
     integer i = -5;
     integer i = -5;
Line 142: Line 128:
         integer C = H3;
         integer C = H3;
         integer D = H4;
         integer D = H4;
         integer F = j = 0;
         j = 0;
         x = [];
         x = [];
         do
         do
         {
         {
             T = llBase64ToInteger((buf = llGetSubString(plain, T = ((i + j) << 4) / 3, T+6)) + "A") << (S = (((i + j) % 3) << 1));
             T = llBase64ToInteger(buf = llGetSubString(plain, T = ((i + j) << 4) / 3, T+6)) << (S = (((i + j) % 3) << 1));
             if(S)
             if(S)
                 T = T | (llBase64ToInteger("A" + (llDeleteSubString(buf, 0, 1)) + "AA") >> (6 - 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)));
             x += (T = (((T & 0xFF) << 24) | ((T & 0xFF00) << 8) | ((T >> 8) & 0xFF00) | ((T >> 24) & 0xFF)));


             F = A + llList2Integer(k1, j) + T + (D ^ (B & (C ^ D)));
             S = A + llList2Integer(k1, j) + T + (D ^ (B & (C ^ D)));
            S = B;
             T = llList2Integer(r1, j & 3);
             T = llList2Integer(r1, j & 3);
            B += (F << T) | ((F >> (32 - T)) & ~(-1 << T));
             A = D;
             A = D;
             D = C;
             D = C;
             C = S;
             C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
         }
         }
         while(16 > (j = -~j));
         while(16 > (j = -~j));
         do
         do
         {
         {
             F = A + llList2Integer(k2, j & 15) + (C ^ (D & (B ^ C))) + llList2Integer(x, (5 * j + 1) & 15);
             S = A + llList2Integer(k2, j & 15) + (C ^ (D & (B ^ C))) + llList2Integer(x, (5 * j + 1) & 15);
            S = B;
             T = llList2Integer(r2, j & 3);
             T = llList2Integer(r2, j & 3);
            B += (F << T) | ((F >> (32 - T)) & ~(-1 << T));
             A = D;
             A = D;
             D = C;
             D = C;
             C = S;
             C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
         }
         }
         while(32 > (j = -~j));
         while(32 > (j = -~j));
         do
         do
         {
         {
             F = A + llList2Integer(k3, j & 15) + (B ^ C ^ D) + llList2Integer(x, (3 * j + 5) & 15);
             S = A + llList2Integer(k3, j & 15) + (B ^ C ^ D) + llList2Integer(x, (3 * j + 5) & 15);
            S = B;
             T = llList2Integer(r3, j & 3);
             T = llList2Integer(r3, j & 3);
            B += (F << T) | ((F >> (32 - T)) & ~(-1 << T));
             A = D;
             A = D;
             D = C;
             D = C;
             C = S;
             C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
         }
         }
         while(48 > (j = -~j));
         while(48 > (j = -~j));
         do
         do
         {
         {
            S = B;
             T = llList2Integer(r4, j & 3);
             T = llList2Integer(r4, j & 3);
             F = A + llList2Integer(k4, j & 15) + (C ^ (B | (~D))) + llList2Integer(x, (7 * j) & 15);
             S = A + llList2Integer(k4, j & 15) + (C ^ (B | (~D))) + llList2Integer(x, (7 * j) & 15);
            B += (F << T) | ((F >> (32 - T)) & ~(-1 << T));
             A = D;
             A = D;
             D = C;
             D = C;
             C = S;
             C = B;
            B += (S << T) | ((S >> (32 - T)) & ~(-1 << T));
         }
         }
         while(64 > (j = -~j));
         while(64 > (j = -~j));
        //llOwnerSay(llList2CSV(x));
//       llOwnerSay(llList2CSV(x));
         H1 += A;
         H1 += A;
         H2 += B;
         H2 += B;
Line 320: Line 302:
          
          
     }
     }
}</pre>
}</source>


[[Category: AW_Groupies]]
[[Category: AW_Groupies]]

Latest revision as of 00:13, 10 May 2021

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);
            }
        }
        
    }
}