/*
	$Id: CACLObject.cpp,v 1.1 2003/04/20 23:33:11 dasenbro Exp $

	File:		CACLObject.cpp

	Contains:	C++ implementation of generic 

	Version:	Apple Mail Server - Mac OS X :  $Revision: 1.1 $

	Written by:	Michael Dasenbrock

	Copyright:	© 1996-2001 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:

		$Log: CACLObject.cpp,v $
		Revision 1.1  2003/04/20 23:33:11  dasenbro
		Initial check-in.
		
		Revision 1.7  2002/05/09 16:58:54  dasenbro
		Changed all str... calls to CUtils::Str... to be NULL safe.
		
		Revision 1.6  2002/03/21 16:24:19  dasenbro
		Updated version information.
		
		Revision 1.5  2001/06/21 20:50:50  dasenbro
		Updated file header info.
		
		Revision 1.4  2001/06/21 16:27:17  dasenbro
		Removed some dead code.
		

	Projector History:

	  <ASM7>	 3/22/99	MED		Added SetACLData() to set the acl data block.
	  <ASM6>	 3/16/99	MED		Deal with U&G getting a user instead of a group with a group id.
	  <ASM5>	 3/15/99	MED		Handle new shared U&G network errors.
	  <ASM4>	  2/8/99	MED		Added a 'create/dont create' boolean to CAccount::Find().
		 <3>	10/22/98	MED		Added RemoveUserRef() to remove the user from an ACL list.
		 <2>	10/12/98	MED		Added RemoveSpoolRef() to remove just the spool ID.
		 <6>	 10/6/98	MED		Make sure to check the short id and not the account id for each
									user in GetACLInfo.
		 <5>	 9/14/98	MED		Added IsSpoolInList and IsUserInList().
		 <4>	  9/8/98	MED		Added GetACLData() and GetNextObjInfo().
		 <3>	 8/18/98	MED		Removed the "Create" flag from the ACL rights list.
		 <2>	 8/10/98	MED		Added QuoteAnySpaces to quote any user names that include
									spaces.

	To Do:
*/


// App
#include "CACLObject.h"
#include "CAccount.h"
#include "CString.h"
#include "CMailSpool.h"
#include "DSMgr.h"
#include "DSMailUser.h"
#include "DSMailGroup.h"
#include "CUtils.h"

//--------------------------------------------------------------------------------------------------
//	* CACLObject
//
//--------------------------------------------------------------------------------------------------

CACLObject::CACLObject ( void ) : CExpansion()

{
} // CACLObject



//--------------------------------------------------------------------------------------------------
//	* ~CACLObject
//
//--------------------------------------------------------------------------------------------------

CACLObject::~CACLObject ( void )
{
} // ~CACLObject


//--------------------------------------------------------------------------------------------------
//	 Done
//
//--------------------------------------------------------------------------------------------------

void CACLObject::Done ( CACLObject* &inPtr )
{
	CDBBaseObject *aDBObject = (CDBBaseObject *) inPtr;
	aDBObject->Done(aDBObject);
	inPtr = (CACLObject *)aDBObject;

}


//--------------------------------------------------------------------------------------------------
//	* GetACLInfo
//
//--------------------------------------------------------------------------------------------------

OSStatus CACLObject::GetACLInfo ( CString &outData )
{
	OSStatus		status		= kNoErr;
	sInt32			siResult	= kNoErr;
	sInt16			i			= 0;
	uInt32			rights		= 0;
	CAccount	   *acctObj		= NULL;
	DSMailGroup	   *mailGroup	= NULL;
	DSMailUser	   *mailUser	= NULL;
	SACLInfo	   *p			= nil;
	CString			name( 32 );
	char			data[ kMaxDataBlockSize ];

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	Try_
	{
		while ( i < GetMaxItems() )
		{
			if ( (p[ i ].fSpoolID != 0) &&
				 (p[ i ].fUserID  != 0) )
			{
				rights = p[ i ].fRights;
				siResult = gDSMgr->GetUserByID( p[i].fUserID, &mailUser );

				if ( mailUser != NULL )
				{
					acctObj = CAccount::Find( mailUser, CAccount::kDontCreate );
					delete( mailUser );
				}

				if ( acctObj != nil )
				{
					outData.Append( " " );
					name.Set( (char *)acctObj->GetAccountName () );
					QuoteAnySpaces( name );
					outData.Append( name.GetData() );
					outData.Append( " " );

					this->GetRightsString( outData, rights );

					acctObj->Done( acctObj );
				}
				else if ( p[ i ].fUserID == kAnyoneUserID )
				{
					outData.Append( " Anyone " );
					this->GetRightsString( outData, rights );
					status = kNoErr;
				}
				else
				{
					gDSMgr->GetGroupByID(p[i].fUserID, &mailGroup );
					if (mailGroup != NULL)
					{
						outData.Append( " " );
						name.Set( (char *)mailGroup->GetName() );
						QuoteAnySpaces( name );
						outData.Append( name.GetData() );
						outData.Append( " " );

						this->GetRightsString( outData, rights );
						
						delete( mailGroup );
						mailGroup = nil;
					}
					else
					{
						// If we haven't found it by now, it doesn't exist
						//	so delete it
						DeleteACLInfo( p[ i ].fUserID, p[ i ].fSpoolID );
					}
				}
			}
			i++;
		}
	}

	Catch_ ( err )
	{
		acctObj->Done( acctObj );
		if (mailUser != NULL)
		{
			delete( mailUser );
			mailUser = nil;
		}
		if (mailGroup != NULL)
		{
			delete( mailGroup );
			mailGroup = nil;
		}
		status = err;
	}

	return( status );

} // GetACLInfo



//--------------------------------------------------------------------------------------------------
//	* GetACLData
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::GetACLData ( ObjID inUserID, SACLInfo &outData )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (i < GetMaxItems()) )
	{
		if ( p[ i ].fUserID == inUserID )
		{
			outData.fSpoolID = p[ i ].fSpoolID;
			outData.fUserID	 = p[ i ].fUserID;
			outData.fRights	 = p[ i ].fRights;

			done = true;
			result = true;
		}
		i++;
	}

	return( result );

} // GetACLData



//--------------------------------------------------------------------------------------------------
//	* SetExistingACLInfo
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::SetExistingACLInfo ( ObjID inUserID, ObjID inSrcSpoolID, uInt32 inRights )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (i < GetMaxItems()) )
	{
		if ( (p[ i ].fSpoolID == inSrcSpoolID) &&
			 (p[ i ].fUserID  == inUserID) )
		{
			p[ i ].fRights = inRights;
			SetDataBlock( data );
			done = true;
			result = true;
		}
		i++;
	}

	return( result );

} // SetExistingACLInfo



//--------------------------------------------------------------------------------------------------
//	* SetNewACLInfo
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::SetNewACLInfo ( ObjID inUserID, ObjID inSrcSpoolID, uInt32 inRights )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	if ( GetItemCount() < GetMaxItems() )
	{
		while ( !done && (i < GetMaxItems()) )
		{
			if ( (p[ i ].fSpoolID == 0) &&
				 (p[ i ].fUserID  == 0) )
			{
				p[ i ].fSpoolID	= inSrcSpoolID;
				p[ i ].fUserID	= inUserID;
				p[ i ].fRights	= inRights;

				IncItemCount();
				SetDataBlock( data );

				done = true;
				result = true;
			}
			i++;
		}
	}

	return( result );

} // SetNewACLInfo



//--------------------------------------------------------------------------------------------------
//	* DeleteACLInfo
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::DeleteACLInfo ( ObjID inUserID, ObjID inSrcSpoolID )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (i < GetMaxItems()) )
	{
		if ( (p[ i ].fSpoolID == inSrcSpoolID) &&
			 (p[ i ].fUserID  == inUserID) )
		{
			p[ i ].fSpoolID	= 0;
			p[ i ].fUserID	= 0;
			p[ i ].fRights	= 0;

			DecItemCount();

			SetDataBlock( data );

			done = true;
			result = true;
		}
		i++;
	}

	return( result );

} // DeleteACLInfo



//--------------------------------------------------------------------------------------------------
//	* RemoveSpoolRef
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::RemoveSpoolRef ( ObjID inSrcSpoolID )
{
	Boolean		result	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( i < GetMaxItems() )
	{
		if ( p[ i ].fSpoolID == inSrcSpoolID )
		{
			p[ i ].fSpoolID	= 0;
			p[ i ].fUserID	= 0;
			p[ i ].fRights	= 0;

			DecItemCount();

			SetDataBlock( data );

			result = true;
		}
		i++;
	}

	return( result );

} // RemoveSpoolRef



//--------------------------------------------------------------------------------------------------
//	* RemoveUserRef
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::RemoveUserRef ( ObjID inUserID )
{
	Boolean		result	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( i < GetMaxItems() )
	{
		if ( p[ i ].fUserID == inUserID )
		{
			p[ i ].fSpoolID	= 0;
			p[ i ].fUserID	= 0;
			p[ i ].fRights	= 0;

			DecItemCount();

			SetDataBlock( data );

			result = true;
		}
		i++;
	}

	return( result );

} // RemoveUserRef



//--------------------------------------------------------------------------------------------------
//	* GetNextObjInfo
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::GetNextObjInfo ( sInt16 &inIterator, SACLInfo &outObjInfo )
{
	Boolean		result	= false;
	Boolean		done	= false;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (inIterator < GetMaxItems()) )
	{
		if ( (p[ inIterator ].fSpoolID != 0) &&
			 (p[ inIterator ].fUserID != 0) )
		{
			outObjInfo.fSpoolID	= p[ inIterator ].fSpoolID;
			outObjInfo.fUserID	= p[ inIterator ].fUserID;
			outObjInfo.fRights	= p[ inIterator ].fRights;

			done = true;
			result = true;
		}
		 inIterator++;
	}

	return( result );

} // GetNextObjInfo



//--------------------------------------------------------------------------------------------------
//	* DeleteAllSpools
//
//--------------------------------------------------------------------------------------------------

void CACLObject::DeleteAllSpools ( void )
{
	sInt16			i		= 0;
	SACLInfo	   *p		= nil;
	CMailSpool	   *mbSpool	= nil;
	char			data[ kMaxDataBlockSize ];

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( i < GetMaxItems() )
	{
		if ( p[ i ].fSpoolID != 0 )
		{
			mbSpool = CMailSpool::FindByID( p[ i ].fSpoolID );
			if ( mbSpool != nil )
			{
				if ( mbSpool->GetFlags() & CMailSpool::kSharedFlag )
				{
					mbSpool->ResetSpoolCounts();
					CMailSpool::Delete( mbSpool );
				}
				mbSpool->Done( mbSpool );
			}
			p[ i ].fSpoolID	= 0;
			p[ i ].fUserID	= 0;
			p[ i ].fRights	= 0;

			DecItemCount();
		}
		i++;
	}

	SetDataBlock( data );

} // DeleteAllSpools



//--------------------------------------------------------------------------------------------------
//	* IsObjectInList
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::IsSpoolInList ( ObjID inSpoolID, SACLInfo *outACLData )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (i < GetMaxItems()) )
	{
		if ( p[ i ].fSpoolID == inSpoolID )
		{
			if ( outACLData != nil )
			{
				outACLData->fSpoolID = p[ i ].fSpoolID;
				outACLData->fUserID	 = p[ i ].fUserID;
				outACLData->fRights	 = p[ i ].fRights;
			}
			done	= true;
			result	= true;
		}
		i++;
	}

	return( result );

} // IsObjectInList



//--------------------------------------------------------------------------------------------------
//	* IsUserInList
//
//--------------------------------------------------------------------------------------------------

Boolean CACLObject::IsUserInList ( ObjID inUserID, SACLInfo *outACLData )
{
	Boolean		result	= false;
	Boolean		done	= false;
	sInt16		i		= 0;
	char		data[ kMaxDataBlockSize ];
	SACLInfo	*p	= nil;

	GetDataBlock( data );
	p = (SACLInfo *)&data;

	while ( !done && (i < GetMaxItems()) )
	{
		if ( p[ i ].fUserID == inUserID )
		{
			if ( outACLData != nil )
			{
				outACLData->fSpoolID = p[ i ].fSpoolID;
				outACLData->fUserID	 = p[ i ].fUserID;
				outACLData->fRights	 = p[ i ].fRights;
			}
			done	= true;
			result	= true;
		}
		i++;
	}

	return( result );

} // IsUserInList



//--------------------------------------------------------------------------------------------------
//	* GetRightsString
//
//--------------------------------------------------------------------------------------------------

void CACLObject::GetRightsString ( CString &outData, uInt32 inRights )
{
	Boolean		haveOne	= false;

	// Look up
	if ( inRights & CMailSpool::kACLLookup )
	{
		outData.Append( "l" );
		haveOne = true;
	}

	// Read
	if ( inRights & CMailSpool::kACLRead )
	{
		outData.Append( "r" );
		haveOne = true;
	}

	// Keep seen
	if ( inRights & CMailSpool::kACLKeepSeen )
	{
		outData.Append( "s" );
		haveOne = true;
	}

	// Write
	if ( inRights & CMailSpool::kACLWrite )
	{
		outData.Append( "w" );
		haveOne = true;
	}

	// Insert
	if ( inRights & CMailSpool::kACLInsert )
	{
		outData.Append( "i" );
		haveOne = true;
	}

	// Post
	if ( inRights & CMailSpool::kACLPost )
	{
		outData.Append( "p" );
		haveOne = true;
	}

	// Create
//	if ( inRights & CMailSpool::kACLCreate )
//	{
//		outData.Append( "c" );
//	}

	// Delete
	if ( inRights & CMailSpool::kACLDelete )
	{
		outData.Append( "d" );
		haveOne = true;
	}

	// Admin
	if ( inRights & CMailSpool::kACLAdmin )
	{
		outData.Append( "a" );
		haveOne = true;
	}

	if ( haveOne == false )
	{
		outData.Append( "\"\"" );
	}

} // GetRightsString



//--------------------------------------------------------------------------------------------------
//	* QuoteAnySpaces
//
//--------------------------------------------------------------------------------------------------

void CACLObject::QuoteAnySpaces ( CString &inData )
{
	if ( CUtils::Strstr( inData.GetData(), " " ) != nil )
	{
		inData.Prepend( "\"" );
		inData.Append( "\"" );
	}
} // QuoteAnySpaces



//--------------------------------------------------------------------------------------------------
//	* SetACLData
//
//--------------------------------------------------------------------------------------------------

void CACLObject::SetACLData ( char *inData )
{
	SetDataBlock( inData );
} // SetACLData





