/*
	File:		CRootObject.10.1.cpp

	Copyright:	© 2006 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:
*/


#include <string.h>

#include "Database.10.1.h"
#include "CRootObject.10.1.h"
#include "CMailSpool.10.1.h"
#include "CGlobals.h"


//--------------------------------------------------------------------------------------------------
//	* Globals
//
//--------------------------------------------------------------------------------------------------

CRootObject_10_1 *gRootObj_10_1 = NULL;


//--------------------------------------------------------------------------------------------------
//	* GetSetFields ()
//
//--------------------------------------------------------------------------------------------------

Boolean	CRootObject_10_1::GetSetFields	(const eFieldDataRequest_10_1 inFieldRequest, const void *inObjDataPtr, void *outFieldData)
{
	Boolean					result = false;
	CRootObjectData_10_1	*theData = (CRootObjectData_10_1 *) inObjDataPtr;
	CRootObject_10_1		*aTempObject	= NULL;
	ObjID					*anObjIDPtr = (ObjID *) outFieldData;

	switch (inFieldRequest)
	{
		case kSetObjID_10_1:
			theData->fRootObjID = *anObjIDPtr;
			break;

		case kObjectPINGRequest_10_1:
			// cause the objects constructor to get called, so we force a check of
			// the struct alignment...
			aTempObject = new CRootObject_10_1;
			delete aTempObject;
			break;

		case k2ndIDTargetChk_10_1:
			// fall through...

		default:
			result = false;
			break;
	}

	return result;
} // GetSetFields


//--------------------------------------------------------------------------------------------------
//	* GetObjectID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetObjectID	( void )
{
	return( fRootObjectData.fRootObjID );
} // GetObjectID


//--------------------------------------------------------------------------------------------------
//	* SetObjectID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetObjectID ( ObjID inObjID )
{
	if ( fRootObjectData.fRootObjID != inObjID )
	{
		fRootObjectData.fRootObjID = inObjID;
		this->SetDirty();
	}
} // SetObjectID


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

void CRootObject_10_1::Done ( CRootObject_10_1* &inPtr )
{
	CDBBaseObject_10_1 *aDBObject = (CDBBaseObject_10_1 *) inPtr;
	aDBObject->Done(aDBObject);

	inPtr = (CRootObject_10_1 *)aDBObject;

}

//--------------------------------------------------------------------------------------------------
//	* CRootObject_10_1 ()
//
//--------------------------------------------------------------------------------------------------

CRootObject_10_1::CRootObject_10_1 ( void ) :
	CDBMailBaseObject_10_1(	&fRootObjectData.fDBHeader,
				&fRootObjectData.fDBFooter,
				&fRootObjectData,
				CRootObject_10_1::GetObjTypeConstant(),
				CRootObject_10_1::GetObjVersConstant(),
				CRootObject_10_1::GetObjSizeConstant() )
{
	fRootObjectData.fRootObjID				= 0;
	fRootObjectData.fInSpoolID				= 0;
	fRootObjectData.fEnvDieSpoolID			= 0;
	fRootObjectData.fStatMgrID				= 0;
	fRootObjectData.fHostDefltPrefsID		= 0;
	fRootObjectData.fActiveHost2ndID		= 0;
	fRootObjectData.fAnyoneACLObjID			= 0;
	fRootObjectData.fRejectSMTPHostID		= 0;
	fRootObjectData.fIndexRefNum			= 0;
	fRootObjectData.fTextObjectID			= 0;
	fRootObjectData.fVerInfo.fVersionInfoID = 0;

	// Reserved
	fRootObjectData.fReserved1				= kReservedConst;
	fRootObjectData.fReserved2				= kReservedConst;

	this->ChkCompilerStructAlignment();
} // CRootObject_10_1



//--------------------------------------------------------------------------------------------------
//	* ~CRootObject_10_1 ()
//
//--------------------------------------------------------------------------------------------------

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


void	CRootObject_10_1::ChkCompilerStructAlignment	( void )
{
	/*
		this dump was aquired by using the MPW command DumpSYM - TTE from the .xsym file produced
		from a Code Warrior Pro 1 Release Build of the AppleShare IP Mail Server for MacOS version 6.2

		this version of the structure is consider the "reference" standard for all future ASIP Mail Servers.
		If the structure does NOT match these offsets the version of the Mail Server that 
		you are compiling will _NOT_ be compatible with AppleShare IP 6.0, 6.1, or 6.2 (this also effects
		the AppleShare IP Mail Tool, and to a more limited extent the AppleShare IP Mail Admin since some
		of these structures are passed across the wire..)

		If _ANY_ of these Asserts "fire" you've got a backwards compatibility problem that _MUST_ be fixed!!

		this code wasn't put here for my personal amusement, this code was put here from a hard earned lesson
		that simple changes to headers/compilers _WILL_ break this stuff, better to know now than after we
		ship.  Look upon this code as a debugging AIDE, not an impediment.

		Type Name:  CRootObjectData		TINFO offset: 25680		(TINFO SYM file offset (hex): $11E450)
			RecordOf 
			offset 0 NamedTypeOf fDBHeader TypeDef of "Type ID 248"
			offset 12 NamedTypeOf fRootObjID 
			offset 16 NamedTypeOf fAnyoneACLObjID unsigned long 
			offset 20 NamedTypeOf fActiveHost2ndID 
			offset 24 NamedTypeOf fInSpoolID unsigned long 
			offset 28 NamedTypeOf fEnvDieSpoolID 
			offset 32 NamedTypeOf fStatMgrID unsigned long 
			offset 36 NamedTypeOf fHostDefltPrefsID 
			offset 40 NamedTypeOf fIndexRefNum unsigned long 
			offset 44 NamedTypeOf fVerInfo 
			offset 48 NamedTypeOf fDBFooter TypeDef of "Type ID 250"
	*/
	static Boolean	aRunOnceFlag = false;
	if (aRunOnceFlag == false)
	{
		//FileFormatSaftyChk(CRootObjectData, fDBHeader,			0);
		//FileFormatSaftyChk(CRootObjectData, fRootObjID,			12);		// this is us (denormalized)
		//FileFormatSaftyChk(CRootObjectData, fAnyoneACLObjID,			16);
		//FileFormatSaftyChk(CRootObjectData, fActiveHost2ndID,	20);	// Holds the ObjID of the Active Host 2nd ID list..
		//FileFormatSaftyChk(CRootObjectData, fInSpoolID,			24);
		//FileFormatSaftyChk(CRootObjectData, fEnvDieSpoolID,		28);
		//FileFormatSaftyChk(CRootObjectData, fStatMgrID,			32);
		//FileFormatSaftyChk(CRootObjectData, fHostDefltPrefsID,	36);
		//FileFormatSaftyChk(CRootObjectData, fIndexRefNum,		40);
		//FileFormatSaftyChk(CRootObjectData, fVerInfo,			44);
		//FileFormatSaftyChk(CRootObjectData, fDBFooter,			48);
//		this->ReportBackwardCompatibility(sizeof(CRootObjectData),	52,	"CRootObjectData", "SIZEOF()");
//		this->ReportBackwardCompatibility(kCRootObjectDataSize,	52,	"CRootObjectData", "kCRootObjectDataSize");
	}

	aRunOnceFlag = true;
}

#pragma mark -

//--------------------------------------------------------------------------------------------------
//	* ObjectAllocNew ()
//
//--------------------------------------------------------------------------------------------------

CDBBaseObject_10_1 * CRootObject_10_1::ObjectAllocNew	( void )
{
	return new CRootObject_10_1;
} // ObjectAllocNew



//--------------------------------------------------------------------------------------------------
//	* FindByID ()
//
//--------------------------------------------------------------------------------------------------

CRootObject_10_1* CRootObject_10_1::FindByID ( const ObjID inObjectID )
{
	return (CRootObject_10_1 *) CDBMailBaseObject_10_1::MailUniversalFindByID(	inObjectID,
														CRootObject_10_1::GetObjTypeConstant(),
														CRootObject_10_1::GetObjVersConstant(),
														CRootObject_10_1::GetObjSizeConstant(),
														CRootObject_10_1::ObjectAllocNew		);
} // FindByID


//--------------------------------------------------------------------------------------------------
//	* Find ()
//
//--------------------------------------------------------------------------------------------------

CRootObject_10_1* CRootObject_10_1::Find ( void )
{
	OSStatus		result;
	ObjID			rootObjID		= 0;
	uInt32			rootObjCount	= 0;
	CRootObject_10_1	   *rootObj			= NULL;
	SDBIterator_10_1		aIterator( gDB_10_1 );

	try
	{
		if ( gRootObj_10_1 == NULL )
		{
			result = gDB_10_1->GetObjectCount( kMailRootSignature_10_1, rootObjCount );
			if ( result == kNoErr )
			{
				if ( rootObjCount == 0 )
				{
					// Need to create it
					rootObj = CRootObject_10_1::Create();
					ThrowIfNULL_( rootObj );
					gRootObj_10_1 = rootObj;
				}
				else if ( rootObjCount != 1 )
				{
					result = gDB_10_1->CreateIterator( kMailRootSignature_10_1, &aIterator );
					while ( gDB_10_1->NextObject( &aIterator, rootObjID ) == kNoErr )
					{
						rootObj = CRootObject_10_1::FindByID( rootObjID );
						if ( rootObj != nil )
						{
							CRootObject_10_1::Delete( rootObj );
							rootObj->Done( rootObj );
							rootObj = nil;
						}
					}
					gDB_10_1->ReleaseIterator( &aIterator );

					// Need to create it
					rootObj = CRootObject_10_1::Create();
					ThrowIfNULL_( rootObj );
					gRootObj_10_1 = rootObj;
				}
				else
				{
					// Lets find it
					rootObj = new CRootObject_10_1;
					ThrowIfNULL_(rootObj);

					result = gDB_10_1->CreateIterator( kMailRootSignature_10_1, &aIterator );
					if ( result == kNoErr )
					{
						if ( gDB_10_1->GetCurObject( &aIterator, rootObjID, rootObj->GetRootObjectData() ) == kNoErr )
						{
							rootObj->Use();
						}
						else
						{
							delete( rootObj );
							rootObj = NULL;
						}
					}
					gDB_10_1->ReleaseIterator( &aIterator );

					gRootObj_10_1 = rootObj;
				}
			}
		}
		else
		{
			rootObj = gRootObj_10_1;
		}
	}

	catch ( ExceptionCode err )
	{
		return( NULL );
	}

	return ( rootObj );

} // Find


//--------------------------------------------------------------------------------------------------
//	* Create ()
//
//--------------------------------------------------------------------------------------------------

CRootObject_10_1* CRootObject_10_1::Create ( void )
{
	OSStatus			result		= kNoErr;
	ObjID				newRootID	= 0;
	CRootObject_10_1   *newRootObj	= nil;
	CMailSpool_10_1	   *pInSpool	= nil;

	try
	{
		newRootObj = new CRootObject_10_1;
		ThrowIfMemFail_( newRootObj );

		(gDB_10_1->GetBaseObjectCachePtr())->LockTheCache( CRootObject_10_1::GetObjTypeConstant() );

		pInSpool = CMailSpool_10_1::Create( CMailSpool_10_1::kIncomingSpool, "Incoming", CMailSpool_10_1::kRootParent );
		ThrowIfNULL_( pInSpool );

		newRootObj->SetSysSpoolID( CMailSpool_10_1::kIncomingSpool, pInSpool->GetMailSpoolID() );

		pInSpool->Done( pInSpool );

		//------------------------------------------------------------------------------
		// Just consume a Database ObjectID to avoid duplicate ID's in the future...
		// this ID is used to "build" the 2nd ID list, that keeps track of dead
		// CEnvelope objects, due to CDatabase's implemenation it is important that this
		// ID _NOT_ be duplicated ever again...so we create an object, save off it's ID
		// and then delete that object to avoid confusing any other code...

		newRootObj->SetEnvelopeDieSpoolID( pInSpool->GetObjectID() );
		pInSpool->Done( pInSpool );

		newRootObj->GetActiveHost2ndID( true );	// force the root obj's 2nd ID to be created...

		result = gDB_10_1->CreateObj( kMailRootSignature_10_1, newRootID, newRootObj->GetRootObjectData() );
		if ( result == CMailDatabase_10_1::kDBNoErr )
		{
			newRootObj->Use();
			newRootObj->SetDirty();
		}
		else
		{
			delete( newRootObj );
			newRootObj = nil;
		}

		(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache( CRootObject_10_1::GetObjTypeConstant() );
	}

	catch ( ExceptionCode err )
	{
		if ( pInSpool != nil )
		{
			pInSpool->Done( pInSpool );
		}
	}

	return( newRootObj );
} // Create


//--------------------------------------------------------------------------------------------------
//	* Delete
//
//--------------------------------------------------------------------------------------------------

Boolean CRootObject_10_1::Delete ( CRootObject_10_1 *inObjPtr )
{
	Boolean deleted = false;
	OSErr	result;

	try
	{
		if ( inObjPtr != nil )
		{
			result = gDB_10_1->RemoveObj( kMailRootSignature_10_1, inObjPtr->GetObjectID() );
			deleted = ( result == kNoErr );
			if ( deleted )
			{
				inObjPtr->SetObjectID( 0 );
			}
		}
	}
	catch ( ExceptionCode err )
	{
	}

	return( deleted );

} // Delete


//--------------------------------------------------------------------------------------------------
//	* GetRootObjectData ()
//
//--------------------------------------------------------------------------------------------------

CRootObjectData_10_1* CRootObject_10_1::GetRootObjectData ( void )
{
	if (this != NULL)
	{
		return &(this->fRootObjectData);
	}
	else
	{
		return NULL;
	}
} // GetRootObjectData



//--------------------------------------------------------------------------------------------------
//	* SetDirty ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetDirty	( void )
{
	if ((this != NULL) && (this->GetRootObjID() != 0))
	{
		setDirty();
	}
} // SetDirty



//--------------------------------------------------------------------------------------------------
//	* GetRootObjID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetRootObjID ( void )
{
	return( fRootObjectData.fRootObjID );
} // GetRootObjID



//--------------------------------------------------------------------------------------------------
//	* GetSysSpoolID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetSysSpoolID ( const OSType inSpoolType )
{
	ObjID	result = 0;
	switch ( inSpoolType )
	{
		case CMailSpool_10_1::kIncomingSpool:
			result = fRootObjectData.fInSpoolID;
			break;

		default:
			break;
	}

	return( result );
} // GetSysSpoolID


//--------------------------------------------------------------------------------------------------
//	* SetSysSpoolID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetSysSpoolID ( const OSType inSpoolType, ObjID inSysSpoolID )
{
	switch ( inSpoolType )
	{
		case CMailSpool_10_1::kIncomingSpool:
			fRootObjectData.fInSpoolID = inSysSpoolID;
			break;

		default:
			break;
	}
	this->SetDirty();
} // SetSysSpoolID



//--------------------------------------------------------------------------------------------------
//	* GetStatMgrID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetStatMgrID ( void )
{
	return( fRootObjectData.fStatMgrID );

} // SetStatMgrID



//--------------------------------------------------------------------------------------------------
//	* GetStatMgrID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetStatMgrID ( ObjID inStatMgrID )
{
	if ( inStatMgrID != fRootObjectData.fStatMgrID )
	{
		fRootObjectData.fStatMgrID = inStatMgrID;
		this->SetDirty();
	}
} // SetStatMgrID



//--------------------------------------------------------------------------------------------------
//	* GetStatMgrID ()
//
//--------------------------------------------------------------------------------------------------

SVersionInfo_10_1* CRootObject_10_1::GetVerInfoID ( void )
{
	return( &fRootObjectData.fVerInfo );

}



//--------------------------------------------------------------------------------------------------
//	* GetStatMgrID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetVerInfoID ( SVersionInfo_10_1 *inVerInfoStruct )
{
	if ( ::memcmp( &fRootObjectData.fVerInfo, inVerInfoStruct, sizeof( SVersionInfo_10_1 ) != 0 ) )
	{
		::memcpy(  &fRootObjectData.fVerInfo, inVerInfoStruct, sizeof( SVersionInfo_10_1 ) );
		this->SetDirty();
	}
} // GetStatMgrID



//--------------------------------------------------------------------------------------------------
//	* GetHostDefltPrefsID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetHostDefltPrefsID ( void )
{
	return ( fRootObjectData.fHostDefltPrefsID );
} // GetHostDefltPrefsID



//--------------------------------------------------------------------------------------------------
//	* SetHostDefltPrefsID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetHostDefltPrefsID ( ObjID inHostDefltPrefsID )
{
	if ( inHostDefltPrefsID != fRootObjectData.fHostDefltPrefsID )
	{
		fRootObjectData.fHostDefltPrefsID = inHostDefltPrefsID;
		this->SetDirty();
	}
} // SetHostDefltPrefsID



//--------------------------------------------------------------------------------------------------
//	* GetEnvelopeDieSpoolID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetEnvelopeDieSpoolID ( void )
{
	return ( fRootObjectData.fEnvDieSpoolID );
} // GetEnvelopeDieSpoolID



//--------------------------------------------------------------------------------------------------
//	* SetEnvelopeDieSpoolID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetEnvelopeDieSpoolID ( const ObjID inDieSpoolID )
{
	if ( inDieSpoolID != fRootObjectData.fEnvDieSpoolID )
	{
		fRootObjectData.fEnvDieSpoolID = inDieSpoolID;
		this->SetDirty();
	}
} // SetEnvelopeDieSpoolID



//--------------------------------------------------------------------------------------------------
//	* GetIndexRefNum ()
//
//--------------------------------------------------------------------------------------------------

uInt32 CRootObject_10_1::GetIndexRefNum ( void )
{
	return ( fRootObjectData.fIndexRefNum );
} // GetIndexRefNum



//--------------------------------------------------------------------------------------------------
//	* SetIndexRefNum ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetIndexRefNum ( uInt32 inRefNum )
{
	if ( inRefNum != fRootObjectData.fIndexRefNum )
	{
		fRootObjectData.fIndexRefNum = inRefNum;
		this->SetDirty();
	}
} // SetIndexRefNum


//--------------------------------------------------------------------------------------------------
//	* GetVersionInfo ()
//
//--------------------------------------------------------------------------------------------------

uInt32 CRootObject_10_1::GetVersionInfo ( void )
{
	return ( fRootObjectData.fVerInfo.fVersionInfoID );
} // GetVersionInfo



//--------------------------------------------------------------------------------------------------
//	* SetVersionInfo ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetVersionInfo ( uInt32 inVersInfo )
{
	if ( fRootObjectData.fVerInfo.fVersionInfoID != inVersInfo )
	{
		fRootObjectData.fVerInfo.fVersionInfoID = inVersInfo;
		this->SetDirty();
	}
} // SetVersionInfo


//--------------------------------------------------------------------------------------------------
//	* GetAnyoneObjID ()
//
//--------------------------------------------------------------------------------------------------

uInt32 CRootObject_10_1::GetAnyoneObjID ( void )
{
	return ( fRootObjectData.fAnyoneACLObjID );
} // GetAnyoneObjID



//--------------------------------------------------------------------------------------------------
//	* SetAnyoneObjID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetAnyoneObjID ( uInt32 inValue )
{
	if ( inValue != fRootObjectData.fAnyoneACLObjID )
	{
		fRootObjectData.fAnyoneACLObjID = inValue;
		this->SetDirty();
	}
} // SetAnyoneObjID



//--------------------------------------------------------------------------------------------------
//	* GetActiveHost2ndID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetActiveHost2ndID ( const Boolean inCreateFlag )
{

	if ( inCreateFlag == true )
	{
		if ( (fRootObjectData.fActiveHost2ndID == 0) || (fRootObjectData.fActiveHost2ndID == 0xf0f0f0f0) )
		{
			CMailSpool_10_1 *anInSpool	= nil;

			//------------------------------------------------------------------------------
			// Just consume a Database ObjectID to avoid duplicate ID's in the future...
			// this ID is used to "build" the 2nd ID list, that keeps track of active host entries..
			// due to CDatabase's implemenation it is important that this
			// ID _NOT_ be duplicated ever again...so we create an object, save off it's ID
			// and then delete that object to avoid confusing any other code...

			anInSpool = CMailSpool_10_1::Create( CMailSpool_10_1::kIncomingSpool, "Active Host Entries", CMailSpool_10_1::kRootParent );
			ThrowIfNULL_(anInSpool);

			this->SetActiveHost2ndID( anInSpool->GetObjectID() );
//			CMailSpool_10_1::Delete(anInSpool);
			anInSpool->Done( anInSpool );
		}
	}

	return ( fRootObjectData.fActiveHost2ndID );
} // GetActiveHost2ndID



//--------------------------------------------------------------------------------------------------
//	* SetActiveHost2ndID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetActiveHost2ndID ( const ObjID inActiveHost2ndID )
{
	if ( inActiveHost2ndID != fRootObjectData.fActiveHost2ndID )
	{
		fRootObjectData.fActiveHost2ndID = inActiveHost2ndID;
		this->SetDirty();
	}
} // SetActiveHost2ndID


//--------------------------------------------------------------------------------------------------
//	* GetSMTPRejectHostID ()
//
//--------------------------------------------------------------------------------------------------

ObjID CRootObject_10_1::GetSMTPRejectHostID ( void )
{
	return ( fRootObjectData.fRejectSMTPHostID );

} // GetSMTPRejectHostID



//--------------------------------------------------------------------------------------------------
//	* SetSMTPRejectHostID ()
//
//--------------------------------------------------------------------------------------------------

void CRootObject_10_1::SetSMTPRejectHostID ( const ObjID inHostID )
{
	if ( inHostID != fRootObjectData.fRejectSMTPHostID )
	{
		fRootObjectData.fRejectSMTPHostID = inHostID;
		this->SetDirty();
	}
} // SetSMTPRejectHostID

// ------------------------------------------------------------------
//	* GetCurrTextObjID
// ------------------------------------------------------------------

ObjID CRootObject_10_1::GetCurrTextObjID ( void )
{
	return( fRootObjectData.fTextObjectID );
} // GetCurrTextObjID


// ------------------------------------------------------------------
//	* SetCurrTextObjID
// ------------------------------------------------------------------

void CRootObject_10_1::SetCurrTextObjID ( ObjID inTextObjID )
{
	if ( fRootObjectData.fTextObjectID != inTextObjID )
	{
		fRootObjectData.fTextObjectID = inTextObjID;
		this->SetDirty();
	}
} // SetCurrTextObjID




