diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 99716ed7be..3135de66cb 100755 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -86,9 +86,13 @@ public: void setType(LLAssetType::EType type); virtual void setCreationDate(time_t creation_date_utc); // only stored for items -private: +// [RLVa:KB] - Checked: 2014-01-07 (RLVa-1.4.10) // in place correction for inventory name string - void correctInventoryName(std::string& name); + static void correctInventoryName(std::string& name); +// [/RLVa:KB] +private: +// // in place correction for inventory name string +// void correctInventoryName(std::string& name); //-------------------------------------------------------------------- // File Support diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3fb5a7dfa3..d75cbae5bb 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1573,11 +1573,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // This is an offer from an agent. In this case, the back // end has already copied the items into your inventory, // so we can fetch it out of our inventory. -// [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e - if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) && - (RlvInventory::instance().getSharedRoot()) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) ) +// [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0) + if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) ) { - RlvGiveToRLVAgentOffer* pOfferObserver = new RlvGiveToRLVAgentOffer(mObjectID); + RlvGiveToRLVAgentOffer* pOfferObserver = new RlvGiveToRLVAgentOffer(mObjectID, mDesc); pOfferObserver->startFetch(); if (pOfferObserver->isFinished()) pOfferObserver->done(); diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 208875a15a..cc51ab42ef 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -101,6 +101,8 @@ const S32 RLVa_VERSION_BUILD = 0; #define RLV_ROOT_FOLDER "#RLV" #define RLV_CMD_PREFIX '@' #define RLV_PUTINV_PREFIX "#RLV/~" +#define RLV_PUTINV_SEPARATOR "/" +#define RLV_PUTINV_MAXDEPTH 4 #define RLV_SETROT_OFFSET F_PI_BY_TWO // @setrot is off by 90° with the rest of SL #define RLV_STRINGS_FILE "rlva_strings.xml" diff --git a/indra/newview/rlvinventory.cpp b/indra/newview/rlvinventory.cpp index 48ef600027..af28ee4874 100644 --- a/indra/newview/rlvinventory.cpp +++ b/indra/newview/rlvinventory.cpp @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2011, Kitty Barnett + * Copyright (c) 2009-2014, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -503,6 +503,82 @@ void RlvRenameOnWearObserver::onCategoryCreate(const LLSD& sdData, void* pParam) // "Give to #RLV" helper classes // +// Checked: 2014-01-07 (RLVa-1.4.10) +RlvGiveToRLVOffer::RlvGiveToRLVOffer(const std::string& strPath) +{ + if (0 == strPath.find(RLV_PUTINV_PREFIX)) + { + boost::split(m_DestPath, strPath, boost::is_any_of(std::string(RLV_PUTINV_SEPARATOR))); + } +} + +// Checked: 2014-01-07 (RLVa-1.4.10) +bool RlvGiveToRLVOffer::createDestinationFolder() +{ + // NOTE: derived classes will delete the instance in their onDestinationCreated override, so don't do anything after triggering the callback + + if ( (m_DestPath.size() >= 2) && (m_DestPath.size() <= RLV_PUTINV_MAXDEPTH) ) + { + const std::string strFolder = m_DestPath.front(); + if (RLV_ROOT_FOLDER == strFolder) + { + m_DestPath.pop_front(); + + const LLUUID& idRlvRoot = RlvInventory::instance().getSharedRootID(); + if (idRlvRoot.notNull()) + { + onCategoryCreateCallback(LLSD().with("folder_id", idRlvRoot), this); + } + else + { + const LLUUID idTemp = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, onCategoryCreateCallback, (void*)this); + if (idTemp.notNull()) + onCategoryCreateCallback(LLSD().with("folder_id", idTemp), this); + } + return true; + } + } + m_DestPath.clear(); + return false; +} + +// Checked: 2014-01-07 (RLVa-1.4.10) +void RlvGiveToRLVOffer::onCategoryCreateCallback(const LLSD& sdData, void* pInstance) +{ + RlvGiveToRLVOffer* pThis = (RlvGiveToRLVOffer*)pInstance; + + LLUUID idFolder = sdData["folder_id"].asUUID(); + if (idFolder.isNull()) + { + // Problem encountered, abort move + pThis->onDestinationCreated(LLUUID::null, LLStringUtil::null); + return; + } + + while (pThis->m_DestPath.size() > 1) + { + std::string strFolder = pThis->m_DestPath.front(); + pThis->m_DestPath.pop_front(); + + LLViewerInventoryCategory* pFolder = RlvInventory::instance().getSharedFolder(idFolder, strFolder); + if (pFolder) + { + idFolder = pFolder->getUUID(); + } + else + { + LLInventoryObject::correctInventoryName(strFolder); + const LLUUID idTemp = gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, onCategoryCreateCallback, pInstance); + if (idTemp.notNull()) + onCategoryCreateCallback(LLSD().with("folder_id", idTemp), pInstance); + return; + } + } + + // Destination folder should exist at this point (we'll be deallocated when the function returns) + pThis->onDestinationCreated(idFolder, pThis->m_DestPath.front()); +} + // Checked: 2010-04-18 (RLVa-1.2.0e) | Added: RLVa-1.2.0e void RlvGiveToRLVTaskOffer::changed(U32 mask) { @@ -568,7 +644,7 @@ void RlvGiveToRLVTaskOffer::doneIdle() delete this; } -// Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e +// Checked: 2010-04-18 (RLVa-1.2.0) void RlvGiveToRLVAgentOffer::done() { gInventory.removeObserver(this); @@ -577,33 +653,42 @@ void RlvGiveToRLVAgentOffer::done() doOnIdleOneTime(boost::bind(&RlvGiveToRLVAgentOffer::doneIdle, this)); } -// Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e +// Checked: 2014-01-07 (RLVa-1.4.10) void RlvGiveToRLVAgentOffer::doneIdle() { - const LLViewerInventoryCategory* pRlvRoot = RlvInventory::instance().getSharedRoot(); - const LLViewerInventoryCategory* pFolder = (mComplete.size()) ? gInventory.getCategory(mComplete[0]) : NULL; - if ( (pRlvRoot) && (pFolder) ) + if (!createDestinationFolder()) { - std::string strName = pFolder->getName(); - if (strName.find(RLV_PUTINV_PREFIX) == 0) + delete this; + } +} + +// Checked: 2010-04-18 (RLVa-1.2.0) +void RlvGiveToRLVAgentOffer::onDestinationCreated(const LLUUID& idFolder, const std::string& strName) +{ + if (idFolder.notNull()) + { + const LLViewerInventoryCategory* pTarget = gInventory.getCategory(idFolder); + const LLViewerInventoryCategory* pFolder = (mComplete.size()) ? gInventory.getCategory(mComplete[0]) : NULL; + if ( (pTarget) && (pFolder) ) { LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate updOldParent(pFolder->getParentUUID(), -1); update.push_back(updOldParent); - LLInventoryModel::LLCategoryUpdate updNewParent(pRlvRoot->getUUID(), 1); + LLInventoryModel::LLCategoryUpdate updNewParent(pTarget->getUUID(), 1); update.push_back(updNewParent); gInventory.accountForUpdate(update); LLPointer pNewFolder = new LLViewerInventoryCategory(pFolder); - pNewFolder->setParent(pRlvRoot->getUUID()); + pNewFolder->setParent(pTarget->getUUID()); pNewFolder->updateParentOnServer(FALSE); - pNewFolder->rename(strName.erase(0, strName.find(RLV_FOLDER_PREFIX_PUTINV))); + pNewFolder->rename(strName); pNewFolder->updateServer(FALSE); gInventory.updateCategory(pNewFolder); gInventory.notifyObservers(); } } + delete this; } diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 1899ece4e0..9001fa966d 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2011, Kitty Barnett + * Copyright (c) 2009-2014, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -118,6 +118,22 @@ protected: // "Give to #RLV" helper classes // +class RlvGiveToRLVOffer +{ +protected: + RlvGiveToRLVOffer(const std::string& strPath); + virtual ~RlvGiveToRLVOffer() {} + +protected: + bool createDestinationFolder(); + virtual void onDestinationCreated(const LLUUID& idFolder, const std::string& strName) = 0; +private: + static void onCategoryCreateCallback(const LLSD& sdData, void* pInstance); + +private: + std::list m_DestPath; +}; + // [See LLInventoryTransactionObserver which says it's not entirely complete?] // NOTE: the offer may span mulitple BulkUpdateInventory messages so if we're no longer around then (ie due to "delete this") then // we'll miss those; in this specific case we only care about the *folder* though and that will be in the very first message @@ -135,13 +151,17 @@ protected: LLUUID m_idTransaction; }; -class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver +class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver, RlvGiveToRLVOffer { public: - RlvGiveToRLVAgentOffer(const LLUUID& idFolder) : LLInventoryFetchDescendentsObserver(idFolder) {} + RlvGiveToRLVAgentOffer(const LLUUID& idFolder, const std::string& strDestPath) : LLInventoryFetchDescendentsObserver(idFolder), RlvGiveToRLVOffer(strDestPath) {} + /*virtual*/ ~RlvGiveToRLVAgentOffer() {} + +public: /*virtual*/ void done(); protected: - void doneIdle(); + void doneIdle(); + /*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName); }; // ============================================================================