|
|
/*
* h t t p u t i l. c p p * * Author: Greg Friedman * * Purpose: Utility functions used to implement http mail. * * Copyright (C) Microsoft Corp. 1998. */
#include "pch.hxx"
#include "httputil.h"
#include "xpcomm.h"
#include "iso8601.h"
#include "storutil.h"
#include "flagconv.h"
#include "demand.h"
//----------------------------------------------------------------------
// Http_FreeTargetList
//----------------------------------------------------------------------
void Http_FreeTargetList(LPHTTPTARGETLIST pTargets) { if (pTargets) { if (pTargets->prgTarget) { for (DWORD dw = 0; dw < pTargets->cTarget; dw++) { if (pTargets->prgTarget[dw]) MemFree(const_cast<char *>(pTargets->prgTarget[dw])); } MemFree(pTargets->prgTarget); } MemFree(pTargets); } }
//----------------------------------------------------------------------
// Http_NameFromUrl
//----------------------------------------------------------------------
HRESULT Http_NameFromUrl(LPCSTR pszUrl, LPSTR pszBuffer, DWORD *pdwBufferLen) { HRESULT hr = S_OK; char szLocalBuf[MAX_PATH]; URL_COMPONENTS urlComponents; DWORD dw = 0;
ZeroMemory(&urlComponents, sizeof(URL_COMPONENTS));
// use wininet to break the path out and to decode the url while
// we're at it.
urlComponents.dwStructSize = sizeof(URL_COMPONENTS); urlComponents.lpszUrlPath = szLocalBuf; urlComponents.dwUrlPathLength = MAX_PATH;
if (!InternetCrackUrl(pszUrl, lstrlen(pszUrl), NOFLAGS /* ICU_DECODE */, &urlComponents)) { hr = GetLastError(); goto exit; } // subtract one to start at the char before the last one. this skips
// the last char in the case of a folder that ends in '/'
dw = urlComponents.dwUrlPathLength - 1; while (dw && ('/' != szLocalBuf[dw - 1])) dw--;
// dw represents the count of chars that are NOT in the
// name. reverse it.
dw = urlComponents.dwUrlPathLength - dw;
if (dw >= *pdwBufferLen) { hr = E_OUTOFMEMORY; goto exit; }
CopyMemory(pszBuffer, &szLocalBuf[urlComponents.dwUrlPathLength - dw], dw + 1); *pdwBufferLen = dw;
exit: return hr; }
//----------------------------------------------------------------------
// Http_AddMessageToFolder
//----------------------------------------------------------------------
HRESULT Http_AddMessageToFolder(IMessageFolder *pFolder, LPSTR pszAcctId, LPHTTPMEMBERINFO pmi, MESSAGEFLAGS dwFlags, LPSTR pszUrl, LPMESSAGEID pidMessage) { HRESULT hr = S_OK; MESSAGEINFO mi; FILETIME ft; DWORD dwTimeFlags = NOFLAGS; LPSTR pszFreeFrom = NULL; LPSTR pszFreeTo = NULL; ADDRESSLIST addrList; char szUrlComponent[MAX_PATH]; DWORD dwUrlComponentLen = MAX_PATH; PROPVARIANT rDecodedSubj; PROPVARIANT rDecodedFrom; PROPVARIANT rDecodedTo; LPSTR pszSubject = NULL;
if (NULL == pszUrl) return E_INVALIDARG;
ZeroMemory(&mi, sizeof(MESSAGEINFO));
rDecodedSubj.vt = rDecodedFrom.vt = rDecodedTo.vt = VT_LPSTR; rDecodedSubj.pszVal = rDecodedFrom.pszVal = rDecodedTo.pszVal = NULL;
// build a message info and pump the header into the store
mi.pszAcctId = pszAcctId;
// get the store to generate an id
if (FAILED(hr = pFolder->GenerateId((DWORD *)&mi.idMessage))) goto exit;
if (NULL != pidMessage) *pidMessage = mi.idMessage;
if (FAILED(hr = Http_NameFromUrl(pszUrl, szUrlComponent, &dwUrlComponentLen))) goto exit;
mi.dwFlags |= dwFlags;
// if a message info was passed in, use its data
if (NULL != pmi) { mi.cbMessage = pmi->dwContentLength;
if (pmi->fRead) mi.dwFlags = ARF_READ;
if (pmi->fHasAttachment) mi.dwFlags |= ARF_HASATTACH;
if (NULL != pmi->pszSubject) { if (SUCCEEDED(MimeOleDecodeHeader(NULL, pmi->pszSubject, &rDecodedSubj, NULL))) pszSubject = rDecodedSubj.pszVal; else pszSubject = pmi->pszSubject; mi.pszSubject = pszSubject; mi.pszNormalSubj = SzNormalizeSubject(pszSubject); if (NULL == mi.pszNormalSubj) mi.pszNormalSubj = pszSubject; }
if (pmi->pszFrom && S_OK == MimeOleParseRfc822Address(IAT_FROM, IET_ENCODED, pmi->pszFrom, &addrList)) { if (addrList.cAdrs > 0) { pszFreeFrom = addrList.prgAdr[0].pszFriendly; addrList.prgAdr[0].pszFriendly = NULL;
// only use the parsed address if it is at least three chars long
if (pszFreeFrom && lstrlen(pszFreeFrom) >= 3) mi.pszDisplayFrom = pszFreeFrom; } g_pMoleAlloc->FreeAddressList(&addrList); }
if (NULL == mi.pszDisplayFrom && NULL != pmi->pszFrom) { if (SUCCEEDED(MimeOleDecodeHeader(NULL, pmi->pszFrom, &rDecodedFrom, NULL))) mi.pszDisplayFrom = rDecodedFrom.pszVal; else mi.pszDisplayFrom = pmi->pszFrom; }
if (SUCCEEDED(iso8601::toFileTime(pmi->pszDate, &ft, &dwTimeFlags))) { if (!(dwTimeFlags & ISO8601_ST_HOUR)) mi.dwFlags |= ARF_PARTIAL_RECVTIME; mi.ftReceived = ft; } if (pmi->pszTo && S_OK == MimeOleParseRfc822Address(IAT_TO, IET_ENCODED, pmi->pszTo, &addrList)) { if (addrList.cAdrs > 0) { pszFreeTo = addrList.prgAdr[0].pszFriendly; addrList.prgAdr[0].pszFriendly = NULL;
// only use the parsed address if it is at least three chars long
if (pszFreeTo && lstrlen(pszFreeTo) >= 3) mi.pszDisplayTo = pszFreeTo; } g_pMoleAlloc->FreeAddressList(&addrList); }
if (NULL == mi.pszDisplayTo && NULL != pmi->pszTo) { if (SUCCEEDED(MimeOleDecodeHeader(NULL, pmi->pszTo, &rDecodedTo, NULL))) mi.pszDisplayTo = rDecodedTo.pszVal; else mi.pszDisplayTo = pmi->pszTo; } }
mi.pszUrlComponent = szUrlComponent;
// Add it to the database
IF_FAILEXIT(hr = pFolder->InsertRecord(&mi));
// normalize the response
hr = S_OK;
exit: SafeMimeOleFree(rDecodedSubj.pszVal); SafeMimeOleFree(rDecodedFrom.pszVal); SafeMimeOleFree(rDecodedTo.pszVal);
SafeMemFree(pszFreeFrom); SafeMemFree(pszFreeTo);
return hr; }
//----------------------------------------------------------------------
// Http_SetMessageStream
//----------------------------------------------------------------------
HRESULT Http_SetMessageStream(IMessageFolder *pFolder, MESSAGEID idMessage, IStream *pStream, LPFILEADDRESS pfa, BOOL fSetDisplayProps) { HRESULT hr = S_OK; IMimeMessage *pMimeMsg = NULL; IMimePropertySet *pPropertySet = NULL; DWORD dwFlags = 0; MESSAGEINFO mi = {0}; LPMESSAGEINFO pmiFree = NULL; FILETIME ftCurrent; PROPVARIANT rVariant; IMimeAddressTable *pAdrTable = NULL; ADDRESSPROPS rAddress = {0};
LPSTR pszDisplayFrom = NULL; LPSTR pszEmailFrom = NULL; LPSTR pszDisplayTo = NULL; LPSTR pszEmailTo = NULL; LPSTR pszMessageId = NULL; LPSTR pszXref = NULL; LPSTR pszReferences = NULL; LPSTR pszSubject = NULL; LPSTR pszNormalSubj = NULL; LPSTR pszAcctId = NULL; LPSTR pszAcctName = NULL; LPSTR pszServer = NULL; LPSTR pszForwardTo = NULL; LPSTR pszMSOESRec = NULL;
// Default Sent and Received Times...
GetSystemTimeAsFileTime(&ftCurrent);
// Create a Message. We can't use the folder's OpenMessage
// method, because the folder's stream will be locked for write
// access.
IF_FAILEXIT(hr = MimeOleCreateMessage(NULL, &pMimeMsg));
IF_FAILEXIT(hr = HrRewindStream(pStream));
IF_FAILEXIT(hr = pMimeMsg->Load(pStream));
// Get the Root Property Set from the Message
IF_FAILEXIT(hr = pMimeMsg->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pPropertySet));
// find the message in the store
IF_FAILEXIT(hr = GetMessageInfo(pFolder, idMessage, &mi));
pmiFree = &mi;
// update the fields of the message info
if (SUCCEEDED(pMimeMsg->GetFlags(&dwFlags))) mi.dwFlags |= ConvertIMFFlagsToARF(dwFlags);
// unset the download flag
mi.dwFlags &= ~ARF_DOWNLOAD;
// Set Variant tyStore
rVariant.vt = VT_UI4;
// Priority
if (SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant))) mi.wPriority = (WORD)rVariant.ulVal;
// Init Variant
rVariant.vt = VT_FILETIME;
if (0 == mi.ftSent.dwLowDateTime && 0 == mi.ftSent.dwHighDateTime) { if (SUCCEEDED(pMimeMsg->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant))) mi.ftSent = rVariant.filetime; else mi.ftSent = ftCurrent; }
if (0 == mi.ftReceived.dwLowDateTime && 0 == mi.ftReceived.dwHighDateTime) { if (SUCCEEDED(pMimeMsg->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &rVariant))) mi.ftReceived = rVariant.filetime; else mi.ftReceived = ftCurrent; } // Get Address Table
IF_FAILEXIT(hr = pPropertySet->BindToObject(IID_IMimeAddressTable, (LPVOID *)&pAdrTable));
// Display From
if (fSetDisplayProps && NULL == mi.pszDisplayFrom) { pAdrTable->GetFormat(IAT_FROM, AFT_DISPLAY_FRIENDLY, &pszDisplayFrom); mi.pszDisplayFrom = pszDisplayFrom; }
// Email From
rAddress.dwProps = IAP_EMAIL; if (NULL == mi.pszEmailFrom && SUCCEEDED(pAdrTable->GetSender(&rAddress))) { pszEmailFrom = rAddress.pszEmail; mi.pszEmailFrom = pszEmailFrom; }
// Display to
if (fSetDisplayProps && NULL == mi.pszDisplayTo) { pAdrTable->GetFormat(IAT_TO, AFT_DISPLAY_FRIENDLY, &pszDisplayTo); mi.pszDisplayTo = pszDisplayTo; }
// Email To
if (NULL == mi.pszEmailTo) { pAdrTable->GetFormat(IAT_TO, AFT_DISPLAY_EMAIL, &pszEmailTo); mi.pszEmailTo = pszEmailTo; }
// String properties
rVariant.vt = VT_LPSTR;
// pszMessageId
if (NULL == mi.pszMessageId && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_HDR_MESSAGEID), NOFLAGS, &rVariant))) { pszMessageId = rVariant.pszVal; mi.pszMessageId = pszMessageId; }
// pszXref
if (NULL == mi.pszXref && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_HDR_XREF), NOFLAGS, &rVariant))) { pszXref = rVariant.pszVal; mi.pszXref = pszXref; }
// pszReferences
if (NULL == mi.pszReferences && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(STR_HDR_REFS), NOFLAGS, &rVariant))) { pszReferences = rVariant.pszVal; mi.pszReferences = pszReferences; }
// pszSubject
if (NULL == mi.pszSubject && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &rVariant))) { pszSubject = rVariant.pszVal; mi.pszSubject = pszSubject; }
// pszNormalSubj
if (fSetDisplayProps && NULL == mi.pszNormalSubj && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_ATT_NORMSUBJ), NOFLAGS, &rVariant))) { pszNormalSubj = rVariant.pszVal; mi.pszNormalSubj = pszNormalSubj; }
// pszAcctId
if (NULL == mi.pszAcctId && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &rVariant))) { pszAcctId = rVariant.pszVal; mi.pszAcctId = pszAcctId; }
// pszAcctName
if (NULL == mi.pszAcctName && SUCCEEDED(pPropertySet->GetProp(STR_ATT_ACCOUNTNAME, NOFLAGS, &rVariant))) { pszAcctName = rVariant.pszVal; mi.pszAcctName = pszAcctName; }
// pszServer
if (NULL == mi.pszServer && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_ATT_SERVER), NOFLAGS, &rVariant))) { pszServer = rVariant.pszVal; mi.pszServer = pszServer; }
// ForwardTo
if (NULL == mi.pszForwardTo && SUCCEEDED(pPropertySet->GetProp(PIDTOSTR(PID_ATT_FORWARDTO), NOFLAGS, &rVariant))) { pszForwardTo = rVariant.pszVal; mi.pszForwardTo = pszForwardTo; }
if (NULL == mi.pszMSOESRec && SUCCEEDED(pPropertySet->GetProp(STR_HDR_XMSOESREC, NOFLAGS, &rVariant))) { pszMSOESRec = rVariant.pszVal; mi.pszMSOESRec = pszMSOESRec; }
IF_FAILEXIT(hr = pFolder->UpdateRecord(&mi));
// if everything succeeded, commit the message to the store
IF_FAILEXIT(hr = pFolder->SetMessageStream(idMessage, pStream));
// the stream has now been used. null out the file address
if (NULL != pfa) *pfa = NULL;
exit: MemFree(pszDisplayFrom); MemFree(pszEmailFrom); MemFree(pszDisplayTo); MemFree(pszEmailTo); MemFree(pszMessageId); MemFree(pszXref); MemFree(pszReferences); MemFree(pszSubject); MemFree(pszNormalSubj); MemFree(pszAcctId); MemFree(pszAcctName); MemFree(pszServer); MemFree(pszForwardTo); MemFree(pszMSOESRec);
SafeRelease(pMimeMsg); SafeRelease(pPropertySet); if (pmiFree) pFolder->FreeRecord(pmiFree); SafeRelease(pAdrTable);
return hr; }
|