llTransferOwnership() with flag 0x4 still allows no-copy inventory duplication.
complete
Lucia Nightfire
llTransferOwnership() with flag 0x4 still allows no-copy inventory duplication.
Call the function with flag 0x4, pending offer is created, disable Locked status, drop in no-copy object, accept pending offer, take no-copy object back to your inventory, repeat.
Similar to how the server removes no-transfer-for-owner content after owner change, it should probably remove no-copy-for-owner content in the original after this function (with flag 0x4) makes an offer.
Log In
This post was marked as
complete
Maestro Linden
marked this post as
tracked
Maestro Linden
Hi Lucia, I gave this a try but can't repro in Apple Cobbler 2024-11-26.12040480539. I'm seeing the expected behavior - the LSL call fails with TRANSFER_NO_PERMS. Is your setup different from mine?
- UserA: obtain an empty object that is modify/no-copy/transfer (appears as 'O:VMT' in 'debug permissions')
- UserA: Create the script shown in child comment in the object
- UserB: Touch the object. The script will then call llTransferOwnership(UserB, TRANSFER_FLAG_COPY)
Expected results (which I am seeing now):
- The llTransferOwnership() call should fail, and return TRANSFER_NO_PERMS (-6)
- The object's ownership should remain unchanged
- UserB's inventory should get no new objects
Maestro Linden
// Basic test script for llTransferOwnership
// https://wiki.secondlife.com/wiki/LlTransferOwnership
string transferReturnCodeToLabel(integer c)
{
// while the error codes are negative, we can take advantage of
// llList2String()'s negative index behavior to return the correct values
list codes = [
TRANSFER_OK,
TRANSFER_NO_ATTACHMENT,
TRANSFER_NO_PERMS,
TRANSFER_BAD_ROOT,
TRANSFER_NO_ITEMS,
TRANSFER_THROTTLE,
TRANSFER_NO_TARGET,
TRANSFER_BAD_OPTS
];
list code_labels = [
"TRANSFER_OK",
"TRANSFER_NO_ATTACHMENT",
"TRANSFER_NO_PERMS",
"TRANSFER_BAD_ROOT",
"TRANSFER_NO_ITEMS",
"TRANSFER_THROTTLE",
"TRANSFER_NO_TARGET",
"TRANSFER_BAD_OPTS"
];
return llList2String(codes, c) + " (" + llList2String(code_labels, c) + ")";
}
setOwnerText()
{
llSetText("Owned by " + (string)llGetOwner(), <1,1,1>, 1);
}
integer touch_count;
default
{
state_entry()
{
llSay(0, "Touch me to take ownership");
setOwnerText();
}
touch_start(integer total_number)
{
integer transferFlags = TRANSFER_FLAG_COPY;
string touch_event = "Touch event " + (string)(touch_count++);
llSay(0, touch_event + ": Current owner is " + (string)llGetOwner());
llSay(0, touch_event + ": Calling llTransferOwnership(\"" + (string)llDetectedKey(0)
+ "\", " + (string)transferFlags + ")");
integer result = llTransferOwnership(llDetectedKey(0), transferFlags);
llSay(0, touch_event + ": llTransferOwnership() result is " + transferReturnCodeToLabel(result));
setOwnerText();
}
changed(integer change)
{
if(change & CHANGED_OWNER)
{
llSay(0, "Changed owner. New owner is " + (string)llGetOwner());
setOwnerText();
}
}
}
Maestro Linden
marked this post as
needs info
Lucia Nightfire
llGiveInventory() will remove no-copy content after execution, so why not llTransferOwnership() (with flag 0x4)?