/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */
#include "nsOEScanBoxes.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIImportService.h"
#include "nsIImportMailboxDescriptor.h"

#include "nsOERegUtil.h"
#include "nsOE5File.h"

#include "OEDebugLog.h"

/*
	.nch file format???

	offset 20 - long = offset to first record

*/

static NS_DEFINE_CID(kImportServiceCID,		NS_IMPORTSERVICE_CID);
static NS_DEFINE_IID(kISupportsIID,			NS_ISUPPORTS_IID);


nsOEScanBoxes::nsOEScanBoxes()
{
	m_pFirst = nsnull;
}

nsOEScanBoxes::~nsOEScanBoxes()
{
	int max = m_entryArray.Count();
	for (int i = 0; i < max; i++) {
		MailboxEntry *pEntry = (MailboxEntry *) m_entryArray.ElementAt( i);
		delete pEntry;
	}
}


/*
 3.x & 4.x registry
	Software/Microsoft/Outlook Express/

 5.0 registry
	Identies - value of "Default User ID" is {GUID}
	Identities/{GUID}/Software/Microsoft/Outlook Express/5.0/
*/

PRBool nsOEScanBoxes::Find50Mail( nsIFileSpec *pWhere)
{
	nsresult 	rv;
	PRBool		success = PR_FALSE;
	HKEY		sKey;

	if (::RegOpenKeyEx( HKEY_CURRENT_USER, "Identities", 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
		BYTE *	pBytes = nsOERegUtil::GetValueBytes( sKey, "Default User ID");
		::RegCloseKey( sKey);
		if (pBytes) {
			nsCString	key( "Identities\\");
			key += (const char *)pBytes;
			nsOERegUtil::FreeValueBytes( pBytes);
			key += "\\Software\\Microsoft\\Outlook Express\\5.0";
			if (::RegOpenKeyEx( HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
				pBytes = nsOERegUtil::GetValueBytes( sKey, "Store Root");
				if (pBytes) {
					pWhere->SetNativePath((char *)pBytes);
					nsOERegUtil::FreeValueBytes( pBytes);
					PRBool	isDir = PR_FALSE;
					rv = pWhere->IsDirectory( &isDir);
					if (isDir && NS_SUCCEEDED( rv))
						success = PR_TRUE;
				}
				::RegCloseKey( sKey);
			}
		}
	}
	
	return( success);
}

PRBool nsOEScanBoxes::FindMail( nsIFileSpec *pWhere)
{
	nsresult 	rv;
	PRBool		success = PR_FALSE;
	HKEY		sKey;
	
	if (Find50Mail( pWhere))
		return( PR_TRUE);

	if (::RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft\\Outlook Express", 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
		LPBYTE	pBytes = nsOERegUtil::GetValueBytes( sKey, "Store Root");
		if (pBytes) {
			pWhere->SetNativePath((char *)pBytes);
			pWhere->AppendRelativeUnixPath( "Mail");
			PRBool	isDir = PR_FALSE;
			rv = pWhere->IsDirectory( &isDir);
			if (isDir && NS_SUCCEEDED( rv))
				success = PR_TRUE;
			delete [] pBytes;
		}
		::RegCloseKey( sKey);		
	}
	
	return( success);
}

PRBool nsOEScanBoxes::GetMailboxes( nsIFileSpec *pWhere, nsISupportsArray **pArray)
{
	char *path = nsnull;
	pWhere->GetNSPRPath( &path);
	if (path) {
		IMPORT_LOG1( "Looking for mail in: %s\n", path);
		nsCRT::free( path);
	}
	else {
		pWhere->GetLeafName( &path);
		if (path) {
			IMPORT_LOG1( "Looking for mail in: %s\n", path);
			nsCRT::free( path);
		}
		else {
			IMPORT_LOG0( "Unable to get info about where to look for mail\n");
		}
	}
	
	nsIFileSpec	*where;
	if (NS_FAILED( NS_NewFileSpec( &where)))
		return( PR_FALSE);
	where->FromFileSpec( pWhere);

	// 1. Look for 5.0 folders.dbx
	// 2. Look for 3.x & 4.x folders.nch
	// 3. Look for 5.0 *.dbx mailboxes
	// 4. Look for 3.x & 4.x *.mbx mailboxes
	
	PRBool	result;

	where->AppendRelativeUnixPath( "folders.dbx");
	if (Find50MailBoxes( where)) {
		where->CloseStream();
		result = GetMailboxList( pWhere, pArray);
	}
	else {
		// 2. Look for 4.x mailboxes
		where->FromFileSpec( pWhere);
		where->AppendRelativeUnixPath( "folders.nch");
	
		if (FindMailBoxes( where)) {
			where->CloseStream();
			result = GetMailboxList( pWhere, pArray);
		}
		else {
			// 3 & 4, look for the specific mailbox files.
			where->CloseStream();
			where->FromFileSpec( pWhere);
			ScanMailboxDir( where);
			result = GetMailboxList( pWhere, pArray);
		}
	}
		
	where->Release();
	return( result);
}



void nsOEScanBoxes::Reset( void)
{
	int max = m_entryArray.Count();
	for (int i = 0; i < max; i++) {
		MailboxEntry *pEntry = (MailboxEntry *) m_entryArray.ElementAt( i);
		delete pEntry;
	}
	m_entryArray.Clear();
	m_pFirst = nsnull;
}


PRBool nsOEScanBoxes::FindMailBoxes( nsIFileSpec* descFile)
{
	Reset();
	
	nsresult	rv;
	PRBool		isFile = PR_FALSE;
	
	rv = descFile->IsFile( &isFile);
	if (NS_FAILED( rv) || !isFile)
		return( PR_FALSE);
	
	rv = descFile->OpenStreamForReading();	
	if (NS_FAILED( rv))
		return( PR_FALSE);

	IMPORT_LOG0( "Reading the folders.nch file\n");
	
	PRUint32		curRec;
	if (!ReadLong( descFile, curRec, 20)) {
		return( PR_FALSE);
	}

	// Now for each record
	PRBool			done = PR_FALSE;
	PRUint32		equal;
	PRUint32		size;
	PRUint32		previous;
	PRUint32		next;
	MailboxEntry *	pEntry;
	PRBool			failed;
	nsCString		ext;
	nsCString		mbxExt( ".mbx");
	
	while (!done) {
		
		if (!ReadLong( descFile, equal, curRec)) return( PR_FALSE);
		if (curRec != equal) {
			IMPORT_LOG1( "Record start invalid: %ld\n", curRec);
			break;
		}
		if (!ReadLong( descFile, size, curRec + 4)) return( PR_FALSE);
		if (!ReadLong( descFile, previous, curRec + 8)) return( PR_FALSE);
		if (!ReadLong( descFile, next, curRec + 12)) return( PR_FALSE);
		failed = PR_FALSE;
		pEntry = new MailboxEntry;
		if (!ReadLong( descFile, pEntry->index, curRec + 16)) failed = PR_TRUE;
		if (!ReadString( descFile, pEntry->mailName, curRec + 20)) failed = PR_TRUE;
		if (!ReadString( descFile, pEntry->fileName, curRec + 279)) failed = PR_TRUE;
		if (!ReadLong( descFile, pEntry->parent, curRec + 539)) failed = PR_TRUE;
		if (!ReadLong( descFile, pEntry->child, curRec + 543)) failed = PR_TRUE;
		if (!ReadLong( descFile, pEntry->sibling, curRec + 547)) failed = PR_TRUE;
		if (!ReadLong( descFile, pEntry->type, curRec + 551)) failed = PR_TRUE;
		if (failed) {
			delete pEntry;
			return( PR_FALSE);
		}

		#ifdef _TRACE_MAILBOX_ENTRIES
		IMPORT_LOG0( "------------\n");
		IMPORT_LOG2( "    Offset: %lx, index: %ld\n", curRec, pEntry->index);
		IMPORT_LOG2( "      previous: %lx, next: %lx\n", previous, next);
		IMPORT_LOG2( "      Name: %S, File: %s\n", (PRUnichar *) pEntry->mailName, (const char *) pEntry->fileName);
		IMPORT_LOG3( "      Parent: %ld, Child: %ld, Sibling: %ld\n", pEntry->parent, pEntry->child, pEntry->sibling);
		#endif
		
		pEntry->fileName.Right( ext, 4);
		if (ext.Compare( mbxExt))
			pEntry->fileName.Append( ".mbx");		
		
		m_entryArray.AppendElement( pEntry);

		curRec = next;
		if (!next)
			done = PR_TRUE;
	}
	
	MailboxEntry *pZero = GetIndexEntry( 0);
	if (pZero)
		m_pFirst = GetIndexEntry( pZero->child);
	
	IMPORT_LOG1( "Read the folders.nch file, found %ld mailboxes\n", (long) m_entryArray.Count());
	
	return( PR_TRUE);
}

PRBool nsOEScanBoxes::Find50MailBoxes( nsIFileSpec* descFile)
{
	Reset();
	
	nsresult	rv;
	PRBool		isFile = PR_FALSE;
	
	rv = descFile->IsFile( &isFile);
	if (NS_FAILED( rv) || !isFile)
		return( PR_FALSE);
	
	rv = descFile->OpenStreamForReading();	
	if (NS_FAILED( rv))
		return( PR_FALSE);

	IMPORT_LOG0( "Reading the folders.dbx file\n");
	
	PRUint32 *		pIndex;
	PRUint32		indexSize = 0;
	if (!nsOE5File::ReadIndex( descFile, &pIndex, &indexSize)) {
		IMPORT_LOG0( "*** NOT USING FOLDERS.DBX!!!\n");
		return( PR_FALSE);
	}
	
	PRUint32	marker;
	PRUint32	size;
	char	*	pBytes;
	PRInt32		cntRead;
	PRInt32		recordId;
	PRInt32		strOffset;

	PRUint8		tag;
	PRUint32	data;
	PRInt32		dataOffset;
	
	PRUint32		id;
	PRUint32		parent;
	PRUint32		numMessages;
	char *			pFileName;
	char *			pDataSource;

	MailboxEntry *	pEntry;
	MailboxEntry *	pLastEntry = nsnull;

	PRUint32	localStoreId = 0;

	for (PRUint32 i = 0; i < indexSize; i++) {
		if (!ReadLong( descFile, marker, pIndex[i])) continue;
		if (marker != pIndex[i]) continue;
		if (!ReadLong( descFile, size, pIndex[i] + 4)) continue;
		size += 4;
		pBytes = new char[size];
		rv = descFile->Read( &pBytes, size, &cntRead);
		if (NS_FAILED( rv) || ((PRUint32)cntRead != size)) {
			delete [] pBytes;
			continue;
		}
		recordId = pBytes[2];
		strOffset = (recordId * 4) + 4;
		if (recordId == 4)
			strOffset += 4;
		
		id = 0;
		parent = 0;
		numMessages = 0;
		pFileName = nsnull;
		pDataSource = nsnull;
		dataOffset = 4;
		while (dataOffset < strOffset) {
			tag = (PRUint8) pBytes[dataOffset];

			nsCRT::memcpy( &data, &(pBytes[dataOffset + 1]), 3);
			switch( tag) {
				case 0x80: // id record
					id = data;
				break;		
				case 0x81:	// parent id
					parent = data;
				break;
				case 0x87:	// number of messages in this mailbox
					numMessages = data;
				break;
				case 0x03:	// file name for this mailbox
					if (((PRUint32)strOffset + data) < size)
						pFileName = (char *)(pBytes + strOffset + data);
				break;
				case 0x05:	// data source for this record (this is not a mailbox!)
					if (((PRUint32)strOffset + data) < size)
						pDataSource = (char *) (pBytes + strOffset + data);
				break;
			}
			dataOffset += 4;
		}
		
		// now build an entry if necessary!
		if (pDataSource) {
			if (!nsCRT::strcasecmp( pDataSource, "LocalStore"))
				localStoreId = id;	
		}
		else if (id && localStoreId && parent) {
			// veryify that this mailbox is in the local store
			data = parent;
			while (data && (data != localStoreId)) {
				pEntry = GetIndexEntry( data);
				if (pEntry)
					data = pEntry->parent;
				else
					data = 0;
			}
			if (data == localStoreId) {
				// Create an entry for this bugger
				pEntry = new MailboxEntry();
				pEntry->index = id;
				pEntry->parent = parent;
				pEntry->child = 0;
				pEntry->type = 0;
				pEntry->sibling = -1;
				pEntry->mailName = (const char *) (pBytes + strOffset);
				if (pFileName)
					pEntry->fileName = pFileName;
				AddChildEntry( pEntry, localStoreId);
			}
		}

		delete [] pBytes;
	}

	
	delete [] pIndex;

	if (m_entryArray.Count())
		return( PR_TRUE);
	else
		return( PR_FALSE);
}


void nsOEScanBoxes::AddChildEntry( MailboxEntry *pEntry, PRUint32 rootIndex)
{
	if (!m_pFirst) {
		if (pEntry->parent == rootIndex) {
			m_pFirst = pEntry;
			m_entryArray.AppendElement( pEntry);
		}
		else {
			delete pEntry;
		}
		return;
	}
	
	MailboxEntry *	pParent = nsnull;
	MailboxEntry *	pSibling = nsnull;
	if (pEntry->parent == rootIndex) {
		pSibling = m_pFirst;
	}
	else {
		pParent = GetIndexEntry( pEntry->parent);
	}
	
	if (!pParent && !pSibling) {
		delete pEntry;
		return;
	}

	if (pParent && (pParent->child == 0)) {
		pParent->child = pEntry->index;
		m_entryArray.AppendElement( pEntry);
		return;
	}
	
	if (!pSibling)
		pSibling = GetIndexEntry( pParent->child);

	while (pSibling && (pSibling->sibling != -1)) {
		pSibling = GetIndexEntry( pSibling->sibling);
	}

	if (!pSibling) {
		delete pEntry;
		return;
	}

	pSibling->sibling = pEntry->index;
	m_entryArray.AppendElement( pEntry);
}

PRBool nsOEScanBoxes::Scan50MailboxDir( nsIFileSpec * srcDir)
{
	Reset();

	MailboxEntry *	pEntry;	
	PRInt32			index = 1;
	char *			pLeaf;
	PRUint32		sLen;
	
	nsIFileSpec *			spec;
	nsIDirectoryIterator *	iter;
	
	if (NS_FAILED( NS_NewDirectoryIterator( &iter)))
		return( PR_FALSE);
	if (NS_FAILED( iter->Init( srcDir, PR_TRUE))) {
		iter->Release();
		return( PR_FALSE);
	}

	nsresult	rv;
	PRBool		exists = PR_FALSE;
	PRBool		isFile;
	
	rv = iter->Exists( &exists);
	while (NS_SUCCEEDED( rv) && exists) {
	    // do something with i.Spec()
	    rv = iter->GetCurrentSpec( &spec);
	    if (NS_SUCCEEDED( rv)) {
	    	isFile = PR_FALSE;
	    	rv = spec->IsFile( &isFile);
			if (NS_SUCCEEDED( rv) && isFile) {
				pLeaf = nsnull;
				rv = spec->GetLeafName( &pLeaf);
				if (NS_SUCCEEDED( rv) && pLeaf && 
					((sLen = nsCRT::strlen( pLeaf)) > 4) && 
					(!nsCRT::strcasecmp( pLeaf + sLen - 3, "dbx"))) {
					// This is a *.dbx file in the mail directory
					if (nsOE5File::IsLocalMailFile( spec)) {
						pEntry = new MailboxEntry;
						pEntry->index = index;
						index++;
						pEntry->parent = 0;
						pEntry->child = 0;
						pEntry->sibling = index;
						pEntry->type = -1;
						pEntry->fileName = pLeaf;
						pLeaf[sLen - 4] = 0;
						pEntry->mailName = pLeaf;
						m_entryArray.AppendElement( pEntry);				
					}
				}
				if (pLeaf)
					nsCRT::free( pLeaf);
			}
		}
		rv = iter->Next();    
		exists = PR_FALSE;
		rv = iter->Exists( &exists);
	}
	
	if (m_entryArray.Count() > 0) {
		pEntry = (MailboxEntry *)m_entryArray.ElementAt( m_entryArray.Count() - 1);
		pEntry->sibling = -1;
		return( PR_TRUE);
	}

	return( PR_FALSE);
}


void nsOEScanBoxes::ScanMailboxDir( nsIFileSpec * srcDir)
{
	if (Scan50MailboxDir( srcDir))
		return;

	Reset();

	MailboxEntry *	pEntry;	
	PRInt32			index = 1;
	char *			pLeaf;
	PRUint32		sLen;
	
	nsIFileSpec *			spec;
	nsIDirectoryIterator *	iter;
	
	if (NS_FAILED( NS_NewDirectoryIterator( &iter)))
		return;
	if (NS_FAILED( iter->Init( srcDir, PR_TRUE))) {
		iter->Release();
		return;
	}
	nsresult	rv;
	PRBool		exists = PR_FALSE;
	PRBool		isFile;
	
	rv = iter->Exists( &exists);
	while (NS_SUCCEEDED( rv) && exists) {
	    // do something with i.Spec()
	    rv = iter->GetCurrentSpec( &spec);
	    if (NS_SUCCEEDED( rv)) {
	    	isFile = PR_FALSE;
	    	rv = spec->IsFile( &isFile);
			if (NS_SUCCEEDED( rv) && isFile) {
				pLeaf = nsnull;
				rv = spec->GetLeafName( &pLeaf);
				if (NS_SUCCEEDED( rv) && pLeaf && 
					((sLen = nsCRT::strlen( pLeaf)) > 4) && 
					(!nsCRT::strcasecmp( pLeaf + sLen - 3, "mbx"))) {
					// This is a *.mbx file in the mail directory
					pEntry = new MailboxEntry;
					pEntry->index = index;
					index++;
					pEntry->parent = 0;
					pEntry->child = 0;
					pEntry->sibling = index;
					pEntry->type = -1;
					pEntry->fileName = pLeaf;
					pLeaf[sLen - 4] = 0;
					pEntry->mailName = pLeaf;
					m_entryArray.AppendElement( pEntry);				
				}
				if (pLeaf)
					nsCRT::free( pLeaf);
			}
		}
		rv = iter->Next();    
		exists = PR_FALSE;
		rv = iter->Exists( &exists);
	}
	
	if (m_entryArray.Count() > 0) {
		pEntry = (MailboxEntry *)m_entryArray.ElementAt( m_entryArray.Count() - 1);
		pEntry->sibling = -1;
	}
}


PRUint32 nsOEScanBoxes::CountMailboxes( MailboxEntry *pBox)
{
	if (pBox == nsnull) {
		if (m_pFirst != nsnull)
			pBox = m_pFirst;
		else {
			if (m_entryArray.Count() > 0)
				pBox = (MailboxEntry *) m_entryArray.ElementAt( 0);
		}
	}
	PRUint32		count = 0;
	
	MailboxEntry *	pChild;
	while (pBox) {
		count++;
		if (pBox->child) {
			pChild = GetIndexEntry( pBox->child);
			if (pChild != nsnull)
				count += CountMailboxes( pChild);
		}
		if (pBox->sibling != -1) {
			pBox = GetIndexEntry( pBox->sibling);
		}
		else
			pBox = nsnull;
	}
	
	return( count);
}

PRBool nsOEScanBoxes::GetMailboxList( nsIFileSpec * root, nsISupportsArray **pArray)
{	
	nsresult rv = NS_NewISupportsArray( pArray);
	if (NS_FAILED( rv)) {
		IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n");
		return( PR_FALSE);
	}
	
	BuildMailboxList( nsnull, root, 1, *pArray);
	
	return( PR_TRUE);
}

void nsOEScanBoxes::BuildMailboxList( MailboxEntry *pBox, nsIFileSpec * root, PRInt32 depth, nsISupportsArray *pArray)
{
	if (pBox == nsnull) {
		if (m_pFirst != nsnull) {
			pBox = m_pFirst;
			
			IMPORT_LOG0( "Assigning start of mailbox list to m_pFirst\n");
		}
		else {
			if (m_entryArray.Count() > 0) {
				pBox = (MailboxEntry *) m_entryArray.ElementAt( 0);
	
				IMPORT_LOG0( "Assigning start of mailbox list to entry at index 0\n");
			}
		}
		
		if (pBox == nsnull) {
			IMPORT_LOG0( "ERROR ASSIGNING STARTING MAILBOX\n");
		}
		
	}
	
	nsresult						rv;
	nsIFileSpec *					file;
	MailboxEntry *					pChild;
	nsIImportMailboxDescriptor *	pID;
	nsISupports *					pInterface;
	PRUint32						size;
	
	NS_WITH_SERVICE( nsIImportService, impSvc, kImportServiceCID, &rv);
	if (NS_FAILED( rv))
		return;
	
	while (pBox) {
		rv = impSvc->CreateNewMailboxDescriptor( &pID);
		if (NS_SUCCEEDED( rv)) {
			pID->SetDepth( depth);
			pID->SetIdentifier( pBox->index);
			pID->SetDisplayName( (PRUnichar *)pBox->mailName.GetUnicode());
			if (pBox->fileName.Length() > 0) {
				pID->GetFileSpec( &file);
				file->FromFileSpec( root);
				file->AppendRelativeUnixPath( (const char *)pBox->fileName);
				size = 0;
				file->GetFileSize( &size);
				pID->SetSize( size);
				file->Release();
			}
			rv = pID->QueryInterface( kISupportsIID, (void **) &pInterface);
			pArray->AppendElement( pInterface);
			pInterface->Release();
			pID->Release();
		}
		
		if (pBox->child) {
			pChild = GetIndexEntry( pBox->child);
			if (pChild != nsnull)
				BuildMailboxList( pChild, root, depth + 1, pArray);
		}
		if (pBox->sibling != -1) {
			pBox = GetIndexEntry( pBox->sibling);
		}
		else
			pBox = nsnull;
	}
	
}



nsOEScanBoxes::MailboxEntry * nsOEScanBoxes::GetIndexEntry( PRUint32 index)
{
	PRInt32 max = m_entryArray.Count();
	for (PRInt32 i = 0; i < max; i++) {
		MailboxEntry *pEntry = (MailboxEntry *) m_entryArray.ElementAt( i);
		if (pEntry->index == index)
			return( pEntry);
	}

	return( nsnull);
}


// -------------------------------------------------------
// File utility routines
// -------------------------------------------------------

PRBool nsOEScanBoxes::ReadLong( nsIFileSpec * stream, PRInt32& val, PRUint32 offset)
{
	nsresult	rv;
	rv = stream->Seek( offset);
	if (NS_FAILED( rv))
		return( PR_FALSE);
	
	PRInt32	cntRead;
	char * pReadTo = (char *)&val;
	rv = stream->Read( &pReadTo, sizeof( val), &cntRead);
	
	if (NS_FAILED( rv) || (cntRead != sizeof( val)))
		return( PR_FALSE);
	return( PR_TRUE);
}

PRBool nsOEScanBoxes::ReadLong( nsIFileSpec * stream, PRUint32& val, PRUint32 offset)
{
	nsresult	rv;
	rv = stream->Seek( offset);
	if (NS_FAILED( rv))
		return( PR_FALSE);
	
	PRInt32	cntRead;
	char * pReadTo = (char *)&val;
	rv = stream->Read( &pReadTo, sizeof( val), &cntRead);
	
	if (NS_FAILED( rv) || (cntRead != sizeof( val)))
		return( PR_FALSE);
	return( PR_TRUE);
}

// It appears as though the strings for file name and mailbox
// name are at least 254 chars - verified - they are probably 255
// but why bother going that far!  If a file name is that long then 
// the heck with it.
#define	kOutlookExpressStringLength	252
PRBool nsOEScanBoxes::ReadString( nsIFileSpec * stream, nsString& str, PRUint32 offset)
{
	
	nsresult	rv;
	rv = stream->Seek( offset);
	if (NS_FAILED( rv))
		return( PR_FALSE);
		

	PRInt32	cntRead;
	char	buffer[kOutlookExpressStringLength];
	char *	pReadTo = buffer;
	rv = stream->Read( &pReadTo, kOutlookExpressStringLength, &cntRead);
	
	if (NS_FAILED( rv) || (cntRead != kOutlookExpressStringLength))
		return( PR_FALSE);
	buffer[kOutlookExpressStringLength - 1] = 0;
	str = buffer;
	return( PR_TRUE);
}

PRBool nsOEScanBoxes::ReadString( nsIFileSpec * stream, nsCString& str, PRUint32 offset)
{
	
	nsresult	rv;
	rv = stream->Seek( offset);
	if (NS_FAILED( rv))
		return( PR_FALSE);
		

	PRInt32	cntRead;
	char	buffer[kOutlookExpressStringLength];
	char *	pReadTo = buffer;
	rv = stream->Read( &pReadTo, kOutlookExpressStringLength, &cntRead);
	
	if (NS_FAILED( rv) || (cntRead != kOutlookExpressStringLength))
		return( PR_FALSE);
	buffer[kOutlookExpressStringLength - 1] = 0;
	str = buffer;
	return( PR_TRUE);
}
