llinventory.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llinventory.h"
00035 
00036 #include "lldbstrings.h"
00037 #include "llxorcipher.h"
00038 #include "llsd.h"
00039 #include "message.h"
00040 #include <boost/tokenizer.hpp>
00041 
00042 #include "llsdutil.h"
00043 
00047 
00048 static const std::string INV_ITEM_ID_LABEL("item_id");
00049 static const std::string INV_FOLDER_ID_LABEL("folder_id");
00050 static const std::string INV_PARENT_ID_LABEL("parent_id");
00051 static const std::string INV_ASSET_TYPE_LABEL("type");
00052 static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
00053 static const std::string INV_INVENTORY_TYPE_LABEL("inv_type");
00054 static const std::string INV_NAME_LABEL("name");
00055 static const std::string INV_DESC_LABEL("desc");
00056 static const std::string INV_PERMISSIONS_LABEL("permissions");
00057 static const std::string INV_SHADOW_ID_LABEL("shadow_id");
00058 static const std::string INV_ASSET_ID_LABEL("asset_id");
00059 static const std::string INV_SALE_INFO_LABEL("sale_info");
00060 static const std::string INV_FLAGS_LABEL("flags");
00061 static const std::string INV_CREATION_DATE_LABEL("created_at");
00062 
00066 
00067 const U8 TASK_INVENTORY_ITEM_KEY = 0;
00068 const U8 TASK_INVENTORY_ASSET_KEY = 1;
00069 
00070 const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730");  
00071         
00072 
00076 
00077 LLInventoryObject::LLInventoryObject(
00078         const LLUUID& uuid,
00079         const LLUUID& parent_uuid,
00080         LLAssetType::EType type,
00081         const LLString& name) :
00082         mUUID(uuid),
00083         mParentUUID(parent_uuid),
00084         mType(type),
00085         mName(name)
00086 {
00087         LLString::replaceNonstandardASCII(mName, ' ');
00088         LLString::replaceChar(mName, '|', ' ');
00089         LLString::trim(mName);
00090         LLString::truncate(mName, DB_INV_ITEM_NAME_STR_LEN);
00091 }
00092 
00093 LLInventoryObject::LLInventoryObject() :
00094         mType(LLAssetType::AT_NONE)
00095 {
00096 }
00097 
00098 LLInventoryObject::~LLInventoryObject( void )
00099 {
00100 }
00101 
00102 void LLInventoryObject::copyObject(const LLInventoryObject* other)
00103 {
00104         mUUID = other->mUUID;
00105         mParentUUID = other->mParentUUID;
00106         mType = other->mType;
00107         mName = other->mName;
00108 }
00109 
00110 const LLUUID& LLInventoryObject::getUUID() const
00111 {
00112         return mUUID;
00113 }
00114 
00115 const LLUUID& LLInventoryObject::getParentUUID() const
00116 {
00117         return mParentUUID;
00118 }
00119 
00120 const LLString& LLInventoryObject::getName() const
00121 {
00122         return mName;
00123 }
00124 
00125 LLAssetType::EType LLInventoryObject::getType() const
00126 {
00127         return mType;
00128 }
00129 
00130 void LLInventoryObject::setUUID(const LLUUID& new_uuid)
00131 {
00132         mUUID = new_uuid;
00133 }
00134 
00135 void LLInventoryObject::rename(const LLString& n)
00136 {
00137         LLString new_name(n);
00138         LLString::replaceNonstandardASCII(new_name, ' ');
00139         LLString::replaceChar(new_name, '|', ' ');
00140         LLString::trim(new_name);
00141         LLString::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
00142 
00143         if( new_name != mName )
00144         {
00145                 mName = new_name;
00146         }
00147 }
00148 
00149 void LLInventoryObject::setParent(const LLUUID& new_parent)
00150 {
00151         mParentUUID = new_parent;
00152 }
00153 
00154 void LLInventoryObject::setType(LLAssetType::EType type)
00155 {
00156         mType = type;
00157 }
00158 
00159 
00160 // virtual
00161 BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
00162 {
00163         // *NOTE: Changing the buffer size will require changing the scanf
00164         // calls below.
00165         char buffer[MAX_STRING];        /* Flawfinder: ignore */
00166         char keyword[MAX_STRING];       /* Flawfinder: ignore */
00167         char valuestr[MAX_STRING];      /* Flawfinder: ignore */
00168 
00169         keyword[0] = '\0';
00170         valuestr[0] = '\0';
00171         while(input_stream.good())
00172         {
00173                 input_stream.getline(buffer, MAX_STRING);
00174                 sscanf(buffer, " %254s %254s", keyword, valuestr);      /* Flawfinder: ignore */
00175                 if(0 == strcmp("{",keyword))
00176                 {
00177                         continue;
00178                 }
00179                 if(0 == strcmp("}", keyword))
00180                 {
00181                         break;
00182                 }
00183                 else if(0 == strcmp("obj_id", keyword))
00184                 {
00185                         mUUID.set(valuestr);
00186                 }
00187                 else if(0 == strcmp("parent_id", keyword))
00188                 {
00189                         mParentUUID.set(valuestr);
00190                 }
00191                 else if(0 == strcmp("type", keyword))
00192                 {
00193                         mType = LLAssetType::lookup(valuestr);
00194                 }
00195                 else if(0 == strcmp("name", keyword))
00196                 {
00197                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
00198                         // *NOTE: Not ANSI C, but widely supported.
00199                         sscanf( /* Flawfinder: ignore */
00200                                 buffer,
00201                                 " %254s %254[^|]",
00202                                 keyword, valuestr);
00203                         mName.assign(valuestr);
00204                         LLString::replaceNonstandardASCII(mName, ' ');
00205                         LLString::replaceChar(mName, '|', ' ');
00206                         LLString::trim(mName);
00207                         LLString::truncate(mName, DB_INV_ITEM_NAME_STR_LEN);
00208                 }
00209                 else
00210                 {
00211                         llwarns << "unknown keyword '" << keyword
00212                                         << "' in LLInventoryObject::importLegacyStream() for object " << mUUID << llendl;
00213                 }
00214         }
00215         return TRUE;
00216 }
00217 
00218 // exportFile should be replaced with exportLegacyStream
00219 // not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented...
00220 BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const
00221 {
00222         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
00223         fprintf(fp, "\tinv_object\t0\n\t{\n");
00224         mUUID.toString(uuid_str);
00225         fprintf(fp, "\t\tobj_id\t%s\n", uuid_str);
00226         mParentUUID.toString(uuid_str);
00227         fprintf(fp, "\t\tparent_id\t%s\n", uuid_str);
00228         fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
00229         fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
00230         fprintf(fp,"\t}\n");
00231         return TRUE;
00232 }
00233 
00234 BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) const
00235 {
00236         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
00237         output_stream <<  "\tinv_object\t0\n\t{\n";
00238         mUUID.toString(uuid_str);
00239         output_stream << "\t\tobj_id\t" << uuid_str << "\n";
00240         mParentUUID.toString(uuid_str);
00241         output_stream << "\t\tparent_id\t" << uuid_str << "\n";
00242         output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
00243         output_stream << "\t\tname\t" << mName.c_str() << "|\n";
00244         output_stream << "\t}\n";
00245         return TRUE;
00246 }
00247 
00248 
00249 void LLInventoryObject::removeFromServer()
00250 {
00251         // don't do nothin'
00252         llwarns << "LLInventoryObject::removeFromServer() called.  Doesn't do anything." << llendl;
00253 }
00254 
00255 void LLInventoryObject::updateParentOnServer(BOOL) const
00256 {
00257         // don't do nothin'
00258         llwarns << "LLInventoryObject::updateParentOnServer() called.  Doesn't do anything." << llendl;
00259 }
00260 
00261 void LLInventoryObject::updateServer(BOOL) const
00262 {
00263         // don't do nothin'
00264         llwarns << "LLInventoryObject::updateServer() called.  Doesn't do anything." << llendl;
00265 }
00266 
00267 
00271 
00272 LLInventoryItem::LLInventoryItem(
00273         const LLUUID& uuid,
00274         const LLUUID& parent_uuid,
00275         const LLPermissions& permissions,
00276         const LLUUID& asset_uuid,
00277         LLAssetType::EType type,
00278         LLInventoryType::EType inv_type,
00279         const LLString& name, 
00280         const LLString& desc,
00281         const LLSaleInfo& sale_info,
00282         U32 flags,
00283         S32 creation_date_utc) :
00284         LLInventoryObject(uuid, parent_uuid, type, name),
00285         mPermissions(permissions),
00286         mAssetUUID(asset_uuid),
00287         mDescription(desc),
00288         mSaleInfo(sale_info),
00289         mInventoryType(inv_type),
00290         mFlags(flags),
00291         mCreationDate(creation_date_utc)
00292 {
00293         LLString::replaceNonstandardASCII(mDescription, ' ');
00294         LLString::replaceChar(mDescription, '|', ' ');
00295 }
00296 
00297 LLInventoryItem::LLInventoryItem() :
00298         LLInventoryObject(),
00299         mPermissions(),
00300         mAssetUUID(),
00301         mDescription(),
00302         mSaleInfo(),
00303         mInventoryType(LLInventoryType::IT_NONE),
00304         mFlags(0),
00305         mCreationDate(0)
00306 {
00307 }
00308 
00309 LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) :
00310         LLInventoryObject()
00311 {
00312         copyItem(other);
00313 }
00314 
00315 LLInventoryItem::~LLInventoryItem()
00316 {
00317 }
00318 
00319 // virtual
00320 void LLInventoryItem::copyItem(const LLInventoryItem* other)
00321 {
00322         copyObject(other);
00323         mPermissions = other->mPermissions;
00324         mAssetUUID = other->mAssetUUID;
00325         mDescription = other->mDescription;
00326         mSaleInfo = other->mSaleInfo;
00327         mInventoryType = other->mInventoryType;
00328         mFlags = other->mFlags;
00329         mCreationDate = other->mCreationDate;
00330 }
00331 
00332 // As a constructor alternative, the clone() method works like a
00333 // copy constructor, but gens a new UUID.
00334 void LLInventoryItem::cloneItem(LLPointer<LLInventoryItem>& newitem) const
00335 {
00336         newitem = new LLInventoryItem;
00337         newitem->copyItem(this);
00338         newitem->mUUID.generate();
00339 }
00340 
00341 const LLPermissions& LLInventoryItem::getPermissions() const
00342 {
00343         return mPermissions;
00344 }
00345 
00346 const LLUUID& LLInventoryItem::getCreatorUUID() const
00347 {
00348         return mPermissions.getCreator();
00349 }
00350 
00351 const LLUUID& LLInventoryItem::getAssetUUID() const
00352 {
00353         return mAssetUUID;
00354 }
00355 
00356 void LLInventoryItem::setAssetUUID(const LLUUID& asset_id)
00357 {
00358         mAssetUUID = asset_id;
00359 }
00360 
00361 
00362 const LLString& LLInventoryItem::getDescription() const
00363 {
00364         return mDescription;
00365 }
00366 
00367 S32 LLInventoryItem::getCreationDate() const
00368 {
00369         return mCreationDate;
00370 }
00371 
00372 U32 LLInventoryItem::getCRC32() const
00373 {
00374         // *FIX: Not a real crc - more of a checksum.
00375         // *NOTE: We currently do not validate the name or description,
00376         // but if they change in transit, it's no big deal.
00377         U32 crc = mUUID.getCRC32();
00378         //lldebugs << "1 crc: " << std::hex << crc << std::dec << llendl;
00379         crc += mParentUUID.getCRC32();
00380         //lldebugs << "2 crc: " << std::hex << crc << std::dec << llendl;
00381         crc += mPermissions.getCRC32();
00382         //lldebugs << "3 crc: " << std::hex << crc << std::dec << llendl;
00383         crc += mAssetUUID.getCRC32();
00384         //lldebugs << "4 crc: " << std::hex << crc << std::dec << llendl;
00385         crc += mType;
00386         //lldebugs << "5 crc: " << std::hex << crc << std::dec << llendl;
00387         crc += mInventoryType;
00388         //lldebugs << "6 crc: " << std::hex << crc << std::dec << llendl;
00389         crc += mFlags;
00390         //lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl;
00391         crc += mSaleInfo.getCRC32();
00392         //lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl;
00393         crc += mCreationDate;
00394         //lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl;
00395         return crc;
00396 }
00397 
00398 
00399 void LLInventoryItem::setDescription(const LLString& d)
00400 {
00401         LLString new_desc(d);
00402         LLString::replaceNonstandardASCII(new_desc, ' ');
00403         LLString::replaceChar(new_desc, '|', ' ');
00404         if( new_desc != mDescription )
00405         {
00406                 mDescription = new_desc;
00407         }
00408 }
00409 
00410 void LLInventoryItem::setPermissions(const LLPermissions& perm)
00411 {
00412         mPermissions = perm;
00413 }
00414 
00415 void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type)
00416 {
00417         mInventoryType = inv_type;
00418 }
00419 
00420 void LLInventoryItem::setFlags(U32 flags)
00421 {
00422         mFlags = flags;
00423 }
00424 
00425 void LLInventoryItem::setCreationDate(S32 creation_date_utc)
00426 {
00427         mCreationDate = creation_date_utc;
00428 }
00429 
00430 
00431 const LLSaleInfo& LLInventoryItem::getSaleInfo() const
00432 {
00433         return mSaleInfo;
00434 }
00435 
00436 void LLInventoryItem::setSaleInfo(const LLSaleInfo& sale_info)
00437 {
00438         mSaleInfo = sale_info;
00439 }
00440 
00441 LLInventoryType::EType LLInventoryItem::getInventoryType() const
00442 {
00443         return mInventoryType;
00444 }
00445 
00446 U32 LLInventoryItem::getFlags() const
00447 {
00448         return mFlags;
00449 }
00450 
00451 // virtual
00452 void LLInventoryItem::packMessage(LLMessageSystem* msg) const
00453 {
00454         msg->addUUIDFast(_PREHASH_ItemID, mUUID);
00455         msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
00456         mPermissions.packMessage(msg);
00457         msg->addUUIDFast(_PREHASH_AssetID, mAssetUUID);
00458         S8 type = static_cast<S8>(mType);
00459         msg->addS8Fast(_PREHASH_Type, type);
00460         type = static_cast<S8>(mInventoryType);
00461         msg->addS8Fast(_PREHASH_InvType, type);
00462         msg->addU32Fast(_PREHASH_Flags, mFlags);
00463         mSaleInfo.packMessage(msg);
00464         msg->addStringFast(_PREHASH_Name, mName);
00465         msg->addStringFast(_PREHASH_Description, mDescription);
00466         msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
00467         U32 crc = getCRC32();
00468         msg->addU32Fast(_PREHASH_CRC, crc);
00469 }
00470 
00471 // virtual
00472 BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
00473 {
00474         msg->getUUIDFast(block, _PREHASH_ItemID, mUUID, block_num);
00475         msg->getUUIDFast(block, _PREHASH_FolderID, mParentUUID, block_num);
00476         mPermissions.unpackMessage(msg, block, block_num);
00477         msg->getUUIDFast(block, _PREHASH_AssetID, mAssetUUID, block_num);
00478 
00479         S8 type;
00480         msg->getS8Fast(block, _PREHASH_Type, type, block_num);
00481         mType = static_cast<LLAssetType::EType>(type);
00482         msg->getS8(block, "InvType", type, block_num);
00483         mInventoryType = static_cast<LLInventoryType::EType>(type);
00484 
00485         msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num);
00486 
00487         mSaleInfo.unpackMultiMessage(msg, block, block_num);
00488 
00489         char name[DB_INV_ITEM_NAME_BUF_SIZE];   /* Flawfinder: ignore */
00490         msg->getStringFast(block, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, block_num);
00491         mName.assign(name);
00492         LLString::replaceNonstandardASCII(mName, ' ');
00493 
00494         char desc[DB_INV_ITEM_DESC_BUF_SIZE];   /* Flawfinder: ignore */
00495         msg->getStringFast(block, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc, block_num);
00496         mDescription.assign(desc);
00497         LLString::replaceNonstandardASCII(mDescription, ' ');
00498 
00499         msg->getS32(block, "CreationDate", mCreationDate, block_num);
00500 
00501         U32 local_crc = getCRC32();
00502         U32 remote_crc = 0;
00503         msg->getU32(block, "CRC", remote_crc, block_num);
00504 //#define CRC_CHECK
00505 #ifdef CRC_CHECK
00506         if(local_crc == remote_crc)
00507         {
00508                 lldebugs << "crc matches" << llendl;
00509                 return TRUE;
00510         }
00511         else
00512         {
00513                 llwarns << "inventory crc mismatch: local=" << std::hex << local_crc
00514                                 << " remote=" << remote_crc << std::dec << llendl;
00515                 return FALSE;
00516         }
00517 #else
00518         return (local_crc == remote_crc);
00519 #endif
00520 }
00521 
00522 // virtual
00523 BOOL LLInventoryItem::importFile(LLFILE* fp)
00524 {
00525         // *NOTE: Changing the buffer size will require changing the scanf
00526         // calls below.
00527         char buffer[MAX_STRING];        /* Flawfinder: ignore */
00528         char keyword[MAX_STRING];       /* Flawfinder: ignore */        
00529         char valuestr[MAX_STRING];      /* Flawfinder: ignore */
00530         char junk[MAX_STRING];  /* Flawfinder: ignore */
00531         BOOL success = TRUE;
00532 
00533         keyword[0] = '\0';
00534         valuestr[0] = '\0';
00535 
00536         mInventoryType = LLInventoryType::IT_NONE;
00537         mAssetUUID.setNull();
00538         while(success && (!feof(fp)))
00539         {
00540                 if (fgets(buffer, MAX_STRING, fp) == NULL)
00541                 {
00542                         buffer[0] = '\0';
00543                 }
00544                 
00545                 sscanf(buffer, " %254s %254s", keyword, valuestr);      /* Flawfinder: ignore */
00546                 if(0 == strcmp("{",keyword))
00547                 {
00548                         continue;
00549                 }
00550                 if(0 == strcmp("}", keyword))
00551                 {
00552                         break;
00553                 }
00554                 else if(0 == strcmp("item_id", keyword))
00555                 {
00556                         mUUID.set(valuestr);
00557                 }
00558                 else if(0 == strcmp("parent_id", keyword))
00559                 {
00560                         mParentUUID.set(valuestr);
00561                 }
00562                 else if(0 == strcmp("permissions", keyword))
00563                 {
00564                         success = mPermissions.importFile(fp);
00565                 }
00566                 else if(0 == strcmp("sale_info", keyword))
00567                 {
00568                         // Sale info used to contain next owner perm. It is now in
00569                         // the permissions. Thus, we read that out, and fix legacy
00570                         // objects. It's possible this op would fail, but it
00571                         // should pick up the vast majority of the tasks.
00572                         BOOL has_perm_mask = FALSE;
00573                         U32 perm_mask = 0;
00574                         success = mSaleInfo.importFile(fp, has_perm_mask, perm_mask);
00575                         if(has_perm_mask)
00576                         {
00577                                 if(perm_mask == PERM_NONE)
00578                                 {
00579                                         perm_mask = mPermissions.getMaskOwner();
00580                                 }
00581                                 // fair use fix.
00582                                 if(!(perm_mask & PERM_COPY))
00583                                 {
00584                                         perm_mask |= PERM_TRANSFER;
00585                                 }
00586                                 mPermissions.setMaskNext(perm_mask);
00587                         }
00588                 }
00589                 else if(0 == strcmp("shadow_id", keyword))
00590                 {
00591                         mAssetUUID.set(valuestr);
00592                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
00593                         cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
00594                 }
00595                 else if(0 == strcmp("asset_id", keyword))
00596                 {
00597                         mAssetUUID.set(valuestr);
00598                 }
00599                 else if(0 == strcmp("type", keyword))
00600                 {
00601                         mType = LLAssetType::lookup(valuestr);
00602                 }
00603                 else if(0 == strcmp("inv_type", keyword))
00604                 {
00605                         mInventoryType = LLInventoryType::lookup(valuestr);
00606                 }
00607                 else if(0 == strcmp("flags", keyword))
00608                 {
00609                         sscanf(valuestr, "%x", &mFlags);
00610                 }
00611                 else if(0 == strcmp("name", keyword))
00612                 {
00613                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
00614                         // *NOTE: Not ANSI C, but widely supported.
00615                         sscanf( /* Flawfinder: ignore */
00616                                 buffer,
00617                                 " %254s%254[\t]%254[^|]",
00618                                 keyword, junk, valuestr);
00619 
00620                         // IW: sscanf chokes and puts | in valuestr if there's no name
00621                         if (valuestr[0] == '|')
00622                         {
00623                                 valuestr[0] = '\000';
00624                         }
00625 
00626                         mName.assign(valuestr);
00627                         LLString::replaceNonstandardASCII(mName, ' ');
00628                         LLString::replaceChar(mName, '|', ' ');
00629                 }
00630                 else if(0 == strcmp("desc", keyword))
00631                 {
00632                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
00633                         // *NOTE: Not ANSI C, but widely supported.
00634                         sscanf( /* Flawfinder: ignore */
00635                                 buffer,
00636                                 " %254s%254[\t]%254[^|]",
00637                                 keyword, junk, valuestr);
00638 
00639                         if (valuestr[0] == '|')
00640                         {
00641                                 valuestr[0] = '\000';
00642                         }
00643 
00644                         mDescription.assign(valuestr);
00645                         LLString::replaceNonstandardASCII(mDescription, ' ');
00646                         /* TODO -- ask Ian about this code
00647                         const char *donkey = mDescription.c_str();
00648                         if (donkey[0] == '|')
00649                         {
00650                                 llerrs << "Donkey" << llendl;
00651                         }
00652                         */
00653                 }
00654                 else if(0 == strcmp("creation_date", keyword))
00655                 {
00656                         sscanf(valuestr, "%d", &mCreationDate);
00657                 }
00658                 else
00659                 {
00660                         llwarns << "unknown keyword '" << keyword
00661                                         << "' in inventory import of item " << mUUID << llendl;
00662                 }
00663         }
00664 
00665         // Need to convert 1.0 simstate files to a useful inventory type
00666         // and potentially deal with bad inventory tyes eg, a landmark
00667         // marked as a texture.
00668         if((LLInventoryType::IT_NONE == mInventoryType)
00669            || !inventory_and_asset_types_match(mInventoryType, mType))
00670         {
00671                 lldebugs << "Resetting inventory type for " << mUUID << llendl;
00672                 mInventoryType = LLInventoryType::defaultForAssetType(mType);
00673         }
00674         return success;
00675 }
00676 
00677 BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const
00678 {
00679         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
00680         fprintf(fp, "\tinv_item\t0\n\t{\n");
00681         mUUID.toString(uuid_str);
00682         fprintf(fp, "\t\titem_id\t%s\n", uuid_str);
00683         mParentUUID.toString(uuid_str);
00684         fprintf(fp, "\t\tparent_id\t%s\n", uuid_str);
00685         mPermissions.exportFile(fp);
00686 
00687         // Check for permissions to see the asset id, and if so write it
00688         // out as an asset id. Otherwise, apply our cheesy encryption.
00689         if(include_asset_key)
00690         {
00691                 U32 mask = mPermissions.getMaskBase();
00692                 if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
00693                    || (mAssetUUID.isNull()))
00694                 {
00695                         mAssetUUID.toString(uuid_str);
00696                         fprintf(fp, "\t\tasset_id\t%s\n", uuid_str);
00697                 }
00698                 else
00699                 {
00700                         LLUUID shadow_id(mAssetUUID);
00701                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
00702                         cipher.encrypt(shadow_id.mData, UUID_BYTES);
00703                         shadow_id.toString(uuid_str);
00704                         fprintf(fp, "\t\tshadow_id\t%s\n", uuid_str);
00705                 }
00706         }
00707         else
00708         {
00709                 LLUUID::null.toString(uuid_str);
00710                 fprintf(fp, "\t\tasset_id\t%s\n", uuid_str);
00711         }
00712         fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
00713         const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
00714         if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str);
00715         fprintf(fp, "\t\tflags\t%08x\n", mFlags);
00716         mSaleInfo.exportFile(fp);
00717         fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
00718         fprintf(fp, "\t\tdesc\t%s|\n", mDescription.c_str());
00719         fprintf(fp, "\t\tcreation_date\t%d\n", mCreationDate);
00720         fprintf(fp,"\t}\n");
00721         return TRUE;
00722 }
00723 
00724 // virtual
00725 BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
00726 {
00727         // *NOTE: Changing the buffer size will require changing the scanf
00728         // calls below.
00729         char buffer[MAX_STRING];        /* Flawfinder: ignore */
00730         char keyword[MAX_STRING];       /* Flawfinder: ignore */
00731         char valuestr[MAX_STRING];      /* Flawfinder: ignore */
00732         char junk[MAX_STRING];  /* Flawfinder: ignore */
00733         BOOL success = TRUE;
00734 
00735         keyword[0] = '\0';
00736         valuestr[0] = '\0';
00737 
00738         mInventoryType = LLInventoryType::IT_NONE;
00739         mAssetUUID.setNull();
00740         while(success && input_stream.good())
00741         {
00742                 input_stream.getline(buffer, MAX_STRING);
00743                 sscanf( /* Flawfinder: ignore */
00744                         buffer,
00745                         " %254s %254s",
00746                         keyword, valuestr);
00747                 if(0 == strcmp("{",keyword))
00748                 {
00749                         continue;
00750                 }
00751                 if(0 == strcmp("}", keyword))
00752                 {
00753                         break;
00754                 }
00755                 else if(0 == strcmp("item_id", keyword))
00756                 {
00757                         mUUID.set(valuestr);
00758                 }
00759                 else if(0 == strcmp("parent_id", keyword))
00760                 {
00761                         mParentUUID.set(valuestr);
00762                 }
00763                 else if(0 == strcmp("permissions", keyword))
00764                 {
00765                         success = mPermissions.importLegacyStream(input_stream);
00766                 }
00767                 else if(0 == strcmp("sale_info", keyword))
00768                 {
00769                         // Sale info used to contain next owner perm. It is now in
00770                         // the permissions. Thus, we read that out, and fix legacy
00771                         // objects. It's possible this op would fail, but it
00772                         // should pick up the vast majority of the tasks.
00773                         BOOL has_perm_mask = FALSE;
00774                         U32 perm_mask = 0;
00775                         success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask);
00776                         if(has_perm_mask)
00777                         {
00778                                 if(perm_mask == PERM_NONE)
00779                                 {
00780                                         perm_mask = mPermissions.getMaskOwner();
00781                                 }
00782                                 // fair use fix.
00783                                 if(!(perm_mask & PERM_COPY))
00784                                 {
00785                                         perm_mask |= PERM_TRANSFER;
00786                                 }
00787                                 mPermissions.setMaskNext(perm_mask);
00788                         }
00789                 }
00790                 else if(0 == strcmp("shadow_id", keyword))
00791                 {
00792                         mAssetUUID.set(valuestr);
00793                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
00794                         cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
00795                 }
00796                 else if(0 == strcmp("asset_id", keyword))
00797                 {
00798                         mAssetUUID.set(valuestr);
00799                 }
00800                 else if(0 == strcmp("type", keyword))
00801                 {
00802                         mType = LLAssetType::lookup(valuestr);
00803                 }
00804                 else if(0 == strcmp("inv_type", keyword))
00805                 {
00806                         mInventoryType = LLInventoryType::lookup(valuestr);
00807                 }
00808                 else if(0 == strcmp("flags", keyword))
00809                 {
00810                         sscanf(valuestr, "%x", &mFlags);
00811                 }
00812                 else if(0 == strcmp("name", keyword))
00813                 {
00814                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
00815                         // *NOTE: Not ANSI C, but widely supported.
00816                         sscanf( /* Flawfinder: ignore */
00817                                 buffer,
00818                                 " %254s%254[\t]%254[^|]",
00819                                 keyword, junk, valuestr);
00820 
00821                         // IW: sscanf chokes and puts | in valuestr if there's no name
00822                         if (valuestr[0] == '|')
00823                         {
00824                                 valuestr[0] = '\000';
00825                         }
00826 
00827                         mName.assign(valuestr);
00828                         LLString::replaceNonstandardASCII(mName, ' ');
00829                         LLString::replaceChar(mName, '|', ' ');
00830                 }
00831                 else if(0 == strcmp("desc", keyword))
00832                 {
00833                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
00834                         // *NOTE: Not ANSI C, but widely supported.
00835                         sscanf( /* Flawfinder: ignore */
00836                                 buffer,
00837                                 " %254s%254[\t]%254[^|]",
00838                                 keyword, junk, valuestr);
00839 
00840                         if (valuestr[0] == '|')
00841                         {
00842                                 valuestr[0] = '\000';
00843                         }
00844 
00845                         mDescription.assign(valuestr);
00846                         LLString::replaceNonstandardASCII(mDescription, ' ');
00847                         /* TODO -- ask Ian about this code
00848                         const char *donkey = mDescription.c_str();
00849                         if (donkey[0] == '|')
00850                         {
00851                                 llerrs << "Donkey" << llendl;
00852                         }
00853                         */
00854                 }
00855                 else if(0 == strcmp("creation_date", keyword))
00856                 {
00857                         sscanf(valuestr, "%d", &mCreationDate);
00858                 }
00859                 else
00860                 {
00861                         llwarns << "unknown keyword '" << keyword
00862                                         << "' in inventory import of item " << mUUID << llendl;
00863                 }
00864         }
00865 
00866         // Need to convert 1.0 simstate files to a useful inventory type
00867         // and potentially deal with bad inventory tyes eg, a landmark
00868         // marked as a texture.
00869         if((LLInventoryType::IT_NONE == mInventoryType)
00870            || !inventory_and_asset_types_match(mInventoryType, mType))
00871         {
00872                 lldebugs << "Resetting inventory type for " << mUUID << llendl;
00873                 mInventoryType = LLInventoryType::defaultForAssetType(mType);
00874         }
00875         return success;
00876 }
00877 
00878 BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key) const
00879 {
00880         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
00881         output_stream << "\tinv_item\t0\n\t{\n";
00882         mUUID.toString(uuid_str);
00883         output_stream << "\t\titem_id\t" << uuid_str << "\n";
00884         mParentUUID.toString(uuid_str);
00885         output_stream << "\t\tparent_id\t" << uuid_str << "\n";
00886         mPermissions.exportLegacyStream(output_stream);
00887 
00888         // Check for permissions to see the asset id, and if so write it
00889         // out as an asset id. Otherwise, apply our cheesy encryption.
00890         if(include_asset_key)
00891         {
00892                 U32 mask = mPermissions.getMaskBase();
00893                 if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
00894                    || (mAssetUUID.isNull()))
00895                 {
00896                         mAssetUUID.toString(uuid_str);
00897                         output_stream << "\t\tasset_id\t" << uuid_str << "\n";
00898                 }
00899                 else
00900                 {
00901                         LLUUID shadow_id(mAssetUUID);
00902                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
00903                         cipher.encrypt(shadow_id.mData, UUID_BYTES);
00904                         shadow_id.toString(uuid_str);
00905                         output_stream << "\t\tshadow_id\t" << uuid_str << "\n";
00906                 }
00907         }
00908         else
00909         {
00910                 LLUUID::null.toString(uuid_str);
00911                 output_stream << "\t\tasset_id\t" << uuid_str << "\n";
00912         }
00913         output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
00914         const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
00915         if(inv_type_str) 
00916                 output_stream << "\t\tinv_type\t" << inv_type_str << "\n";
00917         char buffer[32];        /* Flawfinder: ignore */
00918         snprintf(buffer, sizeof(buffer), "\t\tflags\t%08x\n", mFlags);          /* Flawfinder: ignore */
00919         output_stream << buffer;
00920         mSaleInfo.exportLegacyStream(output_stream);
00921         output_stream << "\t\tname\t" << mName.c_str() << "|\n";
00922         output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n";
00923         output_stream << "\t\tcreation_date\t" << mCreationDate << "\n";
00924         output_stream << "\t}\n";
00925         return TRUE;
00926 }
00927 
00928 LLSD LLInventoryItem::asLLSD() const
00929 {
00930         LLSD sd = LLSD();
00931         sd[INV_ITEM_ID_LABEL] = mUUID;
00932         sd[INV_PARENT_ID_LABEL] = mParentUUID;
00933         sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
00934 
00935         U32 mask = mPermissions.getMaskBase();
00936         if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
00937                 || (mAssetUUID.isNull()))
00938         {
00939                 sd[INV_ASSET_ID_LABEL] = mAssetUUID;
00940         }
00941         else
00942         {
00943                 // *TODO: get rid of this. Phoenix 2008-01-30
00944                 LLUUID shadow_id(mAssetUUID);
00945                 LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
00946                 cipher.encrypt(shadow_id.mData, UUID_BYTES);
00947                 sd[INV_SHADOW_ID_LABEL] = shadow_id;
00948         }
00949         sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
00950         const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
00951         if(inv_type_str)
00952         {
00953                 sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
00954         }
00955         sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
00956         sd[INV_SALE_INFO_LABEL] = mSaleInfo;
00957         sd[INV_NAME_LABEL] = mName;
00958         sd[INV_DESC_LABEL] = mDescription;
00959         sd[INV_CREATION_DATE_LABEL] = mCreationDate;
00960 
00961         return sd;
00962 }
00963 
00964 bool LLInventoryItem::fromLLSD(LLSD& sd)
00965 {
00966         mInventoryType = LLInventoryType::IT_NONE;
00967         mAssetUUID.setNull();
00968         std::string w;
00969 
00970         w = INV_ITEM_ID_LABEL;
00971         if (sd.has(w))
00972         {
00973                 mUUID = sd[w];
00974         }
00975         w = INV_PARENT_ID_LABEL;
00976         if (sd.has(w))
00977         {
00978                 mParentUUID = sd[w];
00979         }
00980         w = INV_PERMISSIONS_LABEL;
00981         if (sd.has(w))
00982         {
00983                 mPermissions = ll_permissions_from_sd(sd[w]);
00984         }
00985         w = INV_SALE_INFO_LABEL;
00986         if (sd.has(w))
00987         {
00988                 // Sale info used to contain next owner perm. It is now in
00989                 // the permissions. Thus, we read that out, and fix legacy
00990                 // objects. It's possible this op would fail, but it
00991                 // should pick up the vast majority of the tasks.
00992                 BOOL has_perm_mask = FALSE;
00993                 U32 perm_mask = 0;
00994                 if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask))
00995                 {
00996                         goto fail;
00997                 }
00998                 if (has_perm_mask)
00999                 {
01000                         if(perm_mask == PERM_NONE)
01001                         {
01002                                 perm_mask = mPermissions.getMaskOwner();
01003                         }
01004                         // fair use fix.
01005                         if(!(perm_mask & PERM_COPY))
01006                         {
01007                                 perm_mask |= PERM_TRANSFER;
01008                         }
01009                         mPermissions.setMaskNext(perm_mask);
01010                 }
01011         }
01012         w = INV_SHADOW_ID_LABEL;
01013         if (sd.has(w))
01014         {
01015                 mAssetUUID = sd[w];
01016                 LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
01017                 cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
01018         }
01019         w = INV_ASSET_ID_LABEL;
01020         if (sd.has(w))
01021         {
01022                 mAssetUUID = sd[w];
01023         }
01024         w = INV_ASSET_TYPE_LABEL;
01025         if (sd.has(w))
01026         {
01027                 mType = LLAssetType::lookup(sd[w].asString().c_str());
01028         }
01029         w = INV_INVENTORY_TYPE_LABEL;
01030         if (sd.has(w))
01031         {
01032                 mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str());
01033         }
01034         w = INV_FLAGS_LABEL;
01035         if (sd.has(w))
01036         {
01037                 mFlags = ll_U32_from_sd(sd[w]);
01038         }
01039         w = INV_NAME_LABEL;
01040         if (sd.has(w))
01041         {
01042                 mName = sd[w].asString();
01043                 LLString::replaceNonstandardASCII(mName, ' ');
01044                 LLString::replaceChar(mName, '|', ' ');
01045         }
01046         w = INV_DESC_LABEL;
01047         if (sd.has(w))
01048         {
01049                 mDescription = sd[w].asString();
01050                 LLString::replaceNonstandardASCII(mDescription, ' ');
01051         }
01052         w = INV_CREATION_DATE_LABEL;
01053         if (sd.has(w))
01054         {
01055                 mCreationDate = sd[w];
01056         }
01057 
01058         // Need to convert 1.0 simstate files to a useful inventory type
01059         // and potentially deal with bad inventory tyes eg, a landmark
01060         // marked as a texture.
01061         if((LLInventoryType::IT_NONE == mInventoryType)
01062            || !inventory_and_asset_types_match(mInventoryType, mType))
01063         {
01064                 lldebugs << "Resetting inventory type for " << mUUID << llendl;
01065                 mInventoryType = LLInventoryType::defaultForAssetType(mType);
01066         }
01067 
01068         return true;
01069 fail:
01070         return false;
01071 
01072 }
01073 
01074 LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const
01075 {
01076         LLMemType m1(LLMemType::MTYPE_INVENTORY);
01077         LLXMLNode *ret = new LLXMLNode("item", FALSE);
01078 
01079         ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID);
01080         ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID);
01081 
01082         mPermissions.exportFileXML()->setParent(ret);
01083 
01084         // Check for permissions to see the asset id, and if so write it
01085         // out as an asset id. Otherwise, apply our cheesy encryption.
01086         if(include_asset_key)
01087         {
01088                 U32 mask = mPermissions.getMaskBase();
01089                 if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
01090                    || (mAssetUUID.isNull()))
01091                 {
01092                         ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID);
01093                 }
01094                 else
01095                 {
01096                         LLUUID shadow_id(mAssetUUID);
01097                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
01098                         cipher.encrypt(shadow_id.mData, UUID_BYTES);
01099 
01100                         ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id);
01101                 }
01102         }
01103 
01104         LLString type_str = LLAssetType::lookup(mType);
01105         LLString inv_type_str = LLInventoryType::lookup(mInventoryType);
01106 
01107         ret->createChild("asset_type", FALSE)->setStringValue(1, &type_str);
01108         ret->createChild("inventory_type", FALSE)->setStringValue(1, &inv_type_str);
01109         S32 tmp_flags = (S32) mFlags;
01110         ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX);
01111 
01112         mSaleInfo.exportFileXML()->setParent(ret);
01113 
01114         LLString temp;
01115         temp.assign(mName);
01116         ret->createChild("name", FALSE)->setStringValue(1, &temp);
01117         temp.assign(mDescription);
01118         ret->createChild("description", FALSE)->setStringValue(1, &temp);
01119         ret->createChild("creation_date", FALSE)->setIntValue(1, &mCreationDate);
01120 
01121         return ret;
01122 }
01123 
01124 BOOL LLInventoryItem::importXML(LLXMLNode* node)
01125 {
01126         BOOL success = FALSE;
01127         if (node)
01128         {
01129                 success = TRUE;
01130                 LLXMLNodePtr sub_node;
01131                 if (node->getChild("uuid", sub_node))
01132                         success = (1 == sub_node->getUUIDValue(1, &mUUID));
01133                 if (node->getChild("parent_uuid", sub_node))
01134                         success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID));
01135                 if (node->getChild("permissions", sub_node))
01136                         success = success && mPermissions.importXML(sub_node);
01137                 if (node->getChild("asset_id", sub_node))
01138                         success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID));
01139                 if (node->getChild("shadow_id", sub_node))
01140                 {
01141                         success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID));
01142                         LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
01143                         cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
01144                 }
01145                 if (node->getChild("asset_type", sub_node))
01146                         mType = LLAssetType::lookup(sub_node->getValue().c_str());
01147                 if (node->getChild("inventory_type", sub_node))
01148                         mInventoryType = LLInventoryType::lookup(sub_node->getValue().c_str());
01149                 if (node->getChild("flags", sub_node))
01150                 {
01151                         S32 tmp_flags = 0;
01152                         success = success && (1 == sub_node->getIntValue(1, &tmp_flags));
01153                         mFlags = (U32) tmp_flags;
01154                 }
01155                 if (node->getChild("sale_info", sub_node))
01156                         success = success && mSaleInfo.importXML(sub_node);
01157                 if (node->getChild("name", sub_node))
01158                         mName = sub_node->getValue();
01159                 if (node->getChild("description", sub_node))
01160                         mDescription = sub_node->getValue();
01161                 if (node->getChild("creation_date", sub_node))
01162                         success = success && (1 == sub_node->getIntValue(1, &mCreationDate));
01163                 if (!success)
01164                 {
01165                         lldebugs << "LLInventory::importXML() failed for node named '" 
01166                                 << node->getName() << "'" << llendl;
01167                 }
01168         }
01169         return success;
01170 }
01171 
01172 S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const
01173 {
01174         // Figure out which permissions to use.
01175         LLPermissions perm;
01176         if (perm_override)
01177         {
01178                 // Use the permissions override.
01179                 perm = *perm_override;
01180         }
01181         else
01182         {
01183                 // Use the current permissions.
01184                 perm = getPermissions();
01185         }
01186 
01187         // describe the inventory item
01188         char* buffer = (char*) bin_bucket;
01189         char creator_id_str[UUID_STR_LENGTH];   /* Flawfinder: ignore */
01190 
01191         perm.getCreator().toString(creator_id_str);
01192         char owner_id_str[UUID_STR_LENGTH];     /* Flawfinder: ignore */
01193         perm.getOwner().toString(owner_id_str);
01194         char last_owner_id_str[UUID_STR_LENGTH];        /* Flawfinder: ignore */
01195         perm.getLastOwner().toString(last_owner_id_str);
01196         char group_id_str[UUID_STR_LENGTH];     /* Flawfinder: ignore */
01197         perm.getGroup().toString(group_id_str);
01198         char asset_id_str[UUID_STR_LENGTH];     /* Flawfinder: ignore */
01199         getAssetUUID().toString(asset_id_str);
01200         S32 size = sprintf(buffer,      /* Flawfinder: ignore */
01201                                            "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
01202                                            getType(),
01203                                            getInventoryType(),
01204                                            getName().c_str(),
01205                                            creator_id_str,
01206                                            owner_id_str,
01207                                            last_owner_id_str,
01208                                            group_id_str,
01209                                            perm.getMaskBase(),
01210                                            perm.getMaskOwner(),
01211                                            perm.getMaskGroup(),
01212                                            perm.getMaskEveryone(),
01213                                            perm.getMaskNextOwner(),
01214                                            asset_id_str,
01215                                            getDescription().c_str(),
01216                                            getSaleInfo().getSaleType(),
01217                                            getSaleInfo().getSalePrice(),
01218                                            getFlags()) + 1;
01219 
01220         return size;
01221 }
01222 
01223 void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size)
01224 {       
01225         // Early exit on an empty binary bucket.
01226         if (bin_bucket_size <= 1) return;
01227 
01228         // Convert the bin_bucket into a string.
01229         char* item_buffer = new char[bin_bucket_size+1];
01230         if ((item_buffer != NULL) && (bin_bucket != NULL))
01231         {
01232                 memcpy(item_buffer, bin_bucket, bin_bucket_size);       /* Flawfinder: ignore */
01233         }
01234         else
01235         {
01236                 llerrs << "unpackBinaryBucket failed. item_buffer or bin_bucket is Null." << llendl;
01237                 delete[] item_buffer;
01238                 return;
01239         }
01240         item_buffer[bin_bucket_size] = '\0';
01241         std::string str(item_buffer);
01242 
01243         lldebugs << "item buffer: " << item_buffer << llendl;
01244         delete[] item_buffer;
01245 
01246         // Tokenize the string.
01247         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
01248         boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
01249         tokenizer tokens(str, sep);
01250         tokenizer::iterator iter = tokens.begin();
01251 
01252         // Extract all values.
01253         LLUUID item_id;
01254         item_id.generate();
01255         setUUID(item_id);
01256 
01257         LLAssetType::EType type;
01258         type = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
01259         setType( type );
01260         
01261         LLInventoryType::EType inv_type;
01262         inv_type = (LLInventoryType::EType)(atoi((*(iter++)).c_str()));
01263         setInventoryType( inv_type );
01264 
01265         LLString name((*(iter++)).c_str());
01266         rename( name );
01267         
01268         LLUUID creator_id((*(iter++)).c_str());
01269         LLUUID owner_id((*(iter++)).c_str());
01270         LLUUID last_owner_id((*(iter++)).c_str());
01271         LLUUID group_id((*(iter++)).c_str());
01272         PermissionMask mask_base = strtoul((*(iter++)).c_str(), NULL, 16);
01273         PermissionMask mask_owner = strtoul((*(iter++)).c_str(), NULL, 16);
01274         PermissionMask mask_group = strtoul((*(iter++)).c_str(), NULL, 16);
01275         PermissionMask mask_every = strtoul((*(iter++)).c_str(), NULL, 16);
01276         PermissionMask mask_next = strtoul((*(iter++)).c_str(), NULL, 16);
01277         LLPermissions perm;
01278         perm.init(creator_id, owner_id, last_owner_id, group_id);
01279         perm.initMasks(mask_base, mask_owner, mask_group, mask_every, mask_next);
01280         setPermissions(perm);
01281         //lldebugs << "perm: " << perm << llendl;
01282 
01283         LLUUID asset_id((*(iter++)).c_str());
01284         setAssetUUID(asset_id);
01285 
01286         LLString desc((*(iter++)).c_str());
01287         setDescription(desc);
01288         
01289         LLSaleInfo::EForSale sale_type;
01290         sale_type = (LLSaleInfo::EForSale)(atoi((*(iter++)).c_str()));
01291         S32 price = atoi((*(iter++)).c_str());
01292         LLSaleInfo sale_info(sale_type, price);
01293         setSaleInfo(sale_info);
01294         
01295         U32 flags = strtoul((*(iter++)).c_str(), NULL, 16);
01296         setFlags(flags);
01297 
01298         time_t now = time(NULL);
01299         setCreationDate(now);
01300 }
01301 
01302 // returns TRUE if a should appear before b
01303 BOOL item_dictionary_sort( LLInventoryItem* a, LLInventoryItem* b )
01304 {
01305         return (LLString::compareDict( a->getName().c_str(), b->getName().c_str() ) < 0);
01306 }
01307 
01308 // returns TRUE if a should appear before b
01309 BOOL item_date_sort( LLInventoryItem* a, LLInventoryItem* b )
01310 {
01311         return a->getCreationDate() < b->getCreationDate();
01312 }
01313 
01314 
01318 
01319 LLInventoryCategory::LLInventoryCategory(
01320         const LLUUID& uuid,
01321         const LLUUID& parent_uuid,
01322         LLAssetType::EType preferred_type,
01323         const LLString& name) :
01324         LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name),
01325         mPreferredType(preferred_type)
01326 {
01327 }
01328 
01329 LLInventoryCategory::LLInventoryCategory() :
01330         mPreferredType(LLAssetType::AT_NONE)
01331 {
01332         mType = LLAssetType::AT_CATEGORY;
01333 }
01334 
01335 LLInventoryCategory::LLInventoryCategory(const LLInventoryCategory* other) :
01336         LLInventoryObject()
01337 {
01338         copyCategory(other);
01339 }
01340 
01341 LLInventoryCategory::~LLInventoryCategory()
01342 {
01343 }
01344 
01345 // virtual
01346 void LLInventoryCategory::copyCategory(const LLInventoryCategory* other)
01347 {
01348         copyObject(other);
01349         mPreferredType = other->mPreferredType;
01350 }
01351 
01352 LLAssetType::EType LLInventoryCategory::getPreferredType() const
01353 {
01354         return mPreferredType;
01355 }
01356 
01357 void LLInventoryCategory::setPreferredType(LLAssetType::EType type)
01358 {
01359         mPreferredType = type;
01360 }
01361 
01362 LLSD LLInventoryCategory::asLLSD() const
01363 {
01364     LLSD sd = LLSD();
01365     sd["item_id"] = mUUID;
01366     sd["parent_id"] = mParentUUID;
01367     S8 type = static_cast<S8>(mPreferredType);
01368     sd["type"]      = type;
01369     sd["name"] = mName;
01370 
01371     return sd;
01372 }
01373 
01374 
01375 // virtual
01376 void LLInventoryCategory::packMessage(LLMessageSystem* msg) const
01377 {
01378         msg->addUUIDFast(_PREHASH_FolderID, mUUID);
01379         msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
01380         S8 type = static_cast<S8>(mPreferredType);
01381         msg->addS8Fast(_PREHASH_Type, type);
01382         msg->addStringFast(_PREHASH_Name, mName);
01383 }
01384 
01385 bool LLInventoryCategory::fromLLSD(LLSD& sd)
01386 {
01387     std::string w;
01388 
01389     w = INV_ITEM_ID_LABEL;
01390     if (sd.has(w))
01391     {
01392         mUUID = sd[w];
01393     }
01394     w = INV_PARENT_ID_LABEL;
01395     if (sd.has(w))
01396     {
01397         mParentUUID = sd[w];
01398     }
01399     w = INV_ASSET_TYPE_LABEL;
01400     if (sd.has(w))
01401     {
01402         S8 type = (U8)sd[w].asInteger();
01403         mPreferredType = static_cast<LLAssetType::EType>(type);
01404     }
01405     w = INV_NAME_LABEL;
01406     if (sd.has(w))
01407     {
01408         mName = sd[w].asString();
01409         LLString::replaceNonstandardASCII(mName, ' ');
01410         LLString::replaceChar(mName, '|', ' ');
01411     }
01412     return true;
01413 }
01414 
01415 // virtual
01416 void LLInventoryCategory::unpackMessage(LLMessageSystem* msg,
01417                                                                                 const char* block,
01418                                                                                 S32 block_num)
01419 {
01420         msg->getUUIDFast(block, _PREHASH_FolderID, mUUID, block_num);
01421         msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num);
01422         S8 type;
01423         msg->getS8Fast(block, _PREHASH_Type, type, block_num);
01424         mPreferredType = static_cast<LLAssetType::EType>(type);
01425         char name[DB_INV_ITEM_NAME_BUF_SIZE];   /* Flawfinder: ignore */
01426         msg->getStringFast(block, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, block_num);
01427         mName.assign(name);
01428         LLString::replaceNonstandardASCII(mName, ' ');
01429 }
01430         
01431 // virtual
01432 BOOL LLInventoryCategory::importFile(LLFILE* fp)
01433 {
01434         // *NOTE: Changing the buffer size will require changing the scanf
01435         // calls below.
01436         char buffer[MAX_STRING];        /* Flawfinder: ignore */
01437         char keyword[MAX_STRING];       /* Flawfinder: ignore */
01438         char valuestr[MAX_STRING];      /* Flawfinder: ignore */
01439 
01440         keyword[0] = '\0';
01441         valuestr[0] = '\0';
01442         while(!feof(fp))
01443         {
01444                 if (fgets(buffer, MAX_STRING, fp) == NULL)
01445                 {
01446                         buffer[0] = '\0';
01447                 }
01448                 
01449                 sscanf( /* Flawfinder: ignore */
01450                         buffer,
01451                         " %254s %254s",
01452                         keyword, valuestr);
01453                 if(0 == strcmp("{",keyword))
01454                 {
01455                         continue;
01456                 }
01457                 if(0 == strcmp("}", keyword))
01458                 {
01459                         break;
01460                 }
01461                 else if(0 == strcmp("cat_id", keyword))
01462                 {
01463                         mUUID.set(valuestr);
01464                 }
01465                 else if(0 == strcmp("parent_id", keyword))
01466                 {
01467                         mParentUUID.set(valuestr);
01468                 }
01469                 else if(0 == strcmp("type", keyword))
01470                 {
01471                         mType = LLAssetType::lookup(valuestr);
01472                 }
01473                 else if(0 == strcmp("pref_type", keyword))
01474                 {
01475                         mPreferredType = LLAssetType::lookup(valuestr);
01476                 }
01477                 else if(0 == strcmp("name", keyword))
01478                 {
01479                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
01480                         // *NOTE: Not ANSI C, but widely supported.
01481                         sscanf( /* Flawfinder: ignore */
01482                                 buffer,
01483                                 " %254s %254[^|]",
01484                                 keyword, valuestr);
01485                         mName.assign(valuestr);
01486                         LLString::replaceNonstandardASCII(mName, ' ');
01487                         LLString::replaceChar(mName, '|', ' ');
01488                 }
01489                 else
01490                 {
01491                         llwarns << "unknown keyword '" << keyword
01492                                         << "' in inventory import category "  << mUUID << llendl;
01493                 }
01494         }
01495         return TRUE;
01496 }
01497 
01498 BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const
01499 {
01500         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
01501         fprintf(fp, "\tinv_category\t0\n\t{\n");
01502         mUUID.toString(uuid_str);
01503         fprintf(fp, "\t\tcat_id\t%s\n", uuid_str);
01504         mParentUUID.toString(uuid_str);
01505         fprintf(fp, "\t\tparent_id\t%s\n", uuid_str);
01506         fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
01507         fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType));
01508         fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
01509         fprintf(fp,"\t}\n");
01510         return TRUE;
01511 }
01512 
01513         
01514 // virtual
01515 BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
01516 {
01517         // *NOTE: Changing the buffer size will require changing the scanf
01518         // calls below.
01519         char buffer[MAX_STRING];        /* Flawfinder: ignore */
01520         char keyword[MAX_STRING];       /* Flawfinder: ignore */
01521         char valuestr[MAX_STRING];      /* Flawfinder: ignore */
01522 
01523         keyword[0] = '\0';
01524         valuestr[0] = '\0';
01525         while(input_stream.good())
01526         {
01527                 input_stream.getline(buffer, MAX_STRING);
01528                 sscanf( /* Flawfinder: ignore */
01529                         buffer,
01530                         " %254s %254s",
01531                         keyword, valuestr);
01532                 if(0 == strcmp("{",keyword))
01533                 {
01534                         continue;
01535                 }
01536                 if(0 == strcmp("}", keyword))
01537                 {
01538                         break;
01539                 }
01540                 else if(0 == strcmp("cat_id", keyword))
01541                 {
01542                         mUUID.set(valuestr);
01543                 }
01544                 else if(0 == strcmp("parent_id", keyword))
01545                 {
01546                         mParentUUID.set(valuestr);
01547                 }
01548                 else if(0 == strcmp("type", keyword))
01549                 {
01550                         mType = LLAssetType::lookup(valuestr);
01551                 }
01552                 else if(0 == strcmp("pref_type", keyword))
01553                 {
01554                         mPreferredType = LLAssetType::lookup(valuestr);
01555                 }
01556                 else if(0 == strcmp("name", keyword))
01557                 {
01558                         //strcpy(valuestr, buffer + strlen(keyword) + 3);
01559                         // *NOTE: Not ANSI C, but widely supported.
01560                         sscanf( /* Flawfinder: ignore */
01561                                 buffer,
01562                                 " %254s %254[^|]",
01563                                 keyword, valuestr);
01564                         mName.assign(valuestr);
01565                         LLString::replaceNonstandardASCII(mName, ' ');
01566                         LLString::replaceChar(mName, '|', ' ');
01567                 }
01568                 else
01569                 {
01570                         llwarns << "unknown keyword '" << keyword
01571                                         << "' in inventory import category "  << mUUID << llendl;
01572                 }
01573         }
01574         return TRUE;
01575 }
01576 
01577 BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) const
01578 {
01579         char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
01580         output_stream << "\tinv_category\t0\n\t{\n";
01581         mUUID.toString(uuid_str);
01582         output_stream << "\t\tcat_id\t" << uuid_str << "\n";
01583         mParentUUID.toString(uuid_str);
01584         output_stream << "\t\tparent_id\t" << uuid_str << "\n";
01585         output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
01586         output_stream << "\t\tpref_type\t" << LLAssetType::lookup(mPreferredType) << "\n";
01587         output_stream << "\t\tname\t" << mName.c_str() << "|\n";
01588         output_stream << "\t}\n";
01589         return TRUE;
01590 }
01591 
01595 
01596 LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item)
01597 {
01598         LLSD rv;
01599         if(item.isNull()) return rv;
01600         if (item->getType() == LLAssetType::AT_NONE)
01601         {
01602                 llwarns << "ll_create_sd_from_inventory_item() for item with AT_NONE"
01603                         << llendl;
01604                 return rv;
01605         }
01606         rv[INV_ITEM_ID_LABEL] =  item->getUUID();
01607         rv[INV_PARENT_ID_LABEL] = item->getParentUUID();
01608         rv[INV_NAME_LABEL] = item->getName();
01609         rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(item->getType());
01610         rv[INV_ASSET_ID_LABEL] = item->getAssetUUID();
01611         rv[INV_DESC_LABEL] = item->getDescription();
01612         rv[INV_SALE_INFO_LABEL] = ll_create_sd_from_sale_info(item->getSaleInfo());
01613         rv[INV_PERMISSIONS_LABEL] =
01614                 ll_create_sd_from_permissions(item->getPermissions());
01615         rv[INV_INVENTORY_TYPE_LABEL] =
01616                 LLInventoryType::lookup(item->getInventoryType());
01617         rv[INV_FLAGS_LABEL] = (S32)item->getFlags();
01618         rv[INV_CREATION_DATE_LABEL] = item->getCreationDate();
01619         return rv;
01620 }
01621 
01622 LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item)
01623 {
01624         LLPointer<LLInventoryItem> rv = new LLInventoryItem;
01625         rv->setUUID(sd_item[INV_ITEM_ID_LABEL].asUUID());
01626         rv->setParent(sd_item[INV_PARENT_ID_LABEL].asUUID());
01627         rv->rename(sd_item[INV_NAME_LABEL].asString());
01628         rv->setType(
01629                 LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString().c_str()));
01630         if (sd_item.has("shadow_id"))
01631         {
01632                 LLUUID asset_id = sd_item["shadow_id"];
01633                 LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
01634                 cipher.decrypt(asset_id.mData, UUID_BYTES);
01635                 rv->setAssetUUID(asset_id);
01636         }
01637         if (sd_item.has(INV_ASSET_ID_LABEL))
01638         {
01639                 rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID());
01640         }
01641         rv->setDescription(sd_item[INV_DESC_LABEL].asString());
01642         rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL]));
01643         rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL]));
01644         rv->setInventoryType(
01645                 LLInventoryType::lookup(
01646                         sd_item[INV_INVENTORY_TYPE_LABEL].asString().c_str()));
01647         rv->setFlags((U32)(sd_item[INV_FLAGS_LABEL].asInteger()));
01648         rv->setCreationDate(sd_item[INV_CREATION_DATE_LABEL].asInteger());
01649         return rv;
01650 }
01651 
01652 LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
01653 {
01654         LLSD rv;
01655         if(cat.isNull()) return rv;
01656         if (cat->getType() == LLAssetType::AT_NONE)
01657         {
01658                 llwarns << "ll_create_sd_from_inventory_category() for cat with AT_NONE"
01659                         << llendl;
01660                 return rv;
01661         }
01662         rv[INV_FOLDER_ID_LABEL] = cat->getUUID();
01663         rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
01664         rv[INV_NAME_LABEL] = cat->getName();
01665         rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
01666         if(LLAssetType::AT_NONE != cat->getPreferredType())
01667         {
01668                 rv[INV_PREFERRED_TYPE_LABEL] =
01669                         LLAssetType::lookup(cat->getPreferredType());
01670         }
01671         return rv;
01672 }
01673 
01674 LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat)
01675 {
01676         LLPointer<LLInventoryCategory> rv = new LLInventoryCategory;
01677         rv->setUUID(sd_cat[INV_FOLDER_ID_LABEL].asUUID());
01678         rv->setParent(sd_cat[INV_PARENT_ID_LABEL].asUUID());
01679         rv->rename(sd_cat[INV_NAME_LABEL].asString());
01680         rv->setType(
01681                 LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString().c_str()));
01682         rv->setPreferredType(
01683                 LLAssetType::lookup(
01684                         sd_cat[INV_PREFERRED_TYPE_LABEL].asString().c_str()));
01685         return rv;
01686 }

Generated on Fri May 16 08:32:12 2008 for SecondLife by  doxygen 1.5.5