// static
bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
													const LLInventoryCategory* cat,
													const LLUUID& im_session_id)

{
	if (!cat)
	{
		return false;
	}
	LL_INFOS() << "LLGiveInventory::commitGiveInventoryCategory() - "
			<< cat->getUUID() << LL_ENDL;

	// Test out how many items are being given.
	LLViewerInventoryCategory::cat_array_t cats;
	LLViewerInventoryItem::item_array_t items;
	LLGiveable giveable;
	gInventory.collectDescendentsIf(cat->getUUID(),
									cats,
									items,
									LLInventoryModel::EXCLUDE_TRASH,
									giveable);

	bool give_successful = true;
	// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
	// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
	// 66. I've cut it down a bit from there to give some pad.
 	S32 count = items.size() + cats.size();
 	if(count > MAX_ITEMS)
  	{
		LLNotificationsUtil::add("TooManyItems");
		give_successful = false;
  	}
 	else if(count == 0)
  	{
		LLNotificationsUtil::add("NoItems");
		give_successful = false;
  	}
	else
	{
		std::string name;
		LLAgentUI::buildFullname(name);
		LLUUID transaction_id;
		transaction_id.generate();
		S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
		U8* bucket = new U8[bucket_size];
		U8* pos = bucket;
		U8 type = (U8)cat->getType();
		memcpy(pos, &type, sizeof(U8));		/* Flawfinder: ignore */
		pos += sizeof(U8);
		memcpy(pos, &(cat->getUUID()), UUID_BYTES);		/* Flawfinder: ignore */
		pos += UUID_BYTES;
		S32 i;
		count = cats.size();
		for(i = 0; i < count; ++i)
		{
			memcpy(pos, &type, sizeof(U8));		/* Flawfinder: ignore */
			pos += sizeof(U8);
			memcpy(pos, &(cats.at(i)->getUUID()), UUID_BYTES);		/* Flawfinder: ignore */
			pos += UUID_BYTES;
		}
		count = items.size();
		for(i = 0; i < count; ++i)
		{
			type = (U8)items.at(i)->getType();
			memcpy(pos, &type, sizeof(U8));		/* Flawfinder: ignore */
			pos += sizeof(U8);
			memcpy(pos, &(items.at(i)->getUUID()), UUID_BYTES);		/* Flawfinder: ignore */
			pos += UUID_BYTES;
		}
		pack_instant_message(
			gMessageSystem,
			gAgent.getID(),
			FALSE,
			gAgent.getSessionID(),
			to_agent,
			name,
			cat->getName(),
			IM_ONLINE,
			IM_INVENTORY_OFFERED,
			transaction_id,
			0,
			LLUUID::null,
			gAgent.getPositionAgent(),
			NO_TIMESTAMP,
			bucket,
			bucket_size);
		gAgent.sendReliableMessage();
		delete[] bucket;

		// <edit>
 		if (gSavedSettings.getBOOL("BroadcastViewerEffects"))
		{
 			// </edit>
			// VEFFECT: giveInventoryCategory
			LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
			effectp->setSourceObject(gAgentAvatarp);
			effectp->setTargetObject(gObjectList.findObject(to_agent));
			effectp->setDuration(LL_HUD_DUR_SHORT);
			effectp->setColor(LLColor4U(gAgent.getEffectColor()));
			// <edit>
		}
		// </edit>
		gFloaterTools->dirty();

		LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);

		logInventoryOffer(to_agent, im_session_id);
	}

	return give_successful;
}
bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
											  const LLInventoryCategory* cat,
											  const LLUUID& im_session_id,
											  const std::string& notification_name)

{
	if (!cat)
	{
		return false;
	}
	LL_INFOS() << "LLGiveInventory::giveInventoryCategory() - "
		<< cat->getUUID() << LL_ENDL;

	if (!isAgentAvatarValid())
	{
		return false;
	}

	bool give_successful = true;
	// Test out how many items are being given.
	LLViewerInventoryCategory::cat_array_t cats;
	LLViewerInventoryItem::item_array_t items;
	LLGiveable giveable;
	gInventory.collectDescendentsIf(cat->getUUID(),
									cats,
									items,
									LLInventoryModel::EXCLUDE_TRASH,
									giveable);
	S32 count = cats.size();
	bool complete = true;
	for(S32 i = 0; i < count; ++i)
	{
		if(!gInventory.isCategoryComplete(cats.at(i)->getUUID()))
		{
			complete = false;
			break;
		}
	}
	if(!complete)
	{
		LLNotificationsUtil::add("IncompleteInventory");
		give_successful = false;
	}
	count = items.size() + cats.size();
	if(count > MAX_ITEMS)
	{
		LLNotificationsUtil::add("TooManyItems");
		give_successful = false;
	}
	else if(count == 0)
	{
		LLNotificationsUtil::add("NoItems");
		give_successful = false;
	}
	else if (give_successful)
	{
		if(0 == giveable.countNoCopy())
		{
			give_successful = LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id);
		}
		else
		{
			LLSD args;
			args["COUNT"] = llformat("%d",giveable.countNoCopy());
			LLSD payload;
			payload["agent_id"] = to_agent;
			payload["folder_id"] = cat->getUUID();
			if (!notification_name.empty())
			{
				payload["success_notification"] = notification_name;
			}
			LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory);
			give_successful = false;
		}
	}

	return give_successful;
}