feat(updater): per #9, move over synthos updater code
Signed-off-by: zontreck <tarapiccari@gmail.com>
This commit is contained in:
parent
ec2f61125f
commit
d7bd3cf805
4 changed files with 479 additions and 0 deletions
141
src/raw/pkg_server/server.lsl
Normal file
141
src/raw/pkg_server/server.lsl
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
#include "includes/common.lsl"
|
||||||
|
|
||||||
|
#define MSGS_0 "Server startup in progress... reading manifest"
|
||||||
|
#define MSGS_1 "Server startup completed with "
|
||||||
|
|
||||||
|
default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
// Startup
|
||||||
|
llOwnerSay(MSGS_0);
|
||||||
|
|
||||||
|
UpdateDSRequest(NULL, llGetNotecardLine("server_manifest", 0), SetDSMeta(["read",0, ""]));
|
||||||
|
}
|
||||||
|
changed(integer iChange)
|
||||||
|
{
|
||||||
|
if(iChange && CHANGED_INVENTORY)
|
||||||
|
{
|
||||||
|
llOwnerSay("Reloading server...");
|
||||||
|
llResetScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listen(integer c,string n,key i,string m)
|
||||||
|
{
|
||||||
|
llWhisper(0, m);
|
||||||
|
if(llJsonGetValue(m, ["operation"]) == "check_package_servers")
|
||||||
|
{
|
||||||
|
llRegionSayTo(i,c,Build("package_server_reply", ["server", g_sServerName]));
|
||||||
|
}else if(llJsonGetValue(m,["operation"]) == "connect")
|
||||||
|
{
|
||||||
|
// This is always going to be successful in reality, so what we do is we send back all package names
|
||||||
|
// Anything beyond that is package specific
|
||||||
|
list lPackages = llJson2List(g_sPackages);
|
||||||
|
integer count = llGetListLength(lPackages)/2;
|
||||||
|
|
||||||
|
list lNames= StrideOfList(lPackages, 2,0,-1);
|
||||||
|
lPackages=[];// Mark for GC
|
||||||
|
|
||||||
|
llRegionSayTo(i,c,Build("package_list", ["packages", llList2Json(JSON_ARRAY, lNames)]));
|
||||||
|
} else if(llJsonGetValue(m,["operation"]) == "check_package")
|
||||||
|
{
|
||||||
|
string sPackage = llJsonGetValue(m,["pkg"]);
|
||||||
|
|
||||||
|
list lPkgDef = llJson2List(llJsonGetValue(g_sPackages,[sPackage]));
|
||||||
|
lPkgDef=StrideOfList(lPkgDef,2,0,-1);
|
||||||
|
|
||||||
|
llRegionSayTo(i,c,Build("package_versions", [sPackage, llList2Json(JSON_ARRAY, lPkgDef)])); // Send all versions
|
||||||
|
|
||||||
|
} else if(llJsonGetValue(m,["operation"]) == "check_version")
|
||||||
|
{
|
||||||
|
string sPackage = llJsonGetValue(m,["pkg"]);
|
||||||
|
string sVer = llJsonGetValue(m,["ver"]);
|
||||||
|
if(sVer == "latest") sVer = llJsonGetValue(g_sPackages, [sPackage, "latest"]);
|
||||||
|
string sCurVer = llJsonGetValue(m,["cur"]);
|
||||||
|
string sCompat = llJsonGetValue(g_sPackages, [sPackage, sVer, "compat"]);
|
||||||
|
|
||||||
|
integer iRes=VersionNumberCompare(sCurVer, sVer);
|
||||||
|
integer iSame;
|
||||||
|
integer iNewer;
|
||||||
|
if(iRes == 0)
|
||||||
|
{
|
||||||
|
iSame=TRUE;
|
||||||
|
}else {
|
||||||
|
iSame=FALSE;
|
||||||
|
if(iRes>0)iNewer=1;
|
||||||
|
else iNewer=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
integer iCompat;
|
||||||
|
|
||||||
|
iRes = VersionNumberCompare(sCurVer, sCompat);
|
||||||
|
if(iRes <= 0)iCompat=1;
|
||||||
|
else iCompat=0;
|
||||||
|
|
||||||
|
llRegionSayTo(i,c,Build("version_back", ["same", iSame, "newer", iNewer, "compatible", iCompat]));
|
||||||
|
} else if(llJsonGetValue(m,["operation"]) == "send")
|
||||||
|
{
|
||||||
|
string sPackage = llJsonGetValue(m,["pkg"]);
|
||||||
|
string sRequest = llJsonGetValue(m,["ver"]);
|
||||||
|
if(sRequest == "latest")sRequest = llJsonGetValue(g_sPackages, [sPackage, "latest"]);
|
||||||
|
|
||||||
|
string sItem = llJsonGetValue(g_sPackages, [sPackage, sRequest, "item"]);
|
||||||
|
|
||||||
|
llGiveInventory(llJsonGetValue(m,["dest"]), sItem);
|
||||||
|
|
||||||
|
llRegionSayTo(i,c,Build("send_back", ["item", sItem]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataserver( key queryid, string data )
|
||||||
|
{
|
||||||
|
if(~HasDSRequest(queryid))
|
||||||
|
{
|
||||||
|
list lMeta = GetMetaList(queryid);
|
||||||
|
string sOp = llList2String(lMeta,0);
|
||||||
|
if(sOp == "read")
|
||||||
|
{
|
||||||
|
integer iLine = (integer)llList2String(lMeta,1);
|
||||||
|
string sPkg = llList2String(lMeta,2);
|
||||||
|
if(data==EOF)
|
||||||
|
{
|
||||||
|
DeleteDSReq(queryid);
|
||||||
|
llOwnerSay(MSGS_1 + (string)llGetFreeMemory()+"b free");
|
||||||
|
|
||||||
|
g_iServerListener = llListen(PACKAGE_SERVER_CHANNEL, "", "", "");
|
||||||
|
} else {
|
||||||
|
iLine++;
|
||||||
|
|
||||||
|
list lOpts = llParseStringKeepNulls(data, [" ", "|"], []);
|
||||||
|
|
||||||
|
if(llList2String(lOpts,0) == "SERVER_NAME")
|
||||||
|
{
|
||||||
|
g_sServerName = llDumpList2String(llList2List(lOpts,1,-1), " ");
|
||||||
|
}else if(llList2String(lOpts,0) == "BEGIN")
|
||||||
|
{
|
||||||
|
sPkg = llDumpList2String(llList2List(lOpts,1,-1), " ");
|
||||||
|
|
||||||
|
g_sPackages = llJsonSetValue(g_sPackages, [sPkg], "{}");
|
||||||
|
} else if(llList2String(lOpts,0) == "LATEST")
|
||||||
|
{
|
||||||
|
g_sPackages = llJsonSetValue(g_sPackages, [sPkg,"latest"], llDumpList2String(llList2List(lOpts,1,-1), " "));
|
||||||
|
}else if(llList2String(lOpts,0) == "END")
|
||||||
|
{
|
||||||
|
sPkg="";
|
||||||
|
}else {
|
||||||
|
string sVer = llList2String(lOpts,0);
|
||||||
|
string sItem = llDumpList2String(llList2List(lOpts,1,-2)," ");
|
||||||
|
// The version number for which this package is backward compatible.
|
||||||
|
// Backwards compatibility means that at least in theory, someone could even downgrade without issues to at least this version number
|
||||||
|
// It also means that no middle steps are required for upgrading. The user can upgrade from the version to this package version without issues.
|
||||||
|
string sBackwardCompat = llList2String(lOpts,2);
|
||||||
|
|
||||||
|
g_sPackages = llJsonSetValue(g_sPackages, [sPkg, sVer], llList2Json(JSON_OBJECT, ["item", sItem, "compat", sBackwardCompat]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UpdateDSRequest(queryid, llGetNotecardLine("server_manifest", iLine), SetDSMeta(["read", iLine, sPkg]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
src/raw/updater/force_update.lsl
Normal file
53
src/raw/updater/force_update.lsl
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is a temporary placeholder for development purposes to help bootstrap the update system. It is a drop in script to immediately start the update
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes/common.lsl"
|
||||||
|
|
||||||
|
default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
// Send the update scan signal
|
||||||
|
VERSION = "0.0.0.0";
|
||||||
|
g_iUpdaterListener = llListen(UPDATER_CHANNEL, "", "", "");
|
||||||
|
llWhisper(UPDATER_CHANNEL, Build("checkupdate", ["myversion", compileVersion()]));
|
||||||
|
|
||||||
|
llSetTimerEvent(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer(){
|
||||||
|
if(llGetTime()>=10){
|
||||||
|
llSay(0, "No updater responded in time, good bye!");
|
||||||
|
llRemoveInventory(llGetScriptName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
listen(integer iChan, string sName, key kID, string sMsg)
|
||||||
|
{
|
||||||
|
//llSay(0, "DEBUG ["+llDumpList2String([iChan, sName, kID, sMsg], " ~ ")+"]");
|
||||||
|
integer iStart=0;
|
||||||
|
if(llJsonGetValue(sMsg,["operation"]) == "available")
|
||||||
|
{
|
||||||
|
// Begin stage 2
|
||||||
|
iStart=1;
|
||||||
|
}else if(llJsonGetValue(sMsg,["operation"]) == "same")
|
||||||
|
{
|
||||||
|
// Impossible as this is the force start. Tell it to start anyway!
|
||||||
|
iStart=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!iStart)return;
|
||||||
|
|
||||||
|
g_iClientPin = llAbs(llRound(llFrand(0xFFFF)));
|
||||||
|
llSetRemoteScriptAccessPin(g_iClientPin);
|
||||||
|
llSleep(1);
|
||||||
|
|
||||||
|
llRegionSayTo(kID, UPDATER_CHANNEL, Build("stage2", ["pin", g_iClientPin]));
|
||||||
|
llSay(0, "Updater found, sent pairing code, good bye!");
|
||||||
|
llRemoveInventory(llGetScriptName());
|
||||||
|
}
|
||||||
|
}
|
129
src/raw/updater/shim.lsl
Normal file
129
src/raw/updater/shim.lsl
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#include "includes/common.lsl"
|
||||||
|
|
||||||
|
default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
// We are installed by the updater.
|
||||||
|
// We can now perform update specific preparations
|
||||||
|
// First off send the update started signal
|
||||||
|
if(llGetStartParameter()==0)llSetScriptState(llGetScriptName(), FALSE);
|
||||||
|
if(llGetInventoryType("SynthOS Installer") == INVENTORY_SCRIPT){
|
||||||
|
llSetScriptState(llGetScriptName(), FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_kSession = MakeSession(SESSION_UPDATE);
|
||||||
|
signal(SIGNAL_UPDATE_START, g_kSession);
|
||||||
|
g_iStartup = llGetStartParameter();
|
||||||
|
|
||||||
|
g_iUpdaterListener = llListen(UPDATER_CHANNEL, "", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
dataserver( key kID, string sData )
|
||||||
|
{
|
||||||
|
if(HasDSRequest(kID)!=-1)
|
||||||
|
{
|
||||||
|
list lMeta = GetMetaList(kID);
|
||||||
|
if(llList2String(lMeta,0) == "read")
|
||||||
|
{
|
||||||
|
if(sData == EOF)
|
||||||
|
{
|
||||||
|
DeleteDSReq(kID);
|
||||||
|
llRemoveInventory(llList2String(lMeta,1)); // Delete the BOM file
|
||||||
|
llRegionSayTo(g_kUpdatePair, UPDATER_CHANNEL, Build("upgrade_security", ["pin", g_iClientPin, "secure_channel", g_iUpdaterSecureChannel]));
|
||||||
|
}else {
|
||||||
|
if(sData=="")jump next;
|
||||||
|
list lTmp = llParseString2List(sData,["|"], []);
|
||||||
|
string sItem = llList2String(lTmp,1);
|
||||||
|
if(llGetInventoryType(sItem) == INVENTORY_NONE)jump next;
|
||||||
|
llRemoveInventory(sItem);
|
||||||
|
|
||||||
|
@next;
|
||||||
|
integer iLine = (integer)llList2String(lMeta,2);
|
||||||
|
iLine++;
|
||||||
|
lMeta[2]=iLine;
|
||||||
|
UpdateDSRequest(kID, llGetNotecardLine(llList2String(lMeta,1), iLine), SetDSMeta(lMeta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(integer iChannel, string sName, key kID, string sMsg)
|
||||||
|
{
|
||||||
|
//llSay(0, "DEBUG ["+llDumpList2String([iChannel, sName, kID, sMsg], " ~ ")+"]");
|
||||||
|
// Check the startup number against the pairing code
|
||||||
|
if(iChannel == UPDATER_CHANNEL)
|
||||||
|
{
|
||||||
|
if(llJsonGetValue(sMsg,["operation"]) == "connect")
|
||||||
|
{
|
||||||
|
integer iPair = (integer)llJsonGetValue(sMsg,["pair"]);
|
||||||
|
if(iPair == g_iStartup){
|
||||||
|
// Upgrade to a secure channel
|
||||||
|
llListenRemove(g_iUpdaterListener);
|
||||||
|
|
||||||
|
g_iUpdaterSecureChannel = llAbs(llRound(llFrand(0xFFFFFF)));
|
||||||
|
g_iUpdaterSecureListener = llListen(g_iUpdaterSecureChannel, "", kID, "");
|
||||||
|
g_kUpdatePair = kID;
|
||||||
|
g_iClientPin = llAbs(llRound(llFrand(0xFFFFFF)));
|
||||||
|
// Inform the updater that we are ready to upgrade to the secure channel
|
||||||
|
llSetRemoteScriptAccessPin(g_iClientPin);
|
||||||
|
|
||||||
|
string sBOM = llJsonGetValue(sMsg,["bom"]);
|
||||||
|
if(llGetInventoryType(sBOM)==INVENTORY_NOTECARD)
|
||||||
|
UpdateDSRequest(NULL, llGetNotecardLine(sBOM,1), SetDSMeta(["read", sBOM, 1])); // Start at line 1 to skip the Version Number
|
||||||
|
else
|
||||||
|
llRegionSayTo(g_kUpdatePair, UPDATER_CHANNEL, Build("upgrade_security", ["pin", g_iClientPin, "secure_channel", g_iUpdaterSecureChannel]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (iChannel == g_iUpdaterSecureChannel)
|
||||||
|
{
|
||||||
|
// This is the secure channel, which means that the handshake was successful
|
||||||
|
// Here we process update signals from the updater itself
|
||||||
|
// The packets from the updater will tell us information about the item in question
|
||||||
|
// Due to SL not telling us UUIDs of things that we do not have full permission to, we must rely on a force update all approach.
|
||||||
|
// This is not ideal but it is how non-full perm stuff must be updated.
|
||||||
|
|
||||||
|
if (llJsonGetValue(sMsg, ["operation"]) == "began")
|
||||||
|
{
|
||||||
|
// The updater has begun to send items or install scripts. It'll be quiet for a little bit while the install happens.
|
||||||
|
// Currently there is nothing here to process
|
||||||
|
} else if(llJsonGetValue(sMsg, ["operation"]) == "ended")
|
||||||
|
{
|
||||||
|
// The updater has sent us everything and it has started to reset itself.
|
||||||
|
// We can safely assume the update is done. Sleep for about 10 seconds and then dispatch the update done signal
|
||||||
|
|
||||||
|
// Sleep for 1 second to let everything settle down
|
||||||
|
llSleep(1);
|
||||||
|
|
||||||
|
integer i=0;
|
||||||
|
integer end = llGetInventoryNumber(INVENTORY_SCRIPT);
|
||||||
|
for(i=0;i<end;i++)
|
||||||
|
{
|
||||||
|
string sName = llGetInventoryName(INVENTORY_SCRIPT, i);
|
||||||
|
llSetScriptState(sName, TRUE); // We do not care about resetting them right here. Let them start up, then sleep and send the update done signal
|
||||||
|
}
|
||||||
|
llSleep(10);
|
||||||
|
signal(SIGNAL_UPDATE_DONE, g_kSession);
|
||||||
|
llSetRemoteScriptAccessPin(0);
|
||||||
|
signal(SIGNAL_RESET, g_kSession);
|
||||||
|
llSleep(1);
|
||||||
|
llSay(0, "Update completed to "+llLinksetDataRead("os.softwareversion"));
|
||||||
|
llRemoveInventory(llGetScriptName()); // Clean up ourself
|
||||||
|
} else if(llJsonGetValue(sMsg, ["operation"]) == "prepare")
|
||||||
|
{
|
||||||
|
string sItem=llJsonGetValue(sMsg,["details", "name"]);
|
||||||
|
// This signal is specific to items that need to be removed to make room for the newer item
|
||||||
|
if(llGetInventoryType(sItem) != INVENTORY_NONE)
|
||||||
|
{
|
||||||
|
llRemoveInventory(sItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send back the details packet which will include details like the item name, and type
|
||||||
|
// We are sending it on the main json payload this time instead of inside a json object ["details"]
|
||||||
|
llRegionSayTo(kID, iChannel, Build("continue", llJson2List(llJsonGetValue(sMsg,["details"]))));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
156
src/raw/updater/updater.lsl
Normal file
156
src/raw/updater/updater.lsl
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is the updater
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include "includes/common.lsl"
|
||||||
|
integer g_iDelOnFinish=0;
|
||||||
|
default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
g_iUpdaterListener = llListen(UPDATER_CHANNEL, "", "", "");
|
||||||
|
|
||||||
|
// Scan for BOM file
|
||||||
|
integer i=0;
|
||||||
|
integer end = llGetInventoryNumber(INVENTORY_NOTECARD);
|
||||||
|
for(i=0;i<end;i++)
|
||||||
|
{
|
||||||
|
string sName = llGetInventoryName(INVENTORY_NOTECARD, i);
|
||||||
|
if(llSubStringIndex(sName, ".BOM")!=-1)
|
||||||
|
{
|
||||||
|
g_sBOM = sName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(g_sBOM == "")
|
||||||
|
llOwnerSay("/!\\ ALERT /!\\ NO BOM DETECTED. INSTALLER WILL NOT WORK");
|
||||||
|
else llOwnerSay("Installer is now operational and set to : "+g_sBOM);
|
||||||
|
|
||||||
|
if(g_sBOM != "")UpdateDSRequest(NULL, llGetNotecardLine(g_sBOM,0), SetDSMeta(["read_version"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
on_rez(integer t){
|
||||||
|
g_iDelOnFinish=t;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed(integer iChange)
|
||||||
|
{
|
||||||
|
if(iChange & CHANGED_INVENTORY)
|
||||||
|
{
|
||||||
|
// Reset ourselves if not update in progress
|
||||||
|
if(g_iClientPin != 0){
|
||||||
|
// We're in a update, scream at the object owner
|
||||||
|
llOwnerSay("/!\\ FATAL /!\\\n \n[ You have changed my contents mid-update. There could be serious problems that arise now. You should repeat the update after this one ends if there are issues ]");
|
||||||
|
}else
|
||||||
|
llResetScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listen( integer iChannel, string sName, key kID, string sMsg )
|
||||||
|
{
|
||||||
|
//llSay(0, "DEBUG ["+llDumpList2String([iChannel, sName, kID, sMsg], " ~ ")+"]");
|
||||||
|
if(iChannel == UPDATER_CHANNEL)
|
||||||
|
{
|
||||||
|
if(llJsonGetValue(sMsg,["operation"]) == "checkupdate")
|
||||||
|
{
|
||||||
|
string sVer = llJsonGetValue(sMsg,["myversion"]);
|
||||||
|
integer iCompare = VersionNumberCompare(compileVersion(), sVer);
|
||||||
|
if(iCompare == 0)
|
||||||
|
{
|
||||||
|
llRegionSayTo(kID, UPDATER_CHANNEL, Build("same", []));
|
||||||
|
}else if(iCompare == -1){
|
||||||
|
// Bingo, we are good to begin
|
||||||
|
llRegionSayTo(kID, UPDATER_CHANNEL, Build("available", []));
|
||||||
|
} else if(iCompare == 1)
|
||||||
|
{
|
||||||
|
llRegionSayTo(kID, UPDATER_CHANNEL, Build("older", []));
|
||||||
|
}
|
||||||
|
} else if(llJsonGetValue(sMsg, ["operation"]) == "stage2")
|
||||||
|
{
|
||||||
|
// Send the shim
|
||||||
|
g_iClientPin = (integer)llJsonGetValue(sMsg, ["pin"]);
|
||||||
|
g_iStartup = llAbs(llRound(llFrand(0xFFFF))); // Pairing code
|
||||||
|
llRemoteLoadScriptPin(kID, UPDATER_SHIM, g_iClientPin, TRUE, g_iStartup);
|
||||||
|
llSleep(5); // Wait for it to start up...and any lag that might be happening
|
||||||
|
llRegionSayTo(kID, UPDATER_CHANNEL, Build("connect", ["pair", g_iStartup, "bom", g_sBOM]));
|
||||||
|
} else if(llJsonGetValue(sMsg,["operation"]) == "upgrade_security")
|
||||||
|
{
|
||||||
|
llListenControl(g_iUpdaterListener, FALSE);
|
||||||
|
g_iUpdaterSecureChannel = (integer)llJsonGetValue(sMsg,["secure_channel"]);
|
||||||
|
g_iClientPin = (integer)llJsonGetValue(sMsg,["pin"]);
|
||||||
|
g_kUpdatePair = kID;
|
||||||
|
g_iUpdaterSecureListener = llListen(g_iUpdaterSecureChannel, "", g_kUpdatePair, "");
|
||||||
|
g_kSession = MakeSession(SESSION_UPDATE);
|
||||||
|
|
||||||
|
// Initial plans had there to be a bundle reader here but this can be done in a single script
|
||||||
|
// Start reading BOM
|
||||||
|
g_kBundleReader = MakeSession(SESSION_UPDATE);
|
||||||
|
UpdateDSRequest(NULL, llGetNotecardLine(g_sBOM, 1), SetDSMeta(["read_bom", 1]));
|
||||||
|
}
|
||||||
|
} else if(iChannel == g_iUpdaterSecureChannel){
|
||||||
|
if(llJsonGetValue(sMsg,["operation"]) == "continue")
|
||||||
|
{
|
||||||
|
integer iScript = (integer)llJsonGetValue(sMsg,["type"]);
|
||||||
|
string sScript = llJsonGetValue(sMsg,["name"]);
|
||||||
|
|
||||||
|
if(iScript)
|
||||||
|
{
|
||||||
|
llOwnerSay("Install: "+sScript);
|
||||||
|
llRemoteLoadScriptPin(g_kUpdatePair, sScript, g_iClientPin, FALSE, 0);
|
||||||
|
}else {
|
||||||
|
llOwnerSay("Give: "+sScript);
|
||||||
|
llGiveInventory(g_kUpdatePair, sScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
list lMeta = GetMetaList(g_kBundleReader);
|
||||||
|
UpdateDSRequest(g_kBundleReader, llGetNotecardLine(g_sBOM, (integer)llList2String(lMeta,1)), SetDSMeta(lMeta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dataserver(key kID, string sData)
|
||||||
|
{
|
||||||
|
if(HasDSRequest(kID)!=-1)
|
||||||
|
{
|
||||||
|
list lMeta = GetMetaList(kID);
|
||||||
|
if(llList2String(lMeta,0)=="read_bom")
|
||||||
|
{
|
||||||
|
if(sData == EOF)
|
||||||
|
{
|
||||||
|
llRegionSayTo(g_kUpdatePair, g_iUpdaterSecureChannel, Build("ended", []));
|
||||||
|
llGiveInventory(g_kUpdatePair, g_sBOM); // Give the manifest. We're done now
|
||||||
|
llSay(0, "Update completed!");
|
||||||
|
llSleep(2);
|
||||||
|
if(g_iDelOnFinish)llDie();
|
||||||
|
llResetScript();
|
||||||
|
}else {
|
||||||
|
integer iLine = (integer)llList2String(lMeta,1);
|
||||||
|
iLine++;
|
||||||
|
lMeta[1]=iLine;
|
||||||
|
|
||||||
|
if(sData == "")jump next;
|
||||||
|
|
||||||
|
list lParams = llParseString2List(sData,["|"], []);
|
||||||
|
|
||||||
|
integer iType = 0;
|
||||||
|
if(llList2String(lParams,0)=="SCRIPT")iType=1;
|
||||||
|
|
||||||
|
string sDetailsPacket = llList2Json(JSON_OBJECT,["name", llList2String(lParams,1), "type", iType]);
|
||||||
|
|
||||||
|
UpdateDSRequest(kID, g_kBundleReader, SetDSMeta(lMeta));
|
||||||
|
llRegionSayTo(g_kUpdatePair, g_iUpdaterSecureChannel, Build("prepare", ["details", sDetailsPacket]));
|
||||||
|
|
||||||
|
jump done;
|
||||||
|
@next;
|
||||||
|
UpdateDSRequest(kID, llGetNotecardLine(g_sBOM, iLine), SetDSMeta(lMeta));
|
||||||
|
|
||||||
|
@done; // Called to await the continue signal
|
||||||
|
}
|
||||||
|
} else if(llList2String(lMeta,0) == "read_version")
|
||||||
|
{
|
||||||
|
VERSION = sData;
|
||||||
|
DeleteDSReq(kID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue