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

	File:		DSPrefs.cpp

	Contains:	implementation of DSPrefs object

	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: DSPrefs.cpp,v $
		Revision 1.1  2003/04/20 23:34:11  dasenbro
		Initial check-in.
		
		Revision 1.5  2002/06/04 18:00:33  dasenbro
		Fixed a memory leak in GetAttributeValues().
		
		Revision 1.4  2002/05/09 16:58:56  dasenbro
		Changed all str... calls to CUtils::Str... to be NULL safe.
		
		Revision 1.3  2002/04/18 18:09:10  dasenbro
		Changed bool to Bool for word alignment.
		
		Revision 1.2  2002/03/21 16:38:52  dasenbro
		Addes network transition support.
		
		Revision 1.1  2002/03/11 23:07:14  dasenbro
		Initial check-in.
		

	To Do:
*/

#include <stdlib.h>

#include "DSPrefs.h"
#include "DSMgr.h"
#include "CUtils.h"

#define		kUserStructUserIDValue			kDSNativeAttrTypePrefix"user_id"
#define		kUserStructUserTypeValue		kDSNativeAttrTypePrefix"user_type"
#define		kUserStructUserNameValue		kDSNativeAttrTypePrefix"user_name"
#define		kUserStructRealNameValue		kDSNativeAttrTypePrefix"real_name"
#define		kUserStructRecordPathValue		kDSNativeAttrTypePrefix"record_path"
#define		kUserStructReservedValue		kDSNativeAttrTypePrefix"reserved"


// --------------------------------------------------------------------------------
//	* DSPrefs ()
//
// --------------------------------------------------------------------------------

DSPrefs::DSPrefs ( void )
{
} // DSPrefs


// --------------------------------------------------------------------------------
//	* ~DSPrefs ()
//
// --------------------------------------------------------------------------------

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


// --------------------------------------------------------------------------------
//	* SetDirRef ()
//
// --------------------------------------------------------------------------------

void DSPrefs::SetDirRef ( const tDirReference inDirRef )
{
	fDirRef = inDirRef;
} // SetDirRef


// --------------------------------------------------------------------------------
//	* SetDirNodeRef ()
//
// --------------------------------------------------------------------------------

void DSPrefs::SetDirNodeRef ( const tDirNodeReference inNodeRef )
{
	fNodeRef = inNodeRef;
} // SetDirNodeRef


// --------------------------------------------------------------------------------
//	* SetDirRecordRef ()
//
// --------------------------------------------------------------------------------

void DSPrefs::SetDirRecordRef ( const tRecordReference inRecordRef )
{
	fRecordRef = inRecordRef;
} // SetDirRecordRef


// --------------------------------------------------------------------------------
//	* AreWeSetup ()
//
// --------------------------------------------------------------------------------

Bool DSPrefs::AreWeSetup ( void )
{
	Bool	bResult	= false;

	if ( (fDirRef != 0) && (fNodeRef != 0) && (fRecordRef != 0) )
	{
		if ( fNodeBuff == nil )
		{
			fNodeBuff = ::dsDataBufferAllocate( fDirRef, 1024 );
		}

		if ( fNodeBuff != nil )
		{
			bResult = true;
		}
	}

	return( bResult );

} // AreWeSetup


// --------------------------------------------------------------------------------
//	* DeInitialize ()
//
// --------------------------------------------------------------------------------

void DSPrefs::DeInitialize ( void )
{
	if ( fRecordRef != 0 )
	{
		(void)::dsCloseRecord( fRecordRef );
		fRecordRef = 0;
	}

	fDirRef		= 0;
	fNodeRef	= 0;

} // DeInitialize


// --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---
//
//	- Private Methods -
//
// --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---  --- ---


// --------------------------------------------------------------------------------
//	* GetAttributeValue ()
//
//		- unsigned long
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::GetAttributeValue ( const char *inAttrType, uInt32 *outValue, tRecordReference inRecRef )
{
	tDirStatus		dsStatus		= eDSNoErr;
	CString			csStr( 32 );

	dsStatus = this->GetAttributeValue( inAttrType, csStr, inRecRef );
	if ( dsStatus == eDSNoErr )
	{
		*outValue = ::strtoul( csStr.GetData(), nil, 0 );
	}

	return( dsStatus );

} // GetAttributeValue


// --------------------------------------------------------------------------------
//	* SetAttributeValue ()
//
//		- unsigned long
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::SetAttributeValue ( const char *inAttrType, uInt32 inValue, tRecordReference inRecRef )
{
	tDirStatus		dsStatus		= eDSNoErr;
	CString			csStr( 32 );

	csStr.Sprintf( "%u", inValue );

	dsStatus = this->SetAttributeValue( inAttrType, csStr.GetData(), inRecRef );

	return( dsStatus );

} // SetAttributeValue


// --------------------------------------------------------------------------------
//	* GetAttributeValue ()
//
//		- string
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::GetAttributeValue ( const char *inAttrType, CString &outStr, tRecordReference inRecRef )
{
	tDirStatus				dsStatus		= eDSNoErr;
	tDataNode			   *pAttrType		= nil;
	tAttributeValueEntry   *pAttrValueEntry	= nil;
	tRecordReference		dsRecRef		= fRecordRef;

	outStr.Clear();

	if ( inRecRef != 0 )
	{
		dsRecRef = inRecRef;
	}

	if ( (AreWeSetup() == true) && (inAttrType != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			dsStatus = ::dsGetRecordAttributeValueByIndex( dsRecRef, pAttrType, 1, &pAttrValueEntry );
			if ( dsStatus == eDSNoErr )
			{
				outStr.Set( pAttrValueEntry->fAttributeValueData.fBufferData, pAttrValueEntry->fAttributeValueData.fBufferLength );
	
				(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );
				pAttrValueEntry = nil;
			}
	
			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
			pAttrType = nil;
		}
		else
		{
			dsStatus = eDSAllocationFailed;
		}
	}
	else
	{
		dsStatus = (tDirStatus) -88;
	}

	return( dsStatus );

} // GetAttributeValue


// --------------------------------------------------------------------------------
//	* SetAttributeValue ()
//
//		- string
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::SetAttributeValue ( const char *inAttrType, const char *inAttrValue, tRecordReference inRecRef )
{
	tDirStatus				dsStatus		= eDSNoErr;
	uInt32					valueID			= 0;
	tDataNode			   *pAttrType		= nil;
	tDataNode			   *pAttrName		= nil;
	tDataNode			   *pAttrValue		= nil;
	tAccessControlEntry		aclEntry;
	tAttributeValueEntry   *pAttrValueEntry	= nil;
	tRecordReference		dsRecRef		= fRecordRef;

	if ( inRecRef != 0 )
	{
		dsRecRef = inRecRef;
	}

	if ( (AreWeSetup() == true) && (inAttrType != nil) && (inAttrValue != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			dsStatus = ::dsGetRecordAttributeValueByIndex( dsRecRef, pAttrType, 1, &pAttrValueEntry );
			if ( dsStatus == eDSAttributeNotFound )
			{
				pAttrName = ::dsDataNodeAllocateString( fDirRef, inAttrType );
				if ( pAttrName != nil )
				{
					pAttrValue = ::dsDataNodeAllocateString( fDirRef, inAttrValue );
					if ( pAttrValue != nil )
					{
						::memset( &aclEntry, 0, sizeof( tAccessControlEntry ) );
			
						dsStatus = ::dsAddAttribute( dsRecRef, pAttrName, &aclEntry, pAttrValue );
			
						(void)::dsDataNodeDeAllocate( fDirRef, pAttrValue );
					}
			
					(void)::dsDataNodeDeAllocate( fDirRef, pAttrName );
				}
			}
			else if ( (dsStatus == eDSNoErr) || (dsStatus == eDSIndexOutOfRange) )
			{
				// Get the value ID
				valueID = pAttrValueEntry->fAttributeValueID;
				(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );

				pAttrValueEntry = ::dsAllocAttributeValueEntry( fDirRef, valueID, (void *)inAttrValue, CUtils::Strlen( inAttrValue ) );
				if ( pAttrValueEntry != nil )
				{
					dsStatus = ::dsSetAttributeValue( dsRecRef, pAttrType, pAttrValueEntry );
	
					(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );
				}
				else
				{
					dsStatus = eDSAllocationFailed;
				}
			}

			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
		}
		else
		{
			dsStatus = eDSAllocationFailed;
		}
	}
	else
	{
		dsStatus = (tDirStatus) -88;
	}

	return( dsStatus );

} // SetAttributeValue


// --------------------------------------------------------------------------------
//	* GetAttributeValues ()
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::GetAttributeValues ( const char *inAttrType, StrListObj **outStrList )
{
	tDirStatus				dsStatus		= eDSNoErr;
	tDataNode			   *pAttrType		= nil;
	tAttributeValueEntry   *pAttrValueEntry	= nil;
	tAttributeEntry		   *pAttrInfo		= nil;
	uInt32					i				= 0;
	uInt32					uiAttrValCount	= 0;
	StrListObj			   *pStrObj			= nil;

	if ( (AreWeSetup() == true) && (inAttrType != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			dsStatus = ::dsGetRecordAttributeInfo( fRecordRef, pAttrType, &pAttrInfo );
			if ( dsStatus == eDSNoErr )
			{
				uiAttrValCount = pAttrInfo->fAttributeValueCount;

				for ( i = 1; i <= uiAttrValCount; i++ )
				{
					dsStatus = ::dsGetRecordAttributeValueByIndex( fRecordRef, pAttrType, i, &pAttrValueEntry );
					if ( dsStatus == eDSNoErr )
					{
						CString::AppendString( outStrList, pAttrValueEntry->fAttributeValueData.fBufferData, pAttrValueEntry->fAttributeValueData.fBufferLength );

						(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );
						pAttrValueEntry = nil;
					}
				}
				if ( pAttrInfo != nil )
				{
					free( pAttrInfo );
					pAttrInfo = nil;
				}
			}

			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
			pAttrType = nil;
		}
		else
		{
			dsStatus = eDSAllocationFailed;
		}
	}
	else
	{
		dsStatus = (tDirStatus) -88;
	}

	return( dsStatus );

} // GetAttributeValues


// --------------------------------------------------------------------------------
//	* AddAttributeValue ()
//
//		- string
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::AddAttributeValue ( const char *inAttrType, const char *inAttrValue )
{
	tDirStatus				dsStatus		= eDSNoErr;
	uInt32					valueID			= 0;
	tDataNode			   *pAttrType		= nil;
	tDataNode			   *pAttrName		= nil;
	tDataNode			   *pAttrValue		= nil;
	tAccessControlEntry		aclEntry;
	tAttributeValueEntry   *pAttrValueEntry	= nil;

	if ( (AreWeSetup() == true) && (inAttrType != nil) && (inAttrValue != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			dsStatus = ::dsGetRecordAttributeValueByIndex( fRecordRef, pAttrType, 1, &pAttrValueEntry );
			if ( dsStatus == eDSAttributeNotFound )
			{
				pAttrName = ::dsDataNodeAllocateString( fDirRef, inAttrType );
				if ( pAttrName != nil )
				{
					pAttrValue = ::dsDataNodeAllocateString( fDirRef, inAttrValue );
					if ( pAttrValue != nil )
					{
						::memset( &aclEntry, 0, sizeof( tAccessControlEntry ) );
			
						dsStatus = ::dsAddAttribute( fRecordRef, pAttrName, &aclEntry, pAttrValue );
			
						(void)::dsDataNodeDeAllocate( fDirRef, pAttrValue );
					}
			
					(void)::dsDataNodeDeAllocate( fDirRef, pAttrName );
				}
			}
			else if ( (dsStatus == eDSNoErr) || (dsStatus == eDSIndexOutOfRange) )
			{
				(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );

				pAttrValue = ::dsDataNodeAllocateString( fDirRef, inAttrValue );
				if ( pAttrValue != nil )
				{
					dsStatus = ::dsAddAttributeValue( fRecordRef, pAttrType, pAttrValue );
	
					(void)::dsDataNodeDeAllocate( fDirRef, pAttrValue );
				}
				else
				{
					dsStatus = eDSAllocationFailed;
				}
			}

			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
		}
		else
		{
			dsStatus = eDSAllocationFailed;
		}
	}
	else
	{
		dsStatus = (tDirStatus) -88;
	}

	return( dsStatus );

} // AddAttributeValue


// --------------------------------------------------------------------------------
//	* RemoveAttributeValue ()
//
//		- string
//
// --------------------------------------------------------------------------------

tDirStatus DSPrefs::RemoveAttributeValue ( const char *inAttrType, const char *inAttrValue )
{
	tDirStatus				dsStatus		= eDSNoErr;
	tDataNode			   *pAttrType		= nil;
	tAttributeValueEntry   *pAttrValueEntry	= nil;
	tAttributeEntry		   *pAttrInfo		= nil;
	uInt32					i				= 0;
	uInt32					uiAttrValCount	= 0;
	uInt32					uiValueID		= 0;
	StrListObj			   *pStrObj			= nil;
	CString					csAttrValue;

	if ( (AreWeSetup() == true) && (inAttrType != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			dsStatus = ::dsGetRecordAttributeInfo( fRecordRef, pAttrType, &pAttrInfo );
			if ( dsStatus == eDSNoErr )
			{
				uiAttrValCount = pAttrInfo->fAttributeValueCount;

				for ( i = 1; i <= uiAttrValCount; i++ )
				{
					dsStatus = ::dsGetRecordAttributeValueByIndex( fRecordRef, pAttrType, i, &pAttrValueEntry );
					if ( dsStatus == eDSNoErr )
					{
						uiValueID = pAttrValueEntry->fAttributeValueID;

						csAttrValue.Set( pAttrValueEntry->fAttributeValueData.fBufferData,
										 pAttrValueEntry->fAttributeValueData.fBufferLength );

						if ( CUtils::Strcmp( inAttrValue, csAttrValue ) == 0 )
						{
							dsStatus = ::dsRemoveAttributeValue( fRecordRef, pAttrType, uiValueID );

							i = uiAttrValCount + 1;
						}

						(void)::dsDeallocAttributeValueEntry( fDirRef, pAttrValueEntry );
						pAttrValueEntry = nil;
					}
				}
			}

			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
			pAttrType = nil;
		}
		else
		{
			dsStatus = eDSAllocationFailed;
		}
	}
	else
	{
		dsStatus = (tDirStatus) -88;
	}

	return( dsStatus );

} // RemoveAttributeValue


//--------------------------------------------------------------------------------------------------
//	* ResetAttribute ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::ResetAttribute ( const char *inAttrType )
{
	tDirStatus				dsStatus		= eDSNoErr;
	tDataNode			   *pAttrType		= nil;

	if ( (AreWeSetup() == true) && (inAttrType != nil) )
	{
		pAttrType = ::dsDataNodeAllocateString( fNodeRef, inAttrType );
		if ( pAttrType != nil )
		{
			(void)::dsRemoveAttribute( fRecordRef, pAttrType );

			dsStatus = SetAttributeValue( inAttrType, "" );

			(void)::dsDataNodeDeAllocate( fNodeRef, pAttrType );
			pAttrType = nil;
		}
	}

	return( dsStatus );

} // ResetAttribute


//--------------------------------------------------------------------------------------------------
//	* GetBoolMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::GetBoolMember ( Bool &inMember, const char *inType,
										  Bool *outFlag,  Bool inForceRead )
{
	tDirStatus		dsStatus		= eDSNoErr;
	uInt32			uiValue			= 0;

	if ( inForceRead == true )
	{
		dsStatus = this->GetAttributeValue( inType, &uiValue );
		if ( dsStatus == eDSNoErr )
		{
			if ( uiValue == 0 )
			{
				inMember = false;
			}
			else
			{
				inMember = true;
			}
		}
	}

	*outFlag = inMember;
	
	return ( dsStatus );

} // GetBoolMember


//--------------------------------------------------------------------------------------------------
//	* SetBoolMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::SetBoolMember ( Bool &inMember, const char *inType,
										  Bool inFlag,	  Bool inForceWrite )
{
	tDirStatus		dsStatus		= eDSNoErr;
	uInt32			uiValue			= 0;		// default is false

	if ( (inMember != inFlag) || (inForceWrite == true) )
	{
		if ( inFlag != false )
		{
			uiValue = 1;
		}

		dsStatus = this->SetAttributeValue( inType, uiValue );
		if ( dsStatus == eDSNoErr )
		{
			// Normalize to 1 or 0
			if ( inFlag == false )
			{
				inMember = 0;
			}
			else
			{
				inMember = 1;
			}
		}
	}

	return ( dsStatus );

} // SetBoolMember


//--------------------------------------------------------------------------------------------------
//	* GetValueMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::GetValueMember ( uInt32 &inMember, const char *inType,
										   uInt32 *outValue, Bool inForceRead )
{
	tDirStatus		dsStatus		= eDSNoErr;
	uInt32			uiValue			= 0;

	if ( inForceRead == true )
	{
		dsStatus = this->GetAttributeValue( inType, &uiValue );
		if ( dsStatus == eDSNoErr )
		{
			inMember = uiValue;
		}
	}

	*outValue = inMember;
	
	return ( dsStatus );

} // GetValueMember


//--------------------------------------------------------------------------------------------------
//	* SetValueMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::SetValueMember ( uInt32 &inMember, const char *inType,
										   uInt32 inValue,   Bool inForceWrite )
{
	tDirStatus		dsStatus		= eDSNoErr;

	if ( (inMember != inValue) || (inForceWrite == true) )
	{
		dsStatus = this->SetAttributeValue( inType, inValue );
		if ( dsStatus == eDSNoErr )
		{
			inMember = inValue;
		}
	}

	return ( dsStatus );

} // SetValueMember


//--------------------------------------------------------------------------------------------------
//	* GetEmailAddrMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::GetEmailAddrMember ( char* &inMember, const char *inType,
											   CString &outStr, Bool inForceRead )
{
	tDirStatus		dsStatus	= eDSNoErr;
	const char	   *pTmpStr		= nil;

	if ( inForceRead == true )
	{
		if ( inMember != nil )
		{
			free( inMember );
			inMember = nil;
		}
	}

	if ( inMember != nil )
	{
		outStr.Set( inMember );
	}
	else
	{
		dsStatus = this->GetAttributeValue( inType, outStr );
		if ( dsStatus == eDSAttributeNotFound )
		{
//			pTmpStr = CNetworkUtilities::GetOurDNSName( kPrimaryIPAddr );
			if ( pTmpStr != nil )
			{
				outStr.Clear();
				outStr.Sprintf( "postmaster@%s", pTmpStr );

				dsStatus = this->SetAttributeValue( inType, outStr.GetData() );
			}
		}

		inMember = (char *)::malloc( outStr.GetLength() + 2 );
		CUtils::Strcpy( inMember, outStr.GetData() );
	}

	return( dsStatus );

} // GetEmailAddrMember


//--------------------------------------------------------------------------------------------------
//	* SetEmailAddrMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::SetEmailAddrMember ( char* &inMember,   const char *inType,
											   const char *inStr, Bool inForceWrite )
{
	tDirStatus		dsStatus	= eDSNoErr;
	uInt32			uiStrLen	= 0;

	if ( inStr != nil )
	{
		if ( inMember != nil )
		{
			if ( (CUtils::Stricmp( inStr, inMember ) != 0) || (inForceWrite == true) )
			{
				free( inMember );
				inMember = nil;

				dsStatus = this->SetAttributeValue( inType, inStr );

				inMember = (char *)::malloc( CUtils::Strlen( inStr ) + 2 );
				CUtils::Strcpy( inMember, inStr );
			}
		}
		else
		{
			dsStatus = this->SetAttributeValue( inType, inStr );

			inMember = (char *)::malloc( CUtils::Strlen( inStr ) + 2 );
			CUtils::Strcpy( inMember, inStr );
		}
	}

	return( dsStatus );

} // SetEmailAddrMember


//--------------------------------------------------------------------------------------------------
//	* GetStringMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::GetStringMember ( char* &inMember, const char *inType,
											CString &outStr, Bool inForceRead )
{
	tDirStatus			dsStatus	= eDSNoErr;
	const char		   *pTmpStr		= nil;

	if ( (inForceRead == true) && (inMember != nil) )
	{
		free( inMember );
		inMember = nil;
	}

	if ( inMember != nil )
	{
		outStr.Set( inMember );
	}
	else
	{
		dsStatus = this->GetAttributeValue( inType, outStr );
		if ( dsStatus == eDSNoErr )
		{
			inMember = (char *)::malloc( outStr.GetLength() + 2 );
			CUtils::Strcpy( inMember, outStr.GetData() );
		}
	}

	return( dsStatus );

} // GetStringMember


//--------------------------------------------------------------------------------------------------
//	* SetStringMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::SetStringMember ( char* &inMember,   const char *inType,
											const char *inStr, Bool inForceWrite )
{
	tDirStatus			dsStatus	= eDSNoErr;

	if ( inStr != nil )
	{
		if ( inMember != nil )
		{
			if ( (CUtils::Stricmp( inStr, inMember ) != 0) || (inForceWrite == true) )
			{
				free( inMember );
				inMember = nil;

				dsStatus = this->SetAttributeValue( inType, inStr );

				inMember = (char *)::malloc( CUtils::Strlen( inStr ) + 2 );
				CUtils::Strcpy( inMember, inStr );
			}
		}
		else
		{
			dsStatus = this->SetAttributeValue( inType, inStr );

			inMember = (char *)::malloc( CUtils::Strlen( inStr ) + 2 );
			CUtils::Strcpy( inMember, inStr );
		}
	}

	return( dsStatus );

} // SetStringMember


//--------------------------------------------------------------------------------------------------
//	* GetUserStructMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::GetUserStructMember ( UserStruct* &inMember, const char *inRecName,
												UserStruct *outUser,   Bool inForceRead )
{
	tDirStatus			dsStatus	= eDSNoErr;
	Bool				bRead		= inForceRead;
	uInt32				uiValue		= 0;
	tDataNodePtr		pRecName	= nil;
	tDataNodePtr		pRecType	= nil;
	tRecordReference	recRef		= 0;
	CString				csStr( 64 );

	if ( inMember == nil )
	{
		inMember = (UserStruct *)::calloc( sizeof( UserStruct ), sizeof( char )  );
		bRead = true;
	}

	if ( (inMember == nil) || (outUser == nil) )
	{
		return( eDSAuthParameterError );
	}

	if ( bRead == true )
	{
		pRecName = ::dsDataNodeAllocateString( fNodeRef, inRecName );
		pRecType = ::dsDataNodeAllocateString( fNodeRef, "dsRecTypeNative:config/AppleMailServer/" );

		dsStatus = ::dsOpenRecord( fNodeRef, pRecType, pRecName, &recRef );
		if ( dsStatus == eDSNoErr )
		{
			::memset( inMember, 0, sizeof( UserStruct ) );

			// Get user ID
			dsStatus = this->GetAttributeValue( kUserStructUserIDValue, &uiValue, recRef );
			if ( dsStatus == eDSNoErr )
			{
				inMember->fID = uiValue;
			}

			// Get user type
			dsStatus = this->GetAttributeValue( kUserStructUserTypeValue, &uiValue, recRef );
			if ( dsStatus == eDSNoErr )
			{
				inMember->fType = (eUGType)uiValue;
			}

			// Get user short name
			dsStatus = this->GetAttributeValue( kUserStructUserNameValue, csStr, recRef );
			if ( dsStatus == eDSNoErr )
			{
				::strncpy( &inMember->fUserName[ 1 ], csStr.GetData(), csStr.GetLength() );
				inMember->fUserName[ 0 ] = csStr.GetLength();
			}

			// Get user real name
			dsStatus = this->GetAttributeValue( kUserStructRealNameValue, csStr, recRef );
			if ( dsStatus == eDSNoErr )
			{
				::strncpy( &inMember->fRealName[ 1 ], csStr.GetData(), csStr.GetLength() );
				inMember->fRealName[ 0 ] = csStr.GetLength();
			}

			// Get record path
			dsStatus = this->GetAttributeValue( kUserStructRecordPathValue, csStr, recRef );
			if ( dsStatus == eDSNoErr )
			{
				::strncpy( &inMember->fPath[ 1 ], csStr.GetData(), csStr.GetLength() );
				inMember->fPath[ 0 ] = csStr.GetLength();
			}

			// Get reserved field
			dsStatus = this->GetAttributeValue( kUserStructReservedValue, &uiValue, recRef );
			if ( dsStatus == eDSNoErr )
			{
				inMember->fReserved = (eUGType)uiValue;
			}
		}
		else if ( dsStatus == eDSRecordNotFound )
		{
			dsStatus = eDSAttributeNotFound;
		}
	}

	// Copy the data into the 
	::memcpy( outUser, inMember, sizeof( UserStruct ) );

	if ( recRef != 0 )
	{
		(void)dsCloseRecord( recRef );
		recRef = 0;
	}

	if ( pRecName != nil )
	{
		(void)::dsDataNodeDeAllocate( fNodeRef, pRecName );
		pRecName = nil;
	}

	if ( pRecType != nil )
	{
		(void)::dsDataNodeDeAllocate( fNodeRef, pRecType );
		pRecType = nil;
	}

	return( dsStatus );

} // GetUserStructMember


//--------------------------------------------------------------------------------------------------
//	* SetUserStructMember ()
//
//--------------------------------------------------------------------------------------------------

tDirStatus DSPrefs::SetUserStructMember ( UserStruct* &inMember,    const char *inRecName,
												const UserStruct *inUser, Bool inForceWrite )
{
	tDirStatus			dsStatus	= eDSNoErr;
	tDataNodePtr		pRecName	= nil;
	tDataNodePtr		pRecType	= nil;
	tRecordReference	recRef		= 0;
	CString				csStr( 64 );

	if ( inMember == nil )
	{
		inMember = (UserStruct *)::calloc( sizeof( UserStruct ), sizeof( char )  );
	}

	if ( (inUser == nil) || (inMember == nil) )
	{
		return( eDSAuthParameterError );
	}

	// Copy the data to the local member
	::memcpy( inMember, inUser, sizeof( UserStruct ) );

	if ( inForceWrite == true )
	{
		pRecName = ::dsDataNodeAllocateString( fNodeRef, inRecName );
		pRecType = ::dsDataNodeAllocateString( fNodeRef, "dsRecTypeNative:config/AppleMailServer/" );
		dsStatus = ::dsOpenRecord( fNodeRef, pRecType, pRecName, &recRef );
		if ( dsStatus != eDSNoErr )
		{
			dsStatus = ::dsCreateRecordAndOpen( fNodeRef, pRecType, pRecName, &recRef );
		}

		if ( dsStatus == eDSNoErr )
		{
			(void)this->SetAttributeValue( kUserStructUserIDValue, inUser->fID, recRef );
			(void)this->SetAttributeValue( kUserStructUserTypeValue, inUser->fType, recRef );

			csStr.Set( &inUser->fUserName[ 1 ], inUser->fUserName[ 0 ] );
			(void)this->SetAttributeValue( kUserStructUserNameValue, csStr.GetData(), recRef );

			csStr.Set( &inUser->fRealName[ 1 ], inUser->fRealName[ 0 ] );
			(void)this->SetAttributeValue( kUserStructRealNameValue, csStr.GetData(), recRef );

			csStr.Set( &inUser->fPath[ 1 ], inUser->fPath[ 0 ] );
			(void)this->SetAttributeValue( kUserStructRecordPathValue, csStr.GetData(), recRef );

			(void)this->SetAttributeValue( kUserStructReservedValue, inUser->fReserved, recRef );
		}

		if ( recRef != 0 )
		{
			(void)dsCloseRecord( recRef );
			recRef = 0;
		}
	
		if ( pRecName != nil )
		{
			(void)::dsDataNodeDeAllocate( fNodeRef, pRecName );
			pRecName = nil;
		}
	
		if ( pRecType != nil )
		{
			(void)::dsDataNodeDeAllocate( fNodeRef, pRecType );
			pRecType = nil;
		}
	}

	return( dsStatus );

} // SetUserStructMember

