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

Generated on Thu Jul 1 06:08:44 2010 for Second Life Viewer by  doxygen 1.4.7