PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llviewerinventory.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2048 lines | 1583 code | 254 blank | 211 comment | 200 complexity | 443d9ac190f49e6dae4d3cbdd8cf37f7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llviewerinventory.cpp
  3. * @brief Implementation of the viewer side inventory objects.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llviewerinventory.h"
  28. #include "llnotificationsutil.h"
  29. #include "llsdserialize.h"
  30. #include "message.h"
  31. #include "llagent.h"
  32. #include "llagentcamera.h"
  33. #include "llagentwearables.h"
  34. #include "llfloatersidepanelcontainer.h"
  35. #include "llviewerfoldertype.h"
  36. #include "llfloatersidepanelcontainer.h"
  37. #include "llfolderview.h"
  38. #include "llviewercontrol.h"
  39. #include "llconsole.h"
  40. #include "llinventorydefines.h"
  41. #include "llinventoryfunctions.h"
  42. #include "llinventorymodel.h"
  43. #include "llinventorymodelbackgroundfetch.h"
  44. #include "llgesturemgr.h"
  45. #include "llinventorybridge.h"
  46. #include "llinventorypanel.h"
  47. #include "llfloaterinventory.h"
  48. #include "lllandmarkactions.h"
  49. #include "llviewerassettype.h"
  50. #include "llviewerregion.h"
  51. #include "llviewerobjectlist.h"
  52. #include "llpreviewgesture.h"
  53. #include "llviewerwindow.h"
  54. #include "lltrans.h"
  55. #include "llappearancemgr.h"
  56. #include "llcommandhandler.h"
  57. #include "llviewermessage.h"
  58. #include "llsidepanelappearance.h"
  59. #include "llavatarnamecache.h"
  60. #include "llavataractions.h"
  61. #include "lllogininstance.h"
  62. ///----------------------------------------------------------------------------
  63. /// Helper class to store special inventory item names and their localized values.
  64. ///----------------------------------------------------------------------------
  65. class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary>
  66. {
  67. public:
  68. std::map<std::string, std::string> mInventoryItemsDict;
  69. LLLocalizedInventoryItemsDictionary()
  70. {
  71. mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape");
  72. mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin");
  73. mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair");
  74. mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes");
  75. mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt");
  76. mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants");
  77. mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes");
  78. mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks");
  79. mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket");
  80. mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves");
  81. mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt");
  82. mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants");
  83. mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt");
  84. mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha");
  85. mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
  86. mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics");
  87. mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
  88. mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
  89. mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
  90. mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
  91. mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
  92. mInventoryItemsDict["Contents"] = LLTrans::getString("Contents");
  93. mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture");
  94. mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures");
  95. mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures");
  96. mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures");
  97. mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures");
  98. mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures");
  99. //predefined gestures
  100. //male
  101. mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me");
  102. mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319
  103. mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss");
  104. mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo");
  105. mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored");
  106. mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey");
  107. mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh");
  108. mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed");
  109. mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug");
  110. mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out");
  111. mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow");
  112. //female
  113. mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle");
  114. mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry");
  115. mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed");
  116. mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me");
  117. mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319
  118. mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss");
  119. mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo");
  120. mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored");
  121. mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey");
  122. mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby");
  123. mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh");
  124. mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good");
  125. mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here");
  126. mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please");
  127. mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed");
  128. mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug");
  129. mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out");
  130. mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow");
  131. //common
  132. mInventoryItemsDict["/bow"] = LLTrans::getString("/bow");
  133. mInventoryItemsDict["/clap"] = LLTrans::getString("/clap");
  134. mInventoryItemsDict["/count"] = LLTrans::getString("/count");
  135. mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish");
  136. mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb");
  137. mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle");
  138. mInventoryItemsDict["/no"] = LLTrans::getString("/no");
  139. mInventoryItemsDict["/no!"] = LLTrans::getString("/no!");
  140. mInventoryItemsDict["/paper"] = LLTrans::getString("/paper");
  141. mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme");
  142. mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou");
  143. mInventoryItemsDict["/rock"] = LLTrans::getString("/rock");
  144. mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor");
  145. mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke");
  146. mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch");
  147. mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle");
  148. mInventoryItemsDict["/yes"] = LLTrans::getString("/yes");
  149. mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!");
  150. mInventoryItemsDict["afk"] = LLTrans::getString("afk");
  151. mInventoryItemsDict["dance1"] = LLTrans::getString("dance1");
  152. mInventoryItemsDict["dance2"] = LLTrans::getString("dance2");
  153. mInventoryItemsDict["dance3"] = LLTrans::getString("dance3");
  154. mInventoryItemsDict["dance4"] = LLTrans::getString("dance4");
  155. mInventoryItemsDict["dance5"] = LLTrans::getString("dance5");
  156. mInventoryItemsDict["dance6"] = LLTrans::getString("dance6");
  157. mInventoryItemsDict["dance7"] = LLTrans::getString("dance7");
  158. mInventoryItemsDict["dance8"] = LLTrans::getString("dance8");
  159. }
  160. /**
  161. * Finds passed name in dictionary and replaces it with found localized value.
  162. *
  163. * @param object_name - string to be localized.
  164. * @return true if passed name was found and localized, false otherwise.
  165. */
  166. bool localizeInventoryObjectName(std::string& object_name)
  167. {
  168. LL_DEBUGS("InventoryLocalize") << "Searching for localization: " << object_name << LL_ENDL;
  169. std::map<std::string, std::string>::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name);
  170. bool found = dictionary_iter != mInventoryItemsDict.end();
  171. if(found)
  172. {
  173. object_name = dictionary_iter->second;
  174. LL_DEBUGS("InventoryLocalize") << "Found, new name is: " << object_name << LL_ENDL;
  175. }
  176. return found;
  177. }
  178. };
  179. ///----------------------------------------------------------------------------
  180. /// Local function declarations, constants, enums, and typedefs
  181. ///----------------------------------------------------------------------------
  182. class LLInventoryHandler : public LLCommandHandler
  183. {
  184. public:
  185. // requires trusted browser to trigger
  186. LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { }
  187. bool handle(const LLSD& params, const LLSD& query_map,
  188. LLMediaCtrl* web)
  189. {
  190. if (params.size() < 1)
  191. {
  192. return false;
  193. }
  194. if (!LLUI::sSettingGroups["config"]->getBOOL("EnableInventory"))
  195. {
  196. LLNotificationsUtil::add("NoInventory", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
  197. return true;
  198. }
  199. // support secondlife:///app/inventory/show
  200. if (params[0].asString() == "show")
  201. {
  202. LLFloaterSidePanelContainer::showPanel("inventory", LLSD());
  203. return true;
  204. }
  205. // otherwise, we need a UUID and a verb...
  206. if (params.size() < 2)
  207. {
  208. return false;
  209. }
  210. LLUUID inventory_id;
  211. if (!inventory_id.set(params[0], FALSE))
  212. {
  213. return false;
  214. }
  215. const std::string verb = params[1].asString();
  216. if (verb == "select")
  217. {
  218. uuid_vec_t items_to_open;
  219. items_to_open.push_back(inventory_id);
  220. //inventory_handler is just a stub, because we don't know from who this offer
  221. open_inventory_offer(items_to_open, "inventory_handler");
  222. return true;
  223. }
  224. return false;
  225. }
  226. };
  227. LLInventoryHandler gInventoryHandler;
  228. ///----------------------------------------------------------------------------
  229. /// Class LLViewerInventoryItem
  230. ///----------------------------------------------------------------------------
  231. LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& uuid,
  232. const LLUUID& parent_uuid,
  233. const LLPermissions& perm,
  234. const LLUUID& asset_uuid,
  235. LLAssetType::EType type,
  236. LLInventoryType::EType inv_type,
  237. const std::string& name,
  238. const std::string& desc,
  239. const LLSaleInfo& sale_info,
  240. U32 flags,
  241. time_t creation_date_utc) :
  242. LLInventoryItem(uuid, parent_uuid, perm, asset_uuid, type, inv_type,
  243. name, desc, sale_info, flags, creation_date_utc),
  244. mIsComplete(TRUE)
  245. {
  246. }
  247. LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& item_id,
  248. const LLUUID& parent_id,
  249. const std::string& name,
  250. LLInventoryType::EType inv_type) :
  251. LLInventoryItem(),
  252. mIsComplete(FALSE)
  253. {
  254. mUUID = item_id;
  255. mParentUUID = parent_id;
  256. mInventoryType = inv_type;
  257. mName = name;
  258. }
  259. LLViewerInventoryItem::LLViewerInventoryItem() :
  260. LLInventoryItem(),
  261. mIsComplete(FALSE)
  262. {
  263. }
  264. LLViewerInventoryItem::LLViewerInventoryItem(const LLViewerInventoryItem* other) :
  265. LLInventoryItem()
  266. {
  267. copyViewerItem(other);
  268. if (!mIsComplete)
  269. {
  270. llwarns << "LLViewerInventoryItem copy constructor for incomplete item"
  271. << mUUID << llendl;
  272. }
  273. }
  274. LLViewerInventoryItem::LLViewerInventoryItem(const LLInventoryItem *other) :
  275. LLInventoryItem(other),
  276. mIsComplete(TRUE)
  277. {
  278. }
  279. LLViewerInventoryItem::~LLViewerInventoryItem()
  280. {
  281. }
  282. void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other)
  283. {
  284. LLInventoryItem::copyItem(other);
  285. mIsComplete = other->mIsComplete;
  286. mTransactionID = other->mTransactionID;
  287. }
  288. // virtual
  289. void LLViewerInventoryItem::copyItem(const LLInventoryItem *other)
  290. {
  291. LLInventoryItem::copyItem(other);
  292. mIsComplete = true;
  293. mTransactionID.setNull();
  294. }
  295. void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& newitem) const
  296. {
  297. newitem = new LLViewerInventoryItem(this);
  298. if(newitem.notNull())
  299. {
  300. LLUUID item_id;
  301. item_id.generate();
  302. newitem->setUUID(item_id);
  303. }
  304. }
  305. void LLViewerInventoryItem::removeFromServer()
  306. {
  307. llinfos << "Removing inventory item " << mUUID << " from server."
  308. << llendl;
  309. LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
  310. gInventory.accountForUpdate(up);
  311. LLMessageSystem* msg = gMessageSystem;
  312. msg->newMessageFast(_PREHASH_RemoveInventoryItem);
  313. msg->nextBlockFast(_PREHASH_AgentData);
  314. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  315. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  316. msg->nextBlockFast(_PREHASH_InventoryData);
  317. msg->addUUIDFast(_PREHASH_ItemID, mUUID);
  318. gAgent.sendReliableMessage();
  319. }
  320. void LLViewerInventoryItem::updateServer(BOOL is_new) const
  321. {
  322. if(!mIsComplete)
  323. {
  324. // *FIX: deal with this better.
  325. // If we're crashing here then the UI is incorrectly enabled.
  326. llerrs << "LLViewerInventoryItem::updateServer() - for incomplete item"
  327. << llendl;
  328. return;
  329. }
  330. if(gAgent.getID() != mPermissions.getOwner())
  331. {
  332. // *FIX: deal with this better.
  333. llwarns << "LLViewerInventoryItem::updateServer() - for unowned item"
  334. << llendl;
  335. return;
  336. }
  337. LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
  338. gInventory.accountForUpdate(up);
  339. LLMessageSystem* msg = gMessageSystem;
  340. msg->newMessageFast(_PREHASH_UpdateInventoryItem);
  341. msg->nextBlockFast(_PREHASH_AgentData);
  342. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  343. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  344. msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
  345. msg->nextBlockFast(_PREHASH_InventoryData);
  346. msg->addU32Fast(_PREHASH_CallbackID, 0);
  347. packMessage(msg);
  348. gAgent.sendReliableMessage();
  349. }
  350. void LLViewerInventoryItem::fetchFromServer(void) const
  351. {
  352. if(!mIsComplete)
  353. {
  354. std::string url;
  355. LLViewerRegion* region = gAgent.getRegion();
  356. // we have to check region. It can be null after region was destroyed. See EXT-245
  357. if (region)
  358. {
  359. if(gAgent.getID() != mPermissions.getOwner())
  360. {
  361. url = region->getCapability("FetchLib2");
  362. }
  363. else
  364. {
  365. url = region->getCapability("FetchInventory2");
  366. }
  367. }
  368. else
  369. {
  370. llwarns << "Agent Region is absent" << llendl;
  371. }
  372. if (!url.empty())
  373. {
  374. LLSD body;
  375. body["agent_id"] = gAgent.getID();
  376. body["items"][0]["owner_id"] = mPermissions.getOwner();
  377. body["items"][0]["item_id"] = mUUID;
  378. LLHTTPClient::post(url, body, new LLInventoryModel::fetchInventoryResponder(body));
  379. }
  380. else
  381. {
  382. LLMessageSystem* msg = gMessageSystem;
  383. msg->newMessage("FetchInventory");
  384. msg->nextBlock("AgentData");
  385. msg->addUUID("AgentID", gAgent.getID());
  386. msg->addUUID("SessionID", gAgent.getSessionID());
  387. msg->nextBlock("InventoryData");
  388. msg->addUUID("OwnerID", mPermissions.getOwner());
  389. msg->addUUID("ItemID", mUUID);
  390. gAgent.sendReliableMessage();
  391. }
  392. }
  393. else
  394. {
  395. // *FIX: this can be removed after a bit.
  396. llwarns << "request to fetch complete item" << llendl;
  397. }
  398. }
  399. // virtual
  400. BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
  401. {
  402. BOOL rv = LLInventoryItem::fromLLSD(item);
  403. LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
  404. mIsComplete = TRUE;
  405. return rv;
  406. }
  407. // virtual
  408. BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
  409. {
  410. BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
  411. LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
  412. mIsComplete = TRUE;
  413. return rv;
  414. }
  415. void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_id)
  416. {
  417. mTransactionID = transaction_id;
  418. }
  419. // virtual
  420. void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
  421. {
  422. msg->addUUIDFast(_PREHASH_ItemID, mUUID);
  423. msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
  424. mPermissions.packMessage(msg);
  425. msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
  426. S8 type = static_cast<S8>(mType);
  427. msg->addS8Fast(_PREHASH_Type, type);
  428. type = static_cast<S8>(mInventoryType);
  429. msg->addS8Fast(_PREHASH_InvType, type);
  430. msg->addU32Fast(_PREHASH_Flags, mFlags);
  431. mSaleInfo.packMessage(msg);
  432. msg->addStringFast(_PREHASH_Name, mName);
  433. msg->addStringFast(_PREHASH_Description, mDescription);
  434. msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
  435. U32 crc = getCRC32();
  436. msg->addU32Fast(_PREHASH_CRC, crc);
  437. }
  438. // virtual
  439. BOOL LLViewerInventoryItem::importFile(LLFILE* fp)
  440. {
  441. BOOL rv = LLInventoryItem::importFile(fp);
  442. mIsComplete = TRUE;
  443. return rv;
  444. }
  445. // virtual
  446. BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream)
  447. {
  448. BOOL rv = LLInventoryItem::importLegacyStream(input_stream);
  449. mIsComplete = TRUE;
  450. return rv;
  451. }
  452. bool LLViewerInventoryItem::importFileLocal(LLFILE* fp)
  453. {
  454. // TODO: convert all functions that return BOOL to return bool
  455. bool rv = (LLInventoryItem::importFile(fp) ? true : false);
  456. mIsComplete = false;
  457. return rv;
  458. }
  459. bool LLViewerInventoryItem::exportFileLocal(LLFILE* fp) const
  460. {
  461. std::string uuid_str;
  462. fprintf(fp, "\tinv_item\t0\n\t{\n");
  463. mUUID.toString(uuid_str);
  464. fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str());
  465. mParentUUID.toString(uuid_str);
  466. fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
  467. mPermissions.exportFile(fp);
  468. fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
  469. const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
  470. if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
  471. fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
  472. fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate);
  473. fprintf(fp,"\t}\n");
  474. return true;
  475. }
  476. void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const
  477. {
  478. LLMessageSystem* msg = gMessageSystem;
  479. msg->newMessageFast(_PREHASH_MoveInventoryItem);
  480. msg->nextBlockFast(_PREHASH_AgentData);
  481. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  482. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  483. msg->addBOOLFast(_PREHASH_Stamp, restamp);
  484. msg->nextBlockFast(_PREHASH_InventoryData);
  485. msg->addUUIDFast(_PREHASH_ItemID, mUUID);
  486. msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
  487. msg->addString("NewName", NULL);
  488. gAgent.sendReliableMessage();
  489. }
  490. //void LLViewerInventoryItem::setCloneCount(S32 clones)
  491. //{
  492. // mClones = clones;
  493. //}
  494. //S32 LLViewerInventoryItem::getCloneCount() const
  495. //{
  496. // return mClones;
  497. //}
  498. ///----------------------------------------------------------------------------
  499. /// Class LLViewerInventoryCategory
  500. ///----------------------------------------------------------------------------
  501. LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid,
  502. const LLUUID& parent_uuid,
  503. LLFolderType::EType pref,
  504. const std::string& name,
  505. const LLUUID& owner_id) :
  506. LLInventoryCategory(uuid, parent_uuid, pref, name),
  507. mOwnerID(owner_id),
  508. mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN),
  509. mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
  510. {
  511. mDescendentsRequested.reset();
  512. }
  513. LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) :
  514. mOwnerID(owner_id),
  515. mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN),
  516. mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
  517. {
  518. mDescendentsRequested.reset();
  519. }
  520. LLViewerInventoryCategory::LLViewerInventoryCategory(const LLViewerInventoryCategory* other)
  521. {
  522. copyViewerCategory(other);
  523. }
  524. LLViewerInventoryCategory::~LLViewerInventoryCategory()
  525. {
  526. }
  527. void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCategory* other)
  528. {
  529. copyCategory(other);
  530. mOwnerID = other->mOwnerID;
  531. mVersion = other->mVersion;
  532. mDescendentCount = other->mDescendentCount;
  533. mDescendentsRequested = other->mDescendentsRequested;
  534. }
  535. void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
  536. {
  537. LLMessageSystem* msg = gMessageSystem;
  538. msg->newMessageFast(_PREHASH_MoveInventoryFolder);
  539. msg->nextBlockFast(_PREHASH_AgentData);
  540. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  541. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  542. msg->addBOOL("Stamp", restamp);
  543. msg->nextBlockFast(_PREHASH_InventoryData);
  544. msg->addUUIDFast(_PREHASH_FolderID, mUUID);
  545. msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
  546. gAgent.sendReliableMessage();
  547. }
  548. void LLViewerInventoryCategory::updateServer(BOOL is_new) const
  549. {
  550. // communicate that change with the server.
  551. if (LLFolderType::lookupIsProtectedType(mPreferredType))
  552. {
  553. LLNotificationsUtil::add("CannotModifyProtectedCategories");
  554. return;
  555. }
  556. LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
  557. gInventory.accountForUpdate(up);
  558. LLMessageSystem* msg = gMessageSystem;
  559. msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
  560. msg->nextBlockFast(_PREHASH_AgentData);
  561. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  562. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  563. msg->nextBlockFast(_PREHASH_FolderData);
  564. packMessage(msg);
  565. gAgent.sendReliableMessage();
  566. }
  567. void LLViewerInventoryCategory::removeFromServer( void )
  568. {
  569. llinfos << "Removing inventory category " << mUUID << " from server."
  570. << llendl;
  571. // communicate that change with the server.
  572. if(LLFolderType::lookupIsProtectedType(mPreferredType))
  573. {
  574. LLNotificationsUtil::add("CannotRemoveProtectedCategories");
  575. return;
  576. }
  577. LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
  578. gInventory.accountForUpdate(up);
  579. LLMessageSystem* msg = gMessageSystem;
  580. msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
  581. msg->nextBlockFast(_PREHASH_AgentData);
  582. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  583. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  584. msg->nextBlockFast(_PREHASH_FolderData);
  585. msg->addUUIDFast(_PREHASH_FolderID, mUUID);
  586. gAgent.sendReliableMessage();
  587. }
  588. bool LLViewerInventoryCategory::fetch()
  589. {
  590. if((VERSION_UNKNOWN == mVersion)
  591. && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads.
  592. {
  593. LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL;
  594. const F32 FETCH_TIMER_EXPIRY = 10.0f;
  595. mDescendentsRequested.reset();
  596. mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY);
  597. // bitfield
  598. // 1 = by date
  599. // 2 = folders by date
  600. // Need to mask off anything but the first bit.
  601. // This comes from LLInventoryFilter from llfolderview.h
  602. U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
  603. // *NOTE: For bug EXT-2879, originally commented out
  604. // gAgent.getRegion()->getCapability in order to use the old
  605. // message-based system. This has been uncommented now that
  606. // AIS folks are aware of the issue and have a fix in process.
  607. // see ticket for details.
  608. std::string url;
  609. if (gAgent.getRegion())
  610. {
  611. url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
  612. }
  613. else
  614. {
  615. llwarns << "agent region is null" << llendl;
  616. }
  617. if (!url.empty()) //Capability found. Build up LLSD and use it.
  618. {
  619. LLInventoryModelBackgroundFetch::instance().start(mUUID, false);
  620. }
  621. else
  622. { //Deprecated, but if we don't have a capability, use the old system.
  623. llinfos << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << llendl;
  624. LLMessageSystem* msg = gMessageSystem;
  625. msg->newMessage("FetchInventoryDescendents");
  626. msg->nextBlock("AgentData");
  627. msg->addUUID("AgentID", gAgent.getID());
  628. msg->addUUID("SessionID", gAgent.getSessionID());
  629. msg->nextBlock("InventoryData");
  630. msg->addUUID("FolderID", mUUID);
  631. msg->addUUID("OwnerID", mOwnerID);
  632. msg->addS32("SortOrder", sort_order);
  633. msg->addBOOL("FetchFolders", FALSE);
  634. msg->addBOOL("FetchItems", TRUE);
  635. gAgent.sendReliableMessage();
  636. }
  637. return true;
  638. }
  639. return false;
  640. }
  641. bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp)
  642. {
  643. // *NOTE: This buffer size is hard coded into scanf() below.
  644. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  645. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  646. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  647. keyword[0] = '\0';
  648. valuestr[0] = '\0';
  649. while(!feof(fp))
  650. {
  651. if (fgets(buffer, MAX_STRING, fp) == NULL)
  652. {
  653. buffer[0] = '\0';
  654. }
  655. sscanf( /* Flawfinder: ignore */
  656. buffer, " %254s %254s", keyword, valuestr);
  657. if(0 == strcmp("{",keyword))
  658. {
  659. continue;
  660. }
  661. if(0 == strcmp("}", keyword))
  662. {
  663. break;
  664. }
  665. else if(0 == strcmp("cat_id", keyword))
  666. {
  667. mUUID.set(valuestr);
  668. }
  669. else if(0 == strcmp("parent_id", keyword))
  670. {
  671. mParentUUID.set(valuestr);
  672. }
  673. else if(0 == strcmp("type", keyword))
  674. {
  675. mType = LLAssetType::lookup(valuestr);
  676. }
  677. else if(0 == strcmp("pref_type", keyword))
  678. {
  679. mPreferredType = LLFolderType::lookup(valuestr);
  680. }
  681. else if(0 == strcmp("name", keyword))
  682. {
  683. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  684. // *NOTE: Not ANSI C, but widely supported.
  685. sscanf( /* Flawfinder: ignore */
  686. buffer, " %254s %254[^|]", keyword, valuestr);
  687. mName.assign(valuestr);
  688. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  689. LLStringUtil::replaceChar(mName, '|', ' ');
  690. }
  691. else if(0 == strcmp("owner_id", keyword))
  692. {
  693. mOwnerID.set(valuestr);
  694. }
  695. else if(0 == strcmp("version", keyword))
  696. {
  697. sscanf(valuestr, "%d", &mVersion);
  698. }
  699. else
  700. {
  701. llwarns << "unknown keyword '" << keyword
  702. << "' in inventory import category " << mUUID << llendl;
  703. }
  704. }
  705. return true;
  706. }
  707. bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
  708. {
  709. std::string uuid_str;
  710. fprintf(fp, "\tinv_category\t0\n\t{\n");
  711. mUUID.toString(uuid_str);
  712. fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str());
  713. mParentUUID.toString(uuid_str);
  714. fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
  715. fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
  716. fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
  717. fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
  718. mOwnerID.toString(uuid_str);
  719. fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str());
  720. fprintf(fp, "\t\tversion\t%d\n", mVersion);
  721. fprintf(fp,"\t}\n");
  722. return true;
  723. }
  724. void LLViewerInventoryCategory::determineFolderType()
  725. {
  726. /* Do NOT uncomment this code. This is for future 2.1 support of ensembles.
  727. llassert(FALSE);
  728. LLFolderType::EType original_type = getPreferredType();
  729. if (LLFolderType::lookupIsProtectedType(original_type))
  730. return;
  731. U64 folder_valid = 0;
  732. U64 folder_invalid = 0;
  733. LLInventoryModel::cat_array_t category_array;
  734. LLInventoryModel::item_array_t item_array;
  735. gInventory.collectDescendents(getUUID(),category_array,item_array,FALSE);
  736. // For ensembles
  737. if (category_array.empty())
  738. {
  739. for (LLInventoryModel::item_array_t::iterator item_iter = item_array.begin();
  740. item_iter != item_array.end();
  741. item_iter++)
  742. {
  743. const LLViewerInventoryItem *item = (*item_iter);
  744. if (item->getIsLinkType())
  745. return;
  746. if (item->isWearableType())
  747. {
  748. const LLWearableType::EType wearable_type = item->getWearableType();
  749. const std::string& wearable_name = LLWearableType::getTypeName(wearable_type);
  750. U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name);
  751. folder_valid |= valid_folder_types;
  752. folder_invalid |= ~valid_folder_types;
  753. }
  754. }
  755. for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++)
  756. {
  757. if ((folder_valid & (1LL << i)) &&
  758. !(folder_invalid & (1LL << i)))
  759. {
  760. changeType((LLFolderType::EType)i);
  761. return;
  762. }
  763. }
  764. }
  765. if (LLFolderType::lookupIsEnsembleType(original_type))
  766. {
  767. changeType(LLFolderType::FT_NONE);
  768. }
  769. llassert(FALSE);
  770. */
  771. }
  772. void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
  773. {
  774. const LLUUID &folder_id = getUUID();
  775. const LLUUID &parent_id = getParentUUID();
  776. const std::string &name = getName();
  777. LLMessageSystem* msg = gMessageSystem;
  778. msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
  779. msg->nextBlockFast(_PREHASH_AgentData);
  780. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  781. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  782. msg->nextBlockFast(_PREHASH_FolderData);
  783. msg->addUUIDFast(_PREHASH_FolderID, folder_id);
  784. msg->addUUIDFast(_PREHASH_ParentID, parent_id);
  785. msg->addS8Fast(_PREHASH_Type, new_folder_type);
  786. msg->addStringFast(_PREHASH_Name, name);
  787. gAgent.sendReliableMessage();
  788. setPreferredType(new_folder_type);
  789. gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
  790. }
  791. void LLViewerInventoryCategory::localizeName()
  792. {
  793. LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
  794. }
  795. ///----------------------------------------------------------------------------
  796. /// Local function definitions
  797. ///----------------------------------------------------------------------------
  798. LLInventoryCallbackManager *LLInventoryCallbackManager::sInstance = NULL;
  799. LLInventoryCallbackManager::LLInventoryCallbackManager() :
  800. mLastCallback(0)
  801. {
  802. if( sInstance != NULL )
  803. {
  804. llwarns << "LLInventoryCallbackManager::LLInventoryCallbackManager: unexpected multiple instances" << llendl;
  805. return;
  806. }
  807. sInstance = this;
  808. }
  809. LLInventoryCallbackManager::~LLInventoryCallbackManager()
  810. {
  811. if( sInstance != this )
  812. {
  813. llwarns << "LLInventoryCallbackManager::~LLInventoryCallbackManager: unexpected multiple instances" << llendl;
  814. return;
  815. }
  816. sInstance = NULL;
  817. }
  818. //static
  819. void LLInventoryCallbackManager::destroyClass()
  820. {
  821. if (sInstance)
  822. {
  823. for (callback_map_t::iterator it = sInstance->mMap.begin(), end_it = sInstance->mMap.end(); it != end_it; ++it)
  824. {
  825. // drop LLPointer reference to callback
  826. it->second = NULL;
  827. }
  828. sInstance->mMap.clear();
  829. }
  830. }
  831. U32 LLInventoryCallbackManager::registerCB(LLPointer<LLInventoryCallback> cb)
  832. {
  833. if (cb.isNull())
  834. return 0;
  835. mLastCallback++;
  836. if (!mLastCallback)
  837. mLastCallback++;
  838. mMap[mLastCallback] = cb;
  839. return mLastCallback;
  840. }
  841. void LLInventoryCallbackManager::fire(U32 callback_id, const LLUUID& item_id)
  842. {
  843. if (!callback_id || item_id.isNull())
  844. return;
  845. std::map<U32, LLPointer<LLInventoryCallback> >::iterator i;
  846. i = mMap.find(callback_id);
  847. if (i != mMap.end())
  848. {
  849. (*i).second->fire(item_id);
  850. mMap.erase(i);
  851. }
  852. }
  853. void WearOnAvatarCallback::fire(const LLUUID& inv_item)
  854. {
  855. if (inv_item.isNull())
  856. return;
  857. LLViewerInventoryItem *item = gInventory.getItem(inv_item);
  858. if (item)
  859. {
  860. LLAppearanceMgr::instance().wearItemOnAvatar(inv_item, true, mReplace);
  861. }
  862. }
  863. void ModifiedCOFCallback::fire(const LLUUID& inv_item)
  864. {
  865. LLAppearanceMgr::instance().updateAppearanceFromCOF();
  866. // Start editing the item if previously requested.
  867. gAgentWearables.editWearableIfRequested(inv_item);
  868. // TODO: camera mode may not be changed if a debug setting is tweaked
  869. if( gAgentCamera.cameraCustomizeAvatar() )
  870. {
  871. // If we're in appearance editing mode, the current tab may need to be refreshed
  872. LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
  873. if (panel)
  874. {
  875. panel->showDefaultSubpart();
  876. }
  877. }
  878. }
  879. RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
  880. {
  881. mAttach = attachmentp;
  882. }
  883. RezAttachmentCallback::~RezAttachmentCallback()
  884. {
  885. }
  886. void RezAttachmentCallback::fire(const LLUUID& inv_item)
  887. {
  888. if (inv_item.isNull())
  889. return;
  890. LLViewerInventoryItem *item = gInventory.getItem(inv_item);
  891. if (item)
  892. {
  893. rez_attachment(item, mAttach);
  894. }
  895. }
  896. void ActivateGestureCallback::fire(const LLUUID& inv_item)
  897. {
  898. if (inv_item.isNull())
  899. return;
  900. LLViewerInventoryItem* item = gInventory.getItem(inv_item);
  901. if (!item)
  902. return;
  903. if (item->getType() != LLAssetType::AT_GESTURE)
  904. return;
  905. LLGestureMgr::instance().activateGesture(inv_item);
  906. }
  907. void CreateGestureCallback::fire(const LLUUID& inv_item)
  908. {
  909. if (inv_item.isNull())
  910. return;
  911. LLGestureMgr::instance().activateGesture(inv_item);
  912. LLViewerInventoryItem* item = gInventory.getItem(inv_item);
  913. if (!item) return;
  914. gInventory.updateItem(item);
  915. gInventory.notifyObservers();
  916. LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null);
  917. // Force to be entirely onscreen.
  918. gFloaterView->adjustToFitScreen(preview, FALSE);
  919. }
  920. void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
  921. {
  922. if (mTargetLandmarkId.isNull()) return;
  923. gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
  924. }
  925. LLInventoryCallbackManager gInventoryCallbacks;
  926. void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
  927. const LLUUID& parent, const LLTransactionID& transaction_id,
  928. const std::string& name,
  929. const std::string& desc, LLAssetType::EType asset_type,
  930. LLInventoryType::EType inv_type, LLWearableType::EType wtype,
  931. U32 next_owner_perm,
  932. LLPointer<LLInventoryCallback> cb)
  933. {
  934. //check if name is equal to one of special inventory items names
  935. //EXT-5839
  936. std::string server_name = name;
  937. {
  938. std::map<std::string, std::string>::const_iterator dictionary_iter;
  939. for (dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.begin();
  940. dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end();
  941. dictionary_iter++)
  942. {
  943. const std::string& localized_name = dictionary_iter->second;
  944. if(localized_name == name)
  945. {
  946. server_name = dictionary_iter->first;
  947. }
  948. }
  949. }
  950. LLMessageSystem* msg = gMessageSystem;
  951. msg->newMessageFast(_PREHASH_CreateInventoryItem);
  952. msg->nextBlock(_PREHASH_AgentData);
  953. msg->addUUIDFast(_PREHASH_AgentID, agent_id);
  954. msg->addUUIDFast(_PREHASH_SessionID, session_id);
  955. msg->nextBlock(_PREHASH_InventoryBlock);
  956. msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
  957. msg->addUUIDFast(_PREHASH_FolderID, parent);
  958. msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
  959. msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm);
  960. msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
  961. msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
  962. msg->addU8Fast(_PREHASH_WearableType, (U8)wtype);
  963. msg->addStringFast(_PREHASH_Name, server_name);
  964. msg->addStringFast(_PREHASH_Description, desc);
  965. gAgent.sendReliableMessage();
  966. }
  967. void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)
  968. {
  969. std::string item_desc = avatar_id.asString();
  970. std::string item_name;
  971. gCacheName->getFullName(avatar_id, item_name);
  972. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  973. parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD,
  974. LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
  975. }
  976. void copy_inventory_item(
  977. const LLUUID& agent_id,
  978. const LLUUID& current_owner,
  979. const LLUUID& item_id,
  980. const LLUUID& parent_id,
  981. const std::string& new_name,
  982. LLPointer<LLInventoryCallback> cb)
  983. {
  984. LLMessageSystem* msg = gMessageSystem;
  985. msg->newMessageFast(_PREHASH_CopyInventoryItem);
  986. msg->nextBlockFast(_PREHASH_AgentData);
  987. msg->addUUIDFast(_PREHASH_AgentID, agent_id);
  988. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  989. msg->nextBlockFast(_PREHASH_InventoryData);
  990. msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
  991. msg->addUUIDFast(_PREHASH_OldAgentID, current_owner);
  992. msg->addUUIDFast(_PREHASH_OldItemID, item_id);
  993. msg->addUUIDFast(_PREHASH_NewFolderID, parent_id);
  994. msg->addStringFast(_PREHASH_NewName, new_name);
  995. gAgent.sendReliableMessage();
  996. }
  997. void link_inventory_item(
  998. const LLUUID& agent_id,
  999. const LLUUID& item_id,
  1000. const LLUUID& parent_id,
  1001. const std::string& new_name,
  1002. const std::string& new_description,
  1003. const LLAssetType::EType asset_type,
  1004. LLPointer<LLInventoryCallback> cb)
  1005. {
  1006. const LLInventoryObject *baseobj = gInventory.getObject(item_id);
  1007. if (!baseobj)
  1008. {
  1009. llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
  1010. return;
  1011. }
  1012. if (baseobj && baseobj->getIsLinkType())
  1013. {
  1014. llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
  1015. return;
  1016. }
  1017. if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
  1018. {
  1019. // Fail if item can be found but is of a type that can't be linked.
  1020. // Arguably should fail if the item can't be found too, but that could
  1021. // be a larger behavioral change.
  1022. llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
  1023. return;
  1024. }
  1025. LLUUID transaction_id;
  1026. LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
  1027. if (dynamic_cast<const LLInventoryCategory *>(baseobj))
  1028. {
  1029. inv_type = LLInventoryType::IT_CATEGORY;
  1030. }
  1031. else
  1032. {
  1033. const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
  1034. if (baseitem)
  1035. {
  1036. inv_type = baseitem->getInventoryType();
  1037. }
  1038. }
  1039. LLMessageSystem* msg = gMessageSystem;
  1040. msg->newMessageFast(_PREHASH_LinkInventoryItem);
  1041. msg->nextBlock(_PREHASH_AgentData);
  1042. {
  1043. msg->addUUIDFast(_PREHASH_AgentID, agent_id);
  1044. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1045. }
  1046. msg->nextBlock(_PREHASH_InventoryBlock);
  1047. {
  1048. msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
  1049. msg->addUUIDFast(_PREHASH_FolderID, parent_id);
  1050. msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
  1051. msg->addUUIDFast(_PREHASH_OldItemID, item_id);
  1052. msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
  1053. msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
  1054. msg->addStringFast(_PREHASH_Name, new_name);
  1055. msg->addStringFast(_PREHASH_Description, new_description);
  1056. }
  1057. gAgent.sendReliableMessage();
  1058. }
  1059. void move_inventory_item(
  1060. const LLUUID& agent_id,
  1061. const LLUUID& session_id,
  1062. const LLUUID& item_id,
  1063. const LLUUID& parent_id,
  1064. const std::string& new_name,
  1065. LLPointer<LLInventoryCallback> cb)
  1066. {
  1067. LLMessageSystem* msg = gMessageSystem;
  1068. msg->newMessageFast(_PREHASH_MoveInventoryItem);
  1069. msg->nextBlockFast(_PREHASH_AgentData);
  1070. msg->addUUIDFast(_PREHASH_AgentID, agent_id);
  1071. msg->addUUIDFast(_PREHASH_SessionID, session_id);
  1072. msg->addBOOLFast(_PREHASH_Stamp, FALSE);
  1073. msg->nextBlockFast(_PREHASH_InventoryData);
  1074. msg->addUUIDFast(_PREHASH_ItemID, item_id);
  1075. msg->addUUIDFast(_PREHASH_FolderID, parent_id);
  1076. msg->addStringFast(_PREHASH_NewName, new_name);
  1077. gAgent.sendReliableMessage();
  1078. }
  1079. const LLUUID get_folder_by_itemtype(const LLInventoryItem *src)
  1080. {
  1081. LLUUID retval = LLUUID::null;
  1082. if (src)
  1083. {
  1084. retval = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType()));
  1085. }
  1086. return retval;
  1087. }
  1088. void copy_inventory_from_notecard(const LLUUID& destination_id,
  1089. const LLUUID& object_id,
  1090. const LLUUID& notecard_inv_id,
  1091. const LLInventoryItem *src,
  1092. U32 callback_id)
  1093. {
  1094. if (NULL == src)
  1095. {
  1096. LL_WARNS("copy_inventory_from_notecard") << "Null pointer to item was passed for object_id "
  1097. << object_id << " and notecard_inv_id "
  1098. << notecard_inv_id << LL_ENDL;
  1099. return;
  1100. }
  1101. LLViewerRegion* viewer_region = NULL;
  1102. LLViewerObject* vo = NULL;
  1103. if (object_id.notNull() && (vo = gObjectList.findObject(object_id)) != NULL)
  1104. {
  1105. viewer_region = vo->getRegion();
  1106. }
  1107. // Fallback to the agents region if for some reason the
  1108. // object isn't found in the viewer.
  1109. if (! viewer_region)
  1110. {
  1111. viewer_region = gAgent.getRegion();
  1112. }
  1113. if (! viewer_region)
  1114. {
  1115. LL_WARNS("copy_inventory_from_notecard") << "Can't find region from object_id "
  1116. << object_id << " or gAgent"
  1117. << LL_ENDL;
  1118. return;
  1119. }
  1120. // check capability to prevent a crash while LL_ERRS in LLCapabilityListener::capListener. See EXT-8459.
  1121. std::string url = viewer_region->getCapability("CopyInventoryFromNotecard");
  1122. if (url.empty())
  1123. {
  1124. LL_WARNS("copy_inventory_from_notecard") << "There is no 'CopyInventoryFromNotecard' capability"
  1125. << " for region: " << viewer_region->getName()
  1126. << LL_ENDL;
  1127. return;
  1128. }
  1129. LLSD request, body;
  1130. body["notecard-id"] = notecard_inv_id;
  1131. body["object-id"] = object_id;
  1132. body["item-id"] = src->getUUID();
  1133. body["folder-id"] = destination_id;
  1134. body["callback-id"] = (LLSD::Integer)callback_id;
  1135. request["message"] = "CopyInventoryFromNotecard";
  1136. request["payload"] = body;
  1137. viewer_region->getCapAPI().post(request);
  1138. }
  1139. void create_new_item(const std::string& name,
  1140. const LLUUID& parent_id,
  1141. LLAssetType::EType asset_type,
  1142. LLInventoryType::EType inv_type,
  1143. U32 next_owner_perm)
  1144. {
  1145. std::string desc;
  1146. LLViewerAssetType::generateDescriptionFor(asset_type, desc);
  1147. next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER;
  1148. if (inv_type == LLInventoryType::IT_GESTURE)
  1149. {
  1150. LLPointer<LLInventoryCallback> cb = new CreateGestureCallback();
  1151. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  1152. parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
  1153. NOT_WEARABLE, next_owner_perm, cb);
  1154. }
  1155. else
  1156. {
  1157. LLPointer<LLInventoryCallback> cb = NULL;
  1158. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  1159. parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
  1160. NOT_WEARABLE, next_owner_perm, cb);
  1161. }
  1162. }
  1163. const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
  1164. const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
  1165. const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
  1166. // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements...
  1167. void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)
  1168. {
  1169. std::string type_name = userdata.asString();
  1170. if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
  1171. {
  1172. LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
  1173. LLUUID parent_id;
  1174. if (bridge)
  1175. {
  1176. parent_id = bridge->getUUID();
  1177. }
  1178. else if (default_parent_uuid.notNull())
  1179. {
  1180. parent_id = default_parent_uuid;
  1181. }
  1182. else
  1183. {
  1184. parent_id = gInventory.getRootFolderID();
  1185. }
  1186. LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);
  1187. gInventory.notifyObservers();
  1188. root->setSelectionByID(category, TRUE);
  1189. }
  1190. else if ("lsl" == type_name)
  1191. {
  1192. const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT);
  1193. create_new_item(NEW_LSL_NAME,
  1194. parent_id,
  1195. LLAssetType::AT_LSL_TEXT,
  1196. LLInventoryType::IT_LSL,
  1197. PERM_MOVE | PERM_TRANSFER);
  1198. }
  1199. else if ("notecard" == type_name)
  1200. {
  1201. const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD);
  1202. create_new_item(NEW_NOTECARD_NAME,
  1203. parent_id,
  1204. LLAssetType::AT_NOTECARD,
  1205. LLInventoryType::IT_NOTECARD,
  1206. PERM_ALL);
  1207. }
  1208. else if ("gesture" == type_name)
  1209. {
  1210. const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
  1211. create_new_item(NEW_GESTURE_NAME,
  1212. parent_id,
  1213. LLAssetType::AT_GESTURE,
  1214. LLInventoryType::IT_GESTURE,
  1215. PERM_ALL);
  1216. }
  1217. else
  1218. {
  1219. // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary.
  1220. LLWearableType::EType wearable_type = LLWearableType::typeNameToType(type_name);
  1221. if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT)
  1222. {
  1223. const LLUUID parent_id = bridge ? bridge->getUUID() : LLUUID::null;
  1224. LLAgentWearables::createWearable(wearable_type, false, parent_id);
  1225. }
  1226. else
  1227. {
  1228. llwarns << "Can't create unrecognized type " << type_name << llendl;
  1229. }
  1230. }
  1231. root->setNeedsAutoRename(TRUE);
  1232. }
  1233. LLAssetType::EType LLViewerInventoryItem::getType() const
  1234. {
  1235. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1236. {
  1237. return linked_item->getType();
  1238. }
  1239. if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
  1240. {
  1241. return linked_category->getType();
  1242. }
  1243. return LLInventoryItem::getType();
  1244. }
  1245. const LLUUID& LLViewerInventoryItem::getAssetUUID() const
  1246. {
  1247. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1248. {
  1249. return linked_item->getAssetUUID();
  1250. }
  1251. return LLInventoryItem::getAssetUUID();
  1252. }
  1253. const LLUUID& LLViewerInventoryItem::getProtectedAssetUUID() const
  1254. {
  1255. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1256. {
  1257. return linked_item->getProtectedAssetUUID();
  1258. }
  1259. // check for conditions under which we may return a visible UUID to the user
  1260. bool item_is_fullperm = getIsFullPerm();
  1261. bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery();
  1262. if (item_is_fullperm || agent_is_godlike)
  1263. {
  1264. return LLInventoryItem::getAssetUUID();
  1265. }
  1266. return LLUUID::null;
  1267. }
  1268. const bool LLViewerInventoryItem::getIsFullPerm() const
  1269. {
  1270. LLPermissions item_permissions = getPermissions();
  1271. // modify-ok & copy-ok & transfer-ok
  1272. return ( item_permissions.allowOperationBy(PERM_MODIFY,
  1273. gAgent.getID(),
  1274. gAgent.getGroupID()) &&
  1275. item_permissions.allowOperationBy(PERM_COPY,
  1276. gAgent.getID(),
  1277. gAgent.getGroupID()) &&
  1278. item_permissions.allowOperationBy(PERM_TRANSFER,
  1279. gAgent.getID(),
  1280. gAgent.getGroupID()) );
  1281. }
  1282. const std::string& LLViewerInventoryItem::getName() const
  1283. {
  1284. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1285. {
  1286. return linked_item->getName();
  1287. }
  1288. if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
  1289. {
  1290. return linked_category->getName();
  1291. }
  1292. return LLInventoryItem::getName();
  1293. }
  1294. /**
  1295. * Class to store sorting order of favorites landmarks in a local file. EXT-3985.
  1296. * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix.
  1297. * Data are stored in user home directory.
  1298. */
  1299. class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
  1300. , public LLDestroyClass<LLFavoritesOrderStorage>
  1301. {
  1302. public:
  1303. /**
  1304. * Sets sort index for specified with LLUUID favorite landmark
  1305. */
  1306. void setSortIndex(const LLUUID& inv_item_id, S32 sort_index);
  1307. /**
  1308. * Gets sort index for specified with LLUUID favorite landmark
  1309. */
  1310. S32 getSortIndex(const LLUUID& inv_item_id);
  1311. void removeSortIndex(const LLUUID& inv_item_id);
  1312. void getSLURL(const LLUUID& asset_id);
  1313. /**
  1314. * Implementation of LLDestroyClass. Calls cleanup() instance method.
  1315. *
  1316. * It is important this callback is called before gInventory is cleaned.
  1317. * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(),
  1318. * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called.
  1319. * @see cleanup()
  1320. */
  1321. static void destroyClass();
  1322. const static S32 NO_INDEX;
  1323. private:
  1324. friend class LLSingleton<LLFavoritesOrderStorage>;
  1325. LLFavoritesOrderStorage() : mIsDirty(false) { load(); }
  1326. ~LLFavoritesOrderStorage() { save(); }
  1327. /**
  1328. * Removes sort indexes for items which are not in Favorites bar for now.
  1329. */
  1330. void cleanup();
  1331. const static std::string SORTING_DATA_FILE_NAME;
  1332. void load();
  1333. void save();
  1334. void saveFavoritesSLURLs();
  1335. // Remove record of current user's favorites from file on disk.
  1336. void removeFavoritesRecordOfUser();
  1337. void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark);
  1338. void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
  1339. typedef std::map<LLUUID, S32> sort_index_map_t;
  1340. sort_index_map_t mSortIndexes;
  1341. typedef std::map<LLUUID, std::string> slurls_map_t;
  1342. slurls_map_t mSLURLs;
  1343. bool mIsDirty;
  1344. struct IsNotInFavorites
  1345. {
  1346. IsNotInFavorites(const LLInventoryModel::item_array_t& items)
  1347. : mFavoriteItems(items)
  1348. {
  1349. }
  1350. /**
  1351. * Returns true if specified item is not found among inventory items
  1352. */
  1353. bool operator()(const sort_index_map_t::value_type& id_index_pair) const
  1354. {
  1355. LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first);
  1356. if (item.isNull()) return true;
  1357. LLInventoryModel::item_array_t::const_iterator found_it =
  1358. std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item);
  1359. return found_it == mFavoriteItems.end();
  1360. }
  1361. private:
  1362. LLInventoryModel::item_array_t mFavoriteItems;
  1363. };
  1364. };
  1365. const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml";
  1366. const S32 LLFavoritesOrderStorage::NO_INDEX = -1;
  1367. void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index)
  1368. {
  1369. mSortIndexes[inv_item_id] = sort_index;
  1370. mIsDirty = true;
  1371. }
  1372. S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id)
  1373. {
  1374. sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id);
  1375. if (it != mSortIndexes.end())
  1376. {
  1377. return it->second;
  1378. }
  1379. return NO_INDEX;
  1380. }
  1381. void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id)
  1382. {
  1383. mSortIndexes.erase(inv_item_id);
  1384. mIsDirty = true;
  1385. }
  1386. void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
  1387. {
  1388. slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id);
  1389. if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached
  1390. LLLandmark* lm = gLandmarkList.getAsset(asset_id,
  1391. boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1));
  1392. if (lm)
  1393. {
  1394. onLandmarkLoaded(asset_id, lm);
  1395. }
  1396. }
  1397. // static
  1398. void LLFavoritesOrderStorage::destroyClass()
  1399. {
  1400. LLFavoritesOrderStorage::instance().cleanup();
  1401. if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
  1402. {
  1403. LLFavoritesOrderStorage::instance().saveFavoritesSLURLs();
  1404. }
  1405. else
  1406. {
  1407. LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser();
  1408. }
  1409. }
  1410. void LLFavoritesOrderStorage::load()
  1411. {
  1412. // load per-resident sorting information
  1413. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
  1414. LLSD settings_llsd;
  1415. llifstream file;
  1416. file.open(filename);
  1417. if (file.is_open())
  1418. {
  1419. LLSDSerialize::fromXML(settings_llsd, file);
  1420. }
  1421. for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
  1422. iter != settings_llsd.endMap(); ++iter)
  1423. {
  1424. mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
  1425. }
  1426. }
  1427. void LLFavoritesOrderStorage::saveFavoritesSLURLs()
  1428. {
  1429. // Do not change the file if we are not logged in yet.
  1430. if (!LLLoginInstance::getInstance()->authSuccess()) return;
  1431. std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
  1432. if (user_dir.empty()) return;
  1433. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
  1434. llifstream in_file;
  1435. in_file.open(filename);
  1436. LLSD fav_llsd;
  1437. if (in_file.is_open())
  1438. {
  1439. LLSDSerialize::fromXML(fav_llsd, in_file);
  1440. }
  1441. const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
  1442. LLInventoryModel::cat_array_t cats;
  1443. LLInventoryModel::item_array_t items;
  1444. gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
  1445. LLSD user_llsd;
  1446. for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
  1447. {
  1448. LLSD value;
  1449. value["name"] = (*it)->getName();
  1450. value["asset_id"] = (*it)->getAssetUUID();
  1451. slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
  1452. if (slurl_iter != mSLURLs.end())
  1453. {
  1454. value["slurl"] = slurl_iter->second;
  1455. user_llsd[(*it)->getSortField()] = value;
  1456. }
  1457. }
  1458. LLAvatarName av_name;
  1459. LLAvatarNameCache::get( gAgentID, &av_name );
  1460. fav_llsd[av_name.getLegacyName()] = user_llsd;
  1461. llofstream file;
  1462. file.open(filename);
  1463. LLSDSerialize::toPrettyXML(fav_llsd, file);
  1464. }
  1465. void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
  1466. {
  1467. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
  1468. LLSD fav_llsd;
  1469. llifstream file;
  1470. file.open(filename);
  1471. if (!file.is_open()) return;
  1472. LLSDSerialize::fromXML(fav_llsd, file);
  1473. LLAvatarName av_name;
  1474. LLAvatarNameCache::get( gAgentID, &av_name );
  1475. if (fav_llsd.has(av_name.getLegacyName()))
  1476. {
  1477. fav_llsd.erase(av_name.getLegacyName());
  1478. }
  1479. llofstream out_file;
  1480. out_file.open(filename);
  1481. LLSDSerialize::toPrettyXML(fav_llsd, out_file);
  1482. }
  1483. void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark)
  1484. {
  1485. if (!landmark) return;
  1486. LLVector3d pos_global;
  1487. if (!landmark->getGlobalPos(pos_global))
  1488. {
  1489. // If global position was unknown on first getGlobalPos() call
  1490. // it should be set for the subsequent calls.
  1491. landmark->getGlobalPos(pos_global);
  1492. }
  1493. if (!pos_global.isExactlyZero())
  1494. {
  1495. LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
  1496. boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
  1497. }
  1498. }
  1499. void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl)
  1500. {
  1501. mSLURLs[asset_id] = slurl;
  1502. }
  1503. void LLFavoritesOrderStorage::save()
  1504. {
  1505. // nothing to save if clean
  1506. if (!mIsDirty) return;
  1507. // If we quit from the login screen we will not have an SL account
  1508. // name. Don't try to save, otherwise we'll dump a file in
  1509. // C:\Program Files\SecondLife\ or similar. JC
  1510. std::string user_dir = gDirUtilp->getLindenUserDir();
  1511. if (!user_dir.empty())
  1512. {
  1513. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
  1514. LLSD settings_llsd;
  1515. for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
  1516. {
  1517. settings_llsd[iter->first.asString()] = iter->second;
  1518. }
  1519. llofstream file;
  1520. file.open(filename);
  1521. LLSDSerialize::toPrettyXML(settings_llsd, file);
  1522. }
  1523. }
  1524. void LLFavoritesOrderStorage::cleanup()
  1525. {
  1526. // nothing to clean
  1527. if (!mIsDirty) return;
  1528. const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
  1529. LLInventoryModel::cat_array_t cats;
  1530. LLInventoryModel::item_array_t items;
  1531. gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
  1532. IsNotInFavorites is_not_in_fav(items);
  1533. sort_index_map_t aTempMap;
  1534. //copy unremoved values from mSortIndexes to aTempMap
  1535. std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
  1536. inserter(aTempMap, aTempMap.begin()),
  1537. is_not_in_fav);
  1538. //Swap the contents of mSortIndexes and aTempMap
  1539. mSortIndexes.swap(aTempMap);
  1540. }
  1541. S32 LLViewerInventoryItem::getSortField() const
  1542. {
  1543. return LLFavoritesOrderStorage::instance().getSortIndex(mUUID);
  1544. }
  1545. void LLViewerInventoryItem::setSortField(S32 sortField)
  1546. {
  1547. LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField);
  1548. getSLURL();
  1549. }
  1550. void LLViewerInventoryItem::getSLURL()
  1551. {
  1552. LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID);
  1553. }
  1554. const LLPermissions& LLViewerInventoryItem::getPermissions() const
  1555. {
  1556. // Use the actual permissions of the symlink, not its parent.
  1557. return LLInventoryItem::getPermissions();
  1558. }
  1559. const LLUUID& LLViewerInventoryItem::getCreatorUUID() const
  1560. {
  1561. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1562. {
  1563. return linked_item->getCreatorUUID();
  1564. }
  1565. return LLInventoryItem::getCreatorUUID();
  1566. }
  1567. const std::string& LLViewerInventoryItem::getDescription() const
  1568. {
  1569. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1570. {
  1571. return linked_item->getDescription();
  1572. }
  1573. return LLInventoryItem::getDescription();
  1574. }
  1575. const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const
  1576. {
  1577. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1578. {
  1579. return linked_item->getSaleInfo();
  1580. }
  1581. return LLInventoryItem::getSaleInfo();
  1582. }
  1583. LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const
  1584. {
  1585. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1586. {
  1587. return linked_item->getInventoryType();
  1588. }
  1589. // Categories don't have types. If this item is an AT_FOLDER_LINK,
  1590. // treat it as a category.
  1591. if (getLinkedCategory())
  1592. {
  1593. return LLInventoryType::IT_CATEGORY;
  1594. }
  1595. return LLInventoryItem::getInventoryType();
  1596. }
  1597. U32 LLViewerInventoryItem::getFlags() const
  1598. {
  1599. if (const LLViewerInventoryItem *linked_item = getLinkedItem())
  1600. {
  1601. return linked_item->getFlags();
  1602. }
  1603. return LLInventoryItem::getFlags();
  1604. }
  1605. bool LLViewerInventoryItem::isWearableType() const
  1606. {
  1607. return (getInventoryType() == LLInventoryType::IT_WEARABLE);
  1608. }
  1609. LLWearableType::EType LLViewerInventoryItem::getWearableType() const
  1610. {
  1611. if (!isWearableType())
  1612. {
  1613. return LLWearableType::WT_INVALID;
  1614. }
  1615. return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
  1616. }
  1617. time_t LLViewerInventoryItem::getCreationDate() const
  1618. {
  1619. return LLInventoryItem::getCreationDate();
  1620. }
  1621. U32 LLViewerInventoryItem::getCRC32() const
  1622. {
  1623. return LLInventoryItem::getCRC32();
  1624. }
  1625. // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985
  1626. static char getSeparator() { return '@'; }
  1627. BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName)
  1628. {
  1629. using std::string;
  1630. using std::stringstream;
  1631. const char separator = getSeparator();
  1632. const string::size_type separatorPos = name.find(separator, 0);
  1633. BOOL result = FALSE;
  1634. if (separatorPos < string::npos)
  1635. {
  1636. if (sortField)
  1637. {
  1638. /*
  1639. * The conversion from string to S32 is made this way instead of old plain
  1640. * atoi() to ensure portability. If on some other platform S32 will not be
  1641. * defined to be signed int, this conversion will still work because of
  1642. * operators overloading, but atoi() may fail.
  1643. */
  1644. stringstream ss(name.substr(0, separatorPos));
  1645. ss >> *sortField;
  1646. }
  1647. if (displayName)
  1648. {
  1649. *displayName = name.substr(separatorPos + 1, string::npos);
  1650. }
  1651. result = TRUE;
  1652. }
  1653. return result;
  1654. }
  1655. // This returns true if the item that this item points to
  1656. // doesn't exist in memory (i.e. LLInventoryModel). The baseitem
  1657. // might still be in the database but just not loaded yet.
  1658. bool LLViewerInventoryItem::getIsBrokenLink() const
  1659. {
  1660. // If the item's type resolves to be a link, that means either:
  1661. // A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory.
  1662. // B. It's pointing to another link, which is illegal.
  1663. return LLAssetType::lookupIsLinkType(getType());
  1664. }
  1665. LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
  1666. {
  1667. if (mType == LLAssetType::AT_LINK)
  1668. {
  1669. LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
  1670. if (linked_item && linked_item->getIsLinkType())
  1671. {
  1672. llwarns << "Warning: Accessing link to link" << llendl;
  1673. return NULL;
  1674. }
  1675. return linked_item;
  1676. }
  1677. return NULL;
  1678. }
  1679. LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
  1680. {
  1681. if (mType == LLAssetType::AT_LINK_FOLDER)
  1682. {
  1683. LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
  1684. return linked_category;
  1685. }
  1686. return NULL;
  1687. }
  1688. bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const
  1689. {
  1690. const LLPermissions& perm = getPermissions();
  1691. PermissionMask curr_mask = PERM_NONE;
  1692. if(perm.getOwner() == gAgent.getID())
  1693. {
  1694. curr_mask = perm.getMaskBase();
  1695. }
  1696. else if(gAgent.isInGroup(perm.getGroup()))
  1697. {
  1698. curr_mask = perm.getMaskGroup();
  1699. }
  1700. else
  1701. {
  1702. curr_mask = perm.getMaskEveryone();
  1703. }
  1704. return ((curr_mask & mask) == mask);
  1705. }
  1706. PermissionMask LLViewerInventoryItem::getPermissionMask() const
  1707. {
  1708. const LLPermissions& permissions = getPermissions();
  1709. BOOL copy = permissions.allowCopyBy(gAgent.getID());
  1710. BOOL mod = permissions.allowModifyBy(gAgent.getID());
  1711. BOOL xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID());
  1712. PermissionMask perm_mask = 0;
  1713. if (copy) perm_mask |= PERM_COPY;
  1714. if (mod) perm_mask |= PERM_MODIFY;
  1715. if (xfer) perm_mask |= PERM_TRANSFER;
  1716. return perm_mask;
  1717. }
  1718. //----------
  1719. void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group)
  1720. {
  1721. rename(name);
  1722. gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
  1723. gInventory.notifyObservers();
  1724. }
  1725. class LLRegenerateLinkCollector : public LLInventoryCollectFunctor
  1726. {
  1727. public:
  1728. LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {}
  1729. virtual ~LLRegenerateLinkCollector() {}
  1730. virtual bool operator()(LLInventoryCategory* cat,
  1731. LLInventoryItem* item)
  1732. {
  1733. if (item)
  1734. {
  1735. if ((item->getName() == mTargetItem->getName()) &&
  1736. (item->getInventoryType() == mTargetItem->getInventoryType()) &&
  1737. (!item->getIsLinkType()))
  1738. {
  1739. return true;
  1740. }
  1741. }
  1742. return false;
  1743. }
  1744. protected:
  1745. const LLViewerInventoryItem* mTargetItem;
  1746. };
  1747. LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_item)
  1748. {
  1749. LLViewerInventoryCategory::cat_array_t cats;
  1750. LLViewerInventoryItem::item_array_t items;
  1751. LLRegenerateLinkCollector candidate_matches(target_item);
  1752. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  1753. cats,
  1754. items,
  1755. LLInventoryModel::EXCLUDE_TRASH,
  1756. candidate_matches);
  1757. for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin();
  1758. item_iter != items.end();
  1759. ++item_iter)
  1760. {
  1761. const LLViewerInventoryItem *item = (*item_iter);
  1762. if (true) return item->getUUID();
  1763. }
  1764. return LLUUID::null;
  1765. }
  1766. // This currently dosen't work, because the sim does not allow us
  1767. // to change an item's assetID.
  1768. BOOL LLViewerInventoryItem::regenerateLink()
  1769. {
  1770. const LLUUID target_item_id = find_possible_item_for_regeneration(this);
  1771. if (target_item_id.isNull())
  1772. return FALSE;
  1773. LLViewerInventoryCategory::cat_array_t cats;
  1774. LLViewerInventoryItem::item_array_t items;
  1775. LLAssetIDMatches asset_id_matches(getAssetUUID());
  1776. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  1777. cats,
  1778. items,
  1779. LLInventoryModel::EXCLUDE_TRASH,
  1780. asset_id_matches);
  1781. for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin();
  1782. item_iter != items.end();
  1783. item_iter++)
  1784. {
  1785. LLViewerInventoryItem *item = (*item_iter);
  1786. item->setAssetUUID(target_item_id);
  1787. item->updateServer(FALSE);
  1788. gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID());
  1789. }
  1790. gInventory.notifyObservers();
  1791. return TRUE;
  1792. }