Click here to Skip to main content
15,885,835 members
Articles / Desktop Programming / ATL

En/Decode MIME-Content with MimeSniffer

Rate me:
Please Sign up or sign in to vote.
4.88/5 (26 votes)
2 Dec 20022 min read 373.2K   7K   74  
RFC-compliant Mime-En/Decoder
// MimeDecoder.cpp : Implementation of CMimeDecoder
#include "stdafx.h"
#include "MimeSniffer.h"
#include "MimeDecoder.h"
#include "FileSystemStorage.h"
#include "DateTime.h"
#include "MimeBody.h"
#include "Quote.h"
#include "MIMECode.h"
#include "ISSHelper.h"

extern void		MimeDecInit();
extern int		MimeDecparse();

CMutex			CMimeDecoder::s_Mutex;
CMimeDecoder*	CMimeDecoder::s_pCurrentMimeDec		= NULL;	


/////////////////////////////////////////////////////////////////////////////
// CMimeDecoder
static ULONG __Write(LPSTREAM pStm, const char* text)
{
	ULONG nWritten = 0;

	pStm->Write(text, strlen(text), &nWritten);

	return nWritten;
}

CMimeDecoder::CMimeDecoder()
{
	m_nVersionMajor				= 1;
	m_nVersionMinor				= 0;

	m_bInterpretReceivedAsRaw	= true;
	m_bInterpretEmbeddedMails	= true;
	m_bErrorOccured				= false;
	m_pParent					= NULL;

	ATLTRACE(_T("----------------- CMimeDecoder() -----------------\n"));
}

CMimeDecoder::~CMimeDecoder()
{
	ATLTRACE(_T("-----------------~CMimeDecoder() -----------------\n"));
}

STDMETHODIMP CMimeDecoder::InitNew()
{
	m_nVersionMajor	= 1;
	m_nVersionMinor	= 0;

	m_ReturnPath.Init();
	m_listReceived.clear();

	m_ReplyTo.Init();
	m_From.Init();
	m_Sender.Init();

	m_ResentReplyTo.Init();
	m_ResentFrom.Init();
	m_ResentSender.Init();

	m_Date.Init();
	m_ResentDate.Init();

	m_To.Init();
	m_ResentTo.Init();
	m_CC.Init();
	m_ResentCC.Init();
	m_BCC.Init();
	m_ResentBCC.Init();

	m_Subject.Init();
	m_MessageID.Init();

	m_ReturnReceiptTo.Init();

	return S_OK;
}

void CMimeDecoder::SaveMailboxes(LPSTREAM pStm, const char* Intro, CYYSType& addr)
{
	__Write(pStm, Intro);

	if (addr.GetType() == CYYSType::type_ParamMap)
	{
		string		str;
		CYYSType	temp;

		for (CYYSType::param_map::reverse_iterator i = addr.m_mVal.rbegin(); i != addr.m_mVal.rend(); ++i)
		{
			if (i != addr.m_mVal.rbegin())
				__Write(pStm, "\t\t, ");
			else
				__Write(pStm, "\t");

			temp = *i;
			temp.FormatAsMailbox(str);

			__Write(pStm, str.c_str());
			__Write(pStm, "\r\n");
		}
	}
	else
	{
		string str;
		addr.FormatAsMailbox(str);

		__Write(pStm, str.c_str());
		__Write(pStm, "\r\n");
	}
}

STDMETHODIMP CMimeDecoder::Load(LPSTREAM pStm)
{
	if (pStm != NULL)
	{
		int nInitPri = GetThreadPriority(GetCurrentThread());

		if (m_pRawCopy != NULL)
			m_pRawCopy.Release();

		m_pRawCopy = new CISSHelper(true);
		
		do
		{
			// freien Slot suchen
			if (s_Mutex.Lock(0))
			{
				// alte Priorit�t wieder herstellen!
				if (nInitPri != GetThreadPriority(GetCurrentThread()))
					SetThreadPriority(GetCurrentThread(), nInitPri);

				ATLASSERT(s_pCurrentMimeDec == NULL);

				s_pCurrentMimeDec	= this;
				m_pStream			= pStm;

				ATLTRACE(_T("--> Parsing with Slot #0"));
				m_bErrorOccured				= false;
				MimeDecInit();
				MimeDecparse();
				ATLTRACE(_T("<-- Parsing with Slot #0"));

				m_pStream.Release();
				s_pCurrentMimeDec	= NULL;

				s_Mutex.Unlock();
				return m_bErrorOccured ? E_ABORT : S_OK;
			}
			ATLTRACE(_T("No Slot found!"));

			// keinen Slot gefunden :-(
			// in dem Fall mit niedriger Priorit�t weiter versuchen
			if (nInitPri == GetThreadPriority(GetCurrentThread()))
			{
				BOOL bSuc = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
				ATLASSERT(bSuc);
			}
		}
		while(true);
	}
	return E_INVALIDARG;
}

void CMimeDecoder::Modified()
{
	if (!m_bErrorOccured)
	{
		m_bModified = true;

		if (m_pRawCopy != NULL)
			m_pRawCopy.Release();

		if (m_pCommit != NULL)
		{
			SETSIZEOF_STREAM(0, m_pCommit)
			Save(m_pCommit, FALSE);
		}

		if (m_pParent != NULL)
			m_pParent->Modified();
	}
}

void CMimeDecoder::IsProxy(LPSTREAM pStream, CMimeDecoder* pParent)
{
	ATLASSERT(pStream != NULL);
	ATLASSERT(pParent != NULL);

	m_pCommit	= pStream;
	m_pParent	= pParent;

	Load(pStream);
}

STDMETHODIMP CMimeDecoder::Save(LPSTREAM pStm, BOOL fClearDirty)
{
	// Solange der Stream nicht ver�ndert wurde,
	// geben wir die rohe Kopie unver�ndert
	// weiter!
	if (m_pRawCopy != NULL && pStm != NULL)
	{
		CMIMECodeRaw copy;

		copy.Decode(m_pRawCopy, pStm);

		return S_OK;
	}
	if (pStm != NULL)
	{
		bool bSaveInterpretEmbeddedMails = m_bInterpretEmbeddedMails;

		m_bInterpretEmbeddedMails = false;

		char buf[512];

		USES_CONVERSION;

		// Zun�chst mal alle Received-Felder
		if (!m_listReceived.empty())
		{
			for (list<pair<CYYSType, CYYSType> >::iterator i = m_listReceived.begin(); i != m_listReceived.end(); ++i)
			{
				const CYYSType& received	= i->first;
				const CYYSType& dt			= i->second;

				if (received.GetType() == CYYSType::type_ParamMap)
				{
					__Write(pStm, "Received: ");

					for (CYYSType::param_map::const_iterator i = received.m_mVal.begin(); i != received.m_mVal.end(); ++i)
					{
						if (i != received.m_mVal.begin())
						{
							__Write(pStm, "\r\n\t\t");
						}
						__Write(pStm, i->first.c_str());
						__Write(pStm, " ");

						if (i->second.vt == VT_BSTR)
						{
							__Write(pStm, OLE2CA(i->second.bstrVal));
						}
						else
						{
							CComVariant vtVal(i->second);

							vtVal.ChangeType(VT_BSTR);

							if (vtVal.vt == VT_BSTR)
							{
								__Write(pStm, OLE2CA(vtVal.bstrVal));
							}
						}
					}
					__Write(pStm, "; ");
					__Write(pStm, dt);
					__Write(pStm, "\r\n");
				}
				else
				{
					ATLASSERT(dt.GetType() == CYYSType::type_Param);

					if (dt.GetType() == CYYSType::type_Param)
					{
						__Write(pStm, dt.m_pVal.first.c_str());
						__Write(pStm, dt);
						__Write(pStm, "\r\n");
					}
				}
			}
		}
		// Return-Path
		if (m_ReturnPath.IsValid())
		{
			ATLASSERT(m_ReturnPath.GetType() == CYYSType::type_Param);

			if (m_ReturnPath.GetType() == CYYSType::type_Param)
			{
				__Write(pStm, "Return-path: ");
				__Write(pStm, m_ReturnPath.m_pVal.first.c_str());
				__Write(pStm, "\r\n");
			}
		}
		// Date
		if (!m_Date.IsValid())
		{
			CDT now = CDT::GetCurrentTime();

			m_Date.PutAsDate(now);
		}
		if (m_Date.IsValid())
		{
			__Write(pStm, "Date: ");
			__Write(pStm, m_Date);
			__Write(pStm, "\r\n");
		}
		// Resent-Date
		if (m_ResentDate.IsValid())
		{
			__Write(pStm, "Resent-Date: ");
			__Write(pStm, m_ResentDate);
			__Write(pStm, "\r\n");
		}
		// Sender
		if (m_Sender.IsValid())
		{
			SaveMailboxes(pStm, "Sender: ", m_Sender);
		}
		// From
		if (m_From.IsValid())
		{
			SaveMailboxes(pStm, "From: ", m_From);
		}
		// Reply-To
		if (m_ReplyTo.IsValid())
		{
			SaveMailboxes(pStm, "Reply-To: ", m_ReplyTo);
		}
		// Resent-Sender
		if (m_ResentSender.IsValid())
		{
			SaveMailboxes(pStm, "Resent-Sender: ", m_ResentSender);
		}
		// Resent-From
		if (m_ResentFrom.IsValid())
		{
			SaveMailboxes(pStm, "Resent-From: ", m_ResentFrom);
		}
		// Resent-Reply-To
		if (m_ResentReplyTo.IsValid())
		{
			SaveMailboxes(pStm, "Resent-Reply-To: ", m_ResentReplyTo);
		}
		// To
		if (m_To.IsValid())
		{
			SaveMailboxes(pStm, "To: ", m_To);
		}
		// Resent-To
		if (m_ResentTo.IsValid())
		{
			SaveMailboxes(pStm, "Resent-To: ", m_ResentTo);
		}
		// CC
		if (m_CC.IsValid())
		{
			SaveMailboxes(pStm, "cc: ", m_CC);
		}
		// Resent-cc
		if (m_ResentCC.IsValid())
		{
			SaveMailboxes(pStm, "Resent-cc: ", m_ResentCC);
		}
		// BCC
		if (m_BCC.IsValid())
		{
			SaveMailboxes(pStm, "bcc: ", m_BCC);
		}
		// Resent-cc
		if (m_ResentBCC.IsValid())
		{
			SaveMailboxes(pStm, "Resent-bcc: ", m_ResentBCC);
		}
		// MIME-Version
		sprintf(buf, "MIME-Version: %ld.%ld\r\n", m_nVersionMajor, m_nVersionMinor);
		__Write(pStm, buf);

		// Message-ID
		if (m_MessageID.IsValid())
		{
			__Write(pStm, "Message-ID: ");
			__Write(pStm, m_MessageID);
			__Write(pStm, "\r\n");
		}
		// Subject
		if (m_Subject.IsValid())
		{
			__Write(pStm, "Subject: ");
			__Write(pStm, m_Subject);
			__Write(pStm, "\r\n");
		}
		// Return-Receipt-To
		if (m_ReturnReceiptTo.IsValid())
		{
			SaveMailboxes(pStm, "Return-Receipt-To: ", m_ReturnReceiptTo);
		}

		// Alle Bodies
		IPersistStreamPtr pBody;
	
		if (SUCCEEDED(CMimeBody::CreateInstance(&pBody)))
		{
			((CMimeBody*)((IPersistStream*)pBody))->Init(&m_Body, this);
			pBody->Save(pStm, fClearDirty);
		}

		// End of Message (as long we are not a proxy)!
		if (m_pParent == NULL)
			__Write(pStm, ".\r\n");

		m_bInterpretEmbeddedMails = bSaveInterpretEmbeddedMails;

		return S_OK;
	}
	return E_INVALIDARG;
}

void CMimeDecoder::OnError(const char* strError, long nLine)
{
	m_bErrorOccured = true;

	CMIMECodeRaw copy;

	if (m_pStream != NULL && m_pRawCopy != NULL)
		copy.Decode(m_pStream, m_pRawCopy);

#ifdef _DEBUG
	USES_CONVERSION;
	Fire_OnError(A2OLE(strError), nLine);
#endif
}

STDMETHODIMP CMimeDecoder::LoadFromFile(BSTR Path, VARIANT_BOOL* pbvarResult)
{
	USES_CONVERSION;
/*
	m_strPath = OLE2CT(Path);
	*pbvarResult = VARIANT_TRUE;
	Start(10000);
*/

	*pbvarResult = VARIANT_FALSE;

	HANDLE hFile = ::CreateFile(OLE2CT(Path), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CFileSystemStream* pStream = new CFileSystemStream(hFile);

		*pbvarResult = SUCCEEDED(Load(pStream)) ? VARIANT_TRUE : VARIANT_FALSE;

		pStream->Release();
	}
	return S_OK;
}

STDMETHODIMP CMimeDecoder::SaveToFile(BSTR Path, VARIANT_BOOL *pbvarResult)
{
	USES_CONVERSION;

	*pbvarResult = VARIANT_FALSE;

	HANDLE hFile = ::CreateFile(OLE2CT(Path), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CFileSystemStream* pStream = new CFileSystemStream(hFile);

		Save(pStream, TRUE);

		pStream->Release();

		*pbvarResult = VARIANT_TRUE;
	}
	return S_OK;
}

void CMimeDecoder::SetVersion(const CYYSType& nMajor, const CYYSType& nMinor)
{
#ifdef _DEBUG
	ATLASSERT(nMajor.GetType() == CYYSType::type_Long && nMinor.GetType() == CYYSType::type_Long);
	ATLTRACE(_T("MIME-Version is: %ld . %ld\n"), (long)nMajor, (long)nMinor);
#endif
	m_nVersionMajor = (long)nMajor;
	m_nVersionMinor = (long)nMinor;
}

void CMimeDecoder::SetReturnPath(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT(addr.GetType() == CYYSType::type_Param);
	ATLTRACE(_T("Return-Path is: %s\n"), addr.m_pVal.first.c_str());
#endif

	m_ReturnPath = addr;
}

void CMimeDecoder::AddReceived(const CYYSType& received, const CYYSType& dt)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLTRACE(_T("Received: %s\n"), (const char*)dt);

	ATLASSERT(received.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = received.m_mVal.begin(); i != received.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("        Parameter:%s          Value:%s\n"), i->first.c_str(), OLE2CT(vtVal.bstrVal));
		}
	}
#endif
	m_listReceived.push_back(pair<CYYSType, CYYSType>(received, dt));
}

void CMimeDecoder::AddReceivedRaw(const CYYSType& field)
{
	ATLASSERT(field.GetType() == CYYSType::type_Param);
	ATLTRACE(_T("%s%s\n"), field.m_pVal.first.c_str(), (const char*)field);

	m_listReceived.push_back(pair<CYYSType, CYYSType>(CYYSType(), field));
}

void CMimeDecoder::SetReplyTo(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT(addr.GetType() == CYYSType::type_Param);
	ATLTRACE(_T("ReplyTo: %s\n"), addr.m_pVal.first.c_str());
#endif

	m_ReplyTo = addr;
}

void CMimeDecoder::SetFrom(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	if (addr.GetType() == CYYSType::type_ParamMap)
	{
		for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
		{
			CComVariant vtVal(i->second);

			vtVal.ChangeType(VT_BSTR);

			if (vtVal.vt == VT_BSTR)
			{
				ATLTRACE(_T("From: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
			}
		}
	}
	else
	{
		ATLASSERT(addr.GetType() == CYYSType::type_Param);

		CComVariant vtVal(addr.m_pVal.second);
		vtVal.ChangeType(VT_BSTR);
		ATLTRACE(_T("From: %s %s\n"), OLE2CT(vtVal.bstrVal), addr.m_pVal.first.c_str());
	}
#endif
	m_From = addr;
}

void CMimeDecoder::SetSender(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT(addr.GetType() == CYYSType::type_Param);
	ATLTRACE(_T("Sender: %s\n"), addr.m_pVal.first.c_str());
#endif
	m_Sender = addr;
}

void CMimeDecoder::SetResentReplyTo(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("From: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_ResentReplyTo = addr;
}

void CMimeDecoder::SetResentFrom(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	if (addr.GetType() == CYYSType::type_ParamMap)
	{
		for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
		{
			CComVariant vtVal(i->second);

			vtVal.ChangeType(VT_BSTR);

			if (vtVal.vt == VT_BSTR)
			{
				ATLTRACE(_T("From: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
			}
		}
	}
	else
	{
		ATLASSERT(addr.GetType() == CYYSType::type_Param);

		CComVariant vtVal(addr.m_pVal.second);
		vtVal.ChangeType(VT_BSTR);
		ATLTRACE(_T("From: %s %s\n"), OLE2CT(vtVal.bstrVal), addr.m_pVal.first.c_str());
	}
#endif
	m_ResentFrom = addr;
}

void CMimeDecoder::SetResentSender(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT(addr.GetType() == CYYSType::type_Param);
	ATLTRACE(_T("Sender: %s\n"), addr.m_pVal.first.c_str());
#endif
	m_ResentSender = addr;
}

void CMimeDecoder::SetDate(const CYYSType& dt)
{
	ATLTRACE(_T("Date: %s\n"), (const char*)dt);
	m_Date = dt;
}

void CMimeDecoder::SetResentDate(const CYYSType& dt)
{
	ATLTRACE(_T("ResentDate: %s\n"), (const char*)dt);
	m_ResentDate = dt;
}

void CMimeDecoder::SetTo(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("To: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_To = addr;
}

void CMimeDecoder::SetReturnReceiptTo(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("ReturnReceiptTo: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_ReturnReceiptTo = addr;
}

void CMimeDecoder::SetResentTo(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("ResentTo: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_ResentTo = addr;
}

void CMimeDecoder::SetCC(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("CC: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_CC = addr;
}

void CMimeDecoder::SetResentCC(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("ResentCC: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_ResentCC = addr;
}

void CMimeDecoder::SetBCC(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("BCC: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_BCC = addr;
}

void CMimeDecoder::SetResentBCC(const CYYSType& addr)
{
#ifdef _DEBUG
	USES_CONVERSION;

	ATLASSERT (addr.GetType() == CYYSType::type_ParamMap);

	for (CYYSType::param_map::const_iterator i = addr.m_mVal.begin(); i != addr.m_mVal.end(); ++i)
	{
		CComVariant vtVal(i->second);

		vtVal.ChangeType(VT_BSTR);

		if (vtVal.vt == VT_BSTR)
		{
			ATLTRACE(_T("ResentBCC: %s %s\n"), OLE2CT(vtVal.bstrVal), i->first.c_str());
		}
	}
#endif
	m_ResentBCC = addr;
}

void CMimeDecoder::SetSubject(const CYYSType& str)
{
	ATLTRACE(_T("Subject is: %s\n"), (const char*)str);
	m_Subject = str;
}

void CMimeDecoder::SetMessageID(const CYYSType& id)
{
	ATLTRACE(_T("Message-ID is: %s\n"), (const char*)id);
	m_MessageID = id;
}

void CMimeDecoder::SetBody(const CYYSType& body)
{
	ATLTRACE(_T("Found Body:\n"));

#ifdef _DEBUG
	body.Dump();
#endif
	m_Body = body;
}

STDMETHODIMP CMimeDecoder::get_ReturnPath(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ReturnPath.IsValid())
	{
		if (!m_ReturnPath.GetAsMailAddress(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ReturnPath(VARIANT newVal)
{
	m_ReturnPath.PutAsMailAddress(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_MajorMimeVersion(long *pVal)
{
	*pVal = m_nVersionMajor;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::put_MajorMimeVersion(long newVal)
{
	m_nVersionMajor = newVal;
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_MinorMimeVersion(long *pVal)
{
	*pVal = m_nVersionMinor;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::put_MinorMimeVersion(long newVal)
{
	m_nVersionMinor = newVal;
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ReplyTo(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ReplyTo.IsValid())
	{
		if (!m_ReplyTo.GetAsMailAddress(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ReplyTo(VARIANT newVal)
{
	m_ReplyTo.PutAsMailAddress(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_From(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_From.IsValid())
	{
		if (m_From.GetType() == CYYSType::type_ParamMap)
		{
			if (!m_From.GetAsMailAddresses(vtResult))
				return E_FAIL;
		}
		else
		{
			if (!m_From.GetAsMailAddress(vtResult))
				return E_FAIL;
		}
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_From(VARIANT newVal)
{
	bool bMultiple = false;

	if (newVal.vt == VT_DISPATCH)
	{
		CComDispatchDriverEx dummy(newVal.pdispVal);

		IEnumVARIANTPtr pTest;

		if (SUCCEEDED(dummy.Enum(&pTest)))
			bMultiple = true;
	}
	if (bMultiple)
		m_From.PutAsMailAddresses(newVal);
	else
		m_From.PutAsMailAddress(newVal);

	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_Sender(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_Sender.IsValid())
	{
		if (!m_Sender.GetAsMailAddress(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_Sender(VARIANT newVal)
{
	m_Sender.PutAsMailAddress(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ResentReplyTo(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ResentReplyTo.IsValid())
	{
		if (!m_ResentReplyTo.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ResentReplyTo(VARIANT newVal)
{
	m_ResentReplyTo.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ResentFrom(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ResentFrom.IsValid())
	{
		if (!m_ResentFrom.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ResentFrom(VARIANT newVal)
{
	m_ResentFrom.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ResentSender(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ResentSender.IsValid())
	{
		if (!m_ResentSender.GetAsMailAddress(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ResentSender(VARIANT newVal)
{
	m_ResentSender.PutAsMailAddress(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_Date(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_Date.IsValid())
	{
		if (!m_Date.GetAsDate(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_Date(VARIANT newVal)
{
	m_Date.PutAsDate(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ResentDate(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ResentDate.IsValid())
	{
		if (!m_ResentDate.GetAsDate(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ResentDate(VARIANT newVal)
{
	m_ResentDate.PutAsDate(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_To(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_To.IsValid())
	{
		if (!m_To.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_To(VARIANT newVal)
{
	m_To.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_CC(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_CC.IsValid())
	{
		if (!m_CC.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_CC(VARIANT newVal)
{
	m_CC.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_BCC(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_BCC.IsValid())
	{
		if (!m_BCC.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_BCC(VARIANT newVal)
{
	m_BCC.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_Subject(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_Subject.IsValid())
	{
		if (!m_Subject.GetAsUnQuotedText(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_Subject(VARIANT newVal)
{
	m_Subject.PutAsQuotedInlineText(newVal);

	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_SubjectRaw(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_Subject.IsValid())
	{
		if (!m_Subject.GetAsPlainText(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_SubjectRaw(VARIANT newVal)
{
	m_Subject.PutAsPlainText(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_MessageID(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_MessageID.IsValid())
	{
		if (!m_MessageID.GetAsPlainText(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_MessageID(VARIANT newVal)
{
	m_MessageID.PutAsPlainText(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ReceivedFieldAsRaw(VARIANT_BOOL *pVal)
{
	*pVal = m_bInterpretReceivedAsRaw ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::put_ReceivedFieldAsRaw(VARIANT_BOOL newVal)
{
	m_bInterpretReceivedAsRaw = newVal != VARIANT_FALSE ? true : false;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_InterpretEmbeddedMails(VARIANT_BOOL *pVal)
{
	*pVal = m_bInterpretEmbeddedMails ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::put_InterpretEmbeddedMails(VARIANT_BOOL newVal)
{
	m_bInterpretEmbeddedMails = newVal != VARIANT_FALSE ? true : false;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_ReturnReceiptTo(VARIANT *pVal)
{
	CComVariant vtResult;

	if (m_ReturnReceiptTo.IsValid())
	{
		if (!m_ReturnReceiptTo.GetAsMailAddresses(vtResult))
			return E_FAIL;
	}
	return ::VariantCopyInd(pVal, &vtResult);
}

STDMETHODIMP CMimeDecoder::put_ReturnReceiptTo(VARIANT newVal)
{
	m_ReturnReceiptTo.PutAsMailAddresses(newVal);
	Modified();

	return S_OK;
}

STDMETHODIMP CMimeDecoder::get_Body(VARIANT *pVal)
{
	HRESULT hr;

	if (pVal->vt != VT_EMPTY)
		::VariantClear(pVal);

	if (!m_bErrorOccured)
	{
		pVal->pdispVal = NULL;

		if (SUCCEEDED(hr = CMimeBody::CreateInstance(&pVal->pdispVal)))
		{
			((CMimeBody*)pVal->pdispVal)->Init(&m_Body, this);
			pVal->vt = VT_DISPATCH;
		}
	}
	else
		hr = S_OK;

	return hr;
}

STDMETHODIMP CMimeDecoder::put_Body(VARIANT newVal)
{
	HRESULT hr = E_FAIL;

	if (newVal.vt == VT_BSTR)
	{
		CComDispatchDriverEx body;

		if (SUCCEEDED(hr = CMimeBody::CreateInstance(&body.p)))
		{
			((CMimeBody*)body.p)->Init(&m_Body, this);

			long val = mimetype_text;
			body.PutProperty(L"MajorContentType", val);

			val = text_subtype_plain;
			body.PutProperty(L"MinorContentType", val);

			val = mechanism_quoted_printable;
			body.PutProperty(L"Encoding", val);

			body.PutPropertyByName(L"Value", &newVal);
		}
	}
	return hr;
}

STDMETHODIMP CMimeDecoder::Load(LPDISPATCH StreamObject, VARIANT_BOOL *pbvarRestult)
{
	IStreamPtr pStream;

	*pbvarRestult = VARIANT_FALSE;

	if (SUCCEEDED(StreamObject->QueryInterface(&pStream)))
	{
		*pbvarRestult = SUCCEEDED(Load(pStream)) ? VARIANT_TRUE : VARIANT_FALSE;
	}
	return S_OK;
}

STDMETHODIMP CMimeDecoder::Save(LPDISPATCH StreamObject, VARIANT_BOOL *pbvarRestult)
{
	IStreamPtr pStream;

	*pbvarRestult = VARIANT_FALSE;

	if (SUCCEEDED(StreamObject->QueryInterface(&pStream)))
	{
		*pbvarRestult = SUCCEEDED(Save(pStream, TRUE)) ? VARIANT_TRUE : VARIANT_FALSE;
	}
	return S_OK;
}


STDMETHODIMP CMimeDecoder::get_CanUpdateName(VARIANT_BOOL *pVal)
{
	*pVal = VARIANT_TRUE;

	return S_OK;
}

STDMETHODIMP CMimeDecoder::put_UpdateName(BSTR newVal)
{
	CComVariant var(newVal);

	HRESULT hr = put_Subject(var);

	return hr;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions