/*
	$Id: CEnvelope.cpp,v 1.2 2003/08/11 20:48:42 dasenbro Exp $

	File:		CEnvelope.cpp

	Contains:	C++ implemenation of the message envelope container class

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

	Written by:	Nick Brosnahan

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

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:

		$Log: CEnvelope.cpp,v $
		Revision 1.2  2003/08/11 20:48:42  dasenbro
		Cyrus expects stores mail in raw network format so none of the <CR><LF>'s
		are stripped.  The export tool was stripping the <LF> causing problems.
		
		Revision 1.1  2003/04/20 23:45:34  dasenbro
		Initial check-in.
		
		Revision 1.16  2002/07/16 01:16:33  dasenbro
		Added better handling of missing data files.
		
		Revision 1.15  2002/07/08 04:56:34  dasenbro
		Added a cache lock for CMessageTOC objects to prevent deadlock.
		
		Revision 1.14  2002/06/13 00:57:01  dasenbro
		Added time to SetCreationTime() to preserver the received time on a DB repair.
		
		Revision 1.13  2002/06/04 17:57:58  dasenbro
		Added UnLockTheCache() to the catch().
		
		Revision 1.12  2002/05/09 16:58:58  dasenbro
		Changed all str... calls to CUtils::Str... to be NULL safe.
		
		Revision 1.11  2002/04/18 18:09:12  dasenbro
		Changed bool to Bool for word alignment.
		
		Revision 1.10  2002/04/16 06:03:38  dasenbro
		Remove unnecessary MailAsserts.
		
		Revision 1.9  2002/03/21 16:41:23  dasenbro
		Updated file version information.
		
		Revision 1.8  2002/03/05 19:49:21  dasenbro
		Added second GetData() which allowes a length parameter.
		
		Revision 1.7  2002/02/20 21:00:52  dasenbro
		Added Get/Set-MsgPartID() for DB migration.
		
		Revision 1.6  2002/01/14 17:27:40  dasenbro
		Initial S4 updates.
		
		Revision 1.5  2001/06/21 17:48:33  dasenbro
		Added Change History.
		

	Projector History:

	 <ASM13>	  4/1/99	MED		b8: Set fCacheFullMessageSize to 0 in AddMessagePart().
	 <ASM12>	 3/28/99	MED		Grab the index semaphore inside the gIndexing object.
	 <ASM11>	 3/15/99	MED		Removed CSmartYield.
	 <ASM10>	 1/29/99	DOR		Try again to check in.
	 <ASM10>	 1/29/99	DOR		Add code to remove reference to prevent us from decrementing the
									reference count below zero..
	  <ASM9>	 1/25/99	MED		Removed an assert that fires during a scavange.
	  <ASM8>	 1/11/99	DOR		Make it so that delete tears down an envelope in the proper
									order.
	  <ASM7>	12/10/98	DOR		Make sure DeleteAllRecipient leaves no trace of the recipient
									list.
		 <6>	11/12/98	DOR		Add some code around the critical values to grab a Mutex before
									+/- on the reference counts, this is to prevent Race conditions
									with MacOS X.
		 <5>	10/21/98	DOR		Fix message prefix.
		 <4>	10/21/98	DOR		Fix it so that we properly calculate the message size...
		 <3>	10/20/98	DOR		Build the message-prefix string on the fly in order to save data
									space...
		 <2>	10/13/98	DOR		Lock the cache when deleting an object.
		<31>	 9/21/98	DOR		Change all uses of "Assert_" to "MailAssert"..
		<30>	 9/21/98	DOR		Don't Use NULL Pointers.
		<29>	 7/23/98	MED		Commented out an unnecessary assert.
		<28>	  6/1/98	DOR		Fix "GetSetFields".
		<27>	  6/1/98	DOR		Remove the "kAdd" argument from Create since we no longer use
									it.
		<26>	  6/1/98	MED		Changed ::Create to be a more kinder and gentler ::Create.
		<25>	 5/19/98	MED		Added future expansion data members.
		<24>	  5/7/98	MED		Don't clear out the v-twin reference number if removing it from
									the index fails.
		<23>	 4/14/98	MED		Added getters and setters for a TOC envelope string to be stored
									in the message prefix data space and added some offset and
									lenght database fields for the TOC envelope string.
		<22>	  4/2/98	DOR		Change call to gDB->removeObject
		<21>	  4/2/98	DOR		Use the proper 2nd ID for dead CEnvelopes.
		<20>	 3/25/98	MED		Added code in ::Delete to remove the data from the V-Twin index
									before removing the envelope from the DB.
		<19>	03/23/98	DOR		Get rid of DeleteAllEnvelopes, and change some code around in
									Delete to close a race condition.
		<18>	03/23/98	DOR		Change GetTOCSemaphore to use the CDBObject Get/Release
									ObjectLock.
		<17>	03/18/98	DOR		Check that the SendID is non-zero before deleting it.
		<16>	 3/14/98	DOR		Close up a race condition in ::Create..
		<14>	 3/11/98	MED		Changed FindByID() to do a Use() only if it created the object,
									FindMe() now does an explicit Use().
		<13>	 3/10/98	DOR		CMailSpool::Remove changed, make adjustments in how we call it..
		<12>	 2/26/98	DOR		We now support "defered" message deletions.
		<11>	 2/23/98	MED		Changed the VTwinReference to a long.
		<10>	 2/19/98	DOR		Use actual semaphores rather than
		 <9>	 2/18/98	MED		Added semaphors for IMAP TOC and Index creation on an as needed
									basis.
		 <8>	 2/13/98	DOR		Add code to set the CMessagePart "isattached" flag, that way we
									can know to clean up/delete the message part from CSMTPServer if
									we encounter an error during message reception.
		 <7>	  2/4/98	DOR		Merge small message part changes from a branch.
		 <6>	  2/3/98	MED		Cleaned OSUtil.cp into CUtils.cp, COSUtils.cp and
									CSmartYield.cp.
		 <5>	 1/15/98	MED		Added a server IP address so we can keep track of which IP
									address this message came in over for 822 header routing.
		 <4>	12/17/97	MED		Added some flags to the envelope and the getters and setters.
		 <3>	12/15/97	DOR		Update the object version to "include" the size of the
									dataportion of the object, and add an assert to "FindByID" that
									checks the version of the object.
		 <2>	11/21/97	DOR		Add field to keep track of warning's.

	To Do:
*/


// System
#include <stdlib.h>

// App
#include "CEnvelope.h"
#include "CStatMgr.h"
#include "CMailSpool.h"
#include "CUtils.h"
#include "Database.h"
#include "time.h"
#include "CRootObject.h"
#include "COSUtils.h"
#include "CGlobals.h"
#include "AppResources.h"

extern CRootObject *gRootObj;
extern  CString		gSrcDir;

Boolean	CEnvelope::GetSetFields	(const eFieldDataRequest inFieldRequest, const void *inObjDataPtr, void *outFieldData)
{
	Boolean	result = false;
	CEnvelopeData	*theData = (CEnvelopeData *) inObjDataPtr;
	CEnvelope		*aTempObject	= NULL;
	ObjID			*anObjIDPtr = (ObjID *) outFieldData;

	switch (inFieldRequest)
	{
		case kSetObjID:
			if (theData != NULL)
			{
				theData->fEnvelopeID = *anObjIDPtr;
			}
			break;
		
		case k2ndIDRequest:
			if (theData != NULL)
			{
				if (theData->fViaCode == CEnvelope::kViaDoorNail)
				{
					if (gRootObj != NULL)
					{
						if (gRootObj->GetEnvelopeDieSpoolID() != 0)
						{
							*anObjIDPtr = gRootObj->GetEnvelopeDieSpoolID();
							result = true;
						}
					}
				}
			}
			break;
					
		case kObjectPINGRequest:
			// cause the objects constructor to get called, so we force a check of
			// the struct alignment...
			aTempObject = new CEnvelope;
			delete aTempObject;
			break;

		case k2ndIDTargetChk:
			// fall through...
			
		default:
			result = false;
			break;
	}
	
	return result;
}


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

ObjID CEnvelope::GetObjectID ( void )
{
	return fEnvelopeData.fEnvelopeID;
} // GetObjectID


//--------------------------------------------------------------------------------------------------
//	* Done ()
//
//--------------------------------------------------------------------------------------------------

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

	inPtr = (CEnvelope *)aDBObject;
} // Done


CDBBaseObject * CEnvelope::ObjectAllocNew	( void )
{
	return new CEnvelope;
}

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


void	CEnvelope::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:  CEnvelopeData		TINFO offset: 53490		(TINFO SYM file offset (hex): $1250F2)
			RecordOf
			offset 0 NamedTypeOf fDBHeader TypeDef of "Type ID 248"
			offset 12 NamedTypeOf fEnvelopeID 
			offset 16 NamedTypeOf fSenderID unsigned long 
			offset 20 NamedTypeOf fMsgTocID 
			offset 24 NamedTypeOf fVTwinReference unsigned long 
			offset 28 NamedTypeOf fRecipListHeadID 
			offset 32 NamedTypeOf fMsgPartListHeadID unsigned long 
			offset 36 NamedTypeOf fSmallMsgPartID 
			offset 40 NamedTypeOf fReserved1 unsigned long 
			offset 44 NamedTypeOf fReserved2 
			offset 48 NamedTypeOf fViaCode unsigned long 
			offset 52 NamedTypeOf fSendingHost 
			offset 308 NamedTypeOf fMessageSize unsigned long 
			offset 312 NamedTypeOf fCreationTime 
			offset 316 NamedTypeOf fWarningSentTime unsigned long 
			offset 320 NamedTypeOf fAttemptTime 
			offset 324 NamedTypeOf fTransports unsigned short 
			offset 326 NamedTypeOf fTOCEnvelopeStrOffset 
			offset 328 NamedTypeOf fTOCEnvelopeStrLength unsigned short 
			offset 330 NamedTypeOf fFilePathLen 
			offset 332 NamedTypeOf fFilePath TypeDef of "Type ID 288"
			offset 1356 NamedTypeOf fServerIPAddr 
			offset 1360 NamedTypeOf fFlags unsigned long 
			offset 1364 NamedTypeOf fSpoolRefCount 
			offset 1366 NamedTypeOf fHostRefCount unsigned short 
			offset 1368 NamedTypeOf fOriginalRecipientCount 
			offset 1370 NamedTypeOf fTotalRecipientCount unsigned short 
			offset 1372 NamedTypeOf fPendingRecipientCount 
			offset 1374 NamedTypeOf fDeliveredRecipients unsigned short 
			offset 1376 NamedTypeOf fErrorRecipientCount 
			offset 1378 NamedTypeOf fGroupRecipientCount unsigned short 
			offset 1380 NamedTypeOf fAutoForwardRecipientCount 
			offset 1382 NamedTypeOf fLocalRecipientCount unsigned short 
			offset 1384 NamedTypeOf fRemoteRecipientCount 
			offset 1386 NamedTypeOf fRemotePostingDone unsigned short 
			offset 1388 NamedTypeOf fMessagePartCount 
			offset 1392 NamedTypeOf fDBFooter TypeDef of "Type ID 250"
	*/

	static Boolean	aRunOnceFlag = false;	
	if (aRunOnceFlag == false)
	{
		//FileFormatSaftyChk(CEnvelopeData, fDBHeader,					0);
		//FileFormatSaftyChk(CEnvelopeData, fEnvelopeID,					12);
		//FileFormatSaftyChk(CEnvelopeData, fSenderID,					16);					// this is our sender recipient object
		//FileFormatSaftyChk(CEnvelopeData, fMsgTocID,					20);					// message table of contents ID
		//FileFormatSaftyChk(CEnvelopeData, fVTwinReference,				24);
		//FileFormatSaftyChk(CEnvelopeData, fRecipListHeadID,				28);			// 
		//FileFormatSaftyChk(CEnvelopeData, fMsgPartListHeadID,			32);			// 
		//FileFormatSaftyChk(CEnvelopeData, fSmallMsgPartID,				36);
		//FileFormatSaftyChk(CEnvelopeData, fReserved1,						40);
		//FileFormatSaftyChk(CEnvelopeData, fReserved2,						44);
		//FileFormatSaftyChk(CEnvelopeData, fViaCode,						48);							// how did we get it
		//FileFormatSaftyChk(CEnvelopeData, fSendingHost[0],				52);	// the sending host name
		//FileFormatSaftyChk(CEnvelopeData, fMessageSize,					308);						// size in bytes of message (cached)
		//FileFormatSaftyChk(CEnvelopeData, fCreationTime,				312);						// time created
		//FileFormatSaftyChk(CEnvelopeData, fWarningSentTime,				316);					// time the Warning was sent...
		//FileFormatSaftyChk(CEnvelopeData, fAttemptTime,					320);						// last attempt at delivery
		//FileFormatSaftyChk(CEnvelopeData, fTransports,					324);						// AppleTalk, TCP/IP, or Bounce
		//FileFormatSaftyChk(CEnvelopeData, fTOCEnvelopeStrOffset,		326);				// Offset for TOC Envelope string
		//FileFormatSaftyChk(CEnvelopeData, fTOCEnvelopeStrLength,		328);				// Lenght of TOC Envelope string
		//FileFormatSaftyChk(CEnvelopeData, fFilePathLen,			330);				// Length of prepended headers
		//FileFormatSaftyChk(CEnvelopeData, fFilePath[0],			332);// prepended headers + TOC Envelope string	
		//FileFormatSaftyChk(CEnvelopeData, fServerIPAddr,				1356);						// server IP Address (used for multihoming)
		//FileFormatSaftyChk(CEnvelopeData, fFlags,						1360);								// envelope flags
		//FileFormatSaftyChk(CEnvelopeData, fSpoolRefCount,				1364);				// Number of CEnvelopeInfo objects referring to me
		//FileFormatSaftyChk(CEnvelopeData, fHostRefCount,				1366);				// Number of Host Spool objects referring to me
		//FileFormatSaftyChk(CEnvelopeData, fOriginalRecipientCount,		1368);	// # Before routing expansions
		//FileFormatSaftyChk(CEnvelopeData, fTotalRecipientCount,			1370);		// # Currently
		//FileFormatSaftyChk(CEnvelopeData, fPendingRecipientCount,		1372);		// # Pending Routing
		//FileFormatSaftyChk(CEnvelopeData, fDeliveredRecipients,			1374);		// # Delivered To Successfully
		//FileFormatSaftyChk(CEnvelopeData, fErrorRecipientCount,			1376);		// # Routing or delivery unsuccessful
		//FileFormatSaftyChk(CEnvelopeData, fGroupRecipientCount,			1378);		// # of groups
		//FileFormatSaftyChk(CEnvelopeData, fAutoForwardRecipientCount,	1380);	// # of autoforwards
		//FileFormatSaftyChk(CEnvelopeData, fLocalRecipientCount,			1382);		// # of local recipients
		//FileFormatSaftyChk(CEnvelopeData, fRemoteRecipientCount,		1384);		// # of remote recipients
		//FileFormatSaftyChk(CEnvelopeData, fRemotePostingDone,			1386);			// true when the router is done posting the message to _ALL_ hosts
		//FileFormatSaftyChk(CEnvelopeData, fMessagePartCount,			1388);
		//FileFormatSaftyChk(CEnvelopeData, fDBFooter,					1392);
//		this->ReportBackwardCompatibility(sizeof(CEnvelopeData), 1396, "CEnvelopeData", "SIZEOF()");
//		this->ReportBackwardCompatibility(kEnvelopeDataSize,	 1396, "CEnvelopeData", "kEnvelopeDataSize");
	}
	
	aRunOnceFlag = true;
}



CEnvelope* CEnvelope::Create ( uInt32 inViaCode, const char* inSendingHost )
{
	OSStatus		result;
	ObjID			aNewID;
	CEnvelope	   *theEnvelope = NULL;

	try
	{
		theEnvelope = new CEnvelope;
		ThrowIfMemFail_ (theEnvelope);

		(gDB->GetBaseObjectCachePtr())->LockTheCache(CEnvelope::GetObjTypeConstant());
		
		result = gDB->CreateObj( kEnvelopeSignature, aNewID, theEnvelope->GetEnvelopeData() );

		if ( result == CMailDatabase::kDBNoErr )
		{
			theEnvelope->Use();
			theEnvelope->SetViaCode(inViaCode);
			theEnvelope->SetSendingHost (inSendingHost);
			theEnvelope->SetCreationTime();
			theEnvelope->SetDirty();
		}
		else
		{
			delete( theEnvelope );
			theEnvelope = NULL;
		}
		
		// denormalize ID into CEnvelope object

		if (theEnvelope != NULL)
		{
			const char* theViaCode = NULL;

			switch ( inViaCode )
			{
				case kViaSMTP:
					theViaCode = "SMTP";
					break;
				case kViaATalk:
					theViaCode = "ATalk";
					break;
				case kViaUUCP:
					theViaCode = "UUCP";
					break;
				case kViaNDR:
					theViaCode = "NDR";
					break;
				case kViaIMAP:
					theViaCode = "IMAP";
					break;
				case kViaUnknown:
				default:
					theViaCode = "Unknown";
					break;
			}

			// Display in the Log
			if (gStatMgr != NULL)
			{
				gStatMgr->AddMessage();		// Maintain statistics
			}
		}

		(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelope::GetObjTypeConstant());
	}

	catch ( ... )
	{
		(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelope::GetObjTypeConstant());
	}
	
	return (theEnvelope);

} // Create


void CEnvelope::SetDirty ( void )
{
	if ((this != NULL) && (this->GetEnvelopeID() != 0))
	{
		setDirty();
	}
}

CEnvelopeData* CEnvelope::GetEnvelopeData	( void )
{
	if ( this != NULL )
	{
		return &( this->fEnvelopeData );
	}
	else
	{
		return( NULL );
	}
} // GetEnvelopeData


Boolean CEnvelope::Delete ( CEnvelope *inEnvelope )
{
	OSStatus	result;
	Boolean		deleted = false;

	try
	{
		if (inEnvelope != NULL)
		{
			(gDB->GetBaseObjectCachePtr())->LockTheCache(CEnvelope::GetObjTypeConstant());

			ObjID theEnvelopeID = inEnvelope->GetEnvelopeID();

#if TARGET_OS_MAC && TARGET_API_MAC_OS8
			// Remove this message from the VTwin index
			if ( gIndexing != nil )
			{
				// Has this message been added to the crrent index
				if ( inEnvelope->GetVTwinReference() == gIndexing->GetIndexRefNum() )
				{
					// We now owne it
					inEnvelope->SetVTwinReference( 0 );
					gIndexing->CleanIndex( inEnvelope );
				}
			}
#endif
			inEnvelope->DeleteSender();
			inEnvelope->DeleteAllRecipients();
			inEnvelope->DeleteDataFile();
			inEnvelope->DeleteMessageTOC();
			
			result = gDB->RemoveObj( kEnvelopeSignature, inEnvelope->GetEnvelopeID() );
			deleted = (result == kNoErr);

			if ( deleted == true )
			{
				inEnvelope->fEnvelopeData.fEnvelopeID = 0;
			}

			if ( gStatMgr != NULL )
			{
				gStatMgr->RemoveMessage();		// Maintain statistics
			}

			(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelope::GetObjTypeConstant());
		}
	}

	catch ( ... )
	{
		(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelope::GetObjTypeConstant());
	}

	return( deleted );

} // Delete

void CEnvelope::DeleteMessageTOC ( void )
{
}


uInt32 CEnvelope::Count ( void )
{
	uInt32	aCount = 0;
	OSErr	result;

	result = gDB->GetObjectCount( kEnvelopeSignature, aCount );

	if (result != kNoErr)
	{
		aCount = 0;
	}
	
	return aCount;
} // Count



SDBIterator* CEnvelope::GetEnvelopeIterator ( void )
{
	OSErr			result;
	SDBIterator	   *aSDBIterator = new SDBIterator(gDB);

	if ( aSDBIterator != NULL )
	{
		result = gDB->CreateIterator( kEnvelopeInfoSignature, aSDBIterator );
		if ( result != kNoErr )
		{
			delete aSDBIterator;
			aSDBIterator = NULL;
		}
	}
	
	return aSDBIterator;
} // GetEnvelopeIterator


void CEnvelope::ReleaseEnvelopeIterator ( SDBIterator* &inIterator )
{
	OSErr			result;

	if (inIterator != NULL)
	{
		result = gDB->ReleaseIterator( inIterator );

		delete inIterator;
		inIterator = NULL;
	}
} // ReleaseEnvelopeIterator


#pragma mark -

CEnvelope::CEnvelope ( void ) :
	CDBMailBaseObject(	&fEnvelopeData.fDBHeader,
				&fEnvelopeData.fDBFooter,
				&fEnvelopeData,
				CEnvelope::GetObjTypeConstant(),
				CEnvelope::GetObjVersConstant(),
				CEnvelope::GetObjSizeConstant() )
{
	fEnvelopeData.fEnvelopeID					= 0;	// this is us (denormalized)
	fEnvelopeData.fSenderID						= 0;	// this is our sender recipient object
	fEnvelopeData.fMsgTocID						= 0;	// message table of contents ID
	fEnvelopeData.fRecipListHeadID				= 0;	// 
	fEnvelopeData.fViaCode						= 0;	// how did we get it
	fEnvelopeData.fMessageSize					= 0;	// size in bytes of message (cached)
	fEnvelopeData.fCreationTime					= 0;	// time created
	fEnvelopeData.fWarningSentTime				= 0;	// time the Warning was sent...
	fEnvelopeData.fAttemptTime					= 0;	// last attempt at delivery
	fEnvelopeData.fTransports					= 0;	// AppleTalk, TCP/IP, or Bounce
	fEnvelopeData.fTOCEnvelopeStrOffset			= 0;	// TOC Envelope string offset
	fEnvelopeData.fTOCEnvelopeStrLength			= 0;	// TOC Envelope string length
	fEnvelopeData.fFilePathLen					= 0;	// Length of prepended headers
	fEnvelopeData.fServerIPAddr					= 0;	// server IP Address (used for multihoming)
	fEnvelopeData.fFlags						= 0;	// envelope flags
	fEnvelopeData.fSpoolRefCount				= 0;	// Number of CEnvelopeInfo objects referring to me
	fEnvelopeData.fHostRefCount					= 0;	// Number of Host Spool objects referring to me
	fEnvelopeData.fOriginalRecipientCount		= 0;	// # Before routing expansions
	fEnvelopeData.fTotalRecipientCount			= 0;	// # Currently
	fEnvelopeData.fPendingRecipientCount		= 0;	// # Pending Routing
	fEnvelopeData.fDeliveredRecipients			= 0;	// # Delivered To Successfully
	fEnvelopeData.fErrorRecipientCount			= 0;	// # Routing or delivery unsuccessful
	fEnvelopeData.fGroupRecipientCount			= 0;	// # of groups
	fEnvelopeData.fAutoForwardRecipientCount	= 0;	// # of autoforwards
	fEnvelopeData.fLocalRecipientCount			= 0;	// # of local recipients
	fEnvelopeData.fRemoteRecipientCount			= 0;	// # of remote recipients
	fEnvelopeData.fRemotePostingDone			= 0;	// true when the router is done posting the message to _ALL_ hosts
	fEnvelopeData.fMessagePartCount				= 0;
	fEnvelopeData.fVTwinReference				= 0;
	::memset( fEnvelopeData.fSendingHost, 0, sizeof(fEnvelopeData.fSendingHost) );		// Sending host name
	::memset( fEnvelopeData.fFilePath, 0, kMaxPathLen );	// Message headers prefix
	::memset( &fEnvelopeData.fDataPathObj,   0, sizeof( TextStrObj ) );	// 
	::memset( &fEnvelopeData.fFromLineObj,   0, sizeof( TextStrObj ) );	// 

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

	fDataFilePath	= nil;
	fFromLine		= nil;

	this->ChkCompilerStructAlignment();
} // CEnvelope

CEnvelope::~CEnvelope(void)
{
	if ( fDataFilePath != nil )
	{
		free( fDataFilePath );
		fDataFilePath = nil;
	}

	if ( fFromLine != nil )
	{
		free( fFromLine );
		fFromLine = nil;
	}

} // ~CEnvelope

#pragma mark -

ObjID CEnvelope::GetEnvelopeID ( void )
{
	return ( fEnvelopeData.fEnvelopeID );
} // GetEnvelopeID


ObjID CEnvelope::GetSenderID ( void )
{
	return ( fEnvelopeData.fSenderID );
} // GetSenderID


void CEnvelope::SetSenderID ( ObjID inSenderID )
{
	fEnvelopeData.fSenderID = inSenderID;
	this->SetDirty();
} // SetSenderID


ObjID CEnvelope::GetMessageTocID ( void )
{
	return( fEnvelopeData.fMsgTocID );
} // GetMessageTocID


void CEnvelope::SetMessageTocID ( ObjID inMsgTocID )
{
	if ( fEnvelopeData.fMsgTocID != inMsgTocID )
	{
		fEnvelopeData.fMsgTocID = inMsgTocID;
		this->SetDirty();
	}
} // SetMessageTocID

#pragma mark -


uInt32 CEnvelope::GetViaCode ( void )
{
	return ( fEnvelopeData.fViaCode );
} // GetViaCode


void CEnvelope::SetViaCode ( uInt32 inViaCode )
{
	fEnvelopeData.fViaCode = inViaCode;
	this->SetDirty();
} // SetViaCode


const char* CEnvelope::GetSendingHost ( void )
{
	return( fEnvelopeData.fSendingHost );
} // GetSendingHost


void CEnvelope::SetSendingHost ( const char* inSendingHost )
{
	CUtils::Strncpy( fEnvelopeData.fSendingHost, inSendingHost, kMaxHostNameLength );
	this->SetDirty();
} // SetSendingHost



//--------------------------------------------------------------------------------------------------
//	* GetTOCEnvStringLength
// 
//--------------------------------------------------------------------------------------------------

//uInt16 CEnvelope::GetTOCEnvStringLength ( void )
//{
//	return ( fEnvelopeData.fTOCEnvelopeStrLength );
//} // GetTOCEnvStringLength


//--------------------------------------------------------------------------------------------------
//	* GetTOCEnvString
// 
//--------------------------------------------------------------------------------------------------

//char* CEnvelope::GetTOCEnvString ( void )
//{
//	return( &fEnvelopeData.fFilePath[ fEnvelopeData.fTOCEnvelopeStrOffset ] );
//} // GetTOCEnvString



//--------------------------------------------------------------------------------------------------
//	* SetTOCEnvString
//
//		- Always put this tring at the end of the storage buffer
//
//--------------------------------------------------------------------------------------------------
//
//void CEnvelope::SetTOCEnvString ( char *inData, uInt16 inLength )
//{
//	uInt16	storageLen = kMaxPathLen - (fEnvelopeData.fFilePathLen + 1);
//
//
//	// Determin if there is room for the envelope string
//	//	- Add 1 to the length to account for the null termination
//	if ( (inLength +1) > storageLen )
//	{
//		// Not enough room so we bail
//		fEnvelopeData.fTOCEnvelopeStrOffset = 0;
//		fEnvelopeData.fTOCEnvelopeStrLength = 0;
//		return;
//	}
//
//	// Put it at the end of the storage buffer
//	fEnvelopeData.fTOCEnvelopeStrOffset = kMaxPathLen - (inLength + 1);
//
//	// Set the length of the data
//	fEnvelopeData.fTOCEnvelopeStrLength = inLength;
//
//	// Set the data in the storage
//	::memcpy( &fEnvelopeData.fFilePath[ fEnvelopeData.fTOCEnvelopeStrOffset ], inData, inLength );
//	fEnvelopeData.fFilePath[ kMaxPathLen - 1 ] = '\0';
//
//	this->SetDirty();
//
//} // SetTOCEnvString


//--------------------------------------------------------------------------------------------------
//	* GetMessageSize ()
// 
//--------------------------------------------------------------------------------------------------

uInt32 CEnvelope::GetMessageSize ( void )
{
	if (this != NULL)
	{
		return ( fEnvelopeData.fMessageSize );
	}

	return ( 0 );
	
} // GetMessageSize


//--------------------------------------------------------------------------------------------------
//	* SetMessageSize ()
// 
//--------------------------------------------------------------------------------------------------

void CEnvelope::SetMessageSize ( uInt32 inMessageSize )
{
	if ( fEnvelopeData.fMessageSize != inMessageSize )
	{
		fEnvelopeData.fMessageSize = inMessageSize;
		this->SetDirty();
	}
} // SetMessageSize


//--------------------------------------------------------------------------------------------------
//	* AddReference ()
// 
//--------------------------------------------------------------------------------------------------

void CEnvelope::AddReference ( uInt32 inType )
{
	if ( this != NULL )
	{
		if ( inType == kSpoolReference )
		{
			fEnvelopeData.fSpoolRefCount++;
		}
		else if ( inType == kHostReference )
		{
			fEnvelopeData.fHostRefCount++;
		}

		this->SetDirty();
		this->ReleaseObjectLock(true);
	}
} // AddReference


Boolean CEnvelope::GetRemotePostingFlag ( void )
{
	return ( this->fEnvelopeData.fRemotePostingDone == true );
} // GetRemotePostingFlag


void CEnvelope::SetRemotePostingFlag ( Boolean inPostingFlag )
{
	if ( this != NULL )
	{
		if ( inPostingFlag != this->fEnvelopeData.fRemotePostingDone )
		{
			this->fEnvelopeData.fRemotePostingDone = inPostingFlag;
			this->SetDirty();
		}

		this->ReleaseObjectLock(true);
	}
} // SetRemotePostingFlag

ObjID CEnvelope::GetRecipListHeadID ( void )
{
	return( fEnvelopeData.fRecipListHeadID );
} // GetRecipListHeadID


void CEnvelope::SetRecipientListHeadID ( ObjID inListHeadID )
{
	if ( fEnvelopeData.fRecipListHeadID != inListHeadID )
	{
		fEnvelopeData.fRecipListHeadID = inListHeadID;
		this->SetDirty();
	}
} // SetRecipientListHeadID


uInt32 CEnvelope::GetServerIPAddr ( void )
{
	return( fEnvelopeData.fServerIPAddr );
} // GetServerIPAddr


void CEnvelope::SetServerIPAddr ( uInt32 inServerIPAddr )
{
	if ( inServerIPAddr != fEnvelopeData.fServerIPAddr )
	{
		fEnvelopeData.fServerIPAddr = inServerIPAddr;
		this->SetDirty();
	}
} // SetServerIPAddr

void CEnvelope::RemoveReference ( uInt32 inType )
{
	if ( this != NULL )
	{
		if ( inType == kSpoolReference )
		{
			if (fEnvelopeData.fSpoolRefCount > 0)
			{
				fEnvelopeData.fSpoolRefCount--;
			}
		}
		else if ( inType == kHostReference )
		{
			if ( fEnvelopeData.fHostRefCount > 0 )
			{
				fEnvelopeData.fHostRefCount--;
			}
		}

		this->SetDirty();

		if ( (fEnvelopeData.fSpoolRefCount + fEnvelopeData.fHostRefCount) == 0 )
		{
			 this->SetViaCode(kViaDoorNail);
		}
		
		this->ReleaseObjectLock(true);
	}
} // RemoveReference


uInt32 CEnvelope::GetRefCount (uInt32 inType)
{
	if ( inType == kSpoolReference )
	{
		return ( fEnvelopeData.fSpoolRefCount );
	}
	else if ( inType == kHostReference )
	{
		return ( fEnvelopeData.fHostRefCount );
	}

	return( 0 );
} // GetRefCount


void CEnvelope::AddTransport ( uInt16 inTransport )
{
	fEnvelopeData.fTransports |= inTransport;
	this->SetDirty();
} // AddTransport


uInt16 CEnvelope::GetTransports ( void )
{
	return( fEnvelopeData.fTransports );
} // GetTransports


uInt32 CEnvelope::GetEnvWarningTime ( void )
{
	return( fEnvelopeData.fWarningSentTime );
} // GetTransports


void CEnvelope::SetEnvWarningTime ( const uInt32 inWarningSentTime )
{
	if (fEnvelopeData.fWarningSentTime != inWarningSentTime)
	{
		fEnvelopeData.fWarningSentTime = inWarningSentTime;
		this->SetDirty();
	}
} // GetTransports


#pragma mark -


void CEnvelope::AddRecipient ( ObjID inRecipientID )
{
} // AddRecipient



void CEnvelope::DeleteAllRecipients ( void )
{
} // DeleteAllRecipients



uInt16 CEnvelope::GetRecipientCount ( uInt32 inType )
{
	switch (inType)
	{
		case kOriginalCount:
			return( fEnvelopeData.fOriginalRecipientCount );
			break;
		case kTotalCount:
			return( fEnvelopeData.fTotalRecipientCount );
			break;
		case kPendingRoutingCount:
			return( fEnvelopeData.fPendingRecipientCount );
			break;
		case kDeliveredCount:
			return( fEnvelopeData.fDeliveredRecipients );
			break;
		case kErrorCount:
			return( fEnvelopeData.fErrorRecipientCount );
			break;
		case kGroupCount:
			return( fEnvelopeData.fGroupRecipientCount );
			break;
		case kAutoForwardCount:
			return( fEnvelopeData.fAutoForwardRecipientCount );
			break;
		case kLocalCount:
			return( fEnvelopeData.fLocalRecipientCount );
			break;
		case kRemoteCount:
			return( fEnvelopeData.fRemoteRecipientCount );
			break;
		default:
			return ( 0 );
			break;
	}
} // GetRecipientCount

void CEnvelope::SetRecipientCount ( uInt32 inType, uInt16 inCount )
{
	switch (inType)
	{
		case kOriginalCount:
			fEnvelopeData.fOriginalRecipientCount = inCount;
			break;
		case kTotalCount:
			fEnvelopeData.fTotalRecipientCount = inCount;
			break;
		case kPendingRoutingCount:
			fEnvelopeData.fPendingRecipientCount = inCount;
			break;
		case kDeliveredCount:
			fEnvelopeData.fDeliveredRecipients = inCount;
			break;
		case kErrorCount:
			fEnvelopeData.fErrorRecipientCount = inCount;
			break;
		case kGroupCount:
			fEnvelopeData.fGroupRecipientCount = inCount;
			break;
		case kAutoForwardCount:
			fEnvelopeData.fAutoForwardRecipientCount = inCount;
			break;
		case kLocalCount:
			fEnvelopeData.fLocalRecipientCount = inCount;
			break;
		case kRemoteCount:
			fEnvelopeData.fRemoteRecipientCount = inCount;
			break;
		default:
			return;
			break;
	}

	this->SetDirty();
} // SetRecipientCount


void CEnvelope::IncrementRecipientCount ( uInt32 inType )
{
	switch (inType)
	{
		case kOriginalCount:
			fEnvelopeData.fOriginalRecipientCount++;
			break;
		case kTotalCount:
			fEnvelopeData.fTotalRecipientCount++;
			break;
		case kPendingRoutingCount:
			fEnvelopeData.fPendingRecipientCount++;
			break;
		case kDeliveredCount:
			fEnvelopeData.fDeliveredRecipients++;
			break;
		case kErrorCount:
			fEnvelopeData.fErrorRecipientCount++;
			break;
		case kGroupCount:
			fEnvelopeData.fGroupRecipientCount++;
			break;
		case kAutoForwardCount:
			fEnvelopeData.fAutoForwardRecipientCount++;
			break;
		case kLocalCount:
			fEnvelopeData.fLocalRecipientCount++;
			break;
		case kRemoteCount:
			fEnvelopeData.fRemoteRecipientCount++;
			break;
		default:
			return;
			break;
	}

	this->SetDirty();
} // IncrementRecipientCount

void CEnvelope::DecrementRecipientCount ( uInt32 inType )
{
	switch (inType)
	{
		case kOriginalCount:
			if ( fEnvelopeData.fOriginalRecipientCount > 0 )
				fEnvelopeData.fOriginalRecipientCount--;
			break;
		case kTotalCount:
			if ( fEnvelopeData.fTotalRecipientCount > 0 )
				fEnvelopeData.fTotalRecipientCount--;
			break;
		case kPendingRoutingCount:
			if ( fEnvelopeData.fPendingRecipientCount > 0 )
				fEnvelopeData.fPendingRecipientCount--;
			break;
		case kDeliveredCount:
			if ( fEnvelopeData.fDeliveredRecipients > 0 )
				fEnvelopeData.fDeliveredRecipients--;
			break;
		case kErrorCount:
			if ( fEnvelopeData.fErrorRecipientCount > 0 )
				fEnvelopeData.fErrorRecipientCount--;
			break;
		case kGroupCount:
			if ( fEnvelopeData.fGroupRecipientCount > 0 )
				fEnvelopeData.fGroupRecipientCount--;
			break;
		case kAutoForwardCount:
			if ( fEnvelopeData.fAutoForwardRecipientCount > 0 )
				fEnvelopeData.fAutoForwardRecipientCount--;
			break;
		case kLocalCount:
			if ( fEnvelopeData.fLocalRecipientCount > 0 )
				fEnvelopeData.fLocalRecipientCount--;
			break;
		case kRemoteCount:
			if ( fEnvelopeData.fRemoteRecipientCount > 0 )
				fEnvelopeData.fRemoteRecipientCount--;
			break;
		default:
			return;
			break;
	}

	this->SetDirty();
} // DecrementRecipientCount


Boolean CEnvelope::DeleteSender ( void )
{
	CRecipient	   *theRecipient = NULL;
	Boolean			successful = false;

	try
	{
		if (this->GetSenderID() != 0)
		{
//			theRecipient = CRecipient::FindByID( this->GetSenderID() );
//			if ( theRecipient != NULL )
//			{
//				successful = CRecipient::Delete( theRecipient );
//				theRecipient->Done( theRecipient );
//			}
		}
	}
	catch ( ... )
	{
	}

	return( successful );
} // DeleteSender

#pragma mark -


//void CEnvelope::AddMessagePart ( ObjID inMessagePartID, const Boolean inSmallMsgPartFlag )
//{
//	if (inSmallMsgPartFlag == false)
//	{
//		CMessagePart* theMessagePart = CMessagePart::FindByID( inMessagePartID );
//		if (theMessagePart != NULL)
//		{
//			if (this->GetMsgPartListHeadID() == 0)
//			{
//				this->SetMsgPartListHeadID(inMessagePartID);
//			}
//		
//			this->fEnvelopeData.fMessageSize += theMessagePart->GetDataLength();
//			this->fEnvelopeData.fMessagePartCount++;
//			theMessagePart->SetMsgHasBeenAttached(true);
//			theMessagePart->Done(theMessagePart);
//			fCacheFullMessageSize = 0;
//		}
//	}
//	else
//	{
//		CSmallMsgPart *theSmallMsgPart = CSmallMsgPart::FindByID(inMessagePartID);
//		if (theSmallMsgPart != NULL)
//		{
//			this->SetSmallMsgPartID(inMessagePartID);
//
//			this->fEnvelopeData.fMessageSize += theSmallMsgPart->GetDataLength();
//			this->fEnvelopeData.fMessagePartCount++;
//			theSmallMsgPart->SetMsgHasBeenAttached(true);
//			theSmallMsgPart->Done(theSmallMsgPart);
//			fCacheFullMessageSize = 0;
//		}
//	}
//
//	this->SetDirty();
//} // AddMessagePart


void CEnvelope::DeleteDataFile ( void )
{
	sInt32		siResult	= 0;
	const char *pFilePath	= nil;

	try
	{
		pFilePath = this->GetDataFilePath();
		if ( pFilePath != nil )
		{
			siResult = ::remove( pFilePath );
			if ( siResult != 0 )
			{
				// xxxxx do some logging
			}

			(void)CTextObjMgr::RemoveString( &fEnvelopeData.fDataPathObj );
			::memset( &fEnvelopeData.fDataPathObj,   0, sizeof( TextStrObj ) );	// 

			(void)CTextObjMgr::RemoveString( &fEnvelopeData.fFromLineObj );
			::memset( &fEnvelopeData.fFromLineObj,   0, sizeof( TextStrObj ) );	// 
		}
	}

	catch ( ... )
	{
		// xxxxx do some logging
	}

} // DeleteDataFile


uInt32 CEnvelope::GetVTwinReference ( void )
{
	return ( fEnvelopeData.fVTwinReference );
} // GetVTwinReference


// Set the V-Twin reference

void CEnvelope::SetVTwinReference ( uInt32 inRef )
{
	if ( fEnvelopeData.fVTwinReference != inRef )
	{
		fEnvelopeData.fVTwinReference = inRef;
		this->SetDirty();
	}
} // SetVTwinReference


void CEnvelope::SetCreationTime ( uInt32 inTime )
{
	if ( inTime == 0 )
	{
		fEnvelopeData.fCreationTime = ::time( NULL );
	}
	else
	{
		fEnvelopeData.fCreationTime = inTime;
	}
	this->SetDirty();
} // SetCreationTime


uInt32 CEnvelope::GetCreationTime ( void )
{
	return ( fEnvelopeData.fCreationTime );
} // GetCreationTime


void CEnvelope::SetLastAttemptTime ( void )
{
	fEnvelopeData.fAttemptTime = ::time( NULL );
	this->SetDirty();
} // SetLastAttemptTime


uInt32 CEnvelope::GetLastAttemptTime ( void )
{
	return ( fEnvelopeData.fAttemptTime );
} // GetLastAttemptTime



ObjID CEnvelope::GetMsgPartID ( void )
{
	return ( fEnvelopeData.fMsgPartID );
} // GetMsgPartID


void CEnvelope::SetMsgPartID ( ObjID inPartID )
{
	fEnvelopeData.fMsgPartID = inPartID;
	this->SetDirty();
} // SetMsgPartID



uInt32 CEnvelope::GetEnvelopeFlags ( void )
{
	return ( fEnvelopeData.fFlags );
} // GetEnvelopeFlags


void CEnvelope::SetEnvelopeFlags ( envFlags inFlags )
{
	uInt32	tmpFlags = fEnvelopeData.fFlags | inFlags;
	if ( fEnvelopeData.fFlags != tmpFlags )
	{
		fEnvelopeData.fFlags = tmpFlags;
		this->SetDirty();
	}
} // SetEnvelopeFlags


Bool CEnvelope::IsFlagSet ( envFlags inFlag )
{
	Bool	bResult	= false;

	if ( fEnvelopeData.fFlags & inFlag )
	{
		bResult = true;
	}

	return( bResult );

} // SetEnvelopeFlags


//--------------------------------------------------------------------------------------------------
//	* GetTOCSemaphore
//
//--------------------------------------------------------------------------------------------------

ExceptionCode CEnvelope::GetTOCSemaphore ( const Boolean inWaitForTOCFlag )
{
	return (this->GetObjectLock(inWaitForTOCFlag));
} // GetTOCSemaphore



//--------------------------------------------------------------------------------------------------
//	* SetTOCSemaphore
//
//--------------------------------------------------------------------------------------------------

void CEnvelope::ReleaseTOCSemaphore ( const Boolean inNotifyOtherThreadsFlag )
{
	this->ReleaseObjectLock(inNotifyOtherThreadsFlag);
} // SetTOCSemaphore



//--------------------------------------------------------------------------------------------------
//	* GetIndexSemaphore
//
//--------------------------------------------------------------------------------------------------

ExceptionCode CEnvelope::GetIndexSemaphore ( const Boolean inWaitForIndexFlag )
{
	return ( 0 );
} // GetIndexSemaphore


//--------------------------------------------------------------------------------------------------
//	* SetIndexSemaphore
//
//--------------------------------------------------------------------------------------------------

void CEnvelope::ReleaseIndexSemaphore ( const Boolean inNotifyOtherThreadsFlag )
{
} // SetIndexSemaphore


//--------------------------------------------------------------------------------------------------
//	* CreateDataFile ()
//
//--------------------------------------------------------------------------------------------------

CFile * CEnvelope::CreateDataFile ( void )
{
	CFile	   *pFile			= nil;
	CString		csFilePath( 128 );
	CString		csFileName( 128 );

	try
	{
		// This is /.../AppleMail/MailStore
		csFilePath.Set( COSUtils::GetMailStoreFolderPath() );
		csFilePath.Append( "/" );

		csFileName.Sprintf( "%s/%s/%u.%u.data", COSUtils::GetCurrentDayFolder(), COSUtils::GetTargetFolder(), gRootObj->GetMessageTag(), this->GetEnvelopeID() );

		csFilePath.Append( csFileName.GetData() );

		pFile = new CFile( csFilePath.GetData(), k600, true );
		if ( pFile != nil )
		{
			this->SetDataFilePath( csFileName.GetData() );
			CGlobals::IncrementCurMsgCount();
		}
	}

	catch ( ... )
	{
	}

	return( pFile );

} // CreateDataFile


//--------------------------------------------------------------------------------------------------
//	* GetDataFile ()
//
//--------------------------------------------------------------------------------------------------

CFile * CEnvelope::GetDataFile ( void )
{
	CFile	   *pFile		= nil;
	const char *pFilePath	= nil;

	try
	{
		pFilePath = this->GetDataFilePath();
		if ( pFilePath != nil )
		{
			pFile = new CFile( pFilePath, k600, false );
		}
	}

	catch ( ... )
	{
	}

	return( pFile );

} // GetDataFile


//--------------------------------------------------------------------------------------------------
//	* GetData ()
//
//		- Method one
//
//--------------------------------------------------------------------------------------------------

char * CEnvelope::GetData ( uInt32 &outLen )
{
	CFile   *pFile		= nil;
	char	*pOutPtr	= nil;

	try
	{
		pFile = this->GetDataFile();
		if ( pFile != nil )
		{
			outLen = (uInt32)pFile->FileSize();
			pOutPtr = (char *)::calloc( outLen + 32, sizeof( char ) );
			ThrowIfNULL_( pOutPtr );
	
			pFile->ReadBlock( pOutPtr, outLen );
		}
	}

	catch ( long err )
	{
	}

	catch ( ... )
	{
	}

	if ( pFile != nil )
	{
		delete( pFile );
		pFile = nil;
	}
	
	return( pOutPtr );

} // GetData


//--------------------------------------------------------------------------------------------------
//	* GetData ()
//
//		- Method two
//
//--------------------------------------------------------------------------------------------------

char * CEnvelope::GetData ( uInt32 &outLen, uInt32 inSize )
{
	CFile   *pFile		= nil;
	char	*pOutPtr	= nil;

	try
	{
		outLen = 0;
		pFile = this->GetDataFile();
		if ( pFile != nil )
		{
			pOutPtr = (char *)::calloc( inSize + 32, sizeof( char ) );
			ThrowIfNULL_( pOutPtr );
	
			outLen = pFile->ReadBlock( pOutPtr, inSize );
		}
	}

	catch ( long err )
	{
	}

	catch ( ... )
	{
	}

	if ( pFile != nil )
	{
		delete( pFile );
		pFile = nil;
	}
	
	return( pOutPtr );

} // GetData


//--------------------------------------------------------------------------------------------------
//	* GetDataFileName ()
//
//--------------------------------------------------------------------------------------------------

char* CEnvelope::GetDataFileName ( void )
{
	char *pOutString	= nil;

	(void)CTextObjMgr::GetString( &fEnvelopeData.fDataPathObj, &pOutString );

	return( pOutString );

} // GetDataFileName


//--------------------------------------------------------------------------------------------------
//	* GetDataFilePath ()
//
//--------------------------------------------------------------------------------------------------

const char* CEnvelope::GetDataFilePath ( void )
{
	char		*p			= NULL;
	sInt32		siResult	= kNoErr;

	if ( fDataFilePath == nil )
	{
		char		*pTmpPath	= nil;
		CString		csFilePath( 128 );

		(void)CTextObjMgr::GetString( &fEnvelopeData.fDataPathObj, &pTmpPath );

		if ( pTmpPath != nil )
		{
			csFilePath.Set( pTmpPath );

			if ( gSrcDir.GetLength() != 0 )
			{
				p = strstr( pTmpPath, "/AppleMail/MailStore/" );
				if ( p != NULL )
				{
					csFilePath.Set( gSrcDir.GetData() );
					csFilePath.Append( p );
				}
			}

			fDataFilePath = (char *)::malloc( csFilePath.GetLength() + 1 );
	
			CUtils::Strcpy( fDataFilePath, csFilePath.GetData() );
	
			free( pTmpPath );
			pTmpPath = nil;
		}
	}

	return( fDataFilePath );

} // GetDataFilePath


//--------------------------------------------------------------------------------------------------
//	* SetDataFilePath ()
//
//--------------------------------------------------------------------------------------------------

void CEnvelope::SetDataFilePath ( const char *inFileName )
{
	sInt32		siResult	= kNoErr;

	if ( inFileName != nil )
	{
		this->GetDataFilePath();
	
		if ( fDataFilePath != nil )
		{
			siResult = CTextObjMgr::RemoveString( &fEnvelopeData.fDataPathObj );

			free( fDataFilePath );
			fDataFilePath = nil;
		}

		siResult = CTextObjMgr::AddString( inFileName, &fEnvelopeData.fDataPathObj );

		this->SetDirty();
	}
} // SetDataFilePath


//--------------------------------------------------------------------------------------------------
//	* GetFromLine ()
//
//--------------------------------------------------------------------------------------------------

const char* CEnvelope::GetFromLine ( void )
{
	sInt32		siResult	= kNoErr;

	if ( fFromLine == nil )
	{
		(void)CTextObjMgr::GetString( &fEnvelopeData.fFromLineObj, &fFromLine );
	}

	return( fFromLine );

} // GetFromLine


//--------------------------------------------------------------------------------------------------
//	* SetFromLine ()
//
//--------------------------------------------------------------------------------------------------

void CEnvelope::SetFromLine ( const char *inFromLine )
{
	sInt32		siResult	= kNoErr;

	if ( inFromLine != nil )
	{
		this->GetFromLine();
	
		if ( (fFromLine == nil) || (CUtils::Strcmp( fFromLine, inFromLine ) != 0) )
		{
			if ( fFromLine != nil )
			{
				siResult = CTextObjMgr::RemoveString( &fEnvelopeData.fFromLineObj );
	
				free( fFromLine );
				fFromLine = nil;
			}
	
			siResult = CTextObjMgr::AddString( inFromLine, &fEnvelopeData.fFromLineObj );
	
			siResult = CTextObjMgr::GetString( &fEnvelopeData.fFromLineObj, &fFromLine );
	
			this->SetDirty();
		}
	}
} // SetFromLine


