void ReadInputStreamData(nsTArray<nsCString>& aProtocolString) { nsLineBuffer<char> lineBuffer; nsCString line; bool more = true; do { NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more); if (line.Length() > 0) { aProtocolString.AppendElement(line); } } while (more && line.Length() > 0); }
void nsMsgLocalStoreUtils::ChangeKeywordsHelper( nsIMsgDBHdr *message, uint64_t desiredOffset, nsLineBuffer<char> *lineBuffer, nsTArray<nsCString> &keywordArray, bool aAdd, nsIOutputStream *outputStream, nsISeekableStream *seekableStream, nsIInputStream *inputStream) { uint32_t bytesWritten; for (uint32_t i = 0; i < keywordArray.Length(); i++) { nsAutoCString header; nsAutoCString keywords; bool done = false; uint32_t len = 0; nsAutoCString keywordToWrite(" "); keywordToWrite.Append(keywordArray[i]); seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, desiredOffset); // need to reset lineBuffer, which is cheaper than creating a new one. lineBuffer->start = lineBuffer->end = lineBuffer->buf; bool inKeywordHeader = false; bool foundKeyword = false; int64_t offsetToAddKeyword = 0; bool more; message->GetMessageSize(&len); // loop through while (!done) { int64_t lineStartPos; seekableStream->Tell(&lineStartPos); // we need to adjust the linestart pos by how much extra the line // buffer has read from the stream. lineStartPos -= (lineBuffer->end - lineBuffer->start); // NS_ReadLine doesn't return line termination chars. nsCString keywordHeaders; nsresult rv = NS_ReadLine(inputStream, lineBuffer, keywordHeaders, &more); if (NS_SUCCEEDED(rv)) { if (keywordHeaders.IsEmpty()) break; // passed headers; no x-mozilla-keywords header; give up. if (StringBeginsWith(keywordHeaders, NS_LITERAL_CSTRING(HEADER_X_MOZILLA_KEYWORDS))) inKeywordHeader = true; else if (inKeywordHeader && (keywordHeaders.CharAt(0) == ' ' || keywordHeaders.CharAt(0) == '\t')) ; // continuation header line else if (inKeywordHeader) break; else continue; uint32_t keywordHdrLength = keywordHeaders.Length(); int32_t startOffset, keywordLength; // check if we have the keyword if (MsgFindKeyword(keywordArray[i], keywordHeaders, &startOffset, &keywordLength)) { foundKeyword = true; if (!aAdd) // if we're removing, remove it, and break; { keywordHeaders.Cut(startOffset, keywordLength); for (int32_t j = keywordLength; j > 0; j--) keywordHeaders.Append(' '); seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, lineStartPos); outputStream->Write(keywordHeaders.get(), keywordHeaders.Length(), &bytesWritten); } offsetToAddKeyword = 0; // if adding and we already have the keyword, done done = true; break; } // argh, we need to check all the lines to see if we already have the // keyword, but if we don't find it, we want to remember the line and // position where we have room to add the keyword. if (aAdd) { nsAutoCString curKeywordHdr(keywordHeaders); // strip off line ending spaces. curKeywordHdr.Trim(" ", false, true); if (!offsetToAddKeyword && curKeywordHdr.Length() + keywordToWrite.Length() < keywordHdrLength) offsetToAddKeyword = lineStartPos + curKeywordHdr.Length(); } } } if (aAdd && !foundKeyword) { if (!offsetToAddKeyword) message->SetUint32Property("growKeywords", 1); else { seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offsetToAddKeyword); outputStream->Write(keywordToWrite.get(), keywordToWrite.Length(), &bytesWritten); } } } }
int nsMsgSendPart::Write() { int status = 0; char *separator = nsnull; bool needToWriteCRLFAfterEncodedBody = false; #define PUSHLEN(str, length) \ do { \ status = mime_write_message_body(m_state, str, length); \ if (status < 0) goto FAIL; \ } while (0) \ #define PUSH(str) PUSHLEN(str, PL_strlen(str)) // rhp: Suppress the output of parts that are empty! if ( (m_parent) && (m_numchildren == 0) && ( (!m_buffer) || (!*m_buffer) ) && (!m_file) && (!m_mainpart) ) return SKIP_EMPTY_PART; if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) { if (m_file) { // The "insert HTML links" code requires a memory buffer, // so read the file into memory. NS_ASSERTION(m_buffer == nsnull, "not-null buffer"); PRInt32 length = 0; PRInt64 fileSize; if (NS_SUCCEEDED(m_file->GetFileSize(&fileSize))) length = fileSize; m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1)); if (m_buffer) { nsCOMPtr<nsIInputStream> inputFile; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputFile), m_file); if (NS_SUCCEEDED(rv)) { PRUint32 bytesRead; rv = inputFile->Read(m_buffer, length, &bytesRead); inputFile->Close(); m_buffer[length] = '\0'; } else PR_Free(m_buffer); } } } if (m_parent && m_parent->m_type && !PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) && m_type && (!PL_strcasecmp(m_type, MESSAGE_RFC822) || !PL_strcasecmp(m_type, MESSAGE_NEWS))) { // If we're in a multipart/digest, and this document is of type // message/rfc822, then it's appropriate to emit no headers. // } else { char *message_headers = 0; char *content_headers = 0; char *content_type_header = 0; status = divide_content_headers(m_other, &message_headers, &content_headers, &content_type_header); if (status < 0) goto FAIL; /* First, write out all of the headers that refer to the message itself (From, Subject, MIME-Version, etc.) */ if (message_headers) { PUSH(message_headers); PR_Free(message_headers); message_headers = 0; } /* Now allow the crypto library to (potentially) insert some text (it may want to wrap the body in an envelope.) */ if (!m_parent) { status = m_state->BeginCryptoEncapsulation(); if (status < 0) goto FAIL; } /* Now make sure there's a Content-Type header. */ if (!content_type_header) { NS_ASSERTION(m_type && *m_type, "null ptr"); bool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN); if (needsCharset) { content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF, (m_type ? m_type : TEXT_PLAIN), m_charset_name); } else content_type_header = PR_smprintf("Content-Type: %s" CRLF, (m_type ? m_type : TEXT_PLAIN)); if (!content_type_header) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } /* If this is a compound object, tack a boundary string onto the Content-Type header. this */ if (m_numchildren > 0) { int L; char *ct2; NS_ASSERTION(m_type, "null ptr"); if (!separator) { separator = mime_make_separator(""); if (!separator) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } L = PL_strlen(content_type_header); if (content_type_header[L-1] == '\n') content_type_header[--L] = 0; if (content_type_header[L-1] == '\r') content_type_header[--L] = 0; ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator); PR_Free(content_type_header); if (!ct2) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } content_type_header = ct2; } // Now write out the Content-Type header... NS_ASSERTION(content_type_header && *content_type_header, "null ptr"); PUSH(content_type_header); PR_Free(content_type_header); content_type_header = 0; /* ...followed by all of the other headers that refer to the body of the message (Content-Transfer-Encoding, Content-Dispositon, etc.) */ if (content_headers) { PUSH(content_headers); PR_Free(content_headers); content_headers = 0; } } PUSH(CRLF); // A blank line, to mark the end of headers. m_firstBlock = true; /* only convert if we need to tag charset */ m_needIntlConversion = mime_type_needs_charset(m_type); if (m_buffer) { status = PushBody(m_buffer, PL_strlen(m_buffer)); if (status < 0) goto FAIL; } else if (m_file) { nsCOMPtr<nsIInputStream> inputStream; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), m_file); if (NS_FAILED(rv)) { // mysteriously disappearing? nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsMsgBuildMessageWithTmpFile(m_file, error_msg); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false); } status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE; goto FAIL; } nsCString curLine; bool more = true; /* Kludge to avoid having to allocate memory on the toy computers... */ if (!mime_mailto_stream_read_buffer) { mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE); if (!mime_mailto_stream_read_buffer) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } char *buffer = mime_mailto_stream_read_buffer; if (m_strip_sensitive_headers) { // We are attaching a message, so we should be careful to // strip out certain sensitive internal header fields. bool skipping = false; nsLineBuffer<char> *lineBuffer; rv = NS_InitLineBuffer(&lineBuffer); NS_ENSURE_SUCCESS(rv, rv); while (more) { // NS_ReadLine doesn't return line termination chars. rv = NS_ReadLine(inputStream.get(), lineBuffer, curLine, &more); curLine.Append(CRLF); char *line = (char *) curLine.get(); if (skipping) { if (*line == ' ' || *line == '\t') continue; else skipping = false; } if (!PL_strncasecmp(line, "From -", 6) || !PL_strncasecmp(line, "BCC:", 4) || !PL_strncasecmp(line, "FCC:", 4) || !PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) || !PL_strncasecmp(line, "Lines:", 6) || !PL_strncasecmp(line, "Status:", 7) || !PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) || !PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) || !PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */ { skipping = true; continue; } PUSH(line); if (curLine.Length() == 2) { nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(inputStream); // seek back the amount of data left in the line buffer... seekableStream->Seek(nsISeekableStream::NS_SEEK_CUR, lineBuffer->start - lineBuffer->end); break; // Now can do normal reads for the body. } } PR_Free(lineBuffer); } while (status >= 0) { PRUint32 bytesRead; nsresult rv = inputStream->Read(buffer, MIME_BUFFER_SIZE, &bytesRead); if (NS_FAILED(rv)) { nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsMsgBuildMessageWithFile(m_file, error_msg); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false); status = NS_MSG_UNABLE_TO_OPEN_FILE; goto FAIL; } } status = PushBody(buffer, bytesRead); if (status < 0) goto FAIL; if (bytesRead < MIME_BUFFER_SIZE) break; } } if (m_encoder_data) { status = MIME_EncoderDestroy(m_encoder_data, false); m_encoder_data = nsnull; needToWriteCRLFAfterEncodedBody = !m_parent; if (status < 0) goto FAIL; } // // Ok, from here we loop and drive the the output of all children // for this message. // if (m_numchildren > 0) { bool writeSeparator = true; for (int i = 0 ; i < m_numchildren ; i ++) { if (writeSeparator) { PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH(CRLF); } status = m_children[i]->Write(); if (status < 0) goto FAIL; if (status == SKIP_EMPTY_PART) writeSeparator = false; else writeSeparator = true; } PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH("--"); PUSH(CRLF); } else if (needToWriteCRLFAfterEncodedBody) PUSH(CRLF); FAIL: PR_FREEIF(separator); return status; }
static nsresult __AddNewMessageToFolder(nsIMsgFolder * dstFolder, ews_msg_item * msg_item, nsIMsgDBHdr* messageToReplace, nsIFile * pSrc, nsIMsgDBHdr ** _msgHdr) { nsCOMPtr<nsIOutputStream> outputStream; nsCOMPtr<nsIMsgPluggableStore> msgStore; nsresult rv; nsCOMPtr<nsIMsgDatabase> destDB; rv = dstFolder->GetMsgDatabase(getter_AddRefs(destDB)); rv = dstFolder->GetMsgStore(getter_AddRefs(msgStore)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIMsgDBHdr> msgHdr; bool reusable; rv = msgStore->GetNewMsgOutputStream(dstFolder, getter_AddRefs(msgHdr), &reusable, getter_AddRefs(outputStream)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsIInputStream> pInputStream; rv = NS_NewLocalFileInputStream(getter_AddRefs(pInputStream), pSrc); NS_ENSURE_SUCCESS(rv, rv); nsAutoPtr<nsLineBuffer<char> > lineBuffer(new nsLineBuffer<char>); NS_ENSURE_TRUE(lineBuffer, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr <nsIMsgParseMailMsgState> msgParser = do_CreateInstance(NS_PARSEMAILMSGSTATE_CONTRACTID, &rv); msgParser->SetMailDB(destDB); msgParser->SetState(nsIMsgParseMailMsgState::ParseHeadersState); msgParser->SetNewMsgHdr(msgHdr); nsCString line; bool more = false; uint32_t write_count = 0; uint32_t msg_size = 0; //Need to write Local message header //From nsAutoCString result; time_t now = time ((time_t*) 0); char *ct = ctime(&now); ct[24] = 0; result = "From - "; result += ct; result += MSG_LINEBREAK; outputStream->Write(result.get(), result.Length(), &write_count); msg_size += write_count; //Status NS_NAMED_LITERAL_CSTRING(MozillaStatus, "X-Mozilla-Status: 0001" MSG_LINEBREAK); outputStream->Write(MozillaStatus.get(), MozillaStatus.Length(), &write_count); msg_size += write_count; //Status2 NS_NAMED_LITERAL_CSTRING(MozillaStatus2, "X-Mozilla-Status2: 00000000" MSG_LINEBREAK); outputStream->Write(MozillaStatus2.get(), MozillaStatus2.Length(), &write_count); msg_size += write_count; do { rv = NS_ReadLine(pInputStream.get(), lineBuffer.get(), line, &more); if (NS_FAILED(rv)) break; nsCString newLine(line); newLine.AppendLiteral("\x0D\x0A"); msgParser->ParseAFolderLine(newLine.get(), newLine.Length()); //Need to replace Date: Header with received time if (!strncmp(line.get(), "Date:", strlen("Date:")) && msg_item && msg_item->item.received_time > 0) { char buf[256] = {0}; size_t len = strftime(buf, 255, "%a, %d %b %Y %H:%M:%S %z", localtime(&msg_item->item.received_time)); outputStream->Write("Date: ", strlen("Date: "), &write_count); msg_size += write_count; outputStream->Write(buf, len, &write_count); msg_size += write_count; outputStream->Write("\x0D\x0A", 2, &write_count); msg_size += write_count; } else if (!strncmp(line.get(), "Subject:", strlen("Subject:"))) { const char * key = line.get() + strlen("Subject:"); uint32_t l = strlen(key); nsCString newSubject("Subject: "); /* strip "Re: " */ nsCString modifiedSubject; if (mailews::NS_MsgStripRE((const char **) &key, &l, modifiedSubject)) { nsString utf16LocalizedRe; mailews::NS_GetLocalizedUnicharPreferenceWithDefault(nullptr, "mailnews.localizedRe", EmptyString(), utf16LocalizedRe); NS_ConvertUTF16toUTF8 localizedRe(utf16LocalizedRe); if (localizedRe.IsEmpty()) { newSubject.Append("Re"); } else { newSubject.Append(localizedRe); } newSubject.Append(": "); } if (!modifiedSubject.IsEmpty()) { newSubject.Append(modifiedSubject); } else { newSubject.AppendLiteral(key); } outputStream->Write(newSubject.get(), newSubject.Length(), &write_count); msg_size += write_count; outputStream->Write("\x0D\x0A", 2, &write_count); msg_size += write_count; } else { outputStream->Write(line.get(), line.Length(), &write_count); msg_size += write_count; outputStream->Write("\x0D\x0A", 2, &write_count); msg_size += write_count; } } while(more); pInputStream->Close(); msgParser->FinishHeader(); msgParser->GetNewMsgHdr(getter_AddRefs(msgHdr)); if (NS_SUCCEEDED(rv)) { if (msg_item) UpdateMsgHdr(msg_item, msgHdr); else if (messageToReplace) { CopyPropertiesToMsgHdr(msgHdr, messageToReplace, true); } msgHdr->SetMessageSize(msg_size); destDB->AddNewHdrToDB(msgHdr, true /* notify */); msgStore->FinishNewMessage(outputStream, msgHdr); dstFolder->UpdateSummaryTotals(true); } else { msgStore->DiscardNewMessage(outputStream, msgHdr); IMPORT_LOG0( "*** Error importing message\n"); } if (!reusable) outputStream->Close(); destDB->Commit(nsMsgDBCommitType::kLargeCommit); if (_msgHdr) msgHdr.swap(*_msgHdr); return rv; }