fix 166111 patch by ch.ey@gmx.net, r=bienvenu, sr=mscott fix handling of downloading of pop3 messages with non-standard line endings

This commit is contained in:
bienvenu%nventure.com 2005-02-04 15:45:56 +00:00
Родитель c2b5d9f9c1
Коммит 235a74f646
5 изменённых файлов: 93 добавлений и 114 удалений

Просмотреть файл

@ -107,7 +107,6 @@ nsMsgLineBuffer::nsMsgLineBuffer(nsMsgLineBufferHandler *handler, PRBool convert
m_handler = handler;
m_convertNewlinesP = convertNewlinesP;
m_lookingForCRLF = PR_TRUE;
m_ignoreCRLFs = PR_FALSE;
}
nsMsgLineBuffer::~nsMsgLineBuffer()
@ -141,8 +140,6 @@ PRInt32 nsMsgLineBuffer::BufferInput(const char *net_buffer, PRInt32 net_buffer_
const char *newline = 0;
const char *s;
if (!m_ignoreCRLFs)
{
for (s = net_buffer; s < net_buffer_end; s++)
{
if (m_lookingForCRLF) {
@ -179,7 +176,6 @@ PRInt32 nsMsgLineBuffer::BufferInput(const char *net_buffer, PRInt32 net_buffer_
}
}
}
}
/* Ensure room in the net_buffer and append some or all of the current
chunk of data to it. */
@ -332,7 +328,7 @@ void nsMsgLineStreamBuffer::ClearBuffer()
// Note to people wishing to modify this function: Be *VERY CAREFUL* this is a critical function used by all of
// our mail protocols including imap, nntp, and pop. If you screw it up, you could break a lot of stuff.....
char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint32 &aNumBytesInLine, PRBool &aPauseForMoreData, nsresult *prv)
char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint32 &aNumBytesInLine, PRBool &aPauseForMoreData, nsresult *prv, PRBool addLineTerminator)
{
// try to extract a line from m_inputBuffer. If we don't have an entire line,
// then read more bytes out from the stream. If the stream is empty then wait
@ -436,7 +432,7 @@ char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint
aNumBytesInLine--;
// PR_CALLOC zeros out the allocated line
char* newLine = (char*) PR_CALLOC(aNumBytesInLine+1);
char* newLine = (char*) PR_CALLOC(aNumBytesInLine + (addLineTerminator ? MSG_LINEBREAK_LEN : 0) + 1);
if (!newLine)
{
aNumBytesInLine = 0;
@ -445,6 +441,11 @@ char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint
}
memcpy(newLine, startOfLine, aNumBytesInLine); // copy the string into the new line buffer
if (addLineTerminator)
{
memcpy(newLine + aNumBytesInLine, MSG_LINEBREAK, MSG_LINEBREAK_LEN);
aNumBytesInLine += MSG_LINEBREAK_LEN;
}
if (m_eatCRLFs)
endOfLine += 1; // advance past LF or CR if we haven't already done so...

Просмотреть файл

@ -90,7 +90,6 @@ protected:
nsMsgLineBufferHandler *m_handler;
PRBool m_convertNewlinesP;
PRBool m_lookingForCRLF;
PRBool m_ignoreCRLFs;
};
// I'm adding this utility class here for lack of a better place. This utility class is similar to nsMsgLineBuffer
@ -122,7 +121,7 @@ public:
// aEndOfLinetoken -- delimiter used to denote the end of a line.
// aNumBytesInLine -- The number of bytes in the line returned
// aPauseForMoreData -- There is not enough data in the stream to make a line at this time...
char * ReadNextLine(nsIInputStream * aInputStream, PRUint32 &anumBytesInLine, PRBool &aPauseForMoreData, nsresult *rv = nsnull);
char * ReadNextLine(nsIInputStream * aInputStream, PRUint32 &anumBytesInLine, PRBool &aPauseForMoreData, nsresult *rv = nsnull, PRBool addLineTerminator = PR_FALSE);
nsresult GrowBuffer(PRInt32 desiredSize);
void ClearBuffer();
PRBool NextLineAvailable();

Просмотреть файл

@ -509,7 +509,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsMsgProtocol)
nsPop3Protocol::nsPop3Protocol(nsIURI* aURL)
: nsMsgProtocol(aURL),
nsMsgLineBuffer(NULL, PR_FALSE),
m_bytesInMsgReceived(0),
m_totalFolderSize(0),
m_totalDownloadSize(0),
@ -520,8 +519,6 @@ nsPop3Protocol::nsPop3Protocol(nsIURI* aURL)
m_responseTimer(nsnull),
m_responseTimeout(45)
{
SetLookingForCRLF(MSG_LINEBREAK_LEN == 2);
m_ignoreCRLFs = PR_TRUE;
}
nsresult nsPop3Protocol::Initialize(nsIURI * aURL)
@ -3020,21 +3017,22 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
{
if (m_pop3ConData->msg_closure)
{
m_ignoreCRLFs = PR_TRUE;
PRInt32 res = BufferInput(line, buffer_size);
if (res < 0) return(Error(POP3_MESSAGE_WRITE_ERROR));
m_ignoreCRLFs = PR_FALSE;
res = BufferInput(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
if (res < 0) return(Error(POP3_MESSAGE_WRITE_ERROR));
rv = HandleLine(line, buffer_size);
if (NS_FAILED(rv))
return (Error(POP3_MESSAGE_WRITE_ERROR));
// not really sure we always had CRLF in input since we
// also treat a single LF as line ending!
m_pop3ConData->parsed_bytes += (buffer_size+2); // including CRLF
}
// now read in the next line
PR_Free(line);
line = m_lineStreamBuffer->ReadNextLine(inputStream, buffer_size,
pauseForMoreData);
pauseForMoreData, &rv, PR_TRUE);
PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS,("RECV: %s", line));
// not really sure we always had CRLF in input since we
// also treat a single LF as line ending!
status += (buffer_size+2); // including CRLF
} while (line);
}
@ -3068,8 +3066,8 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
// (Note: This is only a temp hack until the underlying XPCOM is
// fixed to return errors)
if(NS_FAILED(rv))
return(Error(POP3_MESSAGE_WRITE_ERROR));
if (NS_FAILED(rv))
return (Error(POP3_MESSAGE_WRITE_ERROR));
m_pop3ConData->msg_closure = 0;
}
@ -3195,38 +3193,29 @@ nsPop3Protocol::TopResponse(nsIInputStream* inputStream, PRUint32 length)
return RetrResponse(inputStream, length);
}
PRInt32
/* line is handed over as null-terminated string with MSG_LINEBREAK */
nsresult
nsPop3Protocol::HandleLine(char *line, PRUint32 line_length)
{
nsresult rv;
nsresult rv = NS_OK;
NS_ASSERTION(m_pop3ConData->msg_closure, "m_pop3ConData->msg_closure is null in nsPop3Protocol::HandleLine()");
if (!m_pop3ConData->msg_closure)
return -1;
return NS_ERROR_NULL_POINTER;
if (!m_senderInfo.IsEmpty() && !m_pop3ConData->seenFromHeader)
{
if (line_length > 6 && !PL_strncasecmp("From: ", line, 6))
{
/* Zzzzz PL_strstr only works with NULL terminated string. Since,
* the last character of a line is either a carriage return
* or a linefeed. Temporary setting the last character of the
* line to NULL and later setting it back should be the right
* thing to do.
*/
char ch = line[line_length-1];
line[line_length-1] = 0;
m_pop3ConData->seenFromHeader = PR_TRUE;
if (PL_strstr(line, m_senderInfo.get()) == NULL)
m_nsIPop3Sink->SetSenderAuthedFlag(m_pop3ConData->msg_closure,
PR_FALSE);
line[line_length-1] = ch;
}
}
// line contains only dot and linebreak -> message end
if (line[0] == '.' && line_length == 1 + MSG_LINEBREAK_LEN)
// line contains only a single dot and linebreak -> message end
if (line_length == 1 + MSG_LINEBREAK_LEN && line[0] == '.')
{
m_pop3ConData->assumed_end = PR_TRUE; /* in case byte count from server is */
/* wrong, mark we may have had the end */
@ -3246,35 +3235,25 @@ nsPop3Protocol::HandleLine(char *line, PRUint32 line_length)
// (Note: This is only a temp hack until the underlying XPCOM is
// fixed to return errors)
if(NS_FAILED(rv))
return(Error((rv == NS_MSG_ERROR_COPYING_FROM_TMP_DOWNLOAD)
if (NS_FAILED(rv))
return (Error((rv == NS_MSG_ERROR_COPYING_FROM_TMP_DOWNLOAD)
? POP3_TMP_DOWNLOAD_FAILED
: POP3_MESSAGE_WRITE_ERROR));
m_pop3ConData->msg_closure = 0;
return 0;
m_pop3ConData->msg_closure = nsnull;
return rv;
}
}
/*When examining a multi-line response, the client checks
to see if the line begins with the termination octet. If so and if
octets other than CRLF follow, the first octet of the line (the
termination octet) is stripped away.*/
else if (line_length > 1 && line[0] == '.' && line[1] == '.' )
{
PRUint32 i=0;
while ( i < line_length -1 ){
line[i] = line[i+1];
i++;
}
line[i] = '\0';
line_length -= 1;
/* Check if the line begins with the termination octet. If so
and if another termination octet follows, we step over the
first occurence of it. */
else if (line_length > 1 && line[0] == '.' && line[1] == '.') {
line++;
line_length--;
}
rv = m_nsIPop3Sink->IncorporateWrite(line, line_length);
if(NS_FAILED(rv))
return(Error(POP3_MESSAGE_WRITE_ERROR));
return 0;
return m_nsIPop3Sink->IncorporateWrite(line, line_length);
}
PRInt32 nsPop3Protocol::SendDele()

Просмотреть файл

@ -281,7 +281,7 @@ typedef struct _Pop3ConData {
#define POP3_AUTH_FAILURE 0x00000008 /* extended code said authentication failed */
class nsPop3Protocol : public nsMsgProtocol, public nsMsgLineBuffer, public nsIPop3Protocol
class nsPop3Protocol : public nsMsgProtocol, public nsIPop3Protocol
{
public:
nsPop3Protocol(nsIURI* aURL);
@ -301,8 +301,6 @@ public:
NS_IMETHOD OnTransportStatus(nsITransport *transport, nsresult status, PRUint32 progress, PRUint32 progressMax);
NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports * aContext, nsresult aStatus);
NS_IMETHOD Cancel(nsresult status);
// for nsMsgLineBuffer
virtual PRInt32 HandleLine(char *line, PRUint32 line_length);
static void MarkMsgInHashTable(PLHashTable *hashTable, const Pop3UidlEntry *uidl,
PRBool *changed);
@ -365,6 +363,8 @@ private:
void SetResponseTimer();
void CancelResponseTimer();
nsresult HandleLine(char *line, PRUint32 line_length);
//////////////////////////////////////////////////////////////////////////////////////////
// Begin Pop3 protocol state handlers
//////////////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -2422,14 +2422,14 @@ PRInt32 nsNNTPProtocol::BeginArticle()
PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 length)
{
PRUint32 status = 0;
PRUint32 line_length = 0;
PRBool pauseForMoreData = PR_FALSE;
if (m_channelListener)
{
char *line = m_lineStreamBuffer->ReadNextLine(inputStream, status, pauseForMoreData);
if(pauseForMoreData)
nsresult rv = NS_OK;
char *line = m_lineStreamBuffer->ReadNextLine(inputStream, line_length, pauseForMoreData, &rv, PR_TRUE);
if (pauseForMoreData)
{
PRUint32 inlength = 0;
mDisplayInputStream->Available(&inlength);
@ -2437,13 +2437,14 @@ PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 le
m_channelListener->OnDataAvailable(this, m_channelContext, mDisplayInputStream, 0, inlength);
SetFlag(NNTP_PAUSE_FOR_READ);
PR_Free(line);
return status;
return line_length;
}
if (m_newsFolder)
m_newsFolder->NotifyDownloadedLine(line, m_key);
if (line[0] == '.' && line[1] == 0)
// line only contains a single dot -> message end
if (line_length == 1 + MSG_LINEBREAK_LEN && line[0] == '.')
{
m_nextState = NEWS_DONE;
@ -2454,18 +2455,17 @@ PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 le
if (inlength > 0) // broadcast our batched up ODA changes
m_channelListener->OnDataAvailable(this, m_channelContext, mDisplayInputStream, 0, inlength);
PR_Free(line);
return status;
return line_length;
}
else // we aren't finished with the message yet
{
PRUint32 count = 0;
// skip over the quoted '.'
if (line[0] == '.')
mDisplayOutputStream->Write(line+1, PL_strlen(line)-1, &count);
if (line_length > 1 && line[0] == '.' && line[1] == '.')
mDisplayOutputStream->Write(line+1, line_length-1, &count);
else
mDisplayOutputStream->Write(line, PL_strlen(line), &count);
mDisplayOutputStream->Write(MSG_LINEBREAK, PL_strlen(MSG_LINEBREAK), &count);
mDisplayOutputStream->Write(line, line_length, &count);
}
PR_Free(line);