Match AISAPI refactoring.
This commit is contained in:
@@ -35,305 +35,314 @@
|
||||
#include "llviewerregion.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Classes for AISv3 support.
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
|
||||
AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
|
||||
mCommandFunc(NULL),
|
||||
mCallback(callback)
|
||||
class AISCommand : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
|
||||
}
|
||||
|
||||
bool AISCommand::run_command()
|
||||
{
|
||||
if (NULL == mCommandFunc)
|
||||
{
|
||||
// This may happen if a command failed to initiate itself.
|
||||
LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCommandFunc();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void AISCommand::setCommandFunc(command_func_type command_func)
|
||||
{
|
||||
mCommandFunc = command_func;
|
||||
}
|
||||
public:
|
||||
typedef boost::function<void()> command_func_type;
|
||||
// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
|
||||
AISCommand(AISAPI::COMMAND_TYPE type, const char* name, const LLUUID& targetId, AISAPI::completion_t callback) :
|
||||
mCommandFunc(NULL),
|
||||
mRetryPolicy(new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10)),
|
||||
mCompletionFunc(callback),
|
||||
mTargetId(targetId),
|
||||
mName(name),
|
||||
mType(type)
|
||||
{}
|
||||
|
||||
// virtual
|
||||
bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void AISCommand::httpSuccess()
|
||||
{
|
||||
// Command func holds a reference to self, need to release it
|
||||
// after a success or final failure.
|
||||
setCommandFunc(no_op);
|
||||
|
||||
const LLSD& content = getContent();
|
||||
if (!content.isMap())
|
||||
void run( command_func_type func )
|
||||
{
|
||||
failureResult(400, "Malformed response contents", content);
|
||||
return;
|
||||
(mCommandFunc = func)();
|
||||
}
|
||||
mRetryPolicy->onSuccess();
|
||||
|
||||
gInventory.onAISUpdateReceived("AISCommand", content);
|
||||
|
||||
if (mCallback)
|
||||
char const* getName(void) const
|
||||
{
|
||||
LLUUID id; // will default to null if parse fails.
|
||||
getResponseUUID(content,id);
|
||||
mCallback->fire(id);
|
||||
return mName;
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void AISCommand::httpFailure()
|
||||
{
|
||||
LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
|
||||
S32 status = getStatus();
|
||||
const AIHTTPReceivedHeaders& headers = getResponseHeaders();
|
||||
mRetryPolicy->onFailure(status, headers);
|
||||
F32 seconds_to_wait;
|
||||
if (mRetryPolicy->shouldRetry(seconds_to_wait))
|
||||
void markComplete()
|
||||
{
|
||||
doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
|
||||
mRetryPolicy->onSuccess();
|
||||
}
|
||||
else
|
||||
|
||||
protected:
|
||||
/* virtual */
|
||||
void httpSuccess()
|
||||
{
|
||||
// Command func holds a reference to self, need to release it
|
||||
// after a success or final failure.
|
||||
// *TODO: Notify user? This seems bad.
|
||||
setCommandFunc(no_op);
|
||||
mCommandFunc = no_op;
|
||||
AISAPI::InvokeAISCommandCoro(this, getURL(), mTargetId, getContent(), mCompletionFunc, (AISAPI::COMMAND_TYPE)mType);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
bool AISCommand::isAPIAvailable()
|
||||
/*virtual*/
|
||||
void httpFailure()
|
||||
{
|
||||
LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
|
||||
S32 status = getStatus();
|
||||
const AIHTTPReceivedHeaders& headers = getResponseHeaders();
|
||||
mRetryPolicy->onFailure(status, headers);
|
||||
F32 seconds_to_wait;
|
||||
if (mRetryPolicy->shouldRetry(seconds_to_wait))
|
||||
{
|
||||
doAfterInterval(mCommandFunc,seconds_to_wait);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Command func holds a reference to self, need to release it
|
||||
// after a success or final failure.
|
||||
// *TODO: Notify user? This seems bad.
|
||||
mCommandFunc = no_op;
|
||||
}
|
||||
}
|
||||
|
||||
command_func_type mCommandFunc;
|
||||
LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
|
||||
AISAPI::completion_t mCompletionFunc;
|
||||
const LLUUID mTargetId;
|
||||
const char* mName;
|
||||
AISAPI::COMMAND_TYPE mType;
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");
|
||||
const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3");
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*static*/
|
||||
bool AISAPI::isAvailable()
|
||||
{
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3");
|
||||
return gAgent.getRegion()->isCapabilityAvailable(INVENTORY_CAP_NAME);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
bool AISCommand::getInvCap(std::string& cap)
|
||||
/*static*/
|
||||
void AISAPI::getCapNames(LLSD& capNames)
|
||||
{
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
|
||||
}
|
||||
if (!cap.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
capNames.append(INVENTORY_CAP_NAME);
|
||||
capNames.append(LIBRARY_CAP_NAME);
|
||||
}
|
||||
|
||||
//static
|
||||
bool AISCommand::getLibCap(std::string& cap)
|
||||
/*static*/
|
||||
std::string AISAPI::getInvCap()
|
||||
{
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
cap = gAgent.getRegion()->getCapability("LibraryAPIv3");
|
||||
}
|
||||
if (!cap.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
return gAgent.getRegion()->getCapability(INVENTORY_CAP_NAME);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
//static
|
||||
void AISCommand::getCapabilityNames(LLSD& capabilityNames)
|
||||
/*static*/
|
||||
std::string AISAPI::getLibCap()
|
||||
{
|
||||
capabilityNames.append("InventoryAPIv3");
|
||||
capabilityNames.append("LibraryAPIv3");
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
return gAgent.getRegion()->getCapability(LIBRARY_CAP_NAME);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
AISCommand(callback)
|
||||
/*static*/
|
||||
void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/item/") + item_id.asString();
|
||||
std::string cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
|
||||
std::string url = cap + std::string("/category/") + parentId.asString() + "?tid=" + tid.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
|
||||
setCommandFunc(cmd);
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYINVENTORY, "CreateInventory",parentId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::post, url, newInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
|
||||
}
|
||||
|
||||
RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
AISCommand(callback)
|
||||
/*static*/
|
||||
void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + item_id.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
|
||||
setCommandFunc(cmd);
|
||||
}
|
||||
std::string cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
AISCommand(callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
|
||||
setCommandFunc(cmd);
|
||||
}
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
|
||||
std::string url = cap + std::string("/category/") + folderId.asString() + "/links?tid=" + tid.asString();
|
||||
|
||||
UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
mUpdates(updates),
|
||||
AISCommand(callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/item/") + item_id.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Content-Type", "application/llsd+xml");
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
|
||||
setCommandFunc(cmd);
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(SLAMFOLDER, "SlamFolder", folderId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::put, url, newInventory, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
|
||||
|
||||
}
|
||||
|
||||
UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
mUpdates(updates),
|
||||
AISCommand(callback)
|
||||
void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + cat_id.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Content-Type", "application/llsd+xml");
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
|
||||
setCommandFunc(cmd);
|
||||
std::string cap;
|
||||
|
||||
cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = cap + std::string("/category/") + categoryId.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVECATEGORY, "RemoveCategory",categoryId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
|
||||
}
|
||||
|
||||
CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
|
||||
const LLSD& new_inventory,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
mNewInventory(new_inventory),
|
||||
AISCommand(callback)
|
||||
/*static*/
|
||||
void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Content-Type", "application/llsd+xml");
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
|
||||
setCommandFunc(cmd);
|
||||
std::string cap;
|
||||
|
||||
cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = cap + std::string("/item/") + itemId.asString();
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVEITEM,"RemoveItem",itemId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
|
||||
}
|
||||
|
||||
SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
|
||||
mContents(contents),
|
||||
AISCommand(callback)
|
||||
void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getInvCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
|
||||
LL_INFOS() << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Content-Type", "application/llsd+xml");
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off));
|
||||
setCommandFunc(cmd);
|
||||
std::string cap;
|
||||
|
||||
cap = getLibCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Library cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LL_DEBUGS("Inventory") << "Copying library category: " << sourceId << " => " << destId << LL_ENDL;
|
||||
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
|
||||
std::string url = cap + std::string("/category/") + sourceId.asString() + "?tid=" + tid.asString();
|
||||
if (!copySubfolders)
|
||||
{
|
||||
url += ",depth=0";
|
||||
}
|
||||
LL_INFOS() << url << LL_ENDL;
|
||||
|
||||
std::string destination = destId.asString();
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYLIBRARYCATEGORY, "CopyLibraryCategory",destId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::copy, url, destination, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
|
||||
|
||||
}
|
||||
|
||||
CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
|
||||
const LLUUID& dest_id,
|
||||
LLPointer<LLInventoryCallback> callback):
|
||||
AISCommand(callback)
|
||||
/*static*/
|
||||
void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback)
|
||||
{
|
||||
std::string cap;
|
||||
if (!getLibCap(cap))
|
||||
{
|
||||
LL_WARNS() << "No cap found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
|
||||
LLUUID tid;
|
||||
tid.generate();
|
||||
std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
|
||||
LL_INFOS() << url << LL_ENDL;
|
||||
LLHTTPClient::ResponderPtr responder = this;
|
||||
command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder);
|
||||
setCommandFunc(cmd);
|
||||
std::string cap;
|
||||
|
||||
cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = cap + std::string("/category/") + categoryId.asString() + "/children";
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(PURGEDESCENDENTS, "PurgeDescendents",categoryId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
|
||||
}
|
||||
|
||||
bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id)
|
||||
/*static*/
|
||||
void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback)
|
||||
{
|
||||
if (content.has("category_id"))
|
||||
{
|
||||
id = content["category_id"];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
std::string cap;
|
||||
|
||||
cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + categoryId.asString();
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATECATEGORY, "UpdateCategory",categoryId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback)
|
||||
{
|
||||
|
||||
std::string cap;
|
||||
|
||||
cap = getInvCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/item/") + itemId.asString();
|
||||
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATEITEM, "UpdateItem",itemId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
|
||||
}
|
||||
void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithResult* responder,
|
||||
std::string url,
|
||||
LLUUID targetId, LLSD result, completion_t callback, COMMAND_TYPE type)
|
||||
{
|
||||
{
|
||||
if (!result.isMap())
|
||||
{
|
||||
responder->failureResult(400, "Malformed response contents", result);
|
||||
return;
|
||||
}
|
||||
((AISCommand*)responder)->markComplete();
|
||||
}
|
||||
|
||||
gInventory.onAISUpdateReceived("AISCommand", result);
|
||||
|
||||
if (callback && callback != nullptr)
|
||||
{
|
||||
LLUUID id(LLUUID::null);
|
||||
|
||||
if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
|
||||
{
|
||||
id = result["category_id"];
|
||||
}
|
||||
|
||||
callback(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
AISUpdate::AISUpdate(const LLSD& update)
|
||||
{
|
||||
parseUpdate(update);
|
||||
@@ -550,13 +559,25 @@ void AISUpdate::parseCategory(const LLSD& category_map)
|
||||
parseDescendentCount(category_id, category_map["_embedded"]);
|
||||
}
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat(new LLViewerInventoryCategory(category_id));
|
||||
LLPointer<LLViewerInventoryCategory> new_cat;
|
||||
LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
|
||||
if (curr_cat)
|
||||
{
|
||||
// Default to current values where not provided.
|
||||
new_cat->copyViewerCategory(curr_cat);
|
||||
new_cat = new LLViewerInventoryCategory(curr_cat);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (category_map.has("agent_id"))
|
||||
{
|
||||
new_cat = new LLViewerInventoryCategory(category_map["agent_id"].asUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS() << "No owner provided, folder might be assigned wrong owner" << LL_ENDL;
|
||||
new_cat = new LLViewerInventoryCategory(LLUUID::null);
|
||||
}
|
||||
}
|
||||
BOOL rv = new_cat->unpackMessage(category_map);
|
||||
// *NOTE: unpackMessage does not unpack version or descendent count.
|
||||
//if (category_map.has("version"))
|
||||
@@ -749,7 +770,7 @@ void AISUpdate::doUpdate()
|
||||
for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
|
||||
catit != mCatDescendentDeltas.end(); ++catit)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL;
|
||||
LL_DEBUGS("Inventory") << "descendant accounting for " << catit->first << LL_ENDL;
|
||||
|
||||
const LLUUID cat_id(catit->first);
|
||||
// Don't account for update if we just created this category.
|
||||
@@ -772,7 +793,7 @@ void AISUpdate::doUpdate()
|
||||
{
|
||||
S32 descendent_delta = catit->second;
|
||||
S32 old_count = cat->getDescendentCount();
|
||||
LL_DEBUGS("Inventory") << "Updating descendent count for "
|
||||
LL_DEBUGS("Inventory") << "Updating descendant count for "
|
||||
<< cat->getName() << " " << cat_id
|
||||
<< " with delta " << descendent_delta << " from "
|
||||
<< old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
|
||||
@@ -850,7 +871,7 @@ void AISUpdate::doUpdate()
|
||||
for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin();
|
||||
del_it != mObjectsDeletedIds.end(); ++del_it)
|
||||
{
|
||||
LL_INFOS("Inventory") << "deleted item " << *del_it << LL_ENDL;
|
||||
LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
|
||||
gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
|
||||
}
|
||||
|
||||
@@ -868,7 +889,16 @@ void AISUpdate::doUpdate()
|
||||
{
|
||||
LL_WARNS() << "Possible version mismatch for category " << cat->getName()
|
||||
<< ", viewer version " << cat->getVersion()
|
||||
<< " server version " << version << LL_ENDL;
|
||||
<< " AIS version " << version << " !!!Adjusting local version!!!" << LL_ENDL;
|
||||
|
||||
// the AIS version should be considered the true version. Adjust
|
||||
// our local category model to reflect this version number. Otherwise
|
||||
// it becomes possible to get stuck with the viewer being out of
|
||||
// sync with the inventory system. Under normal circumstances
|
||||
// inventory COF is maintained on the viewer through calls to
|
||||
// LLInventoryModel::accountForUpdate when a changing operation
|
||||
// is performed. This occasionally gets out of sync however.
|
||||
cat->setVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,118 +36,45 @@
|
||||
#include "llhttpretrypolicy.h"
|
||||
#include "llviewerinventory.h"
|
||||
|
||||
class AISCommand: public LLHTTPClient::ResponderWithResult
|
||||
class AISAPI
|
||||
{
|
||||
friend class AISCommand;
|
||||
public:
|
||||
typedef boost::function<void()> command_func_type;
|
||||
typedef std::function<void(const LLUUID &invItem)> completion_t;
|
||||
|
||||
AISCommand(LLPointer<LLInventoryCallback> callback);
|
||||
static bool isAvailable();
|
||||
static void getCapNames(LLSD& capNames);
|
||||
|
||||
virtual ~AISCommand() {}
|
||||
static void CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback = completion_t());
|
||||
static void SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback = completion_t());
|
||||
static void RemoveCategory(const LLUUID &categoryId, completion_t callback = completion_t());
|
||||
static void RemoveItem(const LLUUID &itemId, completion_t callback = completion_t());
|
||||
static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t());
|
||||
static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t());
|
||||
static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t());
|
||||
static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
|
||||
|
||||
bool run_command();
|
||||
private:
|
||||
typedef enum {
|
||||
COPYINVENTORY,
|
||||
SLAMFOLDER,
|
||||
REMOVECATEGORY,
|
||||
REMOVEITEM,
|
||||
PURGEDESCENDENTS,
|
||||
UPDATECATEGORY,
|
||||
UPDATEITEM,
|
||||
COPYLIBRARYCATEGORY
|
||||
} COMMAND_TYPE;
|
||||
|
||||
void setCommandFunc(command_func_type command_func);
|
||||
static const std::string INVENTORY_CAP_NAME;
|
||||
static const std::string LIBRARY_CAP_NAME;
|
||||
|
||||
// Need to do command-specific parsing to get an id here, for
|
||||
// LLInventoryCallback::fire(). May or may not need to bother,
|
||||
// since most LLInventoryCallbacks do their work in the
|
||||
// destructor.
|
||||
static std::string getInvCap();
|
||||
static std::string getLibCap();
|
||||
|
||||
/* virtual */ void httpSuccess();
|
||||
/* virtual */ void httpFailure();
|
||||
|
||||
static bool isAPIAvailable();
|
||||
static bool getInvCap(std::string& cap);
|
||||
static bool getLibCap(std::string& cap);
|
||||
static void getCapabilityNames(LLSD& capabilityNames);
|
||||
|
||||
protected:
|
||||
virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
|
||||
|
||||
private:
|
||||
command_func_type mCommandFunc;
|
||||
LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
|
||||
LLPointer<LLInventoryCallback> mCallback;
|
||||
};
|
||||
|
||||
class RemoveItemCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
RemoveItemCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "RemoveItemCommand"; }
|
||||
};
|
||||
|
||||
class RemoveCategoryCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
RemoveCategoryCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "RemoveCategoryCommand"; }
|
||||
};
|
||||
|
||||
class PurgeDescendentsCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
PurgeDescendentsCommand(const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "PurgeDescendentsCommand"; }
|
||||
|
||||
};
|
||||
|
||||
class UpdateItemCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
UpdateItemCommand(const LLUUID& item_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "UpdateItemCommand"; }
|
||||
|
||||
private:
|
||||
LLSD mUpdates;
|
||||
};
|
||||
|
||||
class UpdateCategoryCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
UpdateCategoryCommand(const LLUUID& cat_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "UpdateCategoryCommand"; }
|
||||
|
||||
private:
|
||||
LLSD mUpdates;
|
||||
};
|
||||
|
||||
class SlamFolderCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "SlamFolderCommand"; }
|
||||
|
||||
private:
|
||||
LLSD mContents;
|
||||
};
|
||||
|
||||
class CopyLibraryCategoryCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "CopyLibraryCategoryCommand"; }
|
||||
|
||||
protected:
|
||||
/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
|
||||
};
|
||||
|
||||
class CreateInventoryCommand: public AISCommand
|
||||
{
|
||||
public:
|
||||
CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer<LLInventoryCallback> callback);
|
||||
/* virtual */ const char* getName() const { return "CreateInventoryCommand"; }
|
||||
|
||||
private:
|
||||
LLSD mNewInventory;
|
||||
static void InvokeAISCommandCoro( LLHTTPClient::ResponderWithResult* responder,
|
||||
std::string url, LLUUID targetId, LLSD body,
|
||||
completion_t callback, COMMAND_TYPE type);
|
||||
};
|
||||
|
||||
class AISUpdate
|
||||
|
||||
@@ -60,6 +60,12 @@
|
||||
#include "rlvlocks.h"
|
||||
// [/RLVa:KB]
|
||||
|
||||
void doAppearanceCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
|
||||
{
|
||||
if (cb.notNull())
|
||||
cb->fire(id);
|
||||
}
|
||||
|
||||
std::string self_av_string()
|
||||
{
|
||||
// On logout gAgentAvatarp can already be invalid
|
||||
@@ -2842,8 +2848,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
|
||||
<< " )" << LL_ENDL;
|
||||
|
||||
// If we are copying from library, attempt to use AIS to copy the category.
|
||||
bool ais_ran=false;
|
||||
if (copy && AISCommand::isAPIAvailable())
|
||||
if (copy && AISAPI::isAvailable())
|
||||
{
|
||||
LLUUID parent_id;
|
||||
parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
|
||||
@@ -2855,11 +2860,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
|
||||
LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append);
|
||||
LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper(
|
||||
std::string("wear_inventory_category_callback"), copy_cb);
|
||||
boost::intrusive_ptr <AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb);
|
||||
ais_ran=cmd_ptr->run_command();
|
||||
}
|
||||
|
||||
if (!ais_ran)
|
||||
AISAPI::completion_t cr = boost::bind(&doAppearanceCb, track_cb, _1);
|
||||
AISAPI::CopyLibraryCategory(category->getUUID(), parent_id, false, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
selfStartPhase("wear_inventory_category_fetch");
|
||||
callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
|
||||
@@ -4123,7 +4128,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitCore(const std::string& new_folder_name, bo
|
||||
|
||||
// First, make a folder in the My Outfits directory.
|
||||
const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
// cap-based category creation was buggy until recently. use
|
||||
// existence of AIS as an indicator the fix is present. Does
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
|
||||
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
|
||||
// bit from there to give some pad.
|
||||
const S32 MAX_ITEMS = 42;
|
||||
const size_t MAX_ITEMS = 42;
|
||||
|
||||
class LLGiveable : public LLInventoryCollectFunctor
|
||||
{
|
||||
@@ -259,9 +259,9 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
|
||||
items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
giveable);
|
||||
S32 count = cats.size();
|
||||
size_t count = cats.size();
|
||||
bool complete = true;
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if(!gInventory.isCategoryComplete(cats.at(i)->getUUID()))
|
||||
{
|
||||
@@ -475,8 +475,8 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
|
||||
items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
remove);
|
||||
S32 count = items.size();
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
size_t count = items.size();
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
{
|
||||
gInventory.deleteObject(items.at(i)->getUUID());
|
||||
}
|
||||
@@ -529,8 +529,8 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
|
||||
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
|
||||
// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
|
||||
// 66. I've cut it down a bit from there to give some pad.
|
||||
S32 count = items.size() + cats.size();
|
||||
if(count > MAX_ITEMS)
|
||||
size_t count = items.size() + cats.size();
|
||||
if (count > MAX_ITEMS)
|
||||
{
|
||||
LLNotificationsUtil::add("TooManyItems");
|
||||
give_successful = false;
|
||||
@@ -546,7 +546,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
|
||||
LLAgentUI::buildFullname(name);
|
||||
LLUUID transaction_id;
|
||||
transaction_id.generate();
|
||||
S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
|
||||
size_t bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
|
||||
U8* bucket = new U8[bucket_size];
|
||||
U8* pos = bucket;
|
||||
U8 type = (U8)cat->getType();
|
||||
@@ -554,7 +554,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
|
||||
pos += sizeof(U8);
|
||||
memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
|
||||
pos += UUID_BYTES;
|
||||
S32 i;
|
||||
size_t i;
|
||||
count = cats.size();
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
typedef std::pair<LLUUID, LLUUID> two_uuids_t;
|
||||
typedef std::list<two_uuids_t> two_uuids_list_t;
|
||||
|
||||
const F32 SOUND_GAIN = 1.0f;
|
||||
|
||||
struct LLMoveInv
|
||||
{
|
||||
LLUUID mObjectID;
|
||||
@@ -1829,13 +1831,15 @@ BOOL LLItemBridge::removeItem()
|
||||
}
|
||||
|
||||
// move it to the trash
|
||||
LLPreview::hide(mUUID, TRUE);
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if(!model) return FALSE;
|
||||
const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
if (!item) return FALSE;
|
||||
|
||||
if (item->getType() != LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
LLPreview::hide(mUUID, TRUE);
|
||||
}
|
||||
// Already in trash
|
||||
if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE;
|
||||
|
||||
@@ -4488,7 +4492,7 @@ void LLSoundBridge::previewItem()
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
if(item)
|
||||
{
|
||||
send_sound_trigger(item->getAssetUUID(), 1.0);
|
||||
send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4554,7 +4558,7 @@ void LLSoundBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
if(item)
|
||||
{
|
||||
send_sound_trigger(item->getAssetUUID(), 1.f);
|
||||
send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
|
||||
}
|
||||
}
|
||||
else if ("open" == action)
|
||||
|
||||
@@ -83,6 +83,12 @@ static const char * const LOG_INV("Inventory");
|
||||
static const char * const LOG_LOCAL("InventoryLocalize");
|
||||
static const char * const LOG_NOTECARD("copy_inventory_from_notecard");
|
||||
|
||||
void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
|
||||
{
|
||||
if (cb.notNull())
|
||||
cb->fire(id);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Helper class to store special inventory item names and their localized values.
|
||||
///----------------------------------------------------------------------------
|
||||
@@ -332,16 +338,42 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const
|
||||
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
|
||||
gInventory.accountForUpdate(up);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryItem);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
|
||||
msg->nextBlockFast(_PREHASH_InventoryData);
|
||||
msg->addU32Fast(_PREHASH_CallbackID, 0);
|
||||
packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD updates = asLLSD();
|
||||
// Replace asset_id and/or shadow_id with transaction_id (hash_id)
|
||||
if (updates.has("asset_id"))
|
||||
{
|
||||
updates.erase("asset_id");
|
||||
if(getTransactionID().notNull())
|
||||
{
|
||||
updates["hash_id"] = getTransactionID();
|
||||
}
|
||||
}
|
||||
if (updates.has("shadow_id"))
|
||||
{
|
||||
updates.erase("shadow_id");
|
||||
if(getTransactionID().notNull())
|
||||
{
|
||||
updates["hash_id"] = getTransactionID();
|
||||
}
|
||||
}
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
|
||||
AISAPI::UpdateItem(getUUID(), updates, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryItem);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
|
||||
msg->nextBlockFast(_PREHASH_InventoryData);
|
||||
msg->addU32Fast(_PREHASH_CallbackID, 0);
|
||||
packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerInventoryItem::fetchFromServer(void) const
|
||||
@@ -584,18 +616,26 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
|
||||
LLNotificationsUtil::add("CannotModifyProtectedCategories");
|
||||
return;
|
||||
}
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD new_llsd = asLLSD();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
|
||||
AISAPI::UpdateCategory(getUUID(), new_llsd, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
|
||||
gInventory.accountForUpdate(up);
|
||||
|
||||
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
|
||||
gInventory.accountForUpdate(up);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_FolderData);
|
||||
packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_FolderData);
|
||||
packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLViewerInventoryCategory::getVersion() const
|
||||
@@ -825,18 +865,33 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
|
||||
const LLUUID &folder_id = getUUID();
|
||||
const LLUUID &parent_id = getParentUUID();
|
||||
const std::string &name = getName();
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_FolderData);
|
||||
msg->addUUIDFast(_PREHASH_FolderID, folder_id);
|
||||
msg->addUUIDFast(_PREHASH_ParentID, parent_id);
|
||||
msg->addS8Fast(_PREHASH_Type, new_folder_type);
|
||||
msg->addStringFast(_PREHASH_Name, name);
|
||||
gAgent.sendReliableMessage();
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(folder_id,
|
||||
parent_id,
|
||||
new_folder_type,
|
||||
name,
|
||||
gAgent.getID());
|
||||
|
||||
|
||||
LLSD new_llsd = new_cat->asLLSD();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>) NULL, _1);
|
||||
AISAPI::UpdateCategory(folder_id, new_llsd, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_FolderData);
|
||||
msg->addUUIDFast(_PREHASH_FolderID, folder_id);
|
||||
msg->addUUIDFast(_PREHASH_ParentID, parent_id);
|
||||
msg->addS8Fast(_PREHASH_Type, new_folder_type);
|
||||
msg->addStringFast(_PREHASH_Name, name);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
setPreferredType(new_folder_type);
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
|
||||
@@ -963,6 +1018,22 @@ void activate_gesture_cb(const LLUUID& inv_item)
|
||||
LLGestureMgr::instance().activateGesture(inv_item);
|
||||
}
|
||||
|
||||
void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type)
|
||||
{
|
||||
llassert(item);
|
||||
LLPermissions perm = item->getPermissions();
|
||||
if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type)
|
||||
|| perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type))
|
||||
{
|
||||
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type));
|
||||
perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type));
|
||||
|
||||
item->setPermissions(perm);
|
||||
|
||||
item->updateServer(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void create_script_cb(const LLUUID& inv_item)
|
||||
{
|
||||
if (!inv_item.isNull())
|
||||
@@ -970,13 +1041,9 @@ void create_script_cb(const LLUUID& inv_item)
|
||||
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
|
||||
if (item)
|
||||
{
|
||||
LLPermissions perm = item->getPermissions();
|
||||
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts"));
|
||||
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts"));
|
||||
set_default_permissions(item, "Scripts");
|
||||
|
||||
item->setPermissions(perm);
|
||||
|
||||
item->updateServer(FALSE);
|
||||
// item was just created, update even if permissions did not changed
|
||||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
@@ -992,16 +1059,12 @@ void create_gesture_cb(const LLUUID& inv_item)
|
||||
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
|
||||
if (item)
|
||||
{
|
||||
LLPermissions perm = item->getPermissions();
|
||||
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
|
||||
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
|
||||
set_default_permissions(item, "Gestures");
|
||||
|
||||
item->setPermissions(perm);
|
||||
|
||||
item->updateServer(FALSE);
|
||||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
|
||||
|
||||
if (!LLPreview::show(inv_item,FALSE))
|
||||
{
|
||||
LLPreviewGesture* preview = LLPreviewGesture::show(std::string("Gesture: ") + item->getName(), inv_item, LLUUID::null);
|
||||
@@ -1019,13 +1082,8 @@ void create_notecard_cb(const LLUUID& inv_item)
|
||||
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
|
||||
if (item)
|
||||
{
|
||||
LLPermissions perm = item->getPermissions();
|
||||
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards"));
|
||||
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards"));
|
||||
set_default_permissions(item, "Notecards");
|
||||
|
||||
item->setPermissions(perm);
|
||||
|
||||
item->updateServer(FALSE);
|
||||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
@@ -1226,16 +1284,14 @@ void link_inventory_array(const LLUUID& category,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ais_ran = false;
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD new_inventory = LLSD::emptyMap();
|
||||
new_inventory["links"] = links;
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb);
|
||||
ais_ran = cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::CreateInventory(category, new_inventory, cr);
|
||||
}
|
||||
|
||||
if (!ais_ran)
|
||||
else
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter )
|
||||
@@ -1292,25 +1348,30 @@ void update_inventory_item(
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
const LLUUID& item_id = update_item->getUUID();
|
||||
bool ais_ran = false;
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD updates = update_item->asLLSD();
|
||||
// Replace asset_id and/or shadow_id with transaction_id (hash_id)
|
||||
if (updates.has("asset_id"))
|
||||
{
|
||||
updates.erase("asset_id");
|
||||
updates["hash_id"] = update_item->getTransactionID();
|
||||
if (update_item->getTransactionID().notNull())
|
||||
{
|
||||
updates["hash_id"] = update_item->getTransactionID();
|
||||
}
|
||||
}
|
||||
if (updates.has("shadow_id"))
|
||||
{
|
||||
updates.erase("shadow_id");
|
||||
updates["hash_id"] = update_item->getTransactionID();
|
||||
if (update_item->getTransactionID().notNull())
|
||||
{
|
||||
updates["hash_id"] = update_item->getTransactionID();
|
||||
}
|
||||
}
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
|
||||
ais_ran = cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::UpdateItem(item_id, updates, cr);
|
||||
}
|
||||
if (!ais_ran)
|
||||
else
|
||||
{
|
||||
LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
|
||||
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
|
||||
@@ -1351,19 +1412,15 @@ void update_inventory_item(
|
||||
// baking when using AISv3. Its omission looks likeley to be inconsequental, but if that's incorrect
|
||||
// any bugs introduced by its removal are minor compared to non-functional serverside baking.
|
||||
|
||||
bool ais_ran = false;
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
|
||||
ais_ran = cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::UpdateItem(item_id, updates, cr);
|
||||
}
|
||||
|
||||
if (!ais_ran)
|
||||
else
|
||||
{
|
||||
LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
|
||||
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
|
||||
LLPointer<LLViewerInventoryItem> new_item = NULL;
|
||||
|
||||
if(obj)
|
||||
{
|
||||
LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
|
||||
@@ -1410,12 +1467,11 @@ void update_inventory_category(
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
|
||||
new_cat->fromLLSD(updates);
|
||||
// FIXME - restore this once the back-end work has been done.
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD new_llsd = new_cat->asLLSD();
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
|
||||
cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::UpdateCategory(cat_id, new_llsd, cr);
|
||||
}
|
||||
else // no cap
|
||||
{
|
||||
@@ -1477,10 +1533,10 @@ void remove_inventory_item(
|
||||
{
|
||||
const LLUUID item_id(obj->getUUID());
|
||||
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL;
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
|
||||
cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
|
||||
AISAPI::RemoveItem(item_id, cr);
|
||||
|
||||
if (immediate_delete)
|
||||
{
|
||||
@@ -1553,10 +1609,10 @@ void remove_inventory_category(
|
||||
LLNotificationsUtil::add("CannotRemoveProtectedCategories");
|
||||
return;
|
||||
}
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
|
||||
cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::RemoveCategory(cat_id, cr);
|
||||
}
|
||||
else // no cap
|
||||
{
|
||||
@@ -1656,10 +1712,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
|
||||
cmd_ptr->run_command();
|
||||
AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
|
||||
AISAPI::PurgeDescendents(id, cr);
|
||||
}
|
||||
else // no cap
|
||||
{
|
||||
@@ -1872,12 +1928,13 @@ void slam_inventory_folder(const LLUUID& folder_id,
|
||||
const LLSD& contents,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
if (AISCommand::isAPIAvailable())
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id
|
||||
<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
|
||||
boost::intrusive_ptr<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
|
||||
cmd_ptr->run_command();
|
||||
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::SlamFolder(folder_id, contents, cr);
|
||||
}
|
||||
else // no cap
|
||||
{
|
||||
@@ -2303,8 +2360,9 @@ LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_i
|
||||
item_iter != items.end();
|
||||
++item_iter)
|
||||
{
|
||||
const LLViewerInventoryItem *item = (*item_iter);
|
||||
if (true) return item->getUUID();
|
||||
const LLViewerInventoryItem *item = (*item_iter);
|
||||
if(item)
|
||||
return item->getUUID();
|
||||
}
|
||||
return LLUUID::null;
|
||||
}
|
||||
|
||||
@@ -1905,7 +1905,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
||||
capabilityNames.append("FetchInventoryDescendents2");
|
||||
capabilityNames.append("IncrementCOFVersion");
|
||||
capabilityNames.append("GamingData"); //Used by certain grids.
|
||||
AISCommand::getCapabilityNames(capabilityNames);
|
||||
AISAPI::getCapNames(capabilityNames);
|
||||
capabilityNames.append("GetDisplayNames");
|
||||
capabilityNames.append("GetMesh");
|
||||
capabilityNames.append("GetMesh2"); // Used on SecondLife(tm) sim versions 280647 and higher (13.09.17).
|
||||
|
||||
Reference in New Issue
Block a user