You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
764 lines
22 KiB
764 lines
22 KiB
// --------------------------------------------------------------------------------
|
|
// InetStm.cpp
|
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
// Steven J. Bailey
|
|
// --------------------------------------------------------------------------------
|
|
#include "pch.hxx"
|
|
#include "inetstm.h"
|
|
#include "stmlock.h"
|
|
#include "shlwapi.h"
|
|
#include "demand.h"
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// INETSTMTRACING
|
|
// --------------------------------------------------------------------------------
|
|
//#define INETSTMTRACING 1
|
|
#ifdef INETSTMTRACING
|
|
#define INETSTMTRACE DebugTrace
|
|
#else
|
|
#define INETSTMTRACE
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::CInternetStream
|
|
// --------------------------------------------------------------------------------
|
|
CInternetStream::CInternetStream(void)
|
|
{
|
|
m_cRef = 1;
|
|
m_pStmLock = NULL;
|
|
m_fFullyAvailable = TRUE;
|
|
ULISet32(m_uliOffset, 0);
|
|
ZeroMemory(&m_rLine, sizeof(INETSTREAMLINE));
|
|
m_rLine.pb = m_rLine.rgbScratch;
|
|
m_rLine.cbAlloc = sizeof(m_rLine.rgbScratch);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::~CInternetStream
|
|
// --------------------------------------------------------------------------------
|
|
CInternetStream::~CInternetStream(void)
|
|
{
|
|
// Do i need to free the line
|
|
if (m_rLine.pb && m_rLine.pb != m_rLine.rgbScratch)
|
|
g_pMalloc->Free(m_rLine.pb);
|
|
|
|
// Reset the position of the stream to the real current offset
|
|
if (m_pStmLock)
|
|
{
|
|
// Preserve the position of the stream
|
|
SideAssert(SUCCEEDED(m_pStmLock->HrSetPosition(m_uliOffset)));
|
|
|
|
// Release the LockBytes
|
|
m_pStmLock->Release();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::AddRef
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CInternetStream::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::Release
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CInternetStream::Release(void)
|
|
{
|
|
if (0 != --m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::HrInitNew
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::HrInitNew(IStream *pStream)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
CStreamLockBytes *pStmLock=NULL;
|
|
DWORD cbOffset;
|
|
|
|
// Invalid Arg
|
|
Assert(pStream);
|
|
|
|
// Wrap pStream in a pStmLock
|
|
CHECKALLOC(pStmLock = new CStreamLockBytes(pStream));
|
|
|
|
// Get Current Stream Position
|
|
CHECKHR(hr = HrGetStreamPos(pStream, &cbOffset));
|
|
|
|
// Create text stream object
|
|
InitNew(cbOffset, pStmLock);
|
|
|
|
exit:
|
|
// Cleanup
|
|
SafeRelease(pStmLock);
|
|
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::InitNew
|
|
// --------------------------------------------------------------------------------
|
|
void CInternetStream::InitNew(DWORD dwOffset, CStreamLockBytes *pStmLock)
|
|
{
|
|
// Invalid Arg
|
|
Assert(pStmLock);
|
|
|
|
// Release Current
|
|
SafeRelease(m_pStmLock);
|
|
|
|
// Zero Current Buffer
|
|
ZeroMemory(&m_rBuffer, sizeof(INETSTREAMBUFFER));
|
|
|
|
// Reset m_rLine
|
|
m_rLine.cb = 0;
|
|
|
|
// Assume new StreamLockBytes
|
|
m_pStmLock = pStmLock;
|
|
m_pStmLock->AddRef();
|
|
|
|
// Safe the Offset
|
|
m_uliOffset.QuadPart = dwOffset;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::GetLockBytes
|
|
// --------------------------------------------------------------------------------
|
|
void CInternetStream::GetLockBytes(CStreamLockBytes **ppStmLock)
|
|
{
|
|
// Invalid Arg
|
|
Assert(ppStmLock && m_pStmLock);
|
|
|
|
// Return It
|
|
(*ppStmLock) = m_pStmLock;
|
|
(*ppStmLock)->AddRef();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::HrGetSize
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::HrGetSize(DWORD *pcbSize)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
STATSTG rStat;
|
|
|
|
// Invalid Arg
|
|
Assert(pcbSize && m_pStmLock);
|
|
|
|
// Get the Stat
|
|
CHECKHR(hr = m_pStmLock->Stat(&rStat, STATFLAG_NONAME));
|
|
|
|
// Return Size
|
|
*pcbSize = (DWORD)rStat.cbSize.QuadPart;
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::Seek
|
|
// --------------------------------------------------------------------------------
|
|
void CInternetStream::Seek(DWORD dwOffset)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
BOOL fResetCache=FALSE;
|
|
DWORD dw;
|
|
|
|
// State Check
|
|
Assert((m_rBuffer.cb == 0) || (m_uliOffset.QuadPart == m_rBuffer.uliOffset.QuadPart + m_rBuffer.i));
|
|
|
|
// Already at the requested position
|
|
if (dwOffset == m_uliOffset.QuadPart)
|
|
goto exit;
|
|
|
|
// Less than current position
|
|
if (dwOffset < m_uliOffset.QuadPart)
|
|
{
|
|
// Compute Offset from current location
|
|
dw = (DWORD)m_uliOffset.QuadPart - dwOffset;
|
|
|
|
// Less than beginning
|
|
if (dw > m_rBuffer.i)
|
|
fResetCache = TRUE;
|
|
else
|
|
{
|
|
Assert(dw <= m_rBuffer.i);
|
|
m_rBuffer.i -= dw;
|
|
}
|
|
}
|
|
|
|
// Else dwOffset > m_uliOffset.QuadPart
|
|
else
|
|
{
|
|
// Compute Offset from current location
|
|
dw = dwOffset - (DWORD)m_uliOffset.QuadPart;
|
|
|
|
// Less than beginning
|
|
if (m_rBuffer.i + dw > m_rBuffer.cb)
|
|
fResetCache = TRUE;
|
|
else
|
|
{
|
|
m_rBuffer.i += dw;
|
|
Assert(m_rBuffer.i <= m_rBuffer.cb);
|
|
}
|
|
}
|
|
|
|
// Reset the cache
|
|
if (fResetCache)
|
|
{
|
|
// Empty current line and buffer
|
|
*m_rLine.pb = *m_rBuffer.rgb = '\0';
|
|
|
|
// No buffer
|
|
m_rBuffer.uliOffset.QuadPart = m_rLine.cb = m_rBuffer.i = m_rBuffer.cb = 0;
|
|
}
|
|
|
|
// Save this position
|
|
m_uliOffset.QuadPart = dwOffset;
|
|
|
|
exit:
|
|
// Done
|
|
return;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::HrReadToEnd
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::HrReadToEnd(void)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
|
|
// While
|
|
while(1)
|
|
{
|
|
// Validate
|
|
Assert(m_rBuffer.i <= m_rBuffer.cb);
|
|
|
|
// Increment Offset to end of current buffer
|
|
m_uliOffset.QuadPart += (m_rBuffer.cb - m_rBuffer.i);
|
|
|
|
// Set m_rBuffer.i to end of current buffer
|
|
m_rBuffer.i = m_rBuffer.cb;
|
|
|
|
// Get next buffer
|
|
CHECKHR(hr = _HrGetNextBuffer());
|
|
|
|
// No more data
|
|
if (0 == m_rBuffer.cb)
|
|
break;
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::_HrGetNextBuffer
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::_HrGetNextBuffer(void)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
ULONG cbRead;
|
|
|
|
// Validate
|
|
Assert(m_rBuffer.i <= m_rBuffer.cb);
|
|
|
|
// Do we need to read a new buffer
|
|
if (m_rBuffer.i == m_rBuffer.cb)
|
|
{
|
|
// Read a block from the stream, this could return E_PENDING
|
|
CHECKHR(hr = m_pStmLock->ReadAt(m_uliOffset, m_rBuffer.rgb, sizeof(m_rBuffer.rgb), &cbRead));
|
|
|
|
// Raid 43408: Work around Urlmon IStream::Read returning S_FALSE when it should return E_PENDING
|
|
#ifdef DEBUG
|
|
if (FALSE == m_fFullyAvailable && 0 == cbRead && S_FALSE == hr)
|
|
{
|
|
//AssertSz(FALSE, "Raid-43408 - Danpo Zhang is working on this bug, I hope.");
|
|
//hr = E_PENDING;
|
|
//goto exit;
|
|
}
|
|
#endif
|
|
|
|
// Save cbRead
|
|
m_rBuffer.cb = cbRead;
|
|
|
|
// Save the offset of the start of this buffer
|
|
m_rBuffer.uliOffset.QuadPart = m_uliOffset.QuadPart;
|
|
|
|
// Reset buffer index
|
|
m_rBuffer.i = 0;
|
|
}
|
|
else
|
|
Assert(m_uliOffset.QuadPart == m_rBuffer.uliOffset.QuadPart + m_rBuffer.i);
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::HrReadLine
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::HrReadLine(LPPROPSTRINGA pLine)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
UCHAR ch,
|
|
chEndOfLine;
|
|
ULONG cbRead,
|
|
iStart;
|
|
BOOL fEndOfLine=FALSE;
|
|
|
|
// Init
|
|
pLine->pszVal = NULL;
|
|
pLine->cchVal = 0;
|
|
|
|
// Reset the line
|
|
if (m_rLine.fReset)
|
|
{
|
|
m_rLine.cb = 0;
|
|
m_rLine.fReset = 0;
|
|
}
|
|
|
|
// Do the loop
|
|
while(1)
|
|
{
|
|
// Get next buffer
|
|
CHECKHR(hr = _HrGetNextBuffer());
|
|
|
|
// Nothing Read ?
|
|
if (m_rBuffer.cb == 0)
|
|
break;
|
|
|
|
// Seek to first '\n'
|
|
iStart = m_rBuffer.i;
|
|
|
|
Assert(chLF<32);
|
|
Assert(chCR<32);
|
|
Assert(0<32);
|
|
|
|
// For large messages, the while-loop below ends up being a big
|
|
// percentage of the execution time for IMimeMessage::Load. So,
|
|
// we have carefully crafted our C++ code so that we get the
|
|
// optimum code generation for this loop (at least, on Intel, with
|
|
// VC 11.00.7071...)
|
|
{
|
|
register UCHAR *pCurr = m_rBuffer.rgb + m_rBuffer.i;
|
|
register UCHAR *pEnd = m_rBuffer.rgb + m_rBuffer.cb;
|
|
|
|
// We need to initialize this variable for two reasons: First,
|
|
// if we don't initialize it, then for some reason VC decides that
|
|
// it doesn't want to enregister it. And more importantly, if
|
|
// we don't enter the while-loop at all, we need this variable
|
|
// to be set this way...
|
|
register UCHAR chPrev = m_rBuffer.chPrev;
|
|
|
|
ch = m_rBuffer.chPrev;
|
|
|
|
// While we have data
|
|
while (pCurr < pEnd)
|
|
{
|
|
|
|
// Remember the previous character.
|
|
chPrev = ch;
|
|
|
|
// Get Character, and Increment
|
|
ch = *pCurr;
|
|
pCurr++;
|
|
|
|
// The most common case - it's just a regular
|
|
// character, and we haven't seen a carriage-return.
|
|
// So jump back to the top of the loop and keep lookin'...
|
|
if ((chCR != chPrev) && (ch >= 32))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// The next most common case - we are at end-of-line because
|
|
// of a line-feed.
|
|
if (chLF == ch)
|
|
{
|
|
chPrev = ch;
|
|
chEndOfLine = ch;
|
|
fEndOfLine = TRUE;
|
|
break;
|
|
}
|
|
|
|
// This case really only happens when we are getting malformed
|
|
// e-mail - there are embedded carriage-returns, which are *not*
|
|
// followed by line-feeds. When we see those lonely CR's,
|
|
// we make it look like we got a normal CR LF sequence.
|
|
if (chCR == chPrev)
|
|
{
|
|
chPrev = chLF;
|
|
pCurr--;
|
|
chEndOfLine = chCR;
|
|
fEndOfLine = TRUE;
|
|
break;
|
|
}
|
|
|
|
// Fairly rare case - these are malformed messages because they
|
|
// have NULL's embedded in them. We silently convert the
|
|
// NULL's to dots.
|
|
if ('\0' == ch)
|
|
{
|
|
ch = '.';
|
|
*(pCurr-1) = ch;
|
|
}
|
|
}
|
|
|
|
m_rBuffer.i = (ULONG) (pCurr - m_rBuffer.rgb);
|
|
m_rBuffer.chPrev = chPrev;
|
|
}
|
|
|
|
// Number of bytes Read
|
|
cbRead = (m_rBuffer.i - iStart);
|
|
|
|
// Increment Position
|
|
m_uliOffset.QuadPart += cbRead;
|
|
|
|
// Do we need to realloc the line buffer ?
|
|
if (m_rLine.cb + cbRead + 2 > m_rLine.cbAlloc)
|
|
{
|
|
// Fixup pszLine
|
|
if (m_rLine.pb == m_rLine.rgbScratch)
|
|
{
|
|
// Null It
|
|
m_rLine.pb = NULL;
|
|
|
|
// Allocate it to m_rLine.cb
|
|
CHECKHR(hr = HrAlloc((LPVOID *)&m_rLine.pb, m_rLine.cb + 1));
|
|
|
|
// Copy static buffer
|
|
CopyMemory(m_rLine.pb, m_rLine.rgbScratch, m_rLine.cb);
|
|
}
|
|
|
|
// Always Add a little extra to reduce the number of allocs
|
|
m_rLine.cbAlloc = m_rLine.cb + cbRead + 256;
|
|
|
|
// Realloc or alloc new
|
|
CHECKHR(hr = HrRealloc((LPVOID *)&m_rLine.pb, m_rLine.cbAlloc));
|
|
}
|
|
|
|
// Copy the data
|
|
CopyMemory(m_rLine.pb + m_rLine.cb, m_rBuffer.rgb + iStart, cbRead);
|
|
|
|
// Update Counters and indexes
|
|
m_rLine.cb += cbRead;
|
|
|
|
// If End of line and last character was a '\r', append a '\n'
|
|
if (TRUE == fEndOfLine)
|
|
{
|
|
// Better have something in the line
|
|
Assert(m_rLine.cb);
|
|
|
|
// If line ended with a '\r'
|
|
if (chCR == chEndOfLine)
|
|
{
|
|
// Better have room for one more char
|
|
Assert(m_rLine.cb + 1 < m_rLine.cbAlloc);
|
|
|
|
// Append a '\n'
|
|
m_rLine.pb[m_rLine.cb] = chLF;
|
|
|
|
// Increment Length
|
|
m_rLine.cb++;
|
|
}
|
|
|
|
// Otherwise...
|
|
else
|
|
{
|
|
// Line better have ended with a \n
|
|
Assert(chLF == chEndOfLine && chLF == m_rLine.pb[m_rLine.cb - 1]);
|
|
|
|
// If Previous Character was not a \r
|
|
if (m_rLine.cb < 2 || chCR != m_rLine.pb[m_rLine.cb - 2])
|
|
{
|
|
// Convert last char from \n to a \r
|
|
m_rLine.pb[m_rLine.cb - 1] = chCR;
|
|
|
|
// Better have room for one more char
|
|
Assert(m_rLine.cb + 1 < m_rLine.cbAlloc);
|
|
|
|
// Append a '\n'
|
|
m_rLine.pb[m_rLine.cb] = chLF;
|
|
|
|
// Increment Length
|
|
m_rLine.cb++;
|
|
}
|
|
}
|
|
|
|
// Done
|
|
break;
|
|
}
|
|
}
|
|
|
|
// A little check
|
|
Assert(fEndOfLine ? m_rLine.cb >= 2 && chLF == m_rLine.pb[m_rLine.cb-1] && chCR == m_rLine.pb[m_rLine.cb-2] : TRUE);
|
|
|
|
// Null terminator
|
|
m_rLine.pb[m_rLine.cb] = '\0';
|
|
|
|
// Set return values
|
|
pLine->pszVal = (LPSTR)m_rLine.pb;
|
|
pLine->cchVal = m_rLine.cb;
|
|
|
|
// Tracking
|
|
INETSTMTRACE("CInternetStream: %s", (LPSTR)m_rLine.pb);
|
|
|
|
// No Line
|
|
m_rLine.fReset = TRUE;
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CInternetStream::HrReadHeaderLine
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CInternetStream::HrReadHeaderLine(LPPROPSTRINGA pLine, LONG *piColonPos)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
CHAR ch;
|
|
ULONG cbRead=0,
|
|
iStart,
|
|
i;
|
|
BOOL fEndOfLine=FALSE;
|
|
DWORD cTrailingSpace=0;
|
|
|
|
// Init
|
|
*piColonPos = -1;
|
|
pLine->pszVal = NULL;
|
|
pLine->cchVal = 0;
|
|
|
|
// Reset the line
|
|
if (m_rLine.fReset)
|
|
{
|
|
m_rLine.cb = 0;
|
|
m_rLine.fReset = 0;
|
|
}
|
|
|
|
// Do the loop
|
|
while(1)
|
|
{
|
|
// Get next buffer
|
|
CHECKHR(hr = _HrGetNextBuffer());
|
|
|
|
// Nothing Read ?
|
|
if (m_rBuffer.cb == 0)
|
|
break;
|
|
|
|
// Reset fSeenN
|
|
fEndOfLine = FALSE;
|
|
|
|
// Initialize
|
|
iStart = m_rBuffer.i;
|
|
|
|
// Seek to first '\n'
|
|
while (m_rBuffer.i < m_rBuffer.cb)
|
|
{
|
|
// Get Character
|
|
ch = *(m_rBuffer.rgb + m_rBuffer.i);
|
|
|
|
// Convert Nulls to '.'
|
|
if ('\0' == ch)
|
|
{
|
|
ch = '.';
|
|
*(m_rBuffer.rgb + m_rBuffer.i) = ch;
|
|
}
|
|
|
|
// Goto next character
|
|
m_rBuffer.i++;
|
|
|
|
// New Line
|
|
if (chLF == ch)
|
|
{
|
|
m_rBuffer.chPrev = ch;
|
|
fEndOfLine = TRUE;
|
|
break;
|
|
}
|
|
|
|
// Otherwise, if previous character was a '\r', then end of line
|
|
else if (chCR == m_rBuffer.chPrev)
|
|
{
|
|
AssertSz(m_rBuffer.i > 0, "This is an un-handled boundary condition");
|
|
if (m_rBuffer.i > 0)
|
|
m_rBuffer.i--;
|
|
m_rBuffer.chPrev = '\0';
|
|
fEndOfLine = TRUE;
|
|
break;
|
|
}
|
|
|
|
// Is Space
|
|
if (' ' == ch || '\t' == ch)
|
|
cTrailingSpace++;
|
|
else
|
|
cTrailingSpace = 0;
|
|
|
|
// Save Previous Character
|
|
m_rBuffer.chPrev = ch;
|
|
}
|
|
|
|
// Number of bytes Read
|
|
cbRead = (m_rBuffer.i - iStart);
|
|
|
|
// Increment Position
|
|
m_uliOffset.QuadPart += cbRead;
|
|
|
|
// Adjust cbRead to remove CRLF
|
|
if (cbRead && chLF == m_rBuffer.rgb[iStart + cbRead - 1])
|
|
cbRead--;
|
|
if (cbRead && chCR == m_rBuffer.rgb[iStart + cbRead - 1])
|
|
cbRead--;
|
|
|
|
// Do we need to realloc the line buffer ?
|
|
if (m_rLine.cb + cbRead + 3 > m_rLine.cbAlloc)
|
|
{
|
|
// Fixup pszLine
|
|
if (m_rLine.pb == m_rLine.rgbScratch)
|
|
{
|
|
// Null It
|
|
m_rLine.pb = NULL;
|
|
|
|
// Allocate it to m_rLine.cb
|
|
CHECKHR(hr = HrAlloc((LPVOID *)&m_rLine.pb, m_rLine.cb + 3));
|
|
|
|
// Copy static buffer
|
|
CopyMemory(m_rLine.pb, m_rLine.rgbScratch, m_rLine.cb);
|
|
}
|
|
|
|
// Always Add a little extra to reduce the number of allocs
|
|
m_rLine.cbAlloc = m_rLine.cb + cbRead + 256;
|
|
|
|
// Realloc or alloc new
|
|
CHECKHR(hr = HrRealloc((LPVOID *)&m_rLine.pb, m_rLine.cbAlloc));
|
|
}
|
|
|
|
// Copy the data
|
|
CopyMemory(m_rLine.pb + m_rLine.cb, m_rBuffer.rgb + iStart, cbRead);
|
|
|
|
// Increment line byte count
|
|
m_rLine.cb += cbRead;
|
|
|
|
// If fSeenN, then check for continuation line (i.e. next character is ' ' or '\t'
|
|
if (fEndOfLine)
|
|
{
|
|
// Get next buffer
|
|
CHECKHR(hr = _HrGetNextBuffer());
|
|
|
|
// Compare for continuation
|
|
ch = m_rBuffer.rgb[m_rBuffer.i];
|
|
|
|
// If line starts with a TAB or a space, this is a continuation line, keep reading
|
|
if ((ch != ' ' && ch != '\t') || (0 == cbRead && 0 == m_rLine.cb))
|
|
{
|
|
// Done
|
|
break;
|
|
}
|
|
|
|
// Otherwise, strip continuation...
|
|
else
|
|
{
|
|
// Per RFC822, we should not step over a space
|
|
if (ch == '\t')
|
|
{
|
|
m_rBuffer.i++;
|
|
m_uliOffset.QuadPart++;
|
|
}
|
|
|
|
// No characters since last whitespace
|
|
if (0 == cTrailingSpace)
|
|
{
|
|
// Locals
|
|
DWORD cFrontSpace=0;
|
|
|
|
// Look ahead in the buffer a little
|
|
for (DWORD iLookAhead = m_rBuffer.i; iLookAhead < m_rBuffer.cb; iLookAhead++)
|
|
{
|
|
// Get Char
|
|
ch = m_rBuffer.rgb[iLookAhead];
|
|
|
|
// Break on non space
|
|
if (' ' != ch && '\t' != ch)
|
|
break;
|
|
|
|
// Count Front Space
|
|
cFrontSpace++;
|
|
}
|
|
|
|
// No Front Space ?
|
|
if (0 == cFrontSpace)
|
|
{
|
|
// Lets do this only fro Received: and for Date: since dates that get split don't get parsed correctly?
|
|
if ((m_rLine.cb >= 4 && 0 == StrCmpNI("Date", (LPCSTR)m_rLine.pb, 4)) || (m_rLine.cb >= 8 && 0 == StrCmpNI("Received", (LPCSTR)m_rLine.pb, 8)))
|
|
{
|
|
// Put a space in
|
|
*(m_rLine.pb + m_rLine.cb) = ' ';
|
|
|
|
// Increment line byte count
|
|
m_rLine.cb += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get next buffer
|
|
CHECKHR(hr = _HrGetNextBuffer());
|
|
|
|
// If Next character is a \r or \n, then stop, NETSCAPE bug
|
|
ch = m_rBuffer.rgb[m_rBuffer.i];
|
|
if (chCR == ch || chLF == ch)
|
|
break;
|
|
}
|
|
|
|
// Reset
|
|
cTrailingSpace = 0;
|
|
}
|
|
}
|
|
|
|
// A little check
|
|
#ifndef _WIN64
|
|
Assert(chLF != m_rLine.pb[m_rLine.cb-1] && chCR != m_rLine.pb[m_rLine.cb-1]);
|
|
#endif
|
|
|
|
// Null terminator
|
|
*(m_rLine.pb + m_rLine.cb) = '\0';
|
|
|
|
// Lets locate the colon
|
|
for (i=0; i<m_rLine.cb; i++)
|
|
{
|
|
// Colon ?
|
|
if (':' == m_rLine.pb[i])
|
|
{
|
|
*piColonPos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set return values
|
|
pLine->pszVal = (LPSTR)m_rLine.pb;
|
|
pLine->cchVal = m_rLine.cb;
|
|
|
|
// Tracking
|
|
INETSTMTRACE("CInternetStream: %s\n", (LPSTR)m_rLine.pb);
|
|
|
|
// Reset the Line
|
|
m_rLine.fReset = TRUE;
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|