PageRenderTime 44ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llinventory/llinventory.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1649 lines | 1324 code | 156 blank | 169 comment | 240 complexity | 2a0917dc0f04177a368db9d3e6fae210 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llinventory.cpp
  3. * @brief Implementation of the inventory system.
  4. *
  5. * $LicenseInfo:firstyear=2001&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 "linden_common.h"
  27. #include "llinventory.h"
  28. #include "lldbstrings.h"
  29. #include "llinventorydefines.h"
  30. #include "llxorcipher.h"
  31. #include "llsd.h"
  32. #include "message.h"
  33. #include <boost/tokenizer.hpp>
  34. #include "llsdutil.h"
  35. ///----------------------------------------------------------------------------
  36. /// Exported functions
  37. ///----------------------------------------------------------------------------
  38. static const std::string INV_ITEM_ID_LABEL("item_id");
  39. static const std::string INV_FOLDER_ID_LABEL("folder_id");
  40. static const std::string INV_PARENT_ID_LABEL("parent_id");
  41. static const std::string INV_ASSET_TYPE_LABEL("type");
  42. static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
  43. static const std::string INV_INVENTORY_TYPE_LABEL("inv_type");
  44. static const std::string INV_NAME_LABEL("name");
  45. static const std::string INV_DESC_LABEL("desc");
  46. static const std::string INV_PERMISSIONS_LABEL("permissions");
  47. static const std::string INV_SHADOW_ID_LABEL("shadow_id");
  48. static const std::string INV_ASSET_ID_LABEL("asset_id");
  49. static const std::string INV_SALE_INFO_LABEL("sale_info");
  50. static const std::string INV_FLAGS_LABEL("flags");
  51. static const std::string INV_CREATION_DATE_LABEL("created_at");
  52. // key used by agent-inventory-service
  53. static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
  54. static const std::string INV_FOLDER_ID_LABEL_WS("category_id");
  55. ///----------------------------------------------------------------------------
  56. /// Local function declarations, constants, enums, and typedefs
  57. ///----------------------------------------------------------------------------
  58. const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730");
  59. ///----------------------------------------------------------------------------
  60. /// Class LLInventoryObject
  61. ///----------------------------------------------------------------------------
  62. LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
  63. const LLUUID& parent_uuid,
  64. LLAssetType::EType type,
  65. const std::string& name) :
  66. mUUID(uuid),
  67. mParentUUID(parent_uuid),
  68. mType(type),
  69. mName(name)
  70. {
  71. correctInventoryName(mName);
  72. }
  73. LLInventoryObject::LLInventoryObject() :
  74. mType(LLAssetType::AT_NONE)
  75. {
  76. }
  77. LLInventoryObject::~LLInventoryObject()
  78. {
  79. }
  80. void LLInventoryObject::copyObject(const LLInventoryObject* other)
  81. {
  82. mUUID = other->mUUID;
  83. mParentUUID = other->mParentUUID;
  84. mType = other->mType;
  85. mName = other->mName;
  86. }
  87. const LLUUID& LLInventoryObject::getUUID() const
  88. {
  89. return mUUID;
  90. }
  91. const LLUUID& LLInventoryObject::getParentUUID() const
  92. {
  93. return mParentUUID;
  94. }
  95. const std::string& LLInventoryObject::getName() const
  96. {
  97. return mName;
  98. }
  99. // To bypass linked items, since llviewerinventory's getType
  100. // will return the linked-to item's type instead of this object's type.
  101. LLAssetType::EType LLInventoryObject::getActualType() const
  102. {
  103. return mType;
  104. }
  105. BOOL LLInventoryObject::getIsLinkType() const
  106. {
  107. return LLAssetType::lookupIsLinkType(mType);
  108. }
  109. // See LLInventoryItem override.
  110. // virtual
  111. const LLUUID& LLInventoryObject::getLinkedUUID() const
  112. {
  113. return mUUID;
  114. }
  115. LLAssetType::EType LLInventoryObject::getType() const
  116. {
  117. return mType;
  118. }
  119. void LLInventoryObject::setUUID(const LLUUID& new_uuid)
  120. {
  121. mUUID = new_uuid;
  122. }
  123. void LLInventoryObject::rename(const std::string& n)
  124. {
  125. std::string new_name(n);
  126. correctInventoryName(new_name);
  127. if( !new_name.empty() && new_name != mName )
  128. {
  129. mName = new_name;
  130. }
  131. }
  132. void LLInventoryObject::setParent(const LLUUID& new_parent)
  133. {
  134. mParentUUID = new_parent;
  135. }
  136. void LLInventoryObject::setType(LLAssetType::EType type)
  137. {
  138. mType = type;
  139. }
  140. // virtual
  141. BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
  142. {
  143. // *NOTE: Changing the buffer size will require changing the scanf
  144. // calls below.
  145. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  146. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  147. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  148. keyword[0] = '\0';
  149. valuestr[0] = '\0';
  150. while(input_stream.good())
  151. {
  152. input_stream.getline(buffer, MAX_STRING);
  153. sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
  154. if(0 == strcmp("{",keyword))
  155. {
  156. continue;
  157. }
  158. if(0 == strcmp("}", keyword))
  159. {
  160. break;
  161. }
  162. else if(0 == strcmp("obj_id", keyword))
  163. {
  164. mUUID.set(valuestr);
  165. }
  166. else if(0 == strcmp("parent_id", keyword))
  167. {
  168. mParentUUID.set(valuestr);
  169. }
  170. else if(0 == strcmp("type", keyword))
  171. {
  172. mType = LLAssetType::lookup(valuestr);
  173. }
  174. else if(0 == strcmp("name", keyword))
  175. {
  176. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  177. // *NOTE: Not ANSI C, but widely supported.
  178. sscanf( /* Flawfinder: ignore */
  179. buffer,
  180. " %254s %254[^|]",
  181. keyword, valuestr);
  182. mName.assign(valuestr);
  183. correctInventoryName(mName);
  184. }
  185. else
  186. {
  187. llwarns << "unknown keyword '" << keyword
  188. << "' in LLInventoryObject::importLegacyStream() for object " << mUUID << llendl;
  189. }
  190. }
  191. return TRUE;
  192. }
  193. // exportFile should be replaced with exportLegacyStream
  194. // not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented...
  195. BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const
  196. {
  197. std::string uuid_str;
  198. fprintf(fp, "\tinv_object\t0\n\t{\n");
  199. mUUID.toString(uuid_str);
  200. fprintf(fp, "\t\tobj_id\t%s\n", uuid_str.c_str());
  201. mParentUUID.toString(uuid_str);
  202. fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
  203. fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
  204. fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
  205. fprintf(fp,"\t}\n");
  206. return TRUE;
  207. }
  208. BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) const
  209. {
  210. std::string uuid_str;
  211. output_stream << "\tinv_object\t0\n\t{\n";
  212. mUUID.toString(uuid_str);
  213. output_stream << "\t\tobj_id\t" << uuid_str << "\n";
  214. mParentUUID.toString(uuid_str);
  215. output_stream << "\t\tparent_id\t" << uuid_str << "\n";
  216. output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
  217. output_stream << "\t\tname\t" << mName.c_str() << "|\n";
  218. output_stream << "\t}\n";
  219. return TRUE;
  220. }
  221. void LLInventoryObject::removeFromServer()
  222. {
  223. // don't do nothin'
  224. llwarns << "LLInventoryObject::removeFromServer() called. Doesn't do anything." << llendl;
  225. }
  226. void LLInventoryObject::updateParentOnServer(BOOL) const
  227. {
  228. // don't do nothin'
  229. llwarns << "LLInventoryObject::updateParentOnServer() called. Doesn't do anything." << llendl;
  230. }
  231. void LLInventoryObject::updateServer(BOOL) const
  232. {
  233. // don't do nothin'
  234. llwarns << "LLInventoryObject::updateServer() called. Doesn't do anything." << llendl;
  235. }
  236. inline
  237. void LLInventoryObject::correctInventoryName(std::string& name)
  238. {
  239. LLStringUtil::replaceNonstandardASCII(name, ' ');
  240. LLStringUtil::replaceChar(name, '|', ' ');
  241. LLStringUtil::trim(name);
  242. LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);
  243. }
  244. ///----------------------------------------------------------------------------
  245. /// Class LLInventoryItem
  246. ///----------------------------------------------------------------------------
  247. LLInventoryItem::LLInventoryItem(const LLUUID& uuid,
  248. const LLUUID& parent_uuid,
  249. const LLPermissions& permissions,
  250. const LLUUID& asset_uuid,
  251. LLAssetType::EType type,
  252. LLInventoryType::EType inv_type,
  253. const std::string& name,
  254. const std::string& desc,
  255. const LLSaleInfo& sale_info,
  256. U32 flags,
  257. S32 creation_date_utc) :
  258. LLInventoryObject(uuid, parent_uuid, type, name),
  259. mPermissions(permissions),
  260. mAssetUUID(asset_uuid),
  261. mDescription(desc),
  262. mSaleInfo(sale_info),
  263. mInventoryType(inv_type),
  264. mFlags(flags),
  265. mCreationDate(creation_date_utc)
  266. {
  267. LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
  268. LLStringUtil::replaceChar(mDescription, '|', ' ');
  269. mPermissions.initMasks(inv_type);
  270. }
  271. LLInventoryItem::LLInventoryItem() :
  272. LLInventoryObject(),
  273. mPermissions(),
  274. mAssetUUID(),
  275. mDescription(),
  276. mSaleInfo(),
  277. mInventoryType(LLInventoryType::IT_NONE),
  278. mFlags(0),
  279. mCreationDate(0)
  280. {
  281. }
  282. LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) :
  283. LLInventoryObject()
  284. {
  285. copyItem(other);
  286. }
  287. LLInventoryItem::~LLInventoryItem()
  288. {
  289. }
  290. // virtual
  291. void LLInventoryItem::copyItem(const LLInventoryItem* other)
  292. {
  293. copyObject(other);
  294. mPermissions = other->mPermissions;
  295. mAssetUUID = other->mAssetUUID;
  296. mDescription = other->mDescription;
  297. mSaleInfo = other->mSaleInfo;
  298. mInventoryType = other->mInventoryType;
  299. mFlags = other->mFlags;
  300. mCreationDate = other->mCreationDate;
  301. }
  302. // If this is a linked item, then the UUID of the base object is
  303. // this item's assetID.
  304. // virtual
  305. const LLUUID& LLInventoryItem::getLinkedUUID() const
  306. {
  307. if (LLAssetType::lookupIsLinkType(getActualType()))
  308. {
  309. return mAssetUUID;
  310. }
  311. return LLInventoryObject::getLinkedUUID();
  312. }
  313. const LLPermissions& LLInventoryItem::getPermissions() const
  314. {
  315. return mPermissions;
  316. }
  317. const LLUUID& LLInventoryItem::getCreatorUUID() const
  318. {
  319. return mPermissions.getCreator();
  320. }
  321. const LLUUID& LLInventoryItem::getAssetUUID() const
  322. {
  323. return mAssetUUID;
  324. }
  325. void LLInventoryItem::setAssetUUID(const LLUUID& asset_id)
  326. {
  327. mAssetUUID = asset_id;
  328. }
  329. const std::string& LLInventoryItem::getDescription() const
  330. {
  331. return mDescription;
  332. }
  333. time_t LLInventoryItem::getCreationDate() const
  334. {
  335. return mCreationDate;
  336. }
  337. U32 LLInventoryItem::getCRC32() const
  338. {
  339. // *FIX: Not a real crc - more of a checksum.
  340. // *NOTE: We currently do not validate the name or description,
  341. // but if they change in transit, it's no big deal.
  342. U32 crc = mUUID.getCRC32();
  343. //lldebugs << "1 crc: " << std::hex << crc << std::dec << llendl;
  344. crc += mParentUUID.getCRC32();
  345. //lldebugs << "2 crc: " << std::hex << crc << std::dec << llendl;
  346. crc += mPermissions.getCRC32();
  347. //lldebugs << "3 crc: " << std::hex << crc << std::dec << llendl;
  348. crc += mAssetUUID.getCRC32();
  349. //lldebugs << "4 crc: " << std::hex << crc << std::dec << llendl;
  350. crc += mType;
  351. //lldebugs << "5 crc: " << std::hex << crc << std::dec << llendl;
  352. crc += mInventoryType;
  353. //lldebugs << "6 crc: " << std::hex << crc << std::dec << llendl;
  354. crc += mFlags;
  355. //lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl;
  356. crc += mSaleInfo.getCRC32();
  357. //lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl;
  358. crc += mCreationDate;
  359. //lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl;
  360. return crc;
  361. }
  362. void LLInventoryItem::setDescription(const std::string& d)
  363. {
  364. std::string new_desc(d);
  365. LLStringUtil::replaceNonstandardASCII(new_desc, ' ');
  366. LLStringUtil::replaceChar(new_desc, '|', ' ');
  367. if( new_desc != mDescription )
  368. {
  369. mDescription = new_desc;
  370. }
  371. }
  372. void LLInventoryItem::setPermissions(const LLPermissions& perm)
  373. {
  374. mPermissions = perm;
  375. // Override permissions to unrestricted if this is a landmark
  376. mPermissions.initMasks(mInventoryType);
  377. }
  378. void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type)
  379. {
  380. mInventoryType = inv_type;
  381. }
  382. void LLInventoryItem::setFlags(U32 flags)
  383. {
  384. mFlags = flags;
  385. }
  386. void LLInventoryItem::setCreationDate(time_t creation_date_utc)
  387. {
  388. mCreationDate = creation_date_utc;
  389. }
  390. // Currently only used in the Viewer to handle calling cards
  391. // where the creator is actually used to store the target.
  392. void LLInventoryItem::setCreator(const LLUUID& creator)
  393. {
  394. mPermissions.setCreator(creator);
  395. }
  396. void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
  397. {
  398. // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags
  399. // because we now detect when they should be set.
  400. setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItemFlags::II_FLAGS_PERM_OVERWRITE_MASK)) );
  401. // Enforce the PERM_OVERWRITE flags for any masks that are different
  402. // but only for AT_OBJECT's since that is the only asset type that can
  403. // exist in-world (instead of only in-inventory or in-object-contents).
  404. if (LLAssetType::AT_OBJECT == getType())
  405. {
  406. LLPermissions old_permissions = old_item.getPermissions();
  407. U32 flags_to_be_set = 0;
  408. if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
  409. {
  410. flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
  411. }
  412. if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
  413. {
  414. flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
  415. }
  416. if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
  417. {
  418. flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
  419. }
  420. LLSaleInfo old_sale_info = old_item.getSaleInfo();
  421. if(old_sale_info != getSaleInfo())
  422. {
  423. flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_SALE;
  424. }
  425. setFlags(getFlags() | flags_to_be_set);
  426. }
  427. }
  428. const LLSaleInfo& LLInventoryItem::getSaleInfo() const
  429. {
  430. return mSaleInfo;
  431. }
  432. void LLInventoryItem::setSaleInfo(const LLSaleInfo& sale_info)
  433. {
  434. mSaleInfo = sale_info;
  435. }
  436. LLInventoryType::EType LLInventoryItem::getInventoryType() const
  437. {
  438. return mInventoryType;
  439. }
  440. U32 LLInventoryItem::getFlags() const
  441. {
  442. return mFlags;
  443. }
  444. // virtual
  445. void LLInventoryItem::packMessage(LLMessageSystem* msg) const
  446. {
  447. msg->addUUIDFast(_PREHASH_ItemID, mUUID);
  448. msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
  449. mPermissions.packMessage(msg);
  450. msg->addUUIDFast(_PREHASH_AssetID, mAssetUUID);
  451. S8 type = static_cast<S8>(mType);
  452. msg->addS8Fast(_PREHASH_Type, type);
  453. type = static_cast<S8>(mInventoryType);
  454. msg->addS8Fast(_PREHASH_InvType, type);
  455. msg->addU32Fast(_PREHASH_Flags, mFlags);
  456. mSaleInfo.packMessage(msg);
  457. msg->addStringFast(_PREHASH_Name, mName);
  458. msg->addStringFast(_PREHASH_Description, mDescription);
  459. msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
  460. U32 crc = getCRC32();
  461. msg->addU32Fast(_PREHASH_CRC, crc);
  462. }
  463. // virtual
  464. BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
  465. {
  466. msg->getUUIDFast(block, _PREHASH_ItemID, mUUID, block_num);
  467. msg->getUUIDFast(block, _PREHASH_FolderID, mParentUUID, block_num);
  468. mPermissions.unpackMessage(msg, block, block_num);
  469. msg->getUUIDFast(block, _PREHASH_AssetID, mAssetUUID, block_num);
  470. S8 type;
  471. msg->getS8Fast(block, _PREHASH_Type, type, block_num);
  472. mType = static_cast<LLAssetType::EType>(type);
  473. msg->getS8(block, "InvType", type, block_num);
  474. mInventoryType = static_cast<LLInventoryType::EType>(type);
  475. mPermissions.initMasks(mInventoryType);
  476. msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num);
  477. mSaleInfo.unpackMultiMessage(msg, block, block_num);
  478. msg->getStringFast(block, _PREHASH_Name, mName, block_num);
  479. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  480. msg->getStringFast(block, _PREHASH_Description, mDescription, block_num);
  481. LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
  482. S32 date;
  483. msg->getS32(block, "CreationDate", date, block_num);
  484. mCreationDate = date;
  485. U32 local_crc = getCRC32();
  486. U32 remote_crc = 0;
  487. msg->getU32(block, "CRC", remote_crc, block_num);
  488. //#define CRC_CHECK
  489. #ifdef CRC_CHECK
  490. if(local_crc == remote_crc)
  491. {
  492. lldebugs << "crc matches" << llendl;
  493. return TRUE;
  494. }
  495. else
  496. {
  497. llwarns << "inventory crc mismatch: local=" << std::hex << local_crc
  498. << " remote=" << remote_crc << std::dec << llendl;
  499. return FALSE;
  500. }
  501. #else
  502. return (local_crc == remote_crc);
  503. #endif
  504. }
  505. // virtual
  506. BOOL LLInventoryItem::importFile(LLFILE* fp)
  507. {
  508. // *NOTE: Changing the buffer size will require changing the scanf
  509. // calls below.
  510. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  511. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  512. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  513. char junk[MAX_STRING]; /* Flawfinder: ignore */
  514. BOOL success = TRUE;
  515. keyword[0] = '\0';
  516. valuestr[0] = '\0';
  517. mInventoryType = LLInventoryType::IT_NONE;
  518. mAssetUUID.setNull();
  519. while(success && (!feof(fp)))
  520. {
  521. if (fgets(buffer, MAX_STRING, fp) == NULL)
  522. {
  523. buffer[0] = '\0';
  524. }
  525. sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
  526. if(0 == strcmp("{",keyword))
  527. {
  528. continue;
  529. }
  530. if(0 == strcmp("}", keyword))
  531. {
  532. break;
  533. }
  534. else if(0 == strcmp("item_id", keyword))
  535. {
  536. mUUID.set(valuestr);
  537. }
  538. else if(0 == strcmp("parent_id", keyword))
  539. {
  540. mParentUUID.set(valuestr);
  541. }
  542. else if(0 == strcmp("permissions", keyword))
  543. {
  544. success = mPermissions.importFile(fp);
  545. }
  546. else if(0 == strcmp("sale_info", keyword))
  547. {
  548. // Sale info used to contain next owner perm. It is now in
  549. // the permissions. Thus, we read that out, and fix legacy
  550. // objects. It's possible this op would fail, but it
  551. // should pick up the vast majority of the tasks.
  552. BOOL has_perm_mask = FALSE;
  553. U32 perm_mask = 0;
  554. success = mSaleInfo.importFile(fp, has_perm_mask, perm_mask);
  555. if(has_perm_mask)
  556. {
  557. if(perm_mask == PERM_NONE)
  558. {
  559. perm_mask = mPermissions.getMaskOwner();
  560. }
  561. // fair use fix.
  562. if(!(perm_mask & PERM_COPY))
  563. {
  564. perm_mask |= PERM_TRANSFER;
  565. }
  566. mPermissions.setMaskNext(perm_mask);
  567. }
  568. }
  569. else if(0 == strcmp("shadow_id", keyword))
  570. {
  571. mAssetUUID.set(valuestr);
  572. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  573. cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
  574. }
  575. else if(0 == strcmp("asset_id", keyword))
  576. {
  577. mAssetUUID.set(valuestr);
  578. }
  579. else if(0 == strcmp("type", keyword))
  580. {
  581. mType = LLAssetType::lookup(valuestr);
  582. }
  583. else if(0 == strcmp("inv_type", keyword))
  584. {
  585. mInventoryType = LLInventoryType::lookup(std::string(valuestr));
  586. }
  587. else if(0 == strcmp("flags", keyword))
  588. {
  589. sscanf(valuestr, "%x", &mFlags);
  590. }
  591. else if(0 == strcmp("name", keyword))
  592. {
  593. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  594. // *NOTE: Not ANSI C, but widely supported.
  595. sscanf( /* Flawfinder: ignore */
  596. buffer,
  597. " %254s%254[\t]%254[^|]",
  598. keyword, junk, valuestr);
  599. // IW: sscanf chokes and puts | in valuestr if there's no name
  600. if (valuestr[0] == '|')
  601. {
  602. valuestr[0] = '\000';
  603. }
  604. mName.assign(valuestr);
  605. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  606. LLStringUtil::replaceChar(mName, '|', ' ');
  607. }
  608. else if(0 == strcmp("desc", keyword))
  609. {
  610. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  611. // *NOTE: Not ANSI C, but widely supported.
  612. sscanf( /* Flawfinder: ignore */
  613. buffer,
  614. " %254s%254[\t]%254[^|]",
  615. keyword, junk, valuestr);
  616. if (valuestr[0] == '|')
  617. {
  618. valuestr[0] = '\000';
  619. }
  620. mDescription.assign(valuestr);
  621. LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
  622. /* TODO -- ask Ian about this code
  623. const char *donkey = mDescription.c_str();
  624. if (donkey[0] == '|')
  625. {
  626. llerrs << "Donkey" << llendl;
  627. }
  628. */
  629. }
  630. else if(0 == strcmp("creation_date", keyword))
  631. {
  632. S32 date;
  633. sscanf(valuestr, "%d", &date);
  634. mCreationDate = date;
  635. }
  636. else
  637. {
  638. llwarns << "unknown keyword '" << keyword
  639. << "' in inventory import of item " << mUUID << llendl;
  640. }
  641. }
  642. // Need to convert 1.0 simstate files to a useful inventory type
  643. // and potentially deal with bad inventory tyes eg, a landmark
  644. // marked as a texture.
  645. if((LLInventoryType::IT_NONE == mInventoryType)
  646. || !inventory_and_asset_types_match(mInventoryType, mType))
  647. {
  648. lldebugs << "Resetting inventory type for " << mUUID << llendl;
  649. mInventoryType = LLInventoryType::defaultForAssetType(mType);
  650. }
  651. mPermissions.initMasks(mInventoryType);
  652. return success;
  653. }
  654. BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const
  655. {
  656. std::string uuid_str;
  657. fprintf(fp, "\tinv_item\t0\n\t{\n");
  658. mUUID.toString(uuid_str);
  659. fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str());
  660. mParentUUID.toString(uuid_str);
  661. fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
  662. mPermissions.exportFile(fp);
  663. // Check for permissions to see the asset id, and if so write it
  664. // out as an asset id. Otherwise, apply our cheesy encryption.
  665. if(include_asset_key)
  666. {
  667. U32 mask = mPermissions.getMaskBase();
  668. if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
  669. || (mAssetUUID.isNull()))
  670. {
  671. mAssetUUID.toString(uuid_str);
  672. fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
  673. }
  674. else
  675. {
  676. LLUUID shadow_id(mAssetUUID);
  677. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  678. cipher.encrypt(shadow_id.mData, UUID_BYTES);
  679. shadow_id.toString(uuid_str);
  680. fprintf(fp, "\t\tshadow_id\t%s\n", uuid_str.c_str());
  681. }
  682. }
  683. else
  684. {
  685. LLUUID::null.toString(uuid_str);
  686. fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
  687. }
  688. fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
  689. const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
  690. if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
  691. fprintf(fp, "\t\tflags\t%08x\n", mFlags);
  692. mSaleInfo.exportFile(fp);
  693. fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
  694. fprintf(fp, "\t\tdesc\t%s|\n", mDescription.c_str());
  695. fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate);
  696. fprintf(fp,"\t}\n");
  697. return TRUE;
  698. }
  699. // virtual
  700. BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
  701. {
  702. // *NOTE: Changing the buffer size will require changing the scanf
  703. // calls below.
  704. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  705. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  706. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  707. char junk[MAX_STRING]; /* Flawfinder: ignore */
  708. BOOL success = TRUE;
  709. keyword[0] = '\0';
  710. valuestr[0] = '\0';
  711. mInventoryType = LLInventoryType::IT_NONE;
  712. mAssetUUID.setNull();
  713. while(success && input_stream.good())
  714. {
  715. input_stream.getline(buffer, MAX_STRING);
  716. sscanf( /* Flawfinder: ignore */
  717. buffer,
  718. " %254s %254s",
  719. keyword, valuestr);
  720. if(0 == strcmp("{",keyword))
  721. {
  722. continue;
  723. }
  724. if(0 == strcmp("}", keyword))
  725. {
  726. break;
  727. }
  728. else if(0 == strcmp("item_id", keyword))
  729. {
  730. mUUID.set(valuestr);
  731. }
  732. else if(0 == strcmp("parent_id", keyword))
  733. {
  734. mParentUUID.set(valuestr);
  735. }
  736. else if(0 == strcmp("permissions", keyword))
  737. {
  738. success = mPermissions.importLegacyStream(input_stream);
  739. }
  740. else if(0 == strcmp("sale_info", keyword))
  741. {
  742. // Sale info used to contain next owner perm. It is now in
  743. // the permissions. Thus, we read that out, and fix legacy
  744. // objects. It's possible this op would fail, but it
  745. // should pick up the vast majority of the tasks.
  746. BOOL has_perm_mask = FALSE;
  747. U32 perm_mask = 0;
  748. success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask);
  749. if(has_perm_mask)
  750. {
  751. if(perm_mask == PERM_NONE)
  752. {
  753. perm_mask = mPermissions.getMaskOwner();
  754. }
  755. // fair use fix.
  756. if(!(perm_mask & PERM_COPY))
  757. {
  758. perm_mask |= PERM_TRANSFER;
  759. }
  760. mPermissions.setMaskNext(perm_mask);
  761. }
  762. }
  763. else if(0 == strcmp("shadow_id", keyword))
  764. {
  765. mAssetUUID.set(valuestr);
  766. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  767. cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
  768. }
  769. else if(0 == strcmp("asset_id", keyword))
  770. {
  771. mAssetUUID.set(valuestr);
  772. }
  773. else if(0 == strcmp("type", keyword))
  774. {
  775. mType = LLAssetType::lookup(valuestr);
  776. }
  777. else if(0 == strcmp("inv_type", keyword))
  778. {
  779. mInventoryType = LLInventoryType::lookup(std::string(valuestr));
  780. }
  781. else if(0 == strcmp("flags", keyword))
  782. {
  783. sscanf(valuestr, "%x", &mFlags);
  784. }
  785. else if(0 == strcmp("name", keyword))
  786. {
  787. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  788. // *NOTE: Not ANSI C, but widely supported.
  789. sscanf( /* Flawfinder: ignore */
  790. buffer,
  791. " %254s%254[\t]%254[^|]",
  792. keyword, junk, valuestr);
  793. // IW: sscanf chokes and puts | in valuestr if there's no name
  794. if (valuestr[0] == '|')
  795. {
  796. valuestr[0] = '\000';
  797. }
  798. mName.assign(valuestr);
  799. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  800. LLStringUtil::replaceChar(mName, '|', ' ');
  801. }
  802. else if(0 == strcmp("desc", keyword))
  803. {
  804. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  805. // *NOTE: Not ANSI C, but widely supported.
  806. sscanf( /* Flawfinder: ignore */
  807. buffer,
  808. " %254s%254[\t]%254[^|]",
  809. keyword, junk, valuestr);
  810. if (valuestr[0] == '|')
  811. {
  812. valuestr[0] = '\000';
  813. }
  814. mDescription.assign(valuestr);
  815. LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
  816. /* TODO -- ask Ian about this code
  817. const char *donkey = mDescription.c_str();
  818. if (donkey[0] == '|')
  819. {
  820. llerrs << "Donkey" << llendl;
  821. }
  822. */
  823. }
  824. else if(0 == strcmp("creation_date", keyword))
  825. {
  826. S32 date;
  827. sscanf(valuestr, "%d", &date);
  828. mCreationDate = date;
  829. }
  830. else
  831. {
  832. llwarns << "unknown keyword '" << keyword
  833. << "' in inventory import of item " << mUUID << llendl;
  834. }
  835. }
  836. // Need to convert 1.0 simstate files to a useful inventory type
  837. // and potentially deal with bad inventory tyes eg, a landmark
  838. // marked as a texture.
  839. if((LLInventoryType::IT_NONE == mInventoryType)
  840. || !inventory_and_asset_types_match(mInventoryType, mType))
  841. {
  842. lldebugs << "Resetting inventory type for " << mUUID << llendl;
  843. mInventoryType = LLInventoryType::defaultForAssetType(mType);
  844. }
  845. mPermissions.initMasks(mInventoryType);
  846. return success;
  847. }
  848. BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key) const
  849. {
  850. std::string uuid_str;
  851. output_stream << "\tinv_item\t0\n\t{\n";
  852. mUUID.toString(uuid_str);
  853. output_stream << "\t\titem_id\t" << uuid_str << "\n";
  854. mParentUUID.toString(uuid_str);
  855. output_stream << "\t\tparent_id\t" << uuid_str << "\n";
  856. mPermissions.exportLegacyStream(output_stream);
  857. // Check for permissions to see the asset id, and if so write it
  858. // out as an asset id. Otherwise, apply our cheesy encryption.
  859. if(include_asset_key)
  860. {
  861. U32 mask = mPermissions.getMaskBase();
  862. if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
  863. || (mAssetUUID.isNull()))
  864. {
  865. mAssetUUID.toString(uuid_str);
  866. output_stream << "\t\tasset_id\t" << uuid_str << "\n";
  867. }
  868. else
  869. {
  870. LLUUID shadow_id(mAssetUUID);
  871. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  872. cipher.encrypt(shadow_id.mData, UUID_BYTES);
  873. shadow_id.toString(uuid_str);
  874. output_stream << "\t\tshadow_id\t" << uuid_str << "\n";
  875. }
  876. }
  877. else
  878. {
  879. LLUUID::null.toString(uuid_str);
  880. output_stream << "\t\tasset_id\t" << uuid_str << "\n";
  881. }
  882. output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
  883. const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
  884. if(!inv_type_str.empty())
  885. output_stream << "\t\tinv_type\t" << inv_type_str << "\n";
  886. std::string buffer;
  887. buffer = llformat( "\t\tflags\t%08x\n", mFlags);
  888. output_stream << buffer;
  889. mSaleInfo.exportLegacyStream(output_stream);
  890. output_stream << "\t\tname\t" << mName.c_str() << "|\n";
  891. output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n";
  892. output_stream << "\t\tcreation_date\t" << mCreationDate << "\n";
  893. output_stream << "\t}\n";
  894. return TRUE;
  895. }
  896. LLSD LLInventoryItem::asLLSD() const
  897. {
  898. LLSD sd = LLSD();
  899. asLLSD(sd);
  900. return sd;
  901. }
  902. void LLInventoryItem::asLLSD( LLSD& sd ) const
  903. {
  904. sd[INV_ITEM_ID_LABEL] = mUUID;
  905. sd[INV_PARENT_ID_LABEL] = mParentUUID;
  906. sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
  907. U32 mask = mPermissions.getMaskBase();
  908. if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
  909. || (mAssetUUID.isNull()))
  910. {
  911. sd[INV_ASSET_ID_LABEL] = mAssetUUID;
  912. }
  913. else
  914. {
  915. // *TODO: get rid of this. Phoenix 2008-01-30
  916. LLUUID shadow_id(mAssetUUID);
  917. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  918. cipher.encrypt(shadow_id.mData, UUID_BYTES);
  919. sd[INV_SHADOW_ID_LABEL] = shadow_id;
  920. }
  921. sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
  922. sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
  923. const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
  924. if(!inv_type_str.empty())
  925. {
  926. sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
  927. }
  928. //sd[INV_FLAGS_LABEL] = (S32)mFlags;
  929. sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
  930. sd[INV_SALE_INFO_LABEL] = mSaleInfo;
  931. sd[INV_NAME_LABEL] = mName;
  932. sd[INV_DESC_LABEL] = mDescription;
  933. sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
  934. }
  935. LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
  936. bool LLInventoryItem::fromLLSD(const LLSD& sd)
  937. {
  938. LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
  939. mInventoryType = LLInventoryType::IT_NONE;
  940. mAssetUUID.setNull();
  941. std::string w;
  942. w = INV_ITEM_ID_LABEL;
  943. if (sd.has(w))
  944. {
  945. mUUID = sd[w];
  946. }
  947. w = INV_PARENT_ID_LABEL;
  948. if (sd.has(w))
  949. {
  950. mParentUUID = sd[w];
  951. }
  952. w = INV_PERMISSIONS_LABEL;
  953. if (sd.has(w))
  954. {
  955. mPermissions = ll_permissions_from_sd(sd[w]);
  956. }
  957. w = INV_SALE_INFO_LABEL;
  958. if (sd.has(w))
  959. {
  960. // Sale info used to contain next owner perm. It is now in
  961. // the permissions. Thus, we read that out, and fix legacy
  962. // objects. It's possible this op would fail, but it
  963. // should pick up the vast majority of the tasks.
  964. BOOL has_perm_mask = FALSE;
  965. U32 perm_mask = 0;
  966. if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask))
  967. {
  968. goto fail;
  969. }
  970. if (has_perm_mask)
  971. {
  972. if(perm_mask == PERM_NONE)
  973. {
  974. perm_mask = mPermissions.getMaskOwner();
  975. }
  976. // fair use fix.
  977. if(!(perm_mask & PERM_COPY))
  978. {
  979. perm_mask |= PERM_TRANSFER;
  980. }
  981. mPermissions.setMaskNext(perm_mask);
  982. }
  983. }
  984. w = INV_SHADOW_ID_LABEL;
  985. if (sd.has(w))
  986. {
  987. mAssetUUID = sd[w];
  988. LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
  989. cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
  990. }
  991. w = INV_ASSET_ID_LABEL;
  992. if (sd.has(w))
  993. {
  994. mAssetUUID = sd[w];
  995. }
  996. w = INV_ASSET_TYPE_LABEL;
  997. if (sd.has(w))
  998. {
  999. if (sd[w].isString())
  1000. {
  1001. mType = LLAssetType::lookup(sd[w].asString().c_str());
  1002. }
  1003. else if (sd[w].isInteger())
  1004. {
  1005. S8 type = (U8)sd[w].asInteger();
  1006. mType = static_cast<LLAssetType::EType>(type);
  1007. }
  1008. }
  1009. w = INV_INVENTORY_TYPE_LABEL;
  1010. if (sd.has(w))
  1011. {
  1012. if (sd[w].isString())
  1013. {
  1014. mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str());
  1015. }
  1016. else if (sd[w].isInteger())
  1017. {
  1018. S8 type = (U8)sd[w].asInteger();
  1019. mInventoryType = static_cast<LLInventoryType::EType>(type);
  1020. }
  1021. }
  1022. w = INV_FLAGS_LABEL;
  1023. if (sd.has(w))
  1024. {
  1025. if (sd[w].isBinary())
  1026. {
  1027. mFlags = ll_U32_from_sd(sd[w]);
  1028. }
  1029. else if(sd[w].isInteger())
  1030. {
  1031. mFlags = sd[w].asInteger();
  1032. }
  1033. }
  1034. w = INV_NAME_LABEL;
  1035. if (sd.has(w))
  1036. {
  1037. mName = sd[w].asString();
  1038. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  1039. LLStringUtil::replaceChar(mName, '|', ' ');
  1040. }
  1041. w = INV_DESC_LABEL;
  1042. if (sd.has(w))
  1043. {
  1044. mDescription = sd[w].asString();
  1045. LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
  1046. }
  1047. w = INV_CREATION_DATE_LABEL;
  1048. if (sd.has(w))
  1049. {
  1050. mCreationDate = sd[w].asInteger();
  1051. }
  1052. // Need to convert 1.0 simstate files to a useful inventory type
  1053. // and potentially deal with bad inventory tyes eg, a landmark
  1054. // marked as a texture.
  1055. if((LLInventoryType::IT_NONE == mInventoryType)
  1056. || !inventory_and_asset_types_match(mInventoryType, mType))
  1057. {
  1058. lldebugs << "Resetting inventory type for " << mUUID << llendl;
  1059. mInventoryType = LLInventoryType::defaultForAssetType(mType);
  1060. }
  1061. mPermissions.initMasks(mInventoryType);
  1062. return true;
  1063. fail:
  1064. return false;
  1065. }
  1066. // Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
  1067. // because I can't find any non-test code references to it. 2009-05-04 JC
  1068. S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const
  1069. {
  1070. // Figure out which permissions to use.
  1071. LLPermissions perm;
  1072. if (perm_override)
  1073. {
  1074. // Use the permissions override.
  1075. perm = *perm_override;
  1076. }
  1077. else
  1078. {
  1079. // Use the current permissions.
  1080. perm = getPermissions();
  1081. }
  1082. // describe the inventory item
  1083. char* buffer = (char*) bin_bucket;
  1084. std::string creator_id_str;
  1085. perm.getCreator().toString(creator_id_str);
  1086. std::string owner_id_str;
  1087. perm.getOwner().toString(owner_id_str);
  1088. std::string last_owner_id_str;
  1089. perm.getLastOwner().toString(last_owner_id_str);
  1090. std::string group_id_str;
  1091. perm.getGroup().toString(group_id_str);
  1092. std::string asset_id_str;
  1093. getAssetUUID().toString(asset_id_str);
  1094. S32 size = sprintf(buffer, /* Flawfinder: ignore */
  1095. "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
  1096. getType(),
  1097. getInventoryType(),
  1098. getName().c_str(),
  1099. creator_id_str.c_str(),
  1100. owner_id_str.c_str(),
  1101. last_owner_id_str.c_str(),
  1102. group_id_str.c_str(),
  1103. perm.getMaskBase(),
  1104. perm.getMaskOwner(),
  1105. perm.getMaskGroup(),
  1106. perm.getMaskEveryone(),
  1107. perm.getMaskNextOwner(),
  1108. asset_id_str.c_str(),
  1109. getDescription().c_str(),
  1110. getSaleInfo().getSaleType(),
  1111. getSaleInfo().getSalePrice(),
  1112. getFlags()) + 1;
  1113. return size;
  1114. }
  1115. void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size)
  1116. {
  1117. // Early exit on an empty binary bucket.
  1118. if (bin_bucket_size <= 1) return;
  1119. if (NULL == bin_bucket)
  1120. {
  1121. llerrs << "unpackBinaryBucket failed. bin_bucket is NULL." << llendl;
  1122. return;
  1123. }
  1124. // Convert the bin_bucket into a string.
  1125. std::vector<char> item_buffer(bin_bucket_size+1);
  1126. memcpy(&item_buffer[0], bin_bucket, bin_bucket_size); /* Flawfinder: ignore */
  1127. item_buffer[bin_bucket_size] = '\0';
  1128. std::string str(&item_buffer[0]);
  1129. lldebugs << "item buffer: " << str << llendl;
  1130. // Tokenize the string.
  1131. typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  1132. boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
  1133. tokenizer tokens(str, sep);
  1134. tokenizer::iterator iter = tokens.begin();
  1135. // Extract all values.
  1136. LLUUID item_id;
  1137. item_id.generate();
  1138. setUUID(item_id);
  1139. LLAssetType::EType type;
  1140. type = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
  1141. setType( type );
  1142. LLInventoryType::EType inv_type;
  1143. inv_type = (LLInventoryType::EType)(atoi((*(iter++)).c_str()));
  1144. setInventoryType( inv_type );
  1145. std::string name((*(iter++)).c_str());
  1146. rename( name );
  1147. LLUUID creator_id((*(iter++)).c_str());
  1148. LLUUID owner_id((*(iter++)).c_str());
  1149. LLUUID last_owner_id((*(iter++)).c_str());
  1150. LLUUID group_id((*(iter++)).c_str());
  1151. PermissionMask mask_base = strtoul((*(iter++)).c_str(), NULL, 16);
  1152. PermissionMask mask_owner = strtoul((*(iter++)).c_str(), NULL, 16);
  1153. PermissionMask mask_group = strtoul((*(iter++)).c_str(), NULL, 16);
  1154. PermissionMask mask_every = strtoul((*(iter++)).c_str(), NULL, 16);
  1155. PermissionMask mask_next = strtoul((*(iter++)).c_str(), NULL, 16);
  1156. LLPermissions perm;
  1157. perm.init(creator_id, owner_id, last_owner_id, group_id);
  1158. perm.initMasks(mask_base, mask_owner, mask_group, mask_every, mask_next);
  1159. setPermissions(perm);
  1160. //lldebugs << "perm: " << perm << llendl;
  1161. LLUUID asset_id((*(iter++)).c_str());
  1162. setAssetUUID(asset_id);
  1163. std::string desc((*(iter++)).c_str());
  1164. setDescription(desc);
  1165. LLSaleInfo::EForSale sale_type;
  1166. sale_type = (LLSaleInfo::EForSale)(atoi((*(iter++)).c_str()));
  1167. S32 price = atoi((*(iter++)).c_str());
  1168. LLSaleInfo sale_info(sale_type, price);
  1169. setSaleInfo(sale_info);
  1170. U32 flags = strtoul((*(iter++)).c_str(), NULL, 16);
  1171. setFlags(flags);
  1172. time_t now = time(NULL);
  1173. setCreationDate(now);
  1174. }
  1175. ///----------------------------------------------------------------------------
  1176. /// Class LLInventoryCategory
  1177. ///----------------------------------------------------------------------------
  1178. LLInventoryCategory::LLInventoryCategory(const LLUUID& uuid,
  1179. const LLUUID& parent_uuid,
  1180. LLFolderType::EType preferred_type,
  1181. const std::string& name) :
  1182. LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name),
  1183. mPreferredType(preferred_type)
  1184. {
  1185. }
  1186. LLInventoryCategory::LLInventoryCategory() :
  1187. mPreferredType(LLFolderType::FT_NONE)
  1188. {
  1189. mType = LLAssetType::AT_CATEGORY;
  1190. }
  1191. LLInventoryCategory::LLInventoryCategory(const LLInventoryCategory* other) :
  1192. LLInventoryObject()
  1193. {
  1194. copyCategory(other);
  1195. }
  1196. LLInventoryCategory::~LLInventoryCategory()
  1197. {
  1198. }
  1199. // virtual
  1200. void LLInventoryCategory::copyCategory(const LLInventoryCategory* other)
  1201. {
  1202. copyObject(other);
  1203. mPreferredType = other->mPreferredType;
  1204. }
  1205. LLFolderType::EType LLInventoryCategory::getPreferredType() const
  1206. {
  1207. return mPreferredType;
  1208. }
  1209. void LLInventoryCategory::setPreferredType(LLFolderType::EType type)
  1210. {
  1211. mPreferredType = type;
  1212. }
  1213. LLSD LLInventoryCategory::asLLSD() const
  1214. {
  1215. LLSD sd = LLSD();
  1216. sd["item_id"] = mUUID;
  1217. sd["parent_id"] = mParentUUID;
  1218. S8 type = static_cast<S8>(mPreferredType);
  1219. sd["type"] = type;
  1220. sd["name"] = mName;
  1221. return sd;
  1222. }
  1223. // virtual
  1224. void LLInventoryCategory::packMessage(LLMessageSystem* msg) const
  1225. {
  1226. msg->addUUIDFast(_PREHASH_FolderID, mUUID);
  1227. msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
  1228. S8 type = static_cast<S8>(mPreferredType);
  1229. msg->addS8Fast(_PREHASH_Type, type);
  1230. msg->addStringFast(_PREHASH_Name, mName);
  1231. }
  1232. bool LLInventoryCategory::fromLLSD(const LLSD& sd)
  1233. {
  1234. std::string w;
  1235. w = INV_FOLDER_ID_LABEL_WS;
  1236. if (sd.has(w))
  1237. {
  1238. mUUID = sd[w];
  1239. }
  1240. w = INV_PARENT_ID_LABEL;
  1241. if (sd.has(w))
  1242. {
  1243. mParentUUID = sd[w];
  1244. }
  1245. w = INV_ASSET_TYPE_LABEL;
  1246. if (sd.has(w))
  1247. {
  1248. S8 type = (U8)sd[w].asInteger();
  1249. mPreferredType = static_cast<LLFolderType::EType>(type);
  1250. }
  1251. w = INV_ASSET_TYPE_LABEL_WS;
  1252. if (sd.has(w))
  1253. {
  1254. S8 type = (U8)sd[w].asInteger();
  1255. mPreferredType = static_cast<LLFolderType::EType>(type);
  1256. }
  1257. w = INV_NAME_LABEL;
  1258. if (sd.has(w))
  1259. {
  1260. mName = sd[w].asString();
  1261. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  1262. LLStringUtil::replaceChar(mName, '|', ' ');
  1263. }
  1264. return true;
  1265. }
  1266. // virtual
  1267. void LLInventoryCategory::unpackMessage(LLMessageSystem* msg,
  1268. const char* block,
  1269. S32 block_num)
  1270. {
  1271. msg->getUUIDFast(block, _PREHASH_FolderID, mUUID, block_num);
  1272. msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num);
  1273. S8 type;
  1274. msg->getS8Fast(block, _PREHASH_Type, type, block_num);
  1275. mPreferredType = static_cast<LLFolderType::EType>(type);
  1276. msg->getStringFast(block, _PREHASH_Name, mName, block_num);
  1277. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  1278. }
  1279. // virtual
  1280. BOOL LLInventoryCategory::importFile(LLFILE* fp)
  1281. {
  1282. // *NOTE: Changing the buffer size will require changing the scanf
  1283. // calls below.
  1284. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  1285. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  1286. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  1287. keyword[0] = '\0';
  1288. valuestr[0] = '\0';
  1289. while(!feof(fp))
  1290. {
  1291. if (fgets(buffer, MAX_STRING, fp) == NULL)
  1292. {
  1293. buffer[0] = '\0';
  1294. }
  1295. sscanf( /* Flawfinder: ignore */
  1296. buffer,
  1297. " %254s %254s",
  1298. keyword, valuestr);
  1299. if(0 == strcmp("{",keyword))
  1300. {
  1301. continue;
  1302. }
  1303. if(0 == strcmp("}", keyword))
  1304. {
  1305. break;
  1306. }
  1307. else if(0 == strcmp("cat_id", keyword))
  1308. {
  1309. mUUID.set(valuestr);
  1310. }
  1311. else if(0 == strcmp("parent_id", keyword))
  1312. {
  1313. mParentUUID.set(valuestr);
  1314. }
  1315. else if(0 == strcmp("type", keyword))
  1316. {
  1317. mType = LLAssetType::lookup(valuestr);
  1318. }
  1319. else if(0 == strcmp("pref_type", keyword))
  1320. {
  1321. mPreferredType = LLFolderType::lookup(valuestr);
  1322. }
  1323. else if(0 == strcmp("name", keyword))
  1324. {
  1325. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  1326. // *NOTE: Not ANSI C, but widely supported.
  1327. sscanf( /* Flawfinder: ignore */
  1328. buffer,
  1329. " %254s %254[^|]",
  1330. keyword, valuestr);
  1331. mName.assign(valuestr);
  1332. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  1333. LLStringUtil::replaceChar(mName, '|', ' ');
  1334. }
  1335. else
  1336. {
  1337. llwarns << "unknown keyword '" << keyword
  1338. << "' in inventory import category " << mUUID << llendl;
  1339. }
  1340. }
  1341. return TRUE;
  1342. }
  1343. BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const
  1344. {
  1345. std::string uuid_str;
  1346. fprintf(fp, "\tinv_category\t0\n\t{\n");
  1347. mUUID.toString(uuid_str);
  1348. fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str());
  1349. mParentUUID.toString(uuid_str);
  1350. fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
  1351. fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
  1352. fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
  1353. fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
  1354. fprintf(fp,"\t}\n");
  1355. return TRUE;
  1356. }
  1357. // virtual
  1358. BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
  1359. {
  1360. // *NOTE: Changing the buffer size will require changing the scanf
  1361. // calls below.
  1362. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  1363. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  1364. char valuestr[MAX_STRING]; /* Flawfinder: ignore */
  1365. keyword[0] = '\0';
  1366. valuestr[0] = '\0';
  1367. while(input_stream.good())
  1368. {
  1369. input_stream.getline(buffer, MAX_STRING);
  1370. sscanf( /* Flawfinder: ignore */
  1371. buffer,
  1372. " %254s %254s",
  1373. keyword, valuestr);
  1374. if(0 == strcmp("{",keyword))
  1375. {
  1376. continue;
  1377. }
  1378. if(0 == strcmp("}", keyword))
  1379. {
  1380. break;
  1381. }
  1382. else if(0 == strcmp("cat_id", keyword))
  1383. {
  1384. mUUID.set(valuestr);
  1385. }
  1386. else if(0 == strcmp("parent_id", keyword))
  1387. {
  1388. mParentUUID.set(valuestr);
  1389. }
  1390. else if(0 == strcmp("type", keyword))
  1391. {
  1392. mType = LLAssetType::lookup(valuestr);
  1393. }
  1394. else if(0 == strcmp("pref_type", keyword))
  1395. {
  1396. mPreferredType = LLFolderType::lookup(valuestr);
  1397. }
  1398. else if(0 == strcmp("name", keyword))
  1399. {
  1400. //strcpy(valuestr, buffer + strlen(keyword) + 3);
  1401. // *NOTE: Not ANSI C, but widely supported.
  1402. sscanf( /* Flawfinder: ignore */
  1403. buffer,
  1404. " %254s %254[^|]",
  1405. keyword, valuestr);
  1406. mName.assign(valuestr);
  1407. LLStringUtil::replaceNonstandardASCII(mName, ' ');
  1408. LLStringUtil::replaceChar(mName, '|', ' ');
  1409. }
  1410. else
  1411. {
  1412. llwarns << "unknown keyword '" << keyword
  1413. << "' in inventory import category " << mUUID << llendl;
  1414. }
  1415. }
  1416. return TRUE;
  1417. }
  1418. BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) const
  1419. {
  1420. std::string uuid_str;
  1421. output_stream << "\tinv_category\t0\n\t{\n";
  1422. mUUID.toString(uuid_str);
  1423. output_stream << "\t\tcat_id\t" << uuid_str << "\n";
  1424. mParentUUID.toString(uuid_str);
  1425. output_stream << "\t\tparent_id\t" << uuid_str << "\n";
  1426. output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
  1427. output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n";
  1428. output_stream << "\t\tname\t" << mName.c_str() << "|\n";
  1429. output_stream << "\t}\n";
  1430. return TRUE;
  1431. }
  1432. ///----------------------------------------------------------------------------
  1433. /// Local function definitions
  1434. ///----------------------------------------------------------------------------
  1435. LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item)
  1436. {
  1437. LLSD rv;
  1438. if(item.isNull()) return rv;
  1439. if (item->getType() == LLAssetType::AT_NONE)
  1440. {
  1441. llwarns << "ll_create_sd_from_inventory_item() for item with AT_NONE"
  1442. << llendl;
  1443. return rv;
  1444. }
  1445. rv[INV_ITEM_ID_LABEL] = item->getUUID();
  1446. rv[INV_PARENT_ID_LABEL] = item->getParentUUID();
  1447. rv[INV_NAME_LABEL] = item->getName();
  1448. rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(item->getType());
  1449. rv[INV_ASSET_ID_LABEL] = item->getAssetUUID();
  1450. rv[INV_DESC_LABEL] = item->getDescription();
  1451. rv[INV_SALE_INFO_LABEL] = ll_create_sd_from_sale_info(item->getSaleInfo());
  1452. rv[INV_PERMISSIONS_LABEL] =
  1453. ll_create_sd_from_permissions(item->getPermissions());
  1454. rv[INV_INVENTORY_TYPE_LABEL] =
  1455. LLInventoryType::lookup(item->getInventoryType());
  1456. rv[INV_FLAGS_LABEL] = (S32)item->getFlags();
  1457. rv[INV_CREATION_DATE_LABEL] = (S32)item->getCreationDate();
  1458. return rv;
  1459. }
  1460. LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
  1461. {
  1462. LLSD rv;
  1463. if(cat.isNull()) return rv;
  1464. if (cat->getType() == LLAssetType::AT_NONE)
  1465. {
  1466. llwarns << "ll_create_sd_from_inventory_category() for cat with AT_NONE"
  1467. << llendl;
  1468. return rv;
  1469. }
  1470. rv[INV_FOLDER_ID_LABEL] = cat->getUUID();
  1471. rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
  1472. rv[INV_NAME_LABEL] = cat->getName();
  1473. rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
  1474. if(LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
  1475. {
  1476. rv[INV_PREFERRED_TYPE_LABEL] =
  1477. LLFolderType::lookup(cat->getPreferredType()).c_str();
  1478. }
  1479. return rv;
  1480. }
  1481. LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat)
  1482. {
  1483. LLPointer<LLInventoryCategory> rv = new LLInventoryCategory;
  1484. rv->setUUID(sd_cat[INV_FOLDER_ID_LABEL].asUUID());
  1485. rv->setParent(sd_cat[INV_PARENT_ID_LABEL].asUUID());
  1486. rv->rename(sd_cat[INV_NAME_LABEL].asString());
  1487. rv->setType(
  1488. LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString()));
  1489. rv->setPreferredType(
  1490. LLFolderType::lookup(
  1491. sd_cat[INV_PREFERRED_TYPE_LABEL].asString()));
  1492. return rv;
  1493. }