www.pudn.com > 20060410_reader_demo.rar > OEReader.cpp, change:2000-02-06,size:12677b


/**************************************************************************** 
 * 
 * Outlook Express File format decoder 
 * 
 **************************************************************************** 
 * 
 * File: OEReader.cpp 
 * 
 * Class implementation by Mladen Bonev (mbonev@dir.bg), based on work by Tom Gallagher 
 * 
 * Copright (c) 1998 Tom Gallagher (teg@cableinet.co.uk) 
 *  
 * Based on initial work by Michael Santovec (michael_santovec@prodigy.net) 
 * and Jeff Evans (evansj@shaw.wave.ca) 
 *  
 * This is not a very complete program but there should be enough info 
 * here for people to create programs to browse their outlook messages 
 * from other OS's if required.  Could also be used to import outlook 
 * messages into other mail readers. 
 * 
 */ 
 
#include "StdAfx.h" //Standard precompiled header of VC 
//If you are using another precomp. header replace this line 
//or if you are using this class in app without precomp. headers include <windows.h> 
#include <stdio.h> 
#include <time.h> 
 
#include "OEReader.h" 
 
#define DBG(s) OutputDebugString(TEXT(s)) 
 
#ifndef DBG1 
#define DBG1(string,value) \ 
	{\ 
		TCHAR szMessageBuf[1024]; \ 
		wsprintf(szMessageBuf,string,value); \ 
		OutputDebugString(TEXT(szMessageBuf));\ 
	} 
#endif 
 
#ifndef DBG2 
#define DBG2(string,value1,value2) \ 
	{\ 
		TCHAR szMessageBuf[1024]; \ 
		wsprintf(szMessageBuf,string,value1,value2); \ 
		OutputDebugString(TEXT(szMessageBuf));\ 
	} 
#endif 
 
 
COE4Reader::COE4Reader() 
{ 
	m_bOpened=FALSE; 
	m_bClosed=TRUE; 
	m_pMailbox=NULL; 
} 
 
COE4Reader::~COE4Reader() 
{ 
	Close(); 
} 
 
time_t COE4Reader::GetMsgSentTime(MAILBOX *pMailBox,DWORD Idx) 
{ 
    DWORD Rem; 
    return FileTimeToUnixTime(&pMailBox->pMsgs[Idx].MsgInfo.Sent,&Rem); 
} 
 
time_t COE4Reader::GetMsgReceivedTime(MAILBOX *pMailBox,DWORD Idx) 
{ 
    DWORD Rem; 
    return FileTimeToUnixTime(&pMailBox->pMsgs[Idx].MsgInfo.Received,&Rem); 
} 
 
/* 
 * Read a variable length string from the IDX file. 
 */ 
int COE4Reader::ReadIdxString(MAILBOX *pMailBox,IDX_STRING *Str) 
{ 
    /* 
     * Read the 4 byte length value 
     */ 
	if (1 != fread(&Str->Length,sizeof(DWORD),1,pMailBox->fptrIDX)) 
	{ 
		DBG("Error reading string length\n"); 
		return FALSE; 
	} 
 
	DBG1("String Length: %d\n",Str->Length); 
 
 
     if (Str->Length > 2048) { 
 
        DBG("String Too Long!!\n"); 
 
        return FALSE; 
 
     }  
 
    /* 
     * Allocate Length + 1 bytes 
     * This routine specifically null terminates the strings 
     * although they appear to have a terminating null stored 
     * in the file anyway. 
     */ 
     
	Str->Data = (BYTE*)malloc(Str->Length+1); 
	 
	if (!Str->Data) 
	{ 
		DBG("Mem alloc err ReadString\n"); 
		return FALSE; 
	} 
	 
	if (1 != fread(Str->Data,Str->Length,1,pMailBox->fptrIDX)) 
	{ 
		DBG("String Data Read Error\n"); 
		return FALSE; 
	} 
	 
	/* Null Terminate */ 
 
	Str->Data[Str->Length] = '\0'; 
 
	DBG1("String Data: %s\n",Str->Data); 
			 
	return TRUE; 
} 
 
 
/* 
 * Read the information that is at the start of each 
 * index entry in the IDX file. 
 */ 
int COE4Reader::ReadIdxMsgHdr(MAILBOX *pMailBox,IDX_MSG_HDR *Entry) 
{ 
 
    int i,j; 
 
	memset(Entry,0,sizeof(IDX_MSG_HDR)); 
	 
	if (1 != fread(Entry,sizeof(IDX_MSG_HDR),1,pMailBox->fptrIDX)) 
	{ 
		DBG("Entry Read Error\n"); 
		return FALSE; 
	} 
 
 
	DBG1("Flags %08X\n",Entry->Flags); 
	DBG1("Entry Num %d\n",Entry->EntryNum); 
	DBG2("nBytes %d (%08X))\n",Entry->nBytes,Entry->nBytes); 
 
	DBG1("Unk1      : %08X\n",Entry->Unk1); 
	DBG1("MBXOffset : %08X\n",Entry->MBXOffset); 
	DBG2("MBXSize   : %d (%08X))\n",Entry->MBXSize,Entry->MBXSize); 
    DBG2("MsgSize   : %d (%08X))\n",Entry->MsgSize,Entry->MsgSize); 
 
    DBG1("(diff))    : %d\n",Entry->MBXSize-Entry->MsgSize); 
 
    DBG2("nAttach   : %d (%08X))\n",Entry->nAttachBytes,Entry->nAttachBytes); 
 
    DBG1("Separators: %d\n",Entry->nSeparators); 
 
    DBG("Padding   : "); 
 
    for(i=0;i<6;i++) 
 
        DBG1("%02X ",Entry->Pad5[i]); 
 
 
 
    DBG("\n"); 
 
    DBG("Padding3  : \n"); 
 
 
 
    for(j=0;j<4;j++) { 
 
        DBG("            "); 
 
        for (i=0;i<16;i++) 
 
            DBG1("%02X ",Entry->Pad3[j*16+i]); 
 
        DBG("\n"); 
 
    }     
 
 
 
    return TRUE; 
 
} 
 
 
 
int COE4Reader::ReadIdxMsgInfo(MAILBOX *pMailbox,IDX_MSG_INFO *pMsgInfo) 
{ 
    memset(pMsgInfo,0,sizeof(IDX_MSG_INFO)); 
 
    if (1 != fread(pMsgInfo,sizeof(IDX_MSG_INFO),1,pMailbox->fptrIDX)) 
    { 
        DBG("MsgInfo Read Error\n"); 
        return FALSE; 
    } 
 
    DBG1("Priority  : %04X\n",pMsgInfo->Priority); 
 
    return TRUE; 
} 
 
int COE4Reader::ReadIdxPart(MAILBOX *pMailbox, IDX_PART *pPart) 
 
{ 
    memset(pPart,0,sizeof(IDX_PART)); 
 
    if (1 != fread(pPart,sizeof(IDX_PART),1,pMailbox->fptrIDX)) 
    { 
        DBG("Part Read Error\n"); 
        return FALSE; 
    } 
 
    return TRUE; 
} 
 
int COE4Reader::CloseMailBox(MAILBOX *pMailBox) 
{ 
    UINT i; 
     
    for(i=0;i<pMailBox->IdxHdr.nItems;i++) 
    { 
        free(pMailBox->pMsgs[i].pParts); 
    } 
     
    free(pMailBox->pMsgs); 
     
    fclose(pMailBox->fptrIDX); 
    fclose(pMailBox->fptrMBX); 
     
    free(pMailBox); 
     
    return TRUE; 
} 
     
 
 
MAILBOX * COE4Reader::OpenMailBox(LPCTSTR Mailbox) 
{ 
    UINT i; 
    char Index[128]; 
    char MBX[128];     
 
    MAILBOX *pMailBox = (MAILBOX *)malloc(sizeof(MAILBOX)); 
 
    strcpy(Index,Mailbox); 
    strcat(Index,".idx"); 
    strcpy(MBX,Mailbox); 
    strcat(MBX,".mbx"); 
 
 
	if (NULL==(pMailBox->fptrIDX=fopen(Index,"rb"))) 
	{ 
		DBG1("Error Opening file - %s\n",Index); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
	if (NULL==(pMailBox->fptrMBX=fopen(MBX,"rb"))) 
	{ 
		DBG1("Error Opening file - %s\n",MBX); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
	if (1 != fread(&pMailBox->IdxHdr,sizeof(IDX_HDR),1,pMailBox->fptrIDX)) 
	{ 
		DBG("IDX Header Read Error\n"); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
	if (1 != fread(&pMailBox->MbxHdr,sizeof(MBX_HDR),1,pMailBox->fptrMBX)) 
	{ 
		DBG("MBX Header Read Error\n"); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
	if (pMailBox->IdxHdr.Magic != IDX_MAGIC) 
	{ 
		DBG("Not an outlook index file\n"); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
	if (pMailBox->MbxHdr.Magic != MBX_MAGIC) 
	{ 
		DBG("Not an outlook MBX file\n"); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		return NULL; 
	} 
 
 
	DBG1("Version %08X\n",pMailBox->IdxHdr.Version); 
	DBG1("n Items  %d\n",pMailBox->IdxHdr.nItems); 
	DBG1("File Size %d\n",pMailBox->IdxHdr.nBytes); 
 
    pMailBox->pMsgs = (MAILMSG *)malloc(pMailBox->IdxHdr.nItems * sizeof(MAILMSG)); 
 
    if (!pMailBox->pMsgs) 
    { 
        DBG("Error allocating memory for message indexes\n"); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
        return NULL; 
    }         
    
    for (i=0;i<pMailBox->IdxHdr.nItems;i++) 
    { 
        ReadMailMsg(pMailBox,&pMailBox->pMsgs[i]); 
    } 
 
	m_bOpened=TRUE; 
	m_bClosed=FALSE; 
    return pMailBox; 
} 
 
int COE4Reader::ReadMailMsg(MAILBOX *pMailBox,MAILMSG *pMsg) 
{ 
    long  CurPos = 0; 
	DWORD Rem = 0; 
	UINT i = 0; 
 
	DBG("************************\n"); 
	 
 
	CurPos = ftell(pMailBox->fptrIDX); 
 
/* 
 * Read the Message Index Entry Header 
 */ 
    ReadIdxMsgHdr(pMailBox,&pMsg->IdxEntry); 
/* 
 * Read the multi part MIME descriptions (if any) 
 */ 
  
    pMsg->pParts = (IDX_PART*)malloc(sizeof(IDX_PART) * pMsg->IdxEntry.nSeparators); 
 
    for (i=0;i<pMsg->IdxEntry.nSeparators;i++) 
    { 
        int j; 
         
        ReadIdxPart(pMailBox,&pMsg->pParts[i]); 
        DBG("****\n"); 
 
        DBG("Pad:\n"); 
        for (j=0;j<7;j++) 
            DBG1("%08X ",pMsg->pParts[i].Pad[j]); 
 
        DBG("\n"); 
 
        DBG("Pad2:\n"); 
        for (j=0;j<10;j++) 
            DBG1("%08X ",pMsg->pParts[i].Pad2[j]); 
 
        DBG("\n"); 
        DBG2("Pad1      : %d (%08X)\n",pMsg->pParts[i].Pad1,pMsg->pParts[i].Pad1); 
        DBG2("Idx?      : %d (%08X)\n",pMsg->pParts[i].Idx ,pMsg->pParts[i].Idx);         
 
        DBG("\n"); 
 
        DBG("****\n"); 
    } 
    /* 50 */ 
/* 
 * Position the file pointer to the trailing data 
 */ 
    fseek(pMailBox->fptrIDX,CurPos+pMsg->IdxEntry.nAttachBytes+0x32,SEEK_SET); 
/* 
 * Read the trailing message information 
 */ 
    ReadIdxMsgInfo(pMailBox,&pMsg->MsgInfo); 
/* 
 * Read the variable length string data 
 */ 
	 if (!ReadIdxString(pMailBox,&pMsg->Subject)) 
	 { 
	 	//return FALSE; 
	 } 
	 
	 if (!ReadIdxString(pMailBox,&pMsg->Sender)) 
	 { 
	 	//return FALSE; 
	 } 
 
	 if (!ReadIdxString(pMailBox,&pMsg->POPServer)) 
	 { 
	 	//return FALSE; 
	 } 
 
	 if (!ReadIdxString(pMailBox,&pMsg->Username)) 
	 { 
	 	//return FALSE; 
	 } 
 
	 if (!ReadIdxString(pMailBox,&pMsg->MailAccount)) 
	 { 
	 	//return FALSE; 
	 } 
 
	 if (!ReadIdxString(pMailBox,&pMsg->POP3Login)) 
	 { 
	 	//return FALSE; 
	 } 
 
	 if (!ReadIdxString(pMailBox,&pMsg->AccDesc)) 
	 { 
	 	//return FALSE; 
	 } 
/* 
 * Position the file pointer to the start if the next index entry 
 */ 
	fseek(pMailBox->fptrIDX,CurPos+pMsg->IdxEntry.nBytes,SEEK_SET); 
	return TRUE; 
} 
 
time_t COE4Reader::FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) 
{ 
    /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ 
#if USE_LONG_LONG 
 
    long long int t = filetime->dwHighDateTime; 
    t <<= 32; 
    t += (UINT32)filetime->dwLowDateTime; 
    t -= 116444736000000000LL; 
    if (t < 0) 
    { 
	if (remainder) *remainder = 9999999 - (-t - 1) % 10000000; 
	return -1 - ((-t - 1) / 10000000); 
    } 
    else 
    { 
	if (remainder) *remainder = t % 10000000; 
	return t / 10000000; 
    } 
 
#else  /* ISO version */ 
 
    UINT32 a0;			/* 16 bit, low    bits */ 
    UINT32 a1;			/* 16 bit, medium bits */ 
    UINT32 a2;			/* 32 bit, high   bits */ 
    UINT32 r;			/* remainder of division */ 
    unsigned int carry;		/* carry bit for subtraction */ 
    int negative;		/* whether a represents a negative value */ 
 
    /* Copy the time values to a2/a1/a0 */ 
    a2 =  (UINT32)filetime->dwHighDateTime; 
    a1 = ((UINT32)filetime->dwLowDateTime ) >> 16; 
    a0 = ((UINT32)filetime->dwLowDateTime ) & 0xffff; 
 
    /* Subtract the time difference */ 
    if (a0 >= 32768           ) a0 -=             32768        , carry = 0; 
    else                        a0 += (1 << 16) - 32768        , carry = 1; 
 
    if (a1 >= 54590    + carry) a1 -=             54590 + carry, carry = 0; 
    else                        a1 += (1 << 16) - 54590 - carry, carry = 1; 
 
    a2 -= 27111902 + carry; 
     
    /* If a is negative, replace a by (-1-a) */ 
    negative = (a2 >= ((UINT32)1) << 31); 
    if (negative) 
    { 
	/* Set a to -a - 1 (a is a2/a1/a0) */ 
	a0 = 0xffff - a0; 
	a1 = 0xffff - a1; 
	a2 = ~a2; 
    } 
 
    /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. 
       Split the divisor into 10000 * 1000 which are both less than 0xffff. */ 
    a1 += (a2 % 10000) << 16; 
    a2 /=       10000; 
    a0 += (a1 % 10000) << 16; 
    a1 /=       10000; 
    r   =  a0 % 10000; 
    a0 /=       10000; 
 
    a1 += (a2 % 1000) << 16; 
    a2 /=       1000; 
    a0 += (a1 % 1000) << 16; 
    a1 /=       1000; 
    r  += (a0 % 1000) * 10000; 
    a0 /=       1000; 
 
    /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ 
    if (negative) 
    { 
	/* Set a to -a - 1 (a is a2/a1/a0) */ 
	a0 = 0xffff - a0; 
	a1 = 0xffff - a1; 
	a2 = ~a2; 
 
        r  = 9999999 - r; 
    } 
 
    if (remainder) *remainder = r; 
 
    /* Do not replace this by << 32, it gives a compiler warning and it does 
       not work. */ 
    return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; 
#endif 
} 
 
BOOL COE4Reader::OpenFile(LPCSTR szFileName) 
{ 
	m_pMailbox = OpenMailBox(szFileName); 
	return (m_pMailbox!=NULL ? TRUE : FALSE); 
} 
 
void COE4Reader::Close() 
{ 
	if(m_bOpened && !m_bClosed && (m_pMailbox!=NULL) ) { 
		CloseMailBox(m_pMailbox); 
		m_bOpened=FALSE; 
		m_bClosed=TRUE; 
		m_pMailbox=NULL; 
	} 
} 
 
const LPMAILMSG COE4Reader::GetMessageAt(int nIndex) 
{ 
	if( (!IsOpen() ) || (nIndex < 0) || (nIndex > (int)m_pMailbox->IdxHdr.nItems)) 
		return NULL; 
	return &m_pMailbox->pMsgs[nIndex]; 
} 
 
BOOL COE4Reader::GetMessageAt(int nIndex, LPMAILMSG lpMsg) 
{ 
	if( (!IsOpen() ) || (nIndex < 0) || \ 
		(nIndex > (int)m_pMailbox->IdxHdr.nItems) || \ 
		(lpMsg==NULL) ) 
		return FALSE; 
	memcpy(lpMsg,&m_pMailbox->pMsgs[nIndex],sizeof(MAILMSG)); 
	return TRUE; 
} 
 
BOOL COE4Reader::GetMailbox(LPMAILBOX lpMailbox) 
{  
	memcpy(lpMailbox,m_pMailbox,sizeof(MAILBOX));  
	return TRUE; 
}