//////////////////////////////////////////////////////////////////////
//
// MIME Encoding/Decoding:
// Quoted-printable and Base64 for content encoding;
// Encoded-word for header field encoding.
//
// Jeff Lee
// Dec 11, 2000
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MimeCode.h"
#include "MimeChar.h"
#include "Mime.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CMimeEnvironment - global environment to manage encoding/decoding
//////////////////////////////////////////////////////////////////////
bool CMimeEnvironment::m_bAutoFolding = false;
string CMimeEnvironment::m_strCharset;
list<CMimeEnvironment::CODER_PAIR> CMimeEnvironment::m_listCoders;
list<CMimeEnvironment::FIELD_CODER_PAIR> CMimeEnvironment::m_listFieldCoders;
list<CMimeEnvironment::MEDIA_TYPE_PAIR> CMimeEnvironment::m_listMediaTypes;
CMimeEnvironment CMimeEnvironment::m_globalMgr;
CMimeEnvironment::CMimeEnvironment()
{
// initialize transfer encoding
//REGISTER_MIMECODER("7bit", CMimeCode7bit);
//REGISTER_MIMECODER("8bit", CMimeCode7bit);
REGISTER_MIMECODER("quoted-printable", CMimeCodeQP);
REGISTER_MIMECODER("base64", CMimeCodeBase64);
// initialize header fields encoding
REGISTER_FIELDCODER("Subject", CFieldCodeText);
REGISTER_FIELDCODER("Comments", CFieldCodeText);
REGISTER_FIELDCODER("Content-Description", CFieldCodeText);
REGISTER_FIELDCODER("From", CFieldCodeAddress);
REGISTER_FIELDCODER("To", CFieldCodeAddress);
REGISTER_FIELDCODER("Resent-To", CFieldCodeAddress);
REGISTER_FIELDCODER("Cc", CFieldCodeAddress);
REGISTER_FIELDCODER("Resent-Cc", CFieldCodeAddress);
REGISTER_FIELDCODER("Bcc", CFieldCodeAddress);
REGISTER_FIELDCODER("Resent-Bcc", CFieldCodeAddress);
REGISTER_FIELDCODER("Reply-To", CFieldCodeAddress);
REGISTER_FIELDCODER("Resent-Reply-To", CFieldCodeAddress);
REGISTER_FIELDCODER("Content-Type", CFieldCodeParameter);
REGISTER_FIELDCODER("Content-Disposition", CFieldCodeParameter);
}
void CMimeEnvironment::SetAutoFolding(bool bAutoFolding)
{
m_bAutoFolding = bAutoFolding;
if (!bAutoFolding)
{
DEREGISTER_MIMECODER("7bit");
DEREGISTER_MIMECODER("8bit");
}
else
{
REGISTER_MIMECODER("7bit", CMimeCode7bit);
REGISTER_MIMECODER("8bit", CMimeCode7bit);
}
}
void CMimeEnvironment::RegisterCoder(const char* pszCodingName, CODER_FACTORY pfnCreateObject/*=NULL*/)
{
ASSERT(pszCodingName != NULL);
list<CODER_PAIR>::iterator it = m_listCoders.begin();
while (it != m_listCoders.end())
{
list<CODER_PAIR>::iterator it2 = it;
it++;
if (!::stricmp(pszCodingName, (*it2).first))
m_listCoders.erase(it2);
}
if (pfnCreateObject != NULL)
{
CODER_PAIR newPair(pszCodingName, pfnCreateObject);
m_listCoders.push_front(newPair);
}
}
CMimeCodeBase* CMimeEnvironment::CreateCoder(const char* pszCodingName)
{
if (!pszCodingName || !::strlen(pszCodingName))
pszCodingName = "7bit";
for (list<CODER_PAIR>::iterator it=m_listCoders.begin(); it!=m_listCoders.end(); it++)
{
ASSERT((*it).first != NULL);
if (!::stricmp(pszCodingName, (*it).first))
{
CODER_FACTORY pfnCreateObject = (*it).second;
ASSERT(pfnCreateObject != NULL);
return pfnCreateObject();
}
}
return new CMimeCodeBase; // default coder for unregistered Content-Transfer-Encoding
}
void CMimeEnvironment::RegisterFieldCoder(const char* pszFieldName, FIELD_CODER_FACTORY pfnCreateObject/*=NULL*/)
{
ASSERT(pszFieldName != NULL);
list<FIELD_CODER_PAIR>::iterator it = m_listFieldCoders.begin();
while (it != m_listFieldCoders.end())
{
list<FIELD_CODER_PAIR>::iterator it2 = it;
it++;
if (!::stricmp(pszFieldName, (*it2).first))
m_listFieldCoders.erase(it2);
}
if (pfnCreateObject != NULL)
{
FIELD_CODER_PAIR newPair(pszFieldName, pfnCreateObject);
m_listFieldCoders.push_front(newPair);
}
}
CFieldCodeBase* CMimeEnvironment::CreateFieldCoder(const char* pszFieldName)
{
ASSERT(pszFieldName != NULL);
for (list<FIELD_CODER_PAIR>::iterator it=m_listFieldCoders.begin(); it!=m_listFieldCoders.end(); it++)
{
ASSERT((*it).first != NULL);
if (!::stricmp(pszFieldName, (*it).first))
{
FIELD_CODER_FACTORY pfnCreateObject = (*it).second;
ASSERT(pfnCreateObject != NULL);
return pfnCreateObject();
}
}
return new CFieldCodeBase; // default coder for unregistered header fields
}
void CMimeEnvironment::RegisterMediaType(const char* pszMediaType, BODY_PART_FACTORY pfnCreateObject/*=NULL*/)
{
ASSERT(pszMediaType != NULL);
list<MEDIA_TYPE_PAIR>::iterator it = m_listMediaTypes.begin();
while (it != m_listMediaTypes.end())
{
list<MEDIA_TYPE_PAIR>::iterator it2 = it;
it++;
if (!::stricmp(pszMediaType, (*it2).first))
m_listMediaTypes.erase(it2);
}
if (pfnCreateObject != NULL)
{
MEDIA_TYPE_PAIR newPair(pszMediaType, pfnCreateObject);
m_listMediaTypes.push_front(newPair);
}
}
CMimeBody* CMimeEnvironment::CreateBodyPart(const char* pszMediaType)
{
if (!pszMediaType || !::strlen(pszMediaType))
pszMediaType = "text";
ASSERT(pszMediaType != NULL);
for (list<MEDIA_TYPE_PAIR>::iterator it=m_listMediaTypes.begin(); it!=m_listMediaTypes.end(); it++)
{
ASSERT((*it).first != NULL);
if (!::stricmp(pszMediaType, (*it).first))
{
BODY_PART_FACTORY pfnCreateObject = (*it).second;
ASSERT(pfnCreateObject != NULL);
return pfnCreateObject();
}
}
return new CMimeBody; // default body part for unregistered media type
}
//////////////////////////////////////////////////////////////////////
// CMimeCode7bit - for 7bit/8bit encoding mechanism (fold long line)
//////////////////////////////////////////////////////////////////////
int CMimeCode7bit::GetEncodeLength() const
{
int nSize = m_nInputSize + m_nInputSize / MAX_MIME_LINE_LEN * 4;
//const unsigned char* pbData = m_pbInput;
//const unsigned char* pbEnd = m_pbInput + m_nInputSize;
//while (++pbData < pbEnd)
// if (*pbData == '.' && *(pbData-1) == '\n')
// nSize++;
nSize += 4;
return nSize;
}
int CMimeCode7bit::Encode(unsigned char* pbOutput, int nMaxSize) const
{
const unsigned char* pbData = m_pbInput;
const unsigned char* pbEnd = m_pbInput + m_nInputSize;
unsigned char* pbOutStart = pbOutput;
unsigned char* pbOutEnd = pbOutput + nMaxSize;
unsigned char* pbSpace = NULL;
int nLineLen = 0;
while (pbData < pbEnd)
{
if (pbOutput >= pbOutEnd)
break;
unsigned char ch = *pbData;
//if (ch == '.' && pbData-m_pbInput >= 2 && !::memcmp(pbData-2, "\r\n.", 3))
//{
// *pbOutput++ = '.'; // avoid confusing with SMTP end flag
// nLineLen++;
//}
if (ch == '\r' || ch == '\n')
{
nLineLen = -1;
pbSpace = NULL;
}
else if (nLineLen > 0 && CMimeChar::IsSpace(ch))
pbSpace = pbOutput;
// fold the line if it's longer than 76
if (nLineLen >= MAX_MIME_LINE_LEN && pbSpace != NULL &&
pbOutput+2 <= pbOutEnd)
{
int nSize = (int)(pbOutput - pbSpace);
::memmove(pbSpace+2, pbSpace, nSize);
*pbSpace++ = '\r';
*pbSpace = '\n';
pbSpace = NULL;
nLineLen = nSize;
pbOutput += 2;
}
*pbOutput++ = ch;
pbData++;
nLineLen++;
}
return (int)(pbOutput - pbOutStart);
}
//////////////////////////////////////////////////////////////////////
// CMimeCodeQP - for quoted-printable encoding mechanism
//////////////////////////////////////////////////////////////////////
int CMimeCodeQP::GetEncodeLength() const
{
int nLength = m_nInputSize;
const unsigned char* pbData = m_pbInput;
const unsigned char* pbEnd = m_pbInput + m_nInputSize;
while (pbData < pbEnd)
if (!CMimeChar::IsPrintable(*pbData++))
nLength += 2;
//int nLength = m_nInputSize * 3;
nLength += nLength / (MAX_MIME_LINE_LEN - 2)
eml文件解析 C++ 代码
5星 · 超过95%的资源 需积分: 50 54 浏览量
2012-07-17
10:27:10
上传
评论 9
收藏 20KB ZIP 举报
ytfrdfiw
- 粉丝: 266
- 资源: 790
- 1
- 2
- 3
- 4
- 5
- 6
前往页