LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item)
{
	LLPointer<LLInventoryItem> rv = new LLInventoryItem;
	rv->setUUID(sd_item[INV_ITEM_ID_LABEL].asUUID());
	rv->setParent(sd_item[INV_PARENT_ID_LABEL].asUUID());
	rv->rename(sd_item[INV_NAME_LABEL].asString());
	rv->setType(
		LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString()));
	if (sd_item.has("shadow_id"))
	{
		LLUUID asset_id = sd_item["shadow_id"];
		LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
		cipher.decrypt(asset_id.mData, UUID_BYTES);
		rv->setAssetUUID(asset_id);
	}
	if (sd_item.has(INV_ASSET_ID_LABEL))
	{
		rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID());
	}
	rv->setDescription(sd_item[INV_DESC_LABEL].asString());
	rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL]));
	rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL]));
	rv->setInventoryType(
		LLInventoryType::lookup(
			sd_item[INV_INVENTORY_TYPE_LABEL].asString()));
	rv->setFlags((U32)(sd_item[INV_FLAGS_LABEL].asInteger()));
	rv->setCreationDate(sd_item[INV_CREATION_DATE_LABEL].asInteger());
	return rv;
}
	void permission_object_t::test<24>()
	{
		LLPermissions perm,perm1;
		LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");	
		LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806"); 
		LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); 
		LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");		
		perm.init(creator,owner,lastOwner,group);
		
		U32 base = PERM_TRANSFER | PERM_COPY;
		U32 ownerp = PERM_TRANSFER;
		U32 groupp = PERM_TRANSFER;
		U32 everyone = PERM_TRANSFER;
		U32 next = PERM_NONE;

		perm.initMasks(base, ownerp, everyone, groupp, next);

		LLSD sd = ll_create_sd_from_permissions(perm);
		perm1 = ll_permissions_from_sd(sd);
		ensure_equals("ll_permissions_from_sd() and ll_create_sd_from_permissions()functions failed", perm, perm1);
	}
bool LLInventoryItem::fromLLSD(LLSD& sd)
{
	mInventoryType = LLInventoryType::IT_NONE;
	mAssetUUID.setNull();
	std::string w;

	w = INV_ITEM_ID_LABEL;
	if (sd.has(w))
	{
		mUUID = sd[w];
	}
	w = INV_PARENT_ID_LABEL;
	if (sd.has(w))
	{
		mParentUUID = sd[w];
	}
	w = INV_PERMISSIONS_LABEL;
	if (sd.has(w))
	{
		mPermissions = ll_permissions_from_sd(sd[w]);
	}
	w = INV_SALE_INFO_LABEL;
	if (sd.has(w))
	{
		// Sale info used to contain next owner perm. It is now in
		// the permissions. Thus, we read that out, and fix legacy
		// objects. It's possible this op would fail, but it
		// should pick up the vast majority of the tasks.
		BOOL has_perm_mask = FALSE;
		U32 perm_mask = 0;
		if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask))
		{
			goto fail;
		}
		if (has_perm_mask)
		{
			if(perm_mask == PERM_NONE)
			{
				perm_mask = mPermissions.getMaskOwner();
			}
			// fair use fix.
			if(!(perm_mask & PERM_COPY))
			{
				perm_mask |= PERM_TRANSFER;
			}
			mPermissions.setMaskNext(perm_mask);
		}
	}
	w = INV_SHADOW_ID_LABEL;
	if (sd.has(w))
	{
		mAssetUUID = sd[w];
		LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
		cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
	}
	w = INV_ASSET_ID_LABEL;
	if (sd.has(w))
	{
		mAssetUUID = sd[w];
	}
	w = INV_ASSET_TYPE_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isString())
		{
			mType = LLAssetType::lookup(sd[w].asString().c_str());
		}
		else if (sd[w].isInteger())
		{
			S8 type = (U8)sd[w].asInteger();
			mType = static_cast<LLAssetType::EType>(type);
		}
	}
	w = INV_INVENTORY_TYPE_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isString())
		{
			mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str());
		}
		else if (sd[w].isInteger())
		{
			S8 type = (U8)sd[w].asInteger();
			mInventoryType = static_cast<LLInventoryType::EType>(type);
		}
	}
	w = INV_FLAGS_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isBinary())
		{
			mFlags = ll_U32_from_sd(sd[w]);
		}
		else if(sd[w].isInteger())
		{
			mFlags = sd[w].asInteger();
		}
	}
	w = INV_NAME_LABEL;
	if (sd.has(w))
	{
		mName = sd[w].asString();
		LLStringUtil::replaceNonstandardASCII(mName, ' ');
		LLStringUtil::replaceChar(mName, '|', ' ');
	}
	w = INV_DESC_LABEL;
	if (sd.has(w))
	{
		mDescription = sd[w].asString();
		LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
	}
	w = INV_CREATION_DATE_LABEL;
	if (sd.has(w))
	{
		mCreationDate = sd[w].asInteger();
	}

	// Need to convert 1.0 simstate files to a useful inventory type
	// and potentially deal with bad inventory tyes eg, a landmark
	// marked as a texture.
	if((LLInventoryType::IT_NONE == mInventoryType)
	   || !inventory_and_asset_types_match(mInventoryType, mType))
	{
		lldebugs << "Resetting inventory type for " << mUUID << llendl;
		mInventoryType = LLInventoryType::defaultForAssetType(mType);
	}

	return true;
fail:
	return false;

}
bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
{

	LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SD_DESERIALIZE);
	if (is_new)
	{
		// If we're adding LLSD to an existing object, need avoid
		// clobbering these fields.
		mInventoryType = LLInventoryType::IT_NONE;
		mAssetUUID.setNull();
	}
	std::string w;

	w = INV_ITEM_ID_LABEL;
	if (sd.has(w))
	{
		mUUID = sd[w];
	}
	w = INV_PARENT_ID_LABEL;
	if (sd.has(w))
	{
		mParentUUID = sd[w];
	}
	w = INV_PERMISSIONS_LABEL;
	if (sd.has(w))
	{
		mPermissions = ll_permissions_from_sd(sd[w]);
	}
	w = INV_SALE_INFO_LABEL;
	if (sd.has(w))
	{
		// Sale info used to contain next owner perm. It is now in
		// the permissions. Thus, we read that out, and fix legacy
		// objects. It's possible this op would fail, but it
		// should pick up the vast majority of the tasks.
		BOOL has_perm_mask = FALSE;
		U32 perm_mask = 0;
		if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask))
		{
			goto fail;
		}
		if (has_perm_mask)
		{
			if(perm_mask == PERM_NONE)
			{
				perm_mask = mPermissions.getMaskOwner();
			}
			// fair use fix.
			if(!(perm_mask & PERM_COPY))
			{
				perm_mask |= PERM_TRANSFER;
			}
			mPermissions.setMaskNext(perm_mask);
		}
	}
	w = INV_SHADOW_ID_LABEL;
	if (sd.has(w))
	{
		mAssetUUID = sd[w];
		LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
		cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
	}
	w = INV_ASSET_ID_LABEL;
	if (sd.has(w))
	{
		mAssetUUID = sd[w];
	}
	w = INV_LINKED_ID_LABEL;
	if (sd.has(w))
	{
		mAssetUUID = sd[w];
	}
	w = INV_ASSET_TYPE_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isString())
		{
			mType = LLAssetType::lookup(sd[w].asString().c_str());
		}
		else if (sd[w].isInteger())
		{
			S8 type = (U8)sd[w].asInteger();
			mType = static_cast<LLAssetType::EType>(type);
		}
	}
	w = INV_INVENTORY_TYPE_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isString())
		{
			mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str());
		}
		else if (sd[w].isInteger())
		{
			S8 type = (U8)sd[w].asInteger();
			mInventoryType = static_cast<LLInventoryType::EType>(type);
		}
	}
	w = INV_FLAGS_LABEL;
	if (sd.has(w))
	{
		if (sd[w].isBinary())
		{
			mFlags = ll_U32_from_sd(sd[w]);
		}
		else if(sd[w].isInteger())
		{
			mFlags = sd[w].asInteger();
		}

		//<singu>
		// Define a few magic constants that are not accessible otherwise, from here.
		// mInventoryType:
		static U32 IT_WEARABLE = 18;	// LLInventoryType::IT_WEARABLE
		// mType, these are the two asset types that are IT_WEARABLE:
		static U32 AT_BODYPART = 13;	// LLAssetType::AT_BODYPART
		// Viewer local values:
		static U32 WT_UNKNOWN = 16;		// LLWearableType::WT_UNKNOWN
		static U32 WT_COUNT = 17;		// LLWearableType::WT_COUNT
		// The last 8 bits of mFlags contain the wearable type.
		static U32 II_FLAGS_WEARABLES_MASK = 0xff;	// LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK

		// The wearable type is stored in the lower 8 bits of mFlags.
		U32 wt = mFlags & II_FLAGS_WEARABLES_MASK;

		// Because WT_UNKNOWN now has locally a special meaning, make sure we don't receive it from the server.
		if (wt == WT_UNKNOWN)
		{
			LL_DEBUGS() << "Received inventory item with wearable type WT_UNKNOWN from server!" << LL_ENDL;
			// Change this new wearable type to WT_COUNT, as if when we had not inserted WT_UNKNOWN locally.
			mFlags += 1;
			wt = WT_COUNT;
		}

		// Detect possible problematic items.
		if (wt == 0 && mInventoryType == IT_WEARABLE && mType != AT_BODYPART)
		{
			// This is not possible, and therefore is probably an item creatd by a pre-multiwear viewer (or Second Inventory, etc).
			// The wearable type is NOT a shape (0) in that case of course, but we don't know what it is without downloading the
			// asset.
			mFlags |= WT_UNKNOWN;
		}
		//</singu>
	}
	w = INV_NAME_LABEL;
	if (sd.has(w))
	{
		mName = sd[w].asString();
		LLStringUtil::replaceNonstandardASCII(mName, ' ');
		LLStringUtil::replaceChar(mName, '|', ' ');
	}
	w = INV_DESC_LABEL;
	if (sd.has(w))
	{
		mDescription = sd[w].asString();
		LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
	}
	w = INV_CREATION_DATE_LABEL;
	if (sd.has(w))
	{
		mCreationDate = sd[w].asInteger();
	}

	// Need to convert 1.0 simstate files to a useful inventory type
	// and potentially deal with bad inventory tyes eg, a landmark
	// marked as a texture.
	if((LLInventoryType::IT_NONE == mInventoryType)
	   || !inventory_and_asset_types_match(mInventoryType, mType))
	{
		LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL;
		mInventoryType = LLInventoryType::defaultForAssetType(mType);
	}

	mPermissions.initMasks(mInventoryType);

	return true;
fail:
	return false;

}