PageRenderTime 124ms CodeModel.GetById 17ms app.highlight 99ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llinventory/llpermissions.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1213 lines | 966 code | 118 blank | 129 comment | 190 complexity | 3b2495c1eda053d032f821d5b1bb5c84 MD5 | raw file
   1/** 
   2 * @file llpermissions.cpp
   3 * @author Phoenix
   4 * @brief Permissions for objects and inventory.
   5 *
   6 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
   7 * Second Life Viewer Source Code
   8 * Copyright (C) 2010, Linden Research, Inc.
   9 * 
  10 * This library is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU Lesser General Public
  12 * License as published by the Free Software Foundation;
  13 * version 2.1 of the License only.
  14 * 
  15 * This library is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * Lesser General Public License for more details.
  19 * 
  20 * You should have received a copy of the GNU Lesser General Public
  21 * License along with this library; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  23 * 
  24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  25 * $/LicenseInfo$
  26 */
  27
  28#include "linden_common.h"
  29
  30#include "llpermissions.h"
  31
  32// library includes
  33#include "message.h"
  34#include "metapropertyt.h"
  35#include "llsd.h"
  36
  37///----------------------------------------------------------------------------
  38/// Class LLPermissions
  39///----------------------------------------------------------------------------
  40
  41const LLPermissions LLPermissions::DEFAULT;
  42
  43// No creator = created by system
  44LLPermissions::LLPermissions()
  45{
  46	init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
  47}
  48
  49
  50// Default to created by system
  51void LLPermissions::init(const LLUUID& creator, const LLUUID& owner, const LLUUID& last_owner, const LLUUID& group)
  52{
  53	mCreator	= creator;
  54	mOwner		= owner;
  55	mLastOwner	= last_owner;
  56	mGroup		= group;
  57
  58	mMaskBase		= PERM_ALL;
  59	mMaskOwner		= PERM_ALL;
  60	mMaskEveryone	= PERM_ALL;
  61	mMaskGroup		= PERM_ALL;
  62	mMaskNextOwner = PERM_ALL;
  63	fixOwnership();
  64}
  65
  66
  67void LLPermissions::initMasks(PermissionMask base, PermissionMask owner,
  68							  PermissionMask everyone, PermissionMask group,
  69							  PermissionMask next)
  70{
  71	mMaskBase		= base;
  72	mMaskOwner		= owner;
  73	mMaskEveryone	= everyone;
  74	mMaskGroup		= group;
  75	mMaskNextOwner = next;
  76	fixFairUse();
  77	fix();
  78}
  79
  80// ! BACKWARDS COMPATIBILITY ! Override masks for inventory types that
  81// no longer can have restricted permissions.  This takes care of previous
  82// version landmarks that could have had no copy/mod/transfer bits set.
  83void LLPermissions::initMasks(LLInventoryType::EType type)
  84{
  85	if (LLInventoryType::cannotRestrictPermissions(type))
  86	{
  87		initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL);
  88	}
  89}
  90
  91BOOL LLPermissions::getOwnership(LLUUID& owner_id, BOOL& is_group_owned) const
  92{
  93	if(mOwner.notNull())
  94	{
  95		owner_id = mOwner;
  96		is_group_owned = FALSE;
  97		return TRUE;
  98	}
  99	else if(mIsGroupOwned)
 100	{
 101		owner_id = mGroup;
 102		is_group_owned = TRUE;
 103		return TRUE;
 104	}
 105	return FALSE;
 106}
 107
 108LLUUID LLPermissions::getSafeOwner() const
 109{
 110	if(mOwner.notNull())
 111	{
 112		return mOwner;
 113	}
 114	else if(mIsGroupOwned)
 115	{
 116		return mGroup;
 117	}
 118	else
 119	{
 120		llwarns << "LLPermissions::getSafeOwner() called with no valid owner!" << llendl;
 121		LLUUID unused_uuid;
 122		unused_uuid.generate();
 123
 124		return unused_uuid;
 125	}
 126}
 127
 128U32 LLPermissions::getCRC32() const
 129{
 130	U32 rv = mCreator.getCRC32();
 131	rv += mOwner.getCRC32();
 132	rv += mLastOwner.getCRC32();
 133	rv += mGroup.getCRC32();
 134	rv += mMaskBase + mMaskOwner + mMaskEveryone + mMaskGroup;
 135	return rv;
 136}
 137
 138void LLPermissions::set(const LLPermissions& from)
 139{
 140	mCreator	= from.mCreator;
 141	mOwner		= from.mOwner;
 142	mLastOwner	= from.mLastOwner;
 143	mGroup		= from.mGroup;
 144
 145	mMaskBase		= from.mMaskBase;
 146	mMaskOwner		= from.mMaskOwner;
 147	mMaskEveryone	= from.mMaskEveryone;
 148	mMaskGroup		= from.mMaskGroup;
 149	mMaskNextOwner = from.mMaskNextOwner;
 150	mIsGroupOwned = from.mIsGroupOwned;
 151}
 152
 153// Fix hierarchy of permissions. 
 154void LLPermissions::fix()
 155{
 156	mMaskOwner &= mMaskBase;
 157	mMaskGroup &= mMaskOwner;
 158	// next owner uses base, since you may want to sell locked objects.
 159	mMaskNextOwner &= mMaskBase;
 160	mMaskEveryone &= mMaskOwner;
 161	mMaskEveryone &= ~PERM_MODIFY;
 162	if(!(mMaskBase & PERM_TRANSFER) && !mIsGroupOwned)
 163	{
 164		mMaskGroup &= ~PERM_COPY;
 165		mMaskEveryone &= ~PERM_COPY;
 166		// Do not set mask next owner to too restrictive because if we
 167		// rez an object, it may require an ownership transfer during
 168		// rez, which will note the overly restrictive perms, and then
 169		// fix them to allow fair use, which may be different than the
 170		// original intention.
 171	}
 172}
 173
 174// Correct for fair use - you can never take away the right to move
 175// stuff you own, and you can never take away the right to transfer
 176// something you cannot otherwise copy.
 177void LLPermissions::fixFairUse()
 178{
 179	mMaskBase |= PERM_MOVE;
 180	if(!(mMaskBase & PERM_COPY))
 181	{
 182		mMaskBase |= PERM_TRANSFER;
 183	}
 184	// (mask next owner == PERM_NONE) iff mask base is no transfer
 185	if(mMaskNextOwner != PERM_NONE)
 186	{
 187		mMaskNextOwner |= PERM_MOVE;
 188	}
 189}
 190
 191void LLPermissions::fixOwnership()
 192{
 193	if(mOwner.isNull() && mGroup.notNull())
 194	{
 195		mIsGroupOwned = true;
 196	}
 197	else
 198	{
 199		mIsGroupOwned = false;
 200	}
 201}
 202
 203// Allow accumulation of permissions. Results in the tightest
 204// permissions possible. In the case of clashing UUIDs, it sets the ID
 205// to LLUUID::null.
 206void LLPermissions::accumulate(const LLPermissions& perm)
 207{
 208	if(perm.mCreator != mCreator)
 209	{
 210		mCreator = LLUUID::null;
 211	}
 212	if(perm.mOwner != mOwner)
 213	{
 214		mOwner = LLUUID::null;
 215	}
 216	if(perm.mLastOwner != mLastOwner)
 217	{
 218		mLastOwner = LLUUID::null;
 219	}
 220	if(perm.mGroup != mGroup)
 221	{
 222		mGroup = LLUUID::null;
 223	}
 224
 225	mMaskBase &= perm.mMaskBase;
 226	mMaskOwner &= perm.mMaskOwner;
 227	mMaskGroup &= perm.mMaskGroup;
 228	mMaskEveryone &= perm.mMaskEveryone;
 229	mMaskNextOwner &= perm.mMaskNextOwner;
 230	fix();
 231}
 232
 233// saves last owner, sets current owner, and sets the group.  note
 234// that this function has to more cleverly apply the fair use
 235// permissions.
 236BOOL LLPermissions::setOwnerAndGroup(
 237	const LLUUID& agent,
 238	const LLUUID& owner,
 239	const LLUUID& group,
 240	bool is_atomic)
 241{
 242	BOOL allowed = FALSE;
 243
 244	if( agent.isNull() || mOwner.isNull()
 245	   || ((agent == mOwner) && ((owner == mOwner) || (mMaskOwner & PERM_TRANSFER)) ) )
 246	{
 247		// ...system can alway set owner
 248		// ...public objects can be claimed by anyone
 249		// ...otherwise, agent must own it and have transfer ability
 250		allowed = TRUE;
 251	}
 252
 253	if (allowed)
 254	{
 255		if(mLastOwner.isNull() || (!mOwner.isNull() && (owner != mLastOwner)))
 256		{
 257			mLastOwner = mOwner;
 258		}
 259		if((mOwner != owner)
 260		   || (mOwner.isNull() && owner.isNull() && (mGroup != group)))
 261		{
 262			mMaskBase = mMaskNextOwner;
 263			mOwner = owner;
 264			// this is a selective use of fair use for atomic
 265			// permissions.
 266			if(is_atomic && !(mMaskBase & PERM_COPY))
 267			{
 268				mMaskBase |= PERM_TRANSFER;
 269			}
 270		}
 271		mGroup = group;
 272		fixOwnership();
 273		// if it's not atomic and we fix fair use, it blows away
 274		//objects as inventory items which have different permissions
 275		//than it's contents. :(
 276		// fixFairUse();
 277		mMaskBase |= PERM_MOVE;
 278		if(mMaskNextOwner != PERM_NONE) mMaskNextOwner |= PERM_MOVE;
 279		fix();
 280	}
 281
 282	return allowed;
 283}
 284
 285//Fix for DEV-33917, last owner isn't used much and has little impact on
 286//permissions so it's reasonably safe to do this, however, for now, 
 287//limiting the functionality of this routine to objects which are 
 288//group owned.
 289void LLPermissions::setLastOwner(const LLUUID& last_owner)
 290{
 291	if (isGroupOwned())
 292		mLastOwner = last_owner;
 293}
 294
 295 
 296// only call this if you know what you're doing
 297// there are usually perm-bit consequences when the 
 298// ownerhsip changes
 299void LLPermissions::yesReallySetOwner(const LLUUID& owner, bool group_owned)
 300{
 301	mOwner = owner;
 302	mIsGroupOwned = group_owned;
 303}
 304
 305BOOL LLPermissions::deedToGroup(const LLUUID& agent, const LLUUID& group)
 306{
 307	if(group.notNull() && (agent.isNull() || ((group == mGroup)
 308											  && (mMaskOwner & PERM_TRANSFER)
 309											  && (mMaskGroup & PERM_MOVE))))
 310	{
 311		if(mOwner.notNull())
 312		{
 313			mLastOwner = mOwner;
 314			mOwner.setNull();
 315		}
 316		mMaskBase = mMaskNextOwner;
 317		mMaskGroup = PERM_NONE;
 318		mGroup = group;
 319		mIsGroupOwned = true;
 320		fixFairUse();
 321		fix();
 322		return TRUE;
 323	}
 324	return FALSE;
 325}
 326
 327BOOL LLPermissions::setBaseBits(const LLUUID& agent, BOOL set, PermissionMask bits)
 328{
 329	BOOL ownership = FALSE;
 330	if(agent.isNull())
 331	{
 332		// only the system is always allowed to change base bits
 333		ownership = TRUE;
 334	}
 335
 336	if (ownership)
 337	{
 338		if (set)
 339		{
 340			mMaskBase |= bits;		// turn on bits
 341		}
 342		else
 343		{
 344			mMaskBase &= ~bits;		// turn off bits
 345		}
 346		fix();
 347	}
 348
 349	return ownership;
 350}
 351
 352
 353// Note: If you attempt to set bits that the base bits doesn't allow,
 354// the function will succeed, but those bits will not be set.
 355BOOL LLPermissions::setOwnerBits(const LLUUID& agent, BOOL set, PermissionMask bits)
 356{
 357	BOOL ownership = FALSE;
 358
 359	if(agent.isNull())
 360	{
 361		// ...system always allowed to change things
 362		ownership = TRUE;
 363	}
 364	else if (agent == mOwner)
 365	{
 366		// ...owner bits can only be set by owner
 367		ownership = TRUE;
 368	}
 369
 370	// If we have correct ownership and 
 371	if (ownership)
 372	{
 373		if (set)
 374		{
 375			mMaskOwner |= bits;			// turn on bits
 376		}
 377		else
 378		{
 379			mMaskOwner &= ~bits;		// turn off bits
 380		}
 381		fix();
 382	}
 383
 384	return (ownership);
 385}
 386
 387BOOL LLPermissions::setGroupBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits)
 388{
 389	BOOL ownership = FALSE;
 390	if((agent.isNull()) || (agent == mOwner)
 391	   || ((group == mGroup) && (!mGroup.isNull())))
 392	{
 393		// The group bits can be set by the system, the owner, or a
 394		// group member.
 395		ownership = TRUE;
 396	}
 397
 398	if (ownership)
 399	{
 400		if (set)
 401		{
 402			mMaskGroup |= bits;
 403		}
 404		else
 405		{
 406			mMaskGroup &= ~bits;
 407		}
 408		fix();
 409	}
 410	return ownership;
 411}
 412
 413
 414// Note: If you attempt to set bits that the creator or owner doesn't allow,
 415// the function will succeed, but those bits will not be set.
 416BOOL LLPermissions::setEveryoneBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits)
 417{
 418	BOOL ownership = FALSE;
 419	if((agent.isNull()) || (agent == mOwner)
 420	   || ((group == mGroup) && (!mGroup.isNull())))
 421	{
 422		// The everyone bits can be set by the system, the owner, or a
 423		// group member.
 424		ownership = TRUE;
 425	}
 426	if (ownership)
 427	{
 428		if (set)
 429		{
 430			mMaskEveryone |= bits;
 431		}
 432		else
 433		{
 434			mMaskEveryone &= ~bits;
 435		}
 436
 437		// Fix hierarchy of permissions
 438		fix();
 439	}
 440	return ownership;
 441}
 442
 443// Note: If you attempt to set bits that the creator or owner doesn't allow,
 444// the function will succeed, but those bits will not be set.
 445BOOL LLPermissions::setNextOwnerBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits)
 446{
 447	BOOL ownership = FALSE;
 448	if((agent.isNull()) || (agent == mOwner)
 449	   || ((group == mGroup) && (!mGroup.isNull())))
 450	{
 451		// The next owner bits can be set by the system, the owner, or
 452		// a group member.
 453		ownership = TRUE;
 454	}
 455	if (ownership)
 456	{
 457		if (set)
 458		{
 459			mMaskNextOwner |= bits;
 460		}
 461		else
 462		{
 463			mMaskNextOwner &= ~bits;
 464		}
 465
 466		// Fix-up permissions
 467		if(!(mMaskNextOwner & PERM_COPY))
 468		{
 469			mMaskNextOwner |= PERM_TRANSFER;
 470		}
 471		fix();
 472	}
 473	return ownership;
 474}
 475
 476bool LLPermissions::allowOperationBy(PermissionBit op, const LLUUID& requester, const LLUUID& group) const
 477{
 478	if(requester.isNull())
 479	{
 480		// ...system making request
 481		// ...not owned
 482		return TRUE;
 483	}
 484	else if (mIsGroupOwned && (mGroup == requester))
 485	{
 486		// group checking ownership permissions
 487		return (mMaskOwner & op);
 488	}
 489	else if (!mIsGroupOwned && (mOwner == requester))
 490	{
 491		// ...owner making request
 492		return (mMaskOwner & op);
 493	}
 494	else if(mGroup.notNull() && (mGroup == group))
 495	{
 496		// group member making request
 497		return ((mMaskGroup & op) || (mMaskEveryone & op));
 498	}
 499	return (mMaskEveryone & op);
 500}
 501
 502//
 503// LLSD support for HTTP messages.
 504//
 505LLSD LLPermissions::packMessage() const
 506{
 507	LLSD result;
 508	result["creator-id"]	= mCreator;
 509	result["owner-id"]		= mOwner;
 510	result["group-id"]		= mGroup;
 511
 512	result["base-mask"]		=	(S32)mMaskBase;
 513	result["owner-mask"]	=	(S32)mMaskOwner;
 514	result["group-mask"]	=	(S32)mMaskGroup;
 515	result["everyone-mask"]	=	(S32)mMaskEveryone;
 516	result["next-owner-mask"]=	(S32)mMaskNextOwner;
 517	result["group-owned"]	= (BOOL)mIsGroupOwned;
 518	return result;
 519}
 520
 521//
 522// Messaging support
 523//
 524void LLPermissions::packMessage(LLMessageSystem* msg) const
 525{
 526	msg->addUUIDFast(_PREHASH_CreatorID, mCreator);
 527	msg->addUUIDFast(_PREHASH_OwnerID, mOwner);
 528	msg->addUUIDFast(_PREHASH_GroupID, mGroup);
 529
 530	msg->addU32Fast(_PREHASH_BaseMask,		mMaskBase );
 531	msg->addU32Fast(_PREHASH_OwnerMask,	mMaskOwner );
 532	msg->addU32Fast(_PREHASH_GroupMask,	mMaskGroup );
 533	msg->addU32Fast(_PREHASH_EveryoneMask,	mMaskEveryone );
 534	msg->addU32Fast(_PREHASH_NextOwnerMask, mMaskNextOwner );
 535	msg->addBOOLFast(_PREHASH_GroupOwned, (BOOL)mIsGroupOwned);
 536}
 537
 538void LLPermissions::unpackMessage(LLSD perms)
 539{
 540	mCreator	=	perms["creator-id"];
 541	mOwner	=	perms["owner-id"];
 542	mGroup	=	perms["group-id"];
 543
 544	mMaskBase	=	(U32)perms["base-mask"].asInteger();
 545	mMaskOwner	=	(U32)perms["owner-mask"].asInteger();
 546	mMaskGroup	=	(U32)perms["group-mask"].asInteger();
 547	mMaskEveryone	=	(U32)perms["everyone-mask"].asInteger();
 548	mMaskNextOwner	=	(U32)perms["next-owner-mask"].asInteger();
 549	mIsGroupOwned	=	perms["group-owned"].asBoolean();
 550}
 551
 552void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
 553{
 554	msg->getUUIDFast(block, _PREHASH_CreatorID,	mCreator, block_num);
 555	msg->getUUIDFast(block, _PREHASH_OwnerID,	mOwner, block_num);
 556	msg->getUUIDFast(block, _PREHASH_GroupID,	mGroup, block_num);
 557
 558	msg->getU32Fast(block, _PREHASH_BaseMask, mMaskBase, block_num );
 559	msg->getU32Fast(block, _PREHASH_OwnerMask, mMaskOwner, block_num );
 560	msg->getU32Fast(block, _PREHASH_GroupMask, mMaskGroup, block_num );
 561	msg->getU32Fast(block, _PREHASH_EveryoneMask, mMaskEveryone, block_num );
 562	msg->getU32Fast(block, _PREHASH_NextOwnerMask, mMaskNextOwner, block_num );
 563	BOOL tmp;
 564	msg->getBOOLFast(block, _PREHASH_GroupOwned, tmp, block_num);
 565	mIsGroupOwned = (bool)tmp;
 566}
 567
 568
 569//
 570// File support
 571//
 572
 573BOOL LLPermissions::importFile(LLFILE* fp)
 574{
 575	init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
 576	const S32 BUFSIZE = 16384;
 577
 578	// *NOTE: Changing the buffer size will require changing the scanf
 579	// calls below.
 580	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 581	char keyword[256];	/* Flawfinder: ignore */
 582	char valuestr[256];	/* Flawfinder: ignore */
 583	char uuid_str[256];	/* Flawfinder: ignore */
 584	U32 mask;
 585
 586	keyword[0]  = '\0';
 587	valuestr[0] = '\0';
 588
 589	while (!feof(fp))
 590	{
 591		if (fgets(buffer, BUFSIZE, fp) == NULL)
 592		{
 593			buffer[0] = '\0';
 594		}
 595		
 596		sscanf( /* Flawfinder: ignore */
 597			buffer,
 598			" %255s %255s",
 599			keyword, valuestr);
 600		if (!strcmp("{", keyword))
 601		{
 602			continue;
 603		}
 604		if (!strcmp("}",keyword))
 605		{
 606			break;
 607		}
 608		else if (!strcmp("creator_mask", keyword))
 609		{
 610			// legacy support for "creator" masks
 611			sscanf(valuestr, "%x", &mask);
 612			mMaskBase = mask;
 613			fixFairUse();
 614		}
 615		else if (!strcmp("base_mask", keyword))
 616		{
 617			sscanf(valuestr, "%x", &mask);
 618			mMaskBase = mask;
 619			//fixFairUse();
 620		}
 621		else if (!strcmp("owner_mask", keyword))
 622		{
 623			sscanf(valuestr, "%x", &mask);
 624			mMaskOwner = mask;
 625		}
 626		else if (!strcmp("group_mask", keyword))
 627		{
 628			sscanf(valuestr, "%x", &mask);
 629			mMaskGroup = mask;
 630		}
 631		else if (!strcmp("everyone_mask", keyword))
 632		{
 633			sscanf(valuestr, "%x", &mask);
 634			mMaskEveryone = mask;
 635		}
 636		else if (!strcmp("next_owner_mask", keyword))
 637		{
 638			sscanf(valuestr, "%x", &mask);
 639			mMaskNextOwner = mask;
 640		}
 641		else if (!strcmp("creator_id", keyword))
 642		{
 643			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
 644			mCreator.set(uuid_str);
 645		}
 646		else if (!strcmp("owner_id", keyword))
 647		{
 648			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
 649			mOwner.set(uuid_str);
 650		}
 651		else if (!strcmp("last_owner_id", keyword))
 652		{
 653			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
 654			mLastOwner.set(uuid_str);
 655		}
 656		else if (!strcmp("group_id", keyword))
 657		{
 658			sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
 659			mGroup.set(uuid_str);
 660		}
 661		else if (!strcmp("group_owned", keyword))
 662		{
 663			sscanf(valuestr, "%d", &mask);
 664			if(mask) mIsGroupOwned = true;
 665			else mIsGroupOwned = false;
 666		}
 667		else
 668		{
 669			llinfos << "unknown keyword " << keyword << " in permissions import" << llendl;
 670		}
 671	}
 672	fix();
 673	return TRUE;
 674}
 675
 676
 677BOOL LLPermissions::exportFile(LLFILE* fp) const
 678{
 679	std::string uuid_str;
 680
 681	fprintf(fp, "\tpermissions 0\n");
 682	fprintf(fp, "\t{\n");
 683
 684	fprintf(fp, "\t\tbase_mask\t%08x\n",		mMaskBase);
 685	fprintf(fp, "\t\towner_mask\t%08x\n",		mMaskOwner);
 686	fprintf(fp, "\t\tgroup_mask\t%08x\n",		mMaskGroup);
 687	fprintf(fp, "\t\teveryone_mask\t%08x\n",	mMaskEveryone);
 688	fprintf(fp, "\t\tnext_owner_mask\t%08x\n",	mMaskNextOwner);
 689
 690	mCreator.toString(uuid_str);
 691	fprintf(fp, "\t\tcreator_id\t%s\n",			uuid_str.c_str());
 692
 693	mOwner.toString(uuid_str);
 694	fprintf(fp, "\t\towner_id\t%s\n",			uuid_str.c_str());
 695
 696	mLastOwner.toString(uuid_str);
 697	fprintf(fp, "\t\tlast_owner_id\t%s\n",		uuid_str.c_str());
 698
 699	mGroup.toString(uuid_str);
 700	fprintf(fp, "\t\tgroup_id\t%s\n",			uuid_str.c_str());
 701
 702	if(mIsGroupOwned)
 703	{
 704		fprintf(fp, "\t\tgroup_owned\t1\n");
 705	}
 706	fprintf(fp,"\t}\n");
 707	return TRUE;
 708}
 709
 710
 711BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
 712{
 713	init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
 714	const S32 BUFSIZE = 16384;
 715
 716	// *NOTE: Changing the buffer size will require changing the scanf
 717	// calls below.
 718	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 719	char keyword[256];	/* Flawfinder: ignore */
 720	char valuestr[256];	/* Flawfinder: ignore */
 721	char uuid_str[256];	/* Flawfinder: ignore */
 722	U32 mask;
 723
 724	keyword[0]  = '\0';
 725	valuestr[0] = '\0';
 726
 727	while (input_stream.good())
 728	{
 729		input_stream.getline(buffer, BUFSIZE);
 730		sscanf( /* Flawfinder: ignore */
 731			buffer,
 732			" %255s %255s",
 733			keyword, valuestr);
 734		if (!strcmp("{", keyword))
 735		{
 736			continue;
 737		}
 738		if (!strcmp("}",keyword))
 739		{
 740			break;
 741		}
 742		else if (!strcmp("creator_mask", keyword))
 743		{
 744			// legacy support for "creator" masks
 745			sscanf(valuestr, "%x", &mask);
 746			mMaskBase = mask;
 747			fixFairUse();
 748		}
 749		else if (!strcmp("base_mask", keyword))
 750		{
 751			sscanf(valuestr, "%x", &mask);
 752			mMaskBase = mask;
 753			//fixFairUse();
 754		}
 755		else if (!strcmp("owner_mask", keyword))
 756		{
 757			sscanf(valuestr, "%x", &mask);
 758			mMaskOwner = mask;
 759		}
 760		else if (!strcmp("group_mask", keyword))
 761		{
 762			sscanf(valuestr, "%x", &mask);
 763			mMaskGroup = mask;
 764		}
 765		else if (!strcmp("everyone_mask", keyword))
 766		{
 767			sscanf(valuestr, "%x", &mask);
 768			mMaskEveryone = mask;
 769		}
 770		else if (!strcmp("next_owner_mask", keyword))
 771		{
 772			sscanf(valuestr, "%x", &mask);
 773			mMaskNextOwner = mask;
 774		}
 775		else if (!strcmp("creator_id", keyword))
 776		{
 777			sscanf(valuestr, "%255s", uuid_str);	/* Flawfinder: ignore */
 778			mCreator.set(uuid_str);
 779		}
 780		else if (!strcmp("owner_id", keyword))
 781		{
 782			sscanf(valuestr, "%255s", uuid_str);	/* Flawfinder: ignore */
 783			mOwner.set(uuid_str);
 784		}
 785		else if (!strcmp("last_owner_id", keyword))
 786		{
 787			sscanf(valuestr, "%255s", uuid_str);	/* Flawfinder: ignore */
 788			mLastOwner.set(uuid_str);
 789		}
 790		else if (!strcmp("group_id", keyword))
 791		{
 792			sscanf(valuestr, "%255s", uuid_str);	/* Flawfinder: ignore */
 793			mGroup.set(uuid_str);
 794		}
 795		else if (!strcmp("group_owned", keyword))
 796		{
 797			sscanf(valuestr, "%d", &mask);
 798			if(mask) mIsGroupOwned = true;
 799			else mIsGroupOwned = false;
 800		}
 801		else
 802		{
 803			llinfos << "unknown keyword " << keyword << " in permissions import" << llendl;
 804		}
 805	}
 806	fix();
 807	return TRUE;
 808}
 809
 810
 811BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const
 812{
 813	std::string uuid_str;
 814
 815	output_stream <<  "\tpermissions 0\n";
 816	output_stream <<  "\t{\n";
 817
 818	std::string buffer;
 819	buffer = llformat( "\t\tbase_mask\t%08x\n",		mMaskBase);
 820	output_stream << buffer;
 821	buffer = llformat( "\t\towner_mask\t%08x\n",		mMaskOwner);
 822	output_stream << buffer;
 823	buffer = llformat( "\t\tgroup_mask\t%08x\n",		mMaskGroup);
 824	output_stream << buffer;
 825	buffer = llformat( "\t\teveryone_mask\t%08x\n",	mMaskEveryone);
 826	output_stream << buffer;
 827	buffer = llformat( "\t\tnext_owner_mask\t%08x\n",	mMaskNextOwner);
 828	output_stream << buffer;
 829
 830	mCreator.toString(uuid_str);
 831	output_stream <<  "\t\tcreator_id\t" << uuid_str << "\n";
 832
 833	mOwner.toString(uuid_str);
 834	output_stream <<  "\t\towner_id\t" << uuid_str << "\n";
 835
 836	mLastOwner.toString(uuid_str);
 837	output_stream <<  "\t\tlast_owner_id\t" << uuid_str << "\n";
 838
 839	mGroup.toString(uuid_str);
 840	output_stream <<  "\t\tgroup_id\t" << uuid_str << "\n";
 841
 842	if(mIsGroupOwned)
 843	{
 844		output_stream <<  "\t\tgroup_owned\t1\n";
 845	}
 846	output_stream << "\t}\n";
 847	return TRUE;
 848}
 849
 850// Deleted LLPermissions::exportFileXML() and LLPermissions::importXML()
 851// because I can't find any non-test code references to it. 2009-05-04 JC
 852
 853bool LLPermissions::operator==(const LLPermissions &rhs) const
 854{   
 855	return 
 856		(mCreator == rhs.mCreator) &&
 857		(mOwner == rhs.mOwner) &&
 858		(mLastOwner == rhs.mLastOwner ) &&
 859		(mGroup == rhs.mGroup ) &&
 860		(mMaskBase == rhs.mMaskBase ) &&
 861		(mMaskOwner == rhs.mMaskOwner ) &&
 862		(mMaskGroup == rhs.mMaskGroup ) &&
 863		(mMaskEveryone == rhs.mMaskEveryone ) &&
 864		(mMaskNextOwner == rhs.mMaskNextOwner ) &&
 865		(mIsGroupOwned == rhs.mIsGroupOwned);
 866}
 867
 868
 869bool LLPermissions::operator!=(const LLPermissions &rhs) const
 870{   
 871	return 
 872		(mCreator != rhs.mCreator) ||
 873		(mOwner != rhs.mOwner) ||
 874		(mLastOwner != rhs.mLastOwner ) ||
 875		(mGroup != rhs.mGroup ) ||
 876		(mMaskBase != rhs.mMaskBase ) ||
 877		(mMaskOwner != rhs.mMaskOwner ) ||
 878		(mMaskGroup != rhs.mMaskGroup ) ||
 879		(mMaskEveryone != rhs.mMaskEveryone ) ||
 880		(mMaskNextOwner != rhs.mMaskNextOwner) ||
 881		(mIsGroupOwned != rhs.mIsGroupOwned);
 882}
 883
 884std::ostream& operator<<(std::ostream &s, const LLPermissions &perm)
 885{
 886	s << "{Creator=" 		<< perm.getCreator();
 887	s << ", Owner=" 		<< perm.getOwner();
 888	s << ", Group=" 		<< perm.getGroup();
 889	s << std::hex << ", BaseMask=0x" << perm.getMaskBase();
 890	s << ", OwnerMask=0x" << perm.getMaskOwner();
 891	s << ", EveryoneMask=0x" << perm.getMaskEveryone();
 892	s << ", GroupMask=0x" << perm.getMaskGroup();
 893	s << ", NextOwnerMask=0x" << perm.getMaskNextOwner() << std::dec;
 894	s << "}";
 895	return s;
 896}
 897
 898template <>
 899void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
 900{
 901	reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
 902	reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
 903	reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
 904	reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
 905}
 906
 907// virtual
 908const LLMetaClass& LLPermissions::getMetaClass() const
 909{
 910	return LLMetaClassT<LLPermissions>::instance();
 911}
 912
 913///----------------------------------------------------------------------------
 914/// Class LLAggregatePermissions
 915///----------------------------------------------------------------------------
 916
 917const LLAggregatePermissions LLAggregatePermissions::empty;
 918
 919
 920LLAggregatePermissions::LLAggregatePermissions()
 921{
 922	for(S32 i = 0; i < PI_COUNT; ++i)
 923	{
 924		mBits[i] = AP_EMPTY;
 925	}
 926}
 927
 928LLAggregatePermissions::EValue LLAggregatePermissions::getValue(PermissionBit bit) const
 929{
 930	EPermIndex idx = perm2PermIndex(bit);
 931	EValue rv = AP_EMPTY;
 932	if(idx != PI_END)
 933	{
 934		rv = (LLAggregatePermissions::EValue)(mBits[idx]);
 935	}
 936	return rv;
 937}
 938
 939// returns the bits compressed into a single byte: 00TTMMCC
 940// where TT = transfer, MM = modify, and CC = copy
 941// LSB is to the right
 942U8 LLAggregatePermissions::getU8() const
 943{
 944	U8 byte = mBits[PI_TRANSFER];
 945	byte <<= 2;
 946	byte |= mBits[PI_MODIFY];
 947	byte <<= 2;
 948	byte |= mBits[PI_COPY];
 949	return byte;
 950}
 951
 952BOOL LLAggregatePermissions::isEmpty() const
 953{
 954	for(S32 i = 0; i < PI_END; ++i)
 955	{
 956		if(mBits[i] != AP_EMPTY)
 957		{
 958			return FALSE;
 959		}
 960	}
 961	return TRUE;
 962}
 963
 964void LLAggregatePermissions::aggregate(PermissionMask mask)
 965{
 966	BOOL is_allowed = mask & PERM_COPY;
 967	aggregateBit(PI_COPY, is_allowed);
 968	is_allowed = mask & PERM_MODIFY;
 969	aggregateBit(PI_MODIFY, is_allowed);
 970	is_allowed = mask & PERM_TRANSFER;
 971	aggregateBit(PI_TRANSFER, is_allowed);
 972}
 973
 974void LLAggregatePermissions::aggregate(const LLAggregatePermissions& ag)
 975{
 976	for(S32 idx = PI_COPY; idx != PI_END; ++idx)
 977	{
 978		aggregateIndex((EPermIndex)idx, ag.mBits[idx]);
 979	}
 980}
 981
 982void LLAggregatePermissions::aggregateBit(EPermIndex idx, BOOL allowed)
 983{
 984	//if(AP_SOME == mBits[idx]) return; // P4 branch prediction optimization
 985	switch(mBits[idx])
 986	{
 987	case AP_EMPTY:
 988		mBits[idx] = allowed ? AP_ALL : AP_NONE;
 989		break;
 990	case AP_NONE:
 991		mBits[idx] = allowed ? AP_SOME: AP_NONE;
 992		break;
 993	case AP_SOME:
 994		// no-op
 995		break;
 996	case AP_ALL:
 997		mBits[idx] = allowed ? AP_ALL : AP_SOME;
 998		break;
 999	default:
1000		llwarns << "Bad aggregateBit " << (S32)idx << " "
1001				<< (allowed ? "true" : "false") << llendl;
1002		break;
1003	}
1004}
1005
1006void LLAggregatePermissions::aggregateIndex(EPermIndex idx, U8 bits)
1007{
1008	switch(mBits[idx])
1009	{
1010	case AP_EMPTY:
1011		mBits[idx] = bits;
1012		break;
1013	case AP_NONE:
1014		switch(bits)
1015		{
1016		case AP_SOME:
1017		case AP_ALL:
1018			mBits[idx] = AP_SOME;
1019			break;
1020		case AP_EMPTY:
1021		case AP_NONE:
1022		default:
1023			// no-op
1024			break;
1025		}
1026		break;
1027	case AP_SOME:
1028		// no-op
1029		break;
1030	case AP_ALL:
1031		switch(bits)
1032		{
1033		case AP_NONE:
1034		case AP_SOME:
1035			mBits[idx] = AP_SOME;
1036			break;
1037		case AP_EMPTY:
1038		case AP_ALL:
1039		default:
1040			// no-op
1041			break;
1042		}
1043		break;
1044	default:
1045		llwarns << "Bad aggregate index " << (S32)idx << " "
1046				<<  (S32)bits << llendl;
1047		break;
1048	}
1049}
1050
1051// static
1052LLAggregatePermissions::EPermIndex LLAggregatePermissions::perm2PermIndex(PermissionBit bit)
1053{
1054	EPermIndex idx = PI_END; // past any good value.
1055	switch(bit)
1056	{
1057	case PERM_COPY:
1058		idx = PI_COPY;
1059		break;
1060	case PERM_MODIFY:
1061		idx = PI_MODIFY;
1062		break;
1063	case PERM_TRANSFER:
1064		idx = PI_TRANSFER;
1065		break;
1066	default:
1067		break;
1068	}
1069	return idx;
1070}
1071
1072
1073void LLAggregatePermissions::packMessage(LLMessageSystem* msg, const char* field) const
1074{
1075	msg->addU8Fast(field, getU8());
1076}
1077
1078void LLAggregatePermissions::unpackMessage(LLMessageSystem* msg, const char* block, const char* field, S32 block_num)
1079{
1080	const U8 TWO_BITS = 0x3; // binary 00000011
1081	U8 bits = 0;
1082	msg->getU8Fast(block, field, bits, block_num);
1083	mBits[PI_COPY] = bits & TWO_BITS;
1084	bits >>= 2;
1085	mBits[PI_MODIFY] = bits & TWO_BITS;
1086	bits >>= 2;
1087	mBits[PI_TRANSFER] = bits & TWO_BITS;
1088}
1089
1090const std::string AGGREGATE_VALUES[4] =
1091	{
1092		std::string( "Empty" ),
1093		std::string( "None" ),
1094		std::string( "Some" ),
1095		std::string( "All" )
1096	};
1097
1098std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm)
1099{
1100	s << "{PI_COPY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_COPY]];
1101	s << ", PI_MODIFY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_MODIFY]];
1102	s << ", PI_TRANSFER=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_TRANSFER]];
1103	s << "}";
1104	return s;
1105}
1106
1107// This converts a permissions mask into a string for debugging use.
1108void mask_to_string(U32 mask, char* str)
1109{
1110	if (mask & PERM_MOVE)
1111	{
1112		*str = 'V';
1113	}
1114	else
1115	{
1116		*str = ' ';
1117	}	
1118	str++;
1119
1120	if (mask & PERM_MODIFY)
1121	{
1122		*str = 'M';
1123	}
1124	else
1125	{
1126		*str = ' ';
1127	}	
1128	str++;
1129	
1130	if (mask & PERM_COPY)
1131	{
1132		*str = 'C';
1133	}
1134	else
1135	{
1136		*str = ' ';
1137	}	
1138	str++;
1139	
1140	if (mask & PERM_TRANSFER)
1141	{
1142		*str = 'T';
1143	}
1144	else
1145	{
1146		*str = ' ';
1147	}	
1148	str++;	
1149	*str = '\0';
1150}
1151
1152std::string mask_to_string(U32 mask)
1153{
1154	char str[16];
1155	mask_to_string(mask, str);
1156	return std::string(str);
1157}
1158
1159///----------------------------------------------------------------------------
1160/// exported functions
1161///----------------------------------------------------------------------------
1162static const std::string PERM_CREATOR_ID_LABEL("creator_id");
1163static const std::string PERM_OWNER_ID_LABEL("owner_id");
1164static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
1165static const std::string PERM_GROUP_ID_LABEL("group_id");
1166static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
1167static const std::string PERM_BASE_MASK_LABEL("base_mask");
1168static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
1169static const std::string PERM_GROUP_MASK_LABEL("group_mask");
1170static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
1171static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
1172
1173LLSD ll_create_sd_from_permissions(const LLPermissions& perm)
1174{
1175	LLSD rv;
1176	rv[PERM_CREATOR_ID_LABEL] = perm.getCreator();
1177	rv[PERM_OWNER_ID_LABEL] = perm.getOwner();
1178	rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner();
1179	rv[PERM_GROUP_ID_LABEL] = perm.getGroup();
1180	rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned();
1181	rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase();
1182	rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner();
1183	rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup();
1184	rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone();
1185	rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner();
1186	return rv;
1187}
1188
1189LLPermissions ll_permissions_from_sd(const LLSD& sd_perm)
1190{
1191	LLPermissions rv;
1192	rv.init(
1193		sd_perm[PERM_CREATOR_ID_LABEL].asUUID(),
1194		sd_perm[PERM_OWNER_ID_LABEL].asUUID(),
1195		sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(),
1196		sd_perm[PERM_GROUP_ID_LABEL].asUUID());
1197
1198	// We do a cast to U32 here since LLSD does not attempt to
1199	// represent unsigned ints.
1200	PermissionMask mask;
1201	mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger());
1202	rv.setMaskBase(mask);
1203	mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger());
1204	rv.setMaskOwner(mask);
1205	mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger());
1206	rv.setMaskEveryone(mask);
1207	mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger());
1208	rv.setMaskGroup(mask);
1209	mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger());
1210	rv.setMaskNext(mask);
1211	rv.fix();
1212	return rv;
1213}