diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 21d6b84ec7044fd9a4b00ec7aa3422e00f374489..2764c3561ca49ffad1dbb83c827340b86ad0a4aa 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2740,6 +2740,66 @@ BOOL LLTextEditor::exportBuffer(std::string &buffer ) return TRUE; } +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + +// Copy/paste from LLScriptEdCore +bool LLTextEditor::loadFromFile(const std::string& filename) +{ + if (filename.empty()) + { + LL_WARNS() << "Empty file name" << LL_ENDL; + return false; + } + + LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + if (!file) + { + LL_WARNS() << "Error opening " << filename << LL_ENDL; + return false; + } + + // read in the whole file + fseek(file, 0L, SEEK_END); + size_t file_length = (size_t) ftell(file); + fseek(file, 0L, SEEK_SET); + char* buffer = new char[file_length+1]; + size_t nread = fread(buffer, 1, file_length, file); + if (nread < file_length) + { + LL_WARNS() << "Short read" << LL_ENDL; + } + buffer[nread] = '\0'; + fclose(file); + + setText(LLStringExplicit(buffer)); + delete[] buffer; + + return true; +} + +// Copy/paste from LLScriptEdCore +bool LLTextEditor::writeToFile(const std::string& filename) +{ + LLFILE* fp = LLFile::fopen(filename, "wb"); + if (!fp) + { + return false; + } + + std::string utf8text = getText(); + + // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 + if (utf8text.size() == 0) + { + utf8text = " "; + } + + fputs(utf8text.c_str(), fp); + fclose(fp); + return true; +} +// [/SL:KB] + void LLTextEditor::updateAllowingLanguageInput() { LLWindow* window = getWindow(); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 5a38d55c476fdd4cd531eb657967cb811eebb66e..c7c024cdb47a4c185b91197c70db0969893e3ff1 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -198,6 +198,12 @@ class LLTextEditor : virtual BOOL importBuffer(const char* buffer, S32 length ); virtual BOOL exportBuffer(std::string& buffer ); +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + // NOTE-Catznip: doesn't save embedded items, text only + bool loadFromFile(const std::string& filename); + bool writeToFile(const std::string& filename); +// [/SL:KB] + const LLUUID& getSourceID() const { return mSourceID; } const LLTextSegmentPtr getPreviousSegment() const; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index be5950a5941b94c5abe71bbde7b5be416d4e2f50..3a41831e5eca3fad792946c46999d05b62104ecc 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -228,6 +228,7 @@ set(viewer_SOURCE_FILES llfirstuse.cpp llflexibleobject.cpp llfloaterabout.cpp + llfloaterassetrecovery.cpp llfloaterbvhpreview.cpp llfloaterauction.cpp llfloaterautoreplacesettings.cpp @@ -888,6 +889,7 @@ set(viewer_HEADER_FILES llfirstuse.h llflexibleobject.h llfloaterabout.h + llfloaterassetrecovery.h llfloaterbvhpreview.h llfloaterauction.h llfloaterautoreplacesettings.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c0ad1b12efc41df058a3297243d4050bcae28581..c536a73e5c1ecaa28a2528c3ead5da75c005872b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -108,6 +108,9 @@ // [/RLVa:KB] #include "llweb.h" +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2011-11-24 (Catznip-3.2) +#include "llfloaterassetrecovery.h" +// [/SL:KB] #include "llfloatertexturefetchdebugger.h" #include "llspellcheck.h" #include "llscenemonitor.h" @@ -5627,6 +5630,10 @@ void LLAppViewer::handleLoginComplete() mOnLoginCompleted(); +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2011-11-24 (Catznip-3.2) + LLAssetRecoverQueue::recoverIfNeeded(); +// [/SL:KB] + writeDebugInfo(); // we logged in successfully, so save settings on logout diff --git a/indra/newview/llfloaterassetrecovery.cpp b/indra/newview/llfloaterassetrecovery.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d5ce3c19a6b3417fd0757cf303240900f0cfe6b --- /dev/null +++ b/indra/newview/llfloaterassetrecovery.cpp @@ -0,0 +1,389 @@ +/** + * + * Copyright (c) 2011-2016, 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; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llcheckboxctrl.h" +#include "lldiriterator.h" +#include "llfloaterreg.h" +#include "llfloaterperms.h" +#include "llfolderview.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llscrolllistctrl.h" +#include "llviewerassettype.h" +#include "llviewerinventory.h" +#include "llviewerregion.h" +#include "llviewerassetupload.h" + +#include "llfloaterassetrecovery.h" + +// ============================================================================ +// LLFloaterAssetRecovery +// + +LLFloaterAssetRecovery::LLFloaterAssetRecovery(const LLSD& sdKey) + : LLFloater(sdKey) +{ +} + +void LLFloaterAssetRecovery::onOpen(const LLSD& sdKey) +{ + LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("item_list"); + + LLSD sdBhvrRow; LLSD& sdBhvrColumns = sdBhvrRow["columns"]; + sdBhvrColumns[0] = LLSD().with("column", "item_check").with("type", "checkbox"); + sdBhvrColumns[1] = LLSD().with("column", "item_name").with("type", "text"); + sdBhvrColumns[2] = LLSD().with("column", "item_type").with("type", "text"); + + pListCtrl->clearRows(); + for (LLSD::array_const_iterator itFile = sdKey["files"].beginArray(), endFile = sdKey["files"].endArray(); + itFile != endFile; ++itFile) + { + const LLSD& sdFile = *itFile; + + sdBhvrRow["value"] = sdFile; + sdBhvrColumns[0]["value"] = true; + sdBhvrColumns[1]["value"] = sdFile["name"]; + sdBhvrColumns[2]["value"] = sdFile["type"]; + + pListCtrl->addElement(sdBhvrRow, ADD_BOTTOM); + } +} + +BOOL LLFloaterAssetRecovery::postBuild() +{ + findChild<LLUICtrl>("recover_btn")->setCommitCallback(boost::bind(&LLFloaterAssetRecovery::onBtnRecover, this)); + findChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterAssetRecovery::onBtnCancel, this)); + + return TRUE; +} + +void LLFloaterAssetRecovery::onBtnCancel() +{ + LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("item_list"); + + // Delete all listed files + std::vector<LLScrollListItem*> items = pListCtrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator itItem = items.begin(); itItem != items.end(); ++itItem) + { + LLFile::remove((*itItem)->getValue()["path"].asString()); + } + + closeFloater(); +} + +void LLFloaterAssetRecovery::onBtnRecover() +{ + LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("item_list"); + + // Recover all selected, delete any unselected + std::vector<LLScrollListItem*> items = pListCtrl->getAllData(); LLSD sdFiles; + for (std::vector<LLScrollListItem*>::const_iterator itItem = items.begin(); itItem != items.end(); ++itItem) + { + LLScrollListCheck* pCheckColumn = dynamic_cast<LLScrollListCheck*>((*itItem)->getColumn(0)); + if (!pCheckColumn) + continue; + + const LLSD sdFile = (*itItem)->getValue(); + if (pCheckColumn->getCheckBox()->getValue().asBoolean()) + sdFiles.append(sdFile); + else + LLFile::remove(sdFile["path"]); + } + + if (!sdFiles.emptyArray()) + new LLAssetRecoverQueue(sdFiles); + + closeFloater(); +} + +// ============================================================================ +// LLCreateRecoverAssetCallback +// + +class LLCreateRecoverAssetCallback : public LLInventoryCallback +{ +public: + LLCreateRecoverAssetCallback(LLAssetRecoverQueue* pRecoverQueue) + : LLInventoryCallback(), mRecoverQueue(pRecoverQueue) + { + } + + void fire(const LLUUID& idItem) + { + mRecoverQueue->onCreateItem(idItem); + } + +protected: + LLAssetRecoverQueue* mRecoverQueue; +}; + +// ============================================================================ +// Helper functions +// + +// static +static bool removeEmbeddedMarkers(const std::string& strFilename) +{ + std::ifstream inNotecardFile(strFilename.c_str(), std::ios::in | std::ios::binary); + if (!inNotecardFile.is_open()) + return false; + + std::string strText((std::istreambuf_iterator<char>(inNotecardFile)), std::istreambuf_iterator<char>()); + inNotecardFile.close(); + + std::string::size_type idxText = strText.find((char)'\xF4', 0), lenText = strText.length(); + while ( (std::string::npos != idxText) && (idxText + 4 <= lenText) ) + { + // In UTF-8 we're looking for F4808080-F48FBFBF + char chByte2 = strText[idxText + 1]; + char chByte3 = strText[idxText + 2]; + char chByte4 = strText[idxText + 3]; + if ( ((chByte2 >= '\x80') && (chByte2 <= '\x8F')) && + ((chByte3 >= '\x80') && (chByte3 <= '\xBF')) && + ((chByte4 >= '\x80') && (chByte4 <= '\xBF')) ) + { + // We're being lazy and replacing embedded markers with spaces since we don't want to adjust the notecard length field + strText.replace(idxText, 4, 4, ' '); + continue; + } + idxText = strText.find('\xF4', idxText + 1); + } + + std::ofstream outNotecardFile(strFilename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); + if (!outNotecardFile.is_open()) + return false; + + outNotecardFile.write(strText.c_str(), strText.length()); + outNotecardFile.close(); + + return true; +} + +// ============================================================================ +// LLAssetRecoverQueue +// + +static void findRecoverFiles(LLSD& sdFiles, const std::string& strPath, const std::string& strMask, const std::string& strType) +{ + LLDirIterator itFiles(strPath, strMask); std::string strFilename; + while (itFiles.next(strFilename)) + { + // Build a friendly name for the file + std::string strName = gDirUtilp->getBaseFileName(strFilename, true); + std::string::size_type offset = strName.find_last_of("-"); + if ( (std::string::npos != offset) && (offset != 0) && (offset == strName.length() - 9)) + strName.erase(strName.length() - 9); + + LLStringUtil::trim(strName); + if (0 == strName.length()) + strName = llformat("(Unknown %s)", strType.c_str()); + + sdFiles.append(LLSD().with("path", strPath + strFilename).with("name", strName).with("type", strType)); + } +} + +// static +void LLAssetRecoverQueue::recoverIfNeeded() +{ + const std::string strTempPath = LLFile::tmpdir(); + LLSD sdData, &sdFiles = sdData["files"]; + + findRecoverFiles(sdFiles, strTempPath, "*.lslbackup", "script"); + findRecoverFiles(sdFiles, strTempPath, "*.ncbackup", "notecard"); + + if (sdFiles.size()) + { + LLFloaterReg::showInstance("asset_recovery", sdData); + } +} + +LLAssetRecoverQueue::LLAssetRecoverQueue(const LLSD& sdFiles) +{ + for (LLSD::array_const_iterator itFile = sdFiles.beginArray(), endFile = sdFiles.endArray(); itFile != endFile; ++itFile) + { + const LLSD& sdFile = *itFile; + if (LLFile::isfile(sdFile["path"])) + { + LLAssetRecoverItem recoveryItem; + recoveryItem.strPath = sdFile["path"].asString(); + recoveryItem.strName = sdFile["name"].asString(); + + // Figure out the asset type + if ("script" == sdFile["type"].asString()) + recoveryItem.eAssetType = LLAssetType::AT_LSL_TEXT; + else if ("notecard" == sdFile["type"].asString()) + recoveryItem.eAssetType = LLAssetType::AT_NOTECARD; + + // Generate description + LLViewerAssetType::generateDescriptionFor(recoveryItem.eAssetType, recoveryItem.strDescription); + + // Per asset type handling + switch (recoveryItem.eAssetType) + { + case LLAssetType::AT_LSL_TEXT: + recoveryItem.eInvType = LLInventoryType::IT_LSL; + recoveryItem.nNextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Scripts"); + break; + case LLAssetType::AT_NOTECARD: + recoveryItem.eInvType = LLInventoryType::IT_NOTECARD; + recoveryItem.nNextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Notecards"); + removeEmbeddedMarkers(recoveryItem.strPath); + break; + } + + if (recoveryItem.eAssetType != LLAssetType::AT_NONE) + m_RecoveryQueue.push_back(recoveryItem); + } + } + + if (!m_RecoveryQueue.empty()) + recoverNext(); + else + delete this; +} + +bool LLAssetRecoverQueue::recoverNext() +{ + /** + * Steps: + * (1) create a script/notecard inventory item under "Lost and Found" + * (2) once we have the item's UUID we can upload it + * (3) once the asset is uploaded we move on to the next item + */ + const LLUUID idFNF = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + + // If the associated UUID is non-null then this file is already being processed + auto itItem = m_RecoveryQueue.cbegin(); + while ( (m_RecoveryQueue.cend() != itItem) && (itItem->idItem.notNull()) ) + ++itItem; + + // Empty queue - pop-up inventory floater + if (m_RecoveryQueue.cend() == itItem) + { + LLInventoryPanel* pInvPanel = LLInventoryPanel::getActiveInventoryPanel(TRUE); + if (pInvPanel) + { + LLFolderViewFolder* pFVF = dynamic_cast<LLFolderViewFolder*>(pInvPanel->getItemByID(idFNF)); + if (pFVF) + { + pFVF->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + pInvPanel->setSelection(idFNF, TRUE); + } + } + + delete this; + return false; + } + + // Otherwise start the recovery cycle + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), idFNF, LLTransactionID::tnull, + itItem->strName, itItem->strDescription, itItem->eAssetType, itItem->eInvType, + NO_INV_SUBTYPE, itItem->nNextOwnerPerm, new LLCreateRecoverAssetCallback(this)); + return true; +} + +void LLAssetRecoverQueue::onCreateItem(const LLUUID& idItem) +{ + const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); + if (!pItem) + { + // CATZ-TODO: error handling (can't call onUploadError or we'll create an endless loop) + return; + } + + // Viewer will localize 'New Script' so we have to undo that + std::string strItemName = pItem->getName(); + LLViewerInventoryItem::lookupSystemName(strItemName); + + auto itItem = m_RecoveryQueue.begin(); + while (m_RecoveryQueue.end() != itItem) + { + if (itItem->strName == strItemName) + break; + ++itItem; + } + + if (m_RecoveryQueue.end() != itItem) + { + itItem->idItem = idItem; + + std::string strCapsUrl, strBuffer; + + std::ifstream inNotecardFile(itItem->strPath.c_str(), std::ios::in | std::ios::binary); + if (inNotecardFile.is_open()) + { + strBuffer.assign((std::istreambuf_iterator<char>(inNotecardFile)), std::istreambuf_iterator<char>()); + inNotecardFile.close(); + } + + LLResourceUploadInfo::ptr_t uploadInfo; + switch (pItem->getType()) + { + case LLAssetType::AT_LSL_TEXT: + strCapsUrl = gAgent.getRegion()->getCapability("UpdateScriptAgent"); + uploadInfo = LLResourceUploadInfo::ptr_t(new LLScriptAssetUpload(idItem, strBuffer, boost::bind(&LLAssetRecoverQueue::onSavedAsset, this, _1, _4))); + break; + case LLAssetType::AT_NOTECARD: + strCapsUrl = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory"); + uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(itItem->idItem, LLAssetType::AT_NOTECARD, strBuffer, boost::bind(&LLAssetRecoverQueue::onSavedAsset, this, _1, _4))); + break; + } + + if ( (!strCapsUrl.empty()) && (uploadInfo) ) + { + uploadInfo->setUploadErrorCb(boost::bind(&LLAssetRecoverQueue::onUploadError, this, _1)); + LLViewerAssetUpload::EnqueueInventoryUpload(strCapsUrl, uploadInfo); + return; + } + } + + // CATZ-TODO: error handling (if we can't find the current item) +} + +void LLAssetRecoverQueue::onSavedAsset(const LLUUID& idItem, const LLSD& sdResponse) +{ + const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); + if (pItem) + { + auto itItem = std::find_if(m_RecoveryQueue.begin(), m_RecoveryQueue.end(), [&idItem](const LLAssetRecoverItem& item)->bool { return item.idItem == idItem; }); + if (m_RecoveryQueue.end() != itItem) + { + LLFile::remove(itItem->strPath); + m_RecoveryQueue.erase(itItem); + } + } + recoverNext(); +} + +void LLAssetRecoverQueue::onUploadError(const LLUUID& idItem) +{ + // Skip over the file when there's an error, we can try again on the next relog + auto itItem = std::find_if(m_RecoveryQueue.begin(), m_RecoveryQueue.end(), [&idItem](const LLAssetRecoverItem& item)->bool { return item.idItem == idItem; }); + if (m_RecoveryQueue.end() != itItem) + { + LLViewerInventoryItem* pItem = gInventory.getItem(itItem->idItem); + if (pItem) + gInventory.changeItemParent(pItem, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH), FALSE); + m_RecoveryQueue.erase(itItem); + } + recoverNext(); +} + +// ============================================================================ diff --git a/indra/newview/llfloaterassetrecovery.h b/indra/newview/llfloaterassetrecovery.h new file mode 100644 index 0000000000000000000000000000000000000000..b0794eff8e7062092e7c404957c8dd1db8be5410 --- /dev/null +++ b/indra/newview/llfloaterassetrecovery.h @@ -0,0 +1,93 @@ +/** + * + * Copyright (c) 2011-2016, 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; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#ifndef LL_FLOATERSCRIPTRECOVER_H +#define LL_FLOATERSCRIPTRECOVER_H + +#include "llfloater.h" + +// ============================================================================ +// LLFloaterAssetRecovery class +// + +class LLFloaterAssetRecovery : public LLFloater +{ + friend class LLFloaterReg; +private: + LLFloaterAssetRecovery(const LLSD& sdKey); + + /* + * LLFloater overrides + */ +public: + /*virtual*/ void onOpen(const LLSD& sdKey); + /*virtual*/ BOOL postBuild(); + + /* + * Member functions + */ +protected: + void onBtnCancel(); + void onBtnRecover(); +}; + +// ============================================================================ +// LLAssetRecoverQueue class +// + +class LLAssetRecoverQueue +{ + friend class LLCreateRecoverAssetCallback; + friend class LLFloaterAssetRecovery; + + struct LLAssetRecoverItem + { + std::string strPath; + std::string strName; + std::string strDescription; + LLAssetType::EType eAssetType; + LLInventoryType::EType eInvType; + U32 nNextOwnerPerm; + LLUUID idItem; + + LLAssetRecoverItem() : eAssetType(LLAssetType::AT_NONE), eInvType(LLInventoryType::IT_NONE) {} + }; +protected: + LLAssetRecoverQueue(const LLSD& sdFiles); + + /* + * Member functions + */ +public: + static void recoverIfNeeded(); +protected: + bool recoverNext(); + + void onCreateItem(const LLUUID& idItem); + void onSavedAsset(const LLUUID& idItem, const LLSD& sdResponse); + void onUploadError(const LLUUID& idItem); + + /* + * Member variables + */ +protected: + typedef std::list<LLAssetRecoverItem> recovery_list_t; + recovery_list_t m_RecoveryQueue; +}; + +// ============================================================================ + +#endif // LL_FLOATERSCRIPTRECOVER_H diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 4b7f90deda7c77108ac404ff70149416916588da..5cecf435467a3ba4113d87db7140a9b2b7dcbac8 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -57,10 +57,29 @@ #include "lltrans.h" #include "roles_constants.h" +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) +#include "lleventtimer.h" + +/// --------------------------------------------------------------------------- +/// Timer helper class +/// --------------------------------------------------------------------------- +class LLPreviewBackupTimer : public LLEventTimer +{ +public: + LLPreviewBackupTimer(F32 nPeriod, LLPreview* pPreview) : LLEventTimer(nPeriod), mPreview(pPreview) {} + /*virtual*/ BOOL tick() { mPreview->onBackupTimer(); return false; } +protected: + LLPreview* mPreview; +}; +// [/SL:KB] + // Constants LLPreview::LLPreview(const LLSD& key) : LLFloater(key), +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + mBackupTimer(NULL), +// [/SL:KB] mItemUUID(key.has("itemid") ? key.get("itemid").asUUID() : key.asUUID()), mObjectUUID(), // set later by setObjectID() mCopyToInvBtn( NULL ), @@ -90,6 +109,15 @@ LLPreview::~LLPreview() { gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() gInventory.removeObserver(this); + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Clean up the backup file (unless we've gotten disconnected) + if ( (gAgent.getRegion()) && (hasBackupFile()) ) + { + removeBackupFile(); + } + delete mBackupTimer; +// [/SL:KB] } void LLPreview::setObjectID(const LLUUID& object_id) @@ -239,6 +267,18 @@ void LLPreview::refreshFromItem() getChild<LLUICtrl>("desc")->setValue(item->getDescription()); getChildView("desc")->setEnabled(canModify(mObjectUUID, item)); + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + if (hasBackupFile()) + { + const std::string strFilename = getBackupFileName(); + if (strFilename != mBackupFilename) + { + LLFile::rename(mBackupFilename, strFilename); + mBackupFilename = strFilename; + } + } +// [/SL:KB] } // static @@ -471,6 +511,63 @@ void LLPreview::handleReshape(const LLRect& new_rect, bool by_user) LLFloater::handleReshape(new_rect, by_user); } +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) +void LLPreview::startBackupTimer(F32 nInterval) +{ + if (nInterval > 0.0f) + { + if (mBackupTimer) + delete mBackupTimer; + mBackupTimer = new LLPreviewBackupTimer(nInterval, this); + } + else + { + delete mBackupTimer; + mBackupTimer = NULL; + } +} + +void LLPreview::removeBackupFile() +{ + if (hasBackupFile()) + { + LLFile::remove(mBackupFilename); + mBackupFilename.clear(); + } +} + +std::string LLPreview::getBackupFileName() const +{ + // NOTE: this function is not guaranteed to return the same filename every time (i.e. the item name may have changed) + std::string strFile = LLFile::tmpdir(); + + // Find the inventory item for this preview + const LLInventoryItem* pItem = getItem(); + if (pItem) + { + strFile += gDirUtilp->getScrubbedFileName(pItem->getName().substr(0, 32)); + strFile += "-"; + } + + // Append a CRC of the item UUID to make the filename (hopefully) unique + LLCRC crcUUID; + crcUUID.update((U8*)(&mItemUUID.mData), UUID_BYTES); + strFile += llformat("%X", crcUUID.getCRC()); + + std::string strTypeExt; + if (pItem) + { + if (LLAssetType::AT_LSL_TEXT == getItem()->getType()) + strTypeExt = "lsl"; + else if (LLAssetType::AT_NOTECARD == getItem()->getType()) + strTypeExt = "nc"; + } + strFile.append(".").append(strTypeExt).append("backup"); + + return strFile; +} +// [/SL:KB] + // // LLMultiPreview // diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 2ee76d590eadb7c1da853b16b62d13ba29ee9167..5269233a7fa0d12a55a88090b4ef7ca73593c408 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -39,6 +39,9 @@ class LLInventoryItem; class LLLineEditor; class LLRadioGroup; class LLPreview; +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) +class LLEventTimer; +// [/SL:KB] class LLMultiPreview final : public LLMultiFloater { @@ -110,6 +113,20 @@ class LLPreview : public LLFloater, LLInventoryObserver // or Item itself is unmodifiable static BOOL canModify(const LLUUID taskUUID, const LLInventoryItem* item); +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-02-06 (Catznip-3.2) + // Backup functionality +public: + void startBackupTimer(F32 nInterval); + bool hasBackupFile() const { return (!mBackupFilename.empty()); } + bool isBackupRunning() const { return (NULL != mBackupTimer); } + void removeBackupFile(); +protected: + virtual std::string getBackupFileName() const; + virtual void onBackupTimer() {} + + friend class LLPreviewBackupTimer; +// [/SL:KB] + protected: virtual void onCommit(); @@ -152,6 +169,11 @@ class LLPreview : public LLFloater, LLInventoryObserver // I am unsure if this is always the same as mObjectUUID, or why it exists // at the LLPreview level. JC 2009-06-24 LLUUID mNotecardObjectID; + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + std::string mBackupFilename; + LLEventTimer* mBackupTimer; +// [/SL:KB] }; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index e1a8da55a6a4543a0269ab359b33db533b8936a1..9c0921deb329e148fa2088e8f776a48fe92372eb 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -42,6 +42,9 @@ #include "llinventorydefines.h" #include "llinventorymodel.h" #include "lllineeditor.h" +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) +#include "llnotecard.h" +// [/SL:KB] #include "llnotificationsutil.h" #include "llresmgr.h" #include "roles_constants.h" @@ -268,6 +271,14 @@ void LLPreviewNotecard::loadAsset() editor->makePristine(); editor->setEnabled(TRUE); mAssetStatus = PREVIEW_ASSET_LOADED; + +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + // Start the timer which will perform regular backup saves + if (!isBackupRunning()) + { + startBackupTimer(60.0f); + } +// [/SL:KB] } else { @@ -409,6 +420,14 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL; preview->mAssetStatus = PREVIEW_ASSET_ERROR; } + +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + // Start the timer which will perform regular backup saves + if (!preview->isBackupRunning()) + { + preview->startBackupTimer(60.0f); + } +// [/SL:KB] } delete floater_key; } @@ -624,6 +643,44 @@ void LLPreviewNotecard::deleteNotecard() LLNotificationsUtil::add("DeleteNotecard", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleConfirmDeleteDialog,this, _1, _2)); } +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) +void LLPreviewNotecard::onBackupTimer() +{ + LLViewerTextEditor* pEditor = findChild<LLViewerTextEditor>("Notecard Editor"); + if ( (pEditor) && (!pEditor->isPristine()) ) + { + if (mBackupFilename.empty()) + mBackupFilename = getBackupFileName(); + + if (!mBackupFilename.empty()) + { + LLNotecard notecard(LLNotecard::MAX_SIZE); + notecard.setText(pEditor->getText()); + + std::stringstream strmNotecard; + notecard.exportStream(strmNotecard); + + std::ofstream outNotecardFile(mBackupFilename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); + if (outNotecardFile.is_open()) + { + outNotecardFile << strmNotecard.rdbuf(); + outNotecardFile.close(); + } + } + } +} + +void LLPreviewNotecard::callbackSaveComplete() +{ + // Notecard was successfully saved so delete our backup copy if we have one and the editor is still pristine + LLViewerTextEditor* pEditor = findChild<LLViewerTextEditor>("Notecard Editor"); + if ( (pEditor) && (pEditor->isPristine()) && (hasBackupFile()) ) + { + removeBackupFile(); + } +} +// [/SL:KB] + // static void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) { diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index fa2bd9665434fe82ede69e2feee61096bb49c47c..47b7234612446d9e934940fde5181d37bb6554e3 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -83,6 +83,10 @@ class LLPreviewNotecard final : public LLPreview void syncExternal(); +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + void callbackSaveComplete(); +// [/SL:KB] + protected: void updateTitleButtons() override; @@ -91,6 +95,10 @@ class LLPreviewNotecard final : public LLPreview void deleteNotecard(); +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + /*virtual*/ void onBackupTimer(); +// [/SL:KB] + static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 31d55de51b26ee3ac899e605cde6f28cebd152b8..5fa7f408ce43c8adc2b5b9e292d5fc73ab31f541 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -601,49 +601,45 @@ void LLScriptEdCore::makeEditorPristine() bool LLScriptEdCore::loadScriptText(const std::string& filename) { - if (filename.empty()) - { - LL_WARNS() << "Empty file name" << LL_ENDL; - return false; - } - - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ - if (!file) - { - LL_WARNS() << "Error opening " << filename << LL_ENDL; - return false; - } - - // read in the whole file - fseek(file, 0L, SEEK_END); - size_t file_length = (size_t) ftell(file); - fseek(file, 0L, SEEK_SET); - if (file_length > 0) - { - auto buffer = std::make_unique<char[]>(file_length + 1); - size_t nread = fread(buffer.get(), 1, file_length, file); - if (nread < file_length) - { - LL_WARNS() << "Short read" << LL_ENDL; - } - buffer[nread] = '\0'; - fclose(file); - - mEditor->setText(LLStringExplicit(buffer.get())); - } - else - { - LL_WARNS() << "Error getting file size " << filename << LL_ENDL; - fclose(file); - return false; - } - return true; +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + return mEditor->loadFromFile(filename); +// [/SL:KB] +// if (filename.empty()) +// { +// LL_WARNS() << "Empty file name" << LL_ENDL; +// return false; +// } +// +// LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ +// if (!file) +// { +// LL_WARNS() << "Error opening " << filename << LL_ENDL; +// return false; +// } +// +// // read in the whole file +// fseek(file, 0L, SEEK_END); +// size_t file_length = (size_t) ftell(file); +// fseek(file, 0L, SEEK_SET); +// char* buffer = new char[file_length+1]; +// size_t nread = fread(buffer, 1, file_length, file); +// if (nread < file_length) +// { +// LL_WARNS() << "Short read" << LL_ENDL; +// } +// buffer[nread] = '\0'; +// fclose(file); +// +// mEditor->setText(LLStringExplicit(buffer)); +// delete[] buffer; +// +// return true; } bool LLScriptEdCore::writeToFile(const std::string& filename) { - LLFILE* fp = LLFile::fopen(filename, "wb"); - if (!fp) +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2013-07-28 (Catznip-3.6) + if (!mEditor->writeToFile(filename)) { LL_WARNS() << "Unable to write to " << filename << LL_ENDL; @@ -653,18 +649,31 @@ bool LLScriptEdCore::writeToFile(const std::string& filename) mErrorList->addElement(row); return false; } - - std::string utf8text = mEditor->getText(); - - // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 - if (utf8text.size() == 0) - { - utf8text = " "; - } - - fputs(utf8text.c_str(), fp); - fclose(fp); return true; +// [/SL:KB] +// LLFILE* fp = LLFile::fopen(filename, "wb"); +// if (!fp) +// { +// LL_WARNS() << "Unable to write to " << filename << LL_ENDL; +// +// LLSD row; +// row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?"; +// row["columns"][0]["font"] = "SANSSERIF_SMALL"; +// mErrorList->addElement(row); +// return false; +// } +// +// std::string utf8text = mEditor->getText(); +// +// // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 +// if (utf8text.size() == 0) +// { +// utf8text = " "; +// } +// +// fputs(utf8text.c_str(), fp); +// fclose(fp); +// return true; } void LLScriptEdCore::sync() @@ -1464,6 +1473,18 @@ LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) : { } +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) +void LLScriptEdContainer::onBackupTimer() +{ + if ( (mScriptEd) && (mScriptEd->hasChanged()) ) + { + if (mBackupFilename.empty()) + mBackupFilename = getBackupFileName(); + mScriptEd->writeToFile(mBackupFilename); + } +} +// [/SL:KB] + std::string LLScriptEdContainer::getTmpFileName() { // Take script inventory item id (within the object inventory) @@ -1567,6 +1588,15 @@ void LLPreviewLSL::callbackLSLCompileSucceeded() LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Script was successfully saved so delete our backup copy if we have one and the editor is still pristine + if ( (!mScriptEd->hasChanged()) && (hasBackupFile()) ) + { + removeBackupFile(); + } +// [/SL:KB] + closeIfNeeded(); } @@ -1587,6 +1617,15 @@ void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) mScriptEd->mErrorList->addElement(row); } mScriptEd->selectFirstError(); + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Script was successfully saved so delete our backup copy if we have one and the editor is still pristine + if ( (!mScriptEd->hasChanged()) && (hasBackupFile()) ) + { + removeBackupFile(); + } +// [/SL:KB] + closeIfNeeded(); } @@ -1710,7 +1749,10 @@ void LLPreviewLSL::finishedLSLUpload(LLUUID itemId, LLSD response) // fails, go ahead and save the text anyway. void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) { - if (!mScriptEd->hasChanged()) +// if(!mScriptEd->hasChanged()) +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-02-10 (Catznip-3.2) + if ( (!mScriptEd->hasChanged()) || (!gAgent.getRegion()) ) +// [/SL:KB] { return; } @@ -1786,6 +1828,14 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset preview->mScriptEd->setScriptName(script_name); preview->mScriptEd->setEnableEditing(is_modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Start the timer which will perform regular backup saves + if (!preview->isBackupRunning()) + { + preview->startBackupTimer(60.0f); + } +// [/SL:KB] } else { @@ -1886,6 +1936,15 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); getChild<LLCheckBoxCtrl>("running")->set(is_script_running); mIsSaving = FALSE; + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Script was successfully saved so delete our backup copy if we have one and the editor is still pristine + if ( (!mScriptEd->hasChanged()) && (hasBackupFile()) ) + { + removeBackupFile(); + } +// [/SL:KB] + closeIfNeeded(); } @@ -1907,6 +1966,15 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) } mScriptEd->selectFirstError(); mIsSaving = FALSE; + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Script was successfully saved so delete our backup copy if we have one and the editor is still pristine + if ( (!mScriptEd->hasChanged()) && (hasBackupFile()) ) + { + removeBackupFile(); + } +// [/SL:KB] + closeIfNeeded(); } @@ -2038,6 +2106,14 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, instance->loadScriptText(vfs, asset_id, type); instance->mScriptEd->setEnableEditing(TRUE); instance->mAssetStatus = PREVIEW_ASSET_LOADED; + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + // Start the timer which will perform regular backup saves + if (!instance->isBackupRunning()) + { + instance->startBackupTimer(60.0f); + } +// [/SL:KB] } else { diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 437e7a04cce79c2b65d2c615be12613de3586fb6..d9a44af685d63fda6bda70fb12f098e503f123cb 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -210,6 +210,10 @@ class LLScriptEdContainer : public LLPreview protected: std::string getTmpFileName(); +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2) + /*virtual*/ void onBackupTimer(); +// [/SL:KB] + bool onExternalChange(const std::string& filename); virtual void saveIfNeeded(bool sync = true) = 0; diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index d53cc3f74571070c61112dfbe3bf3ce6b0540b44..22718f2d63561369bd086411b205feaebcdfcc5a 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -882,6 +882,10 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res } } +// [SL:KB] - Patch: Build-ScriptRecover | Checked: Catznip-4.0 + uploadInfo->callUploadErrorCb(); +// [/SL:KB] + // Let the Snapshot floater know we have failed uploading. LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); if (floater_snapshot && floater_snapshot->isWaitingState()) diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h index d9eacf31675bf73a80d3d7fb289a999c2d7ec60c..3887be1a91741ae833e8ce571b55fdf147fbbe8e 100644 --- a/indra/newview/llviewerassetupload.h +++ b/indra/newview/llviewerassetupload.h @@ -90,6 +90,12 @@ class LLResourceUploadInfo static bool findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type); static bool findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload = true); +// [SL:KB] - Patch: Build-ScriptRecover | Checked: Catznip-4.0 + typedef boost::function<void(LLUUID itemId)> upload_error_f; + // Should add this as a parameter to the constructor but this requires less code changes + void callUploadErrorCb() { if (mUploadErrorFn) { mUploadErrorFn(mItemId); } } + void setUploadErrorCb(upload_error_f fnUploadError) { mUploadErrorFn = fnUploadError; } +// [/SL:KLB] protected: LLResourceUploadInfo( std::string name, @@ -119,6 +125,9 @@ class LLResourceUploadInfo void setAssetId(LLUUID assetId) { mAssetId = assetId; } private: +// [SL:KB] - Patch: Build-ScriptRecover | Checked: Catznip-4.0 + upload_error_f mUploadErrorFn; +// [/SL:KLB] LLTransactionID mTransactionId; LLAssetType::EType mAssetType; std::string mName; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 220125a464e0499f394aefbef774fe3b4bcf0f15..289b1d71cd975efcdf0a4ecd1121e9666219943e 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -38,6 +38,9 @@ #include "llfasttimerview.h" #include "llfloaterabout.h" #include "llfloaterauction.h" +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2011-11-24 (Catznip-3.2) +#include "llfloaterassetrecovery.h" +// [/SL:KB] #include "llfloaterautoreplacesettings.h" #include "llfloateravatar.h" #include "llfloateravatarpicker.h" @@ -204,6 +207,9 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>); LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>); LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); +// [SL:KB] - Patch: Build-AssetRecovery | Checked: 2011-11-24 (Catznip-3.2) + LLFloaterReg::add("asset_recovery", "floater_asset_recovery.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssetRecovery>); +// [/SL:KB] LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>); LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>); LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 4bbcc9674178bb6c3fc117752c8bb3e957d0e438..a4139a4350ec8a3f3996f9592efaf2da5ebd9946 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -129,6 +129,25 @@ class LLLocalizedInventoryItemsDictionary final : public LLSingleton<LLLocalized } return found; } + +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2013-03-10 (Catznip-3.4) + bool revertInventoryObjectName(std::string& object_name) + { + LL_DEBUGS("InventoryLocalize") << "Searching for localization: " << object_name << LL_ENDL; + + for (auto itDict = mInventoryItemsDict.cbegin(); itDict != mInventoryItemsDict.cend(); ++itDict) + { + if (itDict->second == object_name) + { + object_name = itDict->first; + LL_DEBUGS("InventoryLocalize") << "Found, new name is: " << object_name << LL_ENDL; + return true; + } + } + return false; + } +// [/SL:KB] + }; LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() @@ -2061,6 +2080,18 @@ BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na return result; } +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2013-03-10 (Catznip-3.4) +bool LLViewerInventoryItem::lookupLocalizedName(std::string& name) +{ + return LLLocalizedInventoryItemsDictionary::instance().localizeInventoryObjectName(name); +} + +bool LLViewerInventoryItem::lookupSystemName(std::string& name) +{ + return LLLocalizedInventoryItemsDictionary::instance().revertInventoryObjectName(name); +} +// [/SL:KB] + // This returns true if the item that this item points to // doesn't exist in memory (i.e. LLInventoryModel). The baseitem // might still be in the database but just not loaded yet. diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 78f04f8bafdad12e414c493da3da657375fc7dae..322df0602508ba50f2a845dc1a276c1adc04a8c3 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -83,6 +83,10 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr virtual U32 getCRC32() const; // really more of a checksum. static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); +// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2013-03-10 (Catznip-3.4) + static bool lookupLocalizedName(std::string& name); + static bool lookupSystemName(std::string& name); +// [/SL:KB] // construct a complete viewer inventory item LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid, diff --git a/indra/newview/skins/default/xui/en/floater_asset_recovery.xml b/indra/newview/skins/default/xui/en/floater_asset_recovery.xml new file mode 100644 index 0000000000000000000000000000000000000000..45ed375a2233e49b7e113b1a8a6dd70d94af5d78 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_asset_recovery.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_close="false" + can_minimize="false" + can_resize="false" + height="266" + positioning="centered" + name="asset_recovery" + single_instance="true" + title="ASSET RECOVERY" + width="350"> + + <text + follows="top|left|right" + font.style="BOLD" + height="75" + layout="topleft" + left="10" + length="1" + name="txt2" + top="0" + type="string" + word_wrap="true" + width="330"> + [APP_NAME] has detected recoverable items that may have been left over from a recent viewer crash. + +Recovered items will be placed in the 'Lost and Found' inventory folder. + </text> + + <scroll_list + draw_border="false" + draw_heading="true" + draw_stripes="true" + follows="all" + height="150" + layout="topleft" + left="8" + multi_select="false" + name="item_list" + top_pad="5" + width="334"> + <scroll_list.columns + label="" + name="item_check" + width="20" /> + <scroll_list.columns + label="Item Name" + name="item_name" + width="170" /> + <scroll_list.columns + label="Item Type" + name="item_type" + width="70" /> + </scroll_list> + <panel + background_visible="false" + follows="left|right|bottom" + height="25" + label="bottom_panel" + layout="topleft" + left="6" + name="bottom_panel" + top_pad="4" > + <icon + follows="left|right" + height="25" + image_name="Toolbar_Left_Off" + left="0" + name="dummy_icon1" + top="1" + width="30" /> + <button + height="25" + image_color="Green" + image_hover_unselected="Toolbar_Middle_Over" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="Recover" + label_color="White" + left_pad="1" + name="recover_btn" + top="1" + width="120" /> + <icon + follows="left|right" + height="25" + image_name="Toolbar_Middle_Off" + left_pad="1" + name="dummy_icon2" + top="1" + width="34" /> + <button + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="Cancel" + left_pad="1" + name="cancel_btn" + top="1" + width="120" /> + <icon + height="25" + follows="left|right" + image_name="Toolbar_Right_Off" + left_pad="1" + name="dummy_icon3" + top="1" + width="30" /> + </panel> +</floater> \ No newline at end of file