NS_IMETHODIMP nsMsgSaveAsListener::OnDataAvailable(nsIRequest* request, nsISupports* aSupport, nsIInputStream* inStream, uint64_t srcOffset, uint32_t count) { nsresult rv; uint64_t available; rv = inStream->Available(&available); if (!m_writtenData) { m_writtenData = true; rv = SetupMsgWriteStream(m_outputFile, m_addDummyEnvelope); NS_ENSURE_SUCCESS(rv, rv); } bool useCanonicalEnding = false; nsCOMPtr <nsIMsgMessageUrl> msgUrl = do_QueryInterface(aSupport); if (msgUrl) msgUrl->GetCanonicalLineEnding(&useCanonicalEnding); const char *lineEnding = (useCanonicalEnding) ? CRLF : MSG_LINEBREAK; uint32_t lineEndingLength = (useCanonicalEnding) ? 2 : MSG_LINEBREAK_LEN; uint32_t readCount, maxReadCount = SAVE_BUF_SIZE - m_leftOver; uint32_t writeCount; char *start, *end, lastCharInPrevBuf = '\0'; uint32_t linebreak_len = 0; while (count > 0) { if (count < maxReadCount) maxReadCount = count; rv = inStream->Read(m_dataBuffer + m_leftOver, maxReadCount, &readCount); if (NS_FAILED(rv)) return rv; m_leftOver += readCount; m_dataBuffer[m_leftOver] = '\0'; start = m_dataBuffer; // make sure we don't insert another LF, accidentally, by ignoring // second half of CRLF spanning blocks. if (lastCharInPrevBuf == '\r' && *start == '\n') start++; end = PL_strchr(start, '\r'); if (!end) end = PL_strchr(start, '\n'); else if (*(end+1) == '\n' && linebreak_len == 0) linebreak_len = 2; if (linebreak_len == 0) // not initialize yet linebreak_len = 1; count -= readCount; maxReadCount = SAVE_BUF_SIZE - m_leftOver; if (!end && count > maxReadCount) // must be a very very long line; sorry cannot handle it return NS_ERROR_FAILURE; while (start && end) { if (m_outputStream && PL_strncasecmp(start, "X-Mozilla-Status:", 17) && PL_strncasecmp(start, "X-Mozilla-Status2:", 18) && PL_strncmp(start, "From - ", 7)) { rv = m_outputStream->Write(start, end-start, &writeCount); nsresult tmp = m_outputStream->Write(lineEnding, lineEndingLength, &writeCount); if (NS_FAILED(tmp)) { rv = tmp; } } start = end+linebreak_len; if (start >= m_dataBuffer + m_leftOver) { maxReadCount = SAVE_BUF_SIZE; m_leftOver = 0; break; } end = PL_strchr(start, '\r'); if (!end) end = PL_strchr(start, '\n'); if (start && !end) { m_leftOver -= (start - m_dataBuffer); memcpy(m_dataBuffer, start, m_leftOver+1); // including null maxReadCount = SAVE_BUF_SIZE - m_leftOver; } } if (NS_FAILED(rv)) return rv; if (end) lastCharInPrevBuf = *end; } return rv; // rv = m_outputStream->WriteFrom(inStream, std::min(available, count), &bytesWritten); }
NS_IMETHODIMP nsMsgSaveAsListener::OnDataAvailable(nsIRequest* request, nsISupports* aSupport, nsIInputStream* inStream, PRUint32 srcOffset, PRUint32 count) { nsresult rv; PRUint32 available; rv = inStream->Available(&available); if (!m_writtenData) { m_writtenData = PR_TRUE; rv = SetupMsgWriteStream(m_outputFile, m_addDummyEnvelope); NS_ENSURE_SUCCESS(rv, rv); } PRBool useCanonicalEnding = PR_FALSE; nsCOMPtr <nsIMsgMessageUrl> msgUrl = do_QueryInterface(aSupport); if (msgUrl) msgUrl->GetCanonicalLineEnding(&useCanonicalEnding); const char *lineEnding = (useCanonicalEnding) ? CRLF : MSG_LINEBREAK; PRUint32 lineEndingLength = (useCanonicalEnding) ? 2 : MSG_LINEBREAK_LEN; PRUint32 readCount, maxReadCount = SAVE_BUF_SIZE - m_leftOver; PRUint32 writeCount; char *start, *end; PRUint32 linebreak_len = 0; while (count > 0) { if (count < maxReadCount) maxReadCount = count; rv = inStream->Read(m_dataBuffer + m_leftOver, maxReadCount, &readCount); if (NS_FAILED(rv)) return rv; m_leftOver += readCount; m_dataBuffer[m_leftOver] = '\0'; start = m_dataBuffer; end = PL_strchr(start, '\r'); if (!end) end = PL_strchr(start, '\n'); else if (*(end+1) == '\n' && linebreak_len == 0) linebreak_len = 2; if (linebreak_len == 0) // not initialize yet linebreak_len = 1; count -= readCount; maxReadCount = SAVE_BUF_SIZE - m_leftOver; if (!end && count > maxReadCount) // must be a very very long line; sorry cannot handle it return NS_ERROR_FAILURE; while (start && end) { if (PL_strncasecmp(start, "X-Mozilla-Status:", 17) && PL_strncasecmp(start, "X-Mozilla-Status2:", 18) && PL_strncmp(start, "From - ", 7)) { rv = m_outputStream->Write(start, end-start, &writeCount); rv = m_outputStream->Write(lineEnding, lineEndingLength, &writeCount); } start = end+linebreak_len; if (start >= m_dataBuffer + m_leftOver) { maxReadCount = SAVE_BUF_SIZE; m_leftOver = 0; break; } end = PL_strchr(start, '\r'); if (!end) end = PL_strchr(start, '\n'); if (start && !end) { m_leftOver -= (start - m_dataBuffer); memcpy(m_dataBuffer, start, m_leftOver+1); // including null maxReadCount = SAVE_BUF_SIZE - m_leftOver; } } if (NS_FAILED(rv)) return rv; } return rv; // rv = m_outputStream->WriteFrom(inStream, PR_MIN(available, count), &bytesWritten); }