llinventory.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:44k
源码类别:

游戏引擎

开发平台:

C++ Builder

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