1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public
5
* License Version 1.1 (the "MPL"); you may not use this file
6
* except in compliance with the MPL. You may obtain a copy of
7
* the MPL at http://www.mozilla.org/MPL/
9
* Software distributed under the MPL is distributed on an "AS
10
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11
* implied. See the MPL for the specific language governing
12
* rights and limitations under the MPL.
14
* The Original Code is Enigmail.
16
* The Initial Developer of the Original Code is Ramalingam Saravanan.
17
* Portions created by Ramalingam Saravanan <sarava@sarava.net> are
18
* Copyright (C) 2002 Ramalingam Saravanan. All Rights Reserved.
21
* Patrick Brunschwig <patrick@mozilla-enigmail.org>
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
34
* ***** END LICENSE BLOCK ***** */
36
// Logging of debug output
37
// The following define statement should occur before any include statements
38
#define FORCE_PR_LOG /* Allow logging even in release build */
41
#include "nsStringAPI.h"
42
#include "nsIMsgCompFields.h"
43
#include "nsIMsgWindow.h"
44
#include "nsMsgBaseCID.h"
45
#include "nsMsgCompCID.h"
46
#include "nsIMsgMailSession.h"
47
#include "nsIEnigMsgCompFields.h"
48
#include "nsEnigMsgCompose.h"
51
#include "nsIPrompt.h"
52
#include "nsNetUtil.h"
53
#include "nsIThread.h"
55
#include "nsComposeStrings.h"
56
#undef MOZILLA_INTERNAL_API
59
PRLogModuleInfo* gEnigMsgComposeLog = NULL;
62
#define ERROR_LOG(args) PR_LOG(gEnigMsgComposeLog,PR_LOG_ERROR,args)
63
#define WARNING_LOG(args) PR_LOG(gEnigMsgComposeLog,PR_LOG_WARNING,args)
64
#define DEBUG_LOG(args) PR_LOG(gEnigMsgComposeLog,PR_LOG_DEBUG,args)
66
#define NS_MSGCOMPOSESECURE_CID \
67
{ /* dd753201-9a23-4e08-957f-b3616bf7e012 */ \
68
0xdd753201, 0x9a23, 0x4e08, \
69
{0x95, 0x7f, 0xb3, 0x61, 0x6b, 0xf7, 0xe0, 0x12 }}
71
static NS_DEFINE_CID(kMsgComposeSecureCID, NS_MSGCOMPOSESECURE_CID);
73
#define MAX_HEADER_BYTES 16000
74
#define MAX_SIGNATURE_BYTES 16000
76
static const PRUint32 kCharMax = 1024;
78
// nsEnigMsgCompose implementation
80
const char* nsEnigMsgCompose::FromStr = "From ";
81
EMBool nsEnigMsgCompose::mRandomSeeded = PR_FALSE;
83
// nsISupports implementation
84
NS_IMPL_THREADSAFE_ISUPPORTS3(nsEnigMsgCompose,
89
// nsEnigMsgCompose implementation
90
nsEnigMsgCompose::nsEnigMsgCompose()
91
: mInitialized(PR_FALSE),
94
mRequestStopped(PR_FALSE),
106
mMultipartSigned(PR_FALSE),
107
mStripWhitespace(PR_FALSE),
109
mSenderEmailAddr(""),
112
mHashAlgorithm("sha1"),
120
mMsgComposeSecure(NULL),
131
if (gEnigMsgComposeLog == NULL) {
132
gEnigMsgComposeLog = PR_NewLogModule("nsEnigMsgCompose");
136
// Remember to use original CID, not CONTRACTID, to avoid infinite looping!
137
mMsgComposeSecure = do_CreateInstance(kMsgComposeSecureCID, &rv);
140
nsCOMPtr<nsIThread> myThread;
141
rv = ENIG_GET_THREAD(myThread);
142
DEBUG_LOG(("nsEnigMsgCompose:: <<<<<<<<< CTOR(%p): myThread=%p\n",
143
this, myThread.get()));
148
nsEnigMsgCompose::~nsEnigMsgCompose()
152
nsCOMPtr<nsIThread> myThread;
153
rv = ENIG_GET_THREAD(myThread);
154
DEBUG_LOG(("nsEnigMsgCompose:: >>>>>>>>> DTOR(%p): myThread=%p\n",
155
this, myThread.get()));
163
nsEnigMsgCompose::Finalize()
165
DEBUG_LOG(("nsEnigMsgCompose::Finalize:\n"));
167
mMsgComposeSecure = NULL;
168
mMimeListener = NULL;
171
mPipeTrans->Terminate();
181
// Clear encoder buffer
182
MimeEncoderDestroy(mEncoderData, PR_FALSE);
191
nsEnigMsgCompose::GetRandomTime(PRUint32 *_retval)
194
return NS_ERROR_NULL_POINTER;
196
// Current local time (microsecond resolution)
197
PRExplodedTime localTime;
198
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &localTime);
200
PRUint32 randomNumberA = localTime.tm_sec*1000000+localTime.tm_usec;
202
// Elapsed time (1 millisecond to 10 microsecond resolution)
203
PRIntervalTime randomNumberB = PR_IntervalNow();
205
DEBUG_LOG(("nsEnigMsgCompose::GetRandomTime: ranA=0x%p, ranB=0x%p\n",
206
randomNumberA, randomNumberB));
208
*_retval = ((randomNumberA & 0xFFFFF) << 12) | (randomNumberB & 0xFFF);
215
nsEnigMsgCompose::MakeBoundary(const char *prefix)
217
DEBUG_LOG(("nsEnigMsgCompose::MakeBoundary:\n"));
221
if (!mRandomSeeded) {
222
PRUint32 ranTime = 1;
224
rv = GetRandomTime(&ranTime);
229
mRandomSeeded = PR_TRUE;
233
unsigned char ch[13];
234
for( PRUint32 j = 0; j < 12; j++)
235
ch[j] = rand() % 256;
237
char* boundary = PR_smprintf("------------%s"
242
ch[0], ch[1], ch[2], ch[3],
243
ch[4], ch[5], ch[6], ch[7],
244
ch[8], ch[9], ch[10], ch[11]);
247
return NS_ERROR_OUT_OF_MEMORY;
249
DEBUG_LOG(("nsEnigMsgCompose::MakeBoundary: boundary='%s'\n",
253
mBoundary = boundary;
261
nsEnigMsgCompose::WriteEncryptedHeaders()
264
DEBUG_LOG(("nsEnigMsgCompose::WriteEncryptedHeaders:\n"));
266
rv = MakeBoundary("enig");
270
char* headers = PR_smprintf(
271
"Content-Type: multipart/encrypted;\r\n"
272
" protocol=\"application/pgp-encrypted\";\r\n"
273
" boundary=\"%s\"\r\n"
275
"This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)\r\n"
277
"Content-Type: application/pgp-encrypted\r\n"
278
"Content-Description: PGP/MIME version identification\r\n"
283
"Content-Type: application/octet-stream; name=\"encrypted.asc\"\r\n"
284
"Content-Description: OpenPGP encrypted message\r\n"
285
"Content-Disposition: inline; filename=\"encrypted.asc\"\r\n"
287
mBoundary.get(), mBoundary.get(), mBoundary.get());
290
return NS_ERROR_OUT_OF_MEMORY;
292
rv = WriteOut(headers, strlen(headers));
300
nsEnigMsgCompose::WriteSignedHeaders1(EMBool isEightBit)
303
DEBUG_LOG(("nsEnigMsgCompose::WriteSignedHeaders1: %d\n", (int) isEightBit));
305
rv = MakeBoundary("enig");
309
char* headers = PR_smprintf(
310
"Content-Type: multipart/signed; micalg=pgp-%s;\r\n"
311
" protocol=\"application/pgp-signature\";\r\n"
312
" boundary=\"%s\"\r\n"
314
"This is an OpenPGP/MIME signed message (RFC 2440 and 3156)\r\n"
316
mHashAlgorithm.get(), mBoundary.get(),
317
isEightBit ? "Content-Transfer-Encoding: 8bit\r\n\r\n" : "\r\n",
321
return NS_ERROR_OUT_OF_MEMORY;
323
rv = WriteOut(headers, strlen(headers));
331
nsEnigMsgCompose::WriteSignedHeaders2()
334
DEBUG_LOG(("nsEnigMsgCompose::WriteSignedHeaders2:\n"));
336
char* headers = PR_smprintf(
338
"Content-Type: application/pgp-signature; name=\"signature.asc\"\r\n"
339
"Content-Description: OpenPGP digital signature\r\n"
340
"Content-Disposition: attachment; filename=\"signature.asc\"\r\n"
345
return NS_ERROR_OUT_OF_MEMORY;
347
rv = WriteOut(headers, strlen(headers));
355
nsEnigMsgCompose::WriteFinalSeparator()
358
DEBUG_LOG(("nsEnigMsgCompose::WriteSeparator:\n"));
360
if (mBoundary.IsEmpty())
363
// Write out final MIME multipart separator
364
char* separator = PR_smprintf(
369
return NS_ERROR_OUT_OF_MEMORY;
371
rv = WriteOut(separator, strlen(separator));
379
nsEnigMsgCompose::Init()
383
DEBUG_LOG(("nsEnigMsgCompose::Init: sendFlags=%p\n", mSendFlags));
385
EMBool signMsg = mSendFlags & nsIEnigmail::SEND_SIGNED;
386
EMBool encryptMsg = mSendFlags & nsIEnigmail::SEND_ENCRYPTED;
387
EMBool usePgpMime = mSendFlags & nsIEnigmail::SEND_PGP_MIME;
389
mMultipartSigned = usePgpMime && signMsg && !encryptMsg;
391
mWriter = do_CreateInstance(NS_ENIGMIMEWRITER_CONTRACTID, &rv);
392
if (NS_FAILED(rv)) return rv;
394
rv = mWriter->Init(mStream, PR_TRUE);
395
if (NS_FAILED(rv)) return rv;
397
nsCOMPtr<nsIPrompt> prompter;
398
nsCOMPtr <nsIMsgMailSession> mailSession (do_GetService(NS_MSGMAILSESSION_CONTRACTID));
400
nsCOMPtr<nsIMsgWindow> msgWindow;
401
mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
403
msgWindow->GetPromptDialog(getter_AddRefs(prompter));
406
nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
407
if (NS_FAILED(rv)) return rv;
409
if (usePgpMime && signMsg && (! encryptMsg)) {
410
// determine hash algorithm to use for PGP/MIME signed msg
414
rv = enigmailSvc->DetermineHashAlgorithm(prompter,
416
mSenderEmailAddr.get(),
420
DEBUG_LOG(("nsEnigMsgCompose::Init: DetermineHash: rv=%d, exitCode=%d\n", rv, exitCode));
426
return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
428
mHashAlgorithm = NS_ConvertUTF16toUTF8(ha).get();
429
DEBUG_LOG(("nsEnigMsgCompose::Init: hashAlgorithm=%s\n", mHashAlgorithm.get()));
433
PRUint32 statusFlags;
434
rv = enigmailSvc->EncryptMessageStart(NULL, prompter,
436
mSenderEmailAddr.get(),
439
mHashAlgorithm.get(),
441
(nsIStreamListener*)(mWriter),
443
getter_Copies(errorMsg),
444
getter_AddRefs(mPipeTrans) );
448
if (statusFlags & nsIEnigmail::MISSING_PASSPHRASE)
449
return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
454
rv = enigmailSvc->StripWhitespace(mSendFlags,
459
mInitialized = PR_TRUE;
464
///////////////////////////////////////////////////////////////////////////////
465
// nsIMsgComposeSecure methods:
466
///////////////////////////////////////////////////////////////////////////////
469
nsEnigMsgCompose::RequiresCryptoEncapsulation(
470
nsIMsgIdentity* aIdentity,
471
nsIMsgCompFields* aCompFields,
472
EMBool* aRequiresEncryptionWork)
475
DEBUG_LOG(("nsEnigMsgCompose::RequiresCryptoEncapsulation: \n"));
477
if (!mMsgComposeSecure)
478
return NS_ERROR_FAILURE;
480
rv = mMsgComposeSecure->RequiresCryptoEncapsulation(aIdentity,
487
DEBUG_LOG(("nsEnigMsgCompose::RequiresCryptoEncapsulation: Using SMIME\n"));
488
*aRequiresEncryptionWork = PR_TRUE;
493
#ifdef __gen_nsIMsgSecurityInfo_h__
494
nsCOMPtr<nsIMsgSecurityInfo> securityInfo;
496
nsCOMPtr<nsISupports> securityInfo;
499
rv = aCompFields->GetSecurityInfo(getter_AddRefs(securityInfo));
504
DEBUG_LOG(("nsEnigMsgCompose::RequiresCryptoEncapsulation: no crypto required\n"));
505
*aRequiresEncryptionWork = PR_FALSE;
509
nsCOMPtr<nsIEnigMsgCompFields> enigSecurityInfo = do_QueryInterface(securityInfo);
511
if (enigSecurityInfo) {
513
rv = enigSecurityInfo->GetSendFlags(&sendFlags);
517
*aRequiresEncryptionWork = sendFlags &
518
(nsIEnigmail::SEND_SIGNED | nsIEnigmail::SEND_ENCRYPTED);
521
DEBUG_LOG(("nsEnigMsgCompose::RequiresCryptoEncapsulation: no Enigmail crypto required\n"));
522
*aRequiresEncryptionWork = PR_FALSE;
530
nsEnigMsgCompose::BeginCryptoEncapsulation(
531
nsIOutputStream* aStream,
532
const char* aRecipients,
533
nsIMsgCompFields* aCompFields,
534
nsIMsgIdentity* aIdentity,
535
nsIMsgSendReport* sendReport,
540
DEBUG_LOG(("nsEnigMsgCompose::BeginCryptoEncapsulation: %s\n", aRecipients));
542
if (!mMsgComposeSecure) {
543
ERROR_LOG(("nsEnigMsgCompose::BeginCryptoEncapsulation: ERROR MsgComposeSecure not instantiated\n"));
544
return NS_ERROR_FAILURE;
548
return mMsgComposeSecure->BeginCryptoEncapsulation(aStream, aRecipients,
549
aCompFields, aIdentity,
550
sendReport, aIsDraft);
554
return NS_ERROR_NULL_POINTER;
560
#ifdef __gen_nsIMsgSecurityInfo_h__
561
nsCOMPtr<nsIMsgSecurityInfo> securityInfo;
563
nsCOMPtr<nsISupports> securityInfo;
566
rv = aCompFields->GetSecurityInfo(getter_AddRefs(securityInfo));
571
return NS_ERROR_FAILURE;
573
nsCOMPtr<nsIEnigMsgCompFields> enigSecurityInfo = do_QueryInterface(securityInfo);
575
if (!enigSecurityInfo)
576
return NS_ERROR_FAILURE;
578
rv = enigSecurityInfo->GetSendFlags(&mSendFlags);
582
rv = enigSecurityInfo->GetUIFlags(&mUIFlags);
586
rv = enigSecurityInfo->GetSenderEmailAddr(mSenderEmailAddr);
590
rv = enigSecurityInfo->GetRecipients(mRecipients);
594
rv = enigSecurityInfo->GetBccRecipients(mBccAddr);
598
rv = enigSecurityInfo->GetHashAlgorithm(mHashAlgorithm);
603
// Create listener to intercept MIME headers
604
mMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
605
if (NS_FAILED(rv)) return rv;
607
rv = mMimeListener->Init((nsIStreamListener*) this, NULL,
608
MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
609
if (NS_FAILED(rv)) return rv;
616
nsEnigMsgCompose::FinishCryptoEncapsulation(EMBool aAbort,
617
nsIMsgSendReport* sendReport)
621
DEBUG_LOG(("nsEnigMsgCompose::FinishCryptoEncapsulation: \n"));
623
if (!mMsgComposeSecure)
624
return NS_ERROR_NOT_INITIALIZED;
627
return mMsgComposeSecure->FinishCryptoEncapsulation(aAbort, sendReport);
631
if (!mInitialized || !mPipeTrans)
632
return NS_ERROR_NOT_INITIALIZED;
634
rv = FinishAux(aAbort, sendReport);
644
nsEnigMsgCompose::FinishAux(EMBool aAbort,
645
nsIMsgSendReport* sendReport)
649
if (mMatchFrom > 0) {
650
// Flush "buffer" for detecting lines beginning with "From "
651
rv = WriteCopy(FromStr, mMatchFrom);
652
if (NS_FAILED(rv)) return rv;
655
DEBUG_LOG(("nsEnigMsgCompose::FinishAux: \n"));
657
if (mMultipartSigned) {
658
rv = WriteSignedHeaders2();
659
if (NS_FAILED(rv)) return rv;
662
// Wait for STDOUT to close
663
rv = mPipeTrans->Join();
664
if (NS_FAILED(rv)) return rv;
668
mPipeTrans->Terminate();
671
return NS_ERROR_FAILURE;
674
rv = WriteFinalSeparator();
675
if (NS_FAILED(rv)) return rv;
677
// Count total bytes sent to writer
678
PRUint32 cmdOutputLen;
679
rv = mWriter->GetBytesWritten(&cmdOutputLen);
680
if (NS_FAILED(rv)) return rv;
682
// Exclude passthru bytes to determine STDOUT bytes
683
cmdOutputLen -= mOutputLen;
685
// Close STDOUT writer
689
nsCOMPtr<nsIPrompt> prompter;
690
nsCOMPtr <nsIMsgMailSession> mailSession (do_GetService(NS_MSGMAILSESSION_CONTRACTID));
692
nsCOMPtr<nsIMsgWindow> msgWindow;
693
mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
695
msgWindow->GetPromptDialog(getter_AddRefs(prompter));
698
nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
699
if (NS_FAILED(rv)) return rv;
702
PRUint32 statusFlags;
704
rv = enigmailSvc->EncryptMessageEnd(NULL,
711
getter_Copies(errorMsg),
713
if (NS_FAILED(rv)) return rv;
716
DEBUG_LOG(("nsEnigMsgCompose::FinishAux: ERROR EXIT %d\n", exitCode));
717
return NS_ERROR_FAILURE;
725
nsEnigMsgCompose::MimeCryptoWriteBlock(const char *aBuf, PRInt32 aLen)
729
DEBUG_LOG(("nsEnigMsgCompose::MimeCryptoWriteBlock: \n"));
731
if (!mMsgComposeSecure)
732
return NS_ERROR_FAILURE;
735
return mMsgComposeSecure->MimeCryptoWriteBlock(aBuf, aLen);
739
nsCAutoString temStr(aBuf, aLen);
740
DEBUG_LOG(("nsEnigMsgCompose::MimeCryptoWriteBlock: aBuf='%s'\n",
743
if (!mMultipartSigned) {
744
return WriteCopy(aBuf, aLen);
747
// Mangle lines beginning with "From "
748
// strip trailing whitespaces prior to signing
750
PRUint32 writeCount = 0;
752
for (PRUint32 j=0; j<((PRUint32) aLen); j++) {
753
if ((mSpace > 0) && ((aBuf[j] == '\r') || (aBuf[j] == '\n'))) {
754
// strip trailing spaces and tabs
755
writeCount = j-offset-mSpace;
756
WriteCopy(&aBuf[offset], writeCount);
757
DEBUG_LOG(("nsEnigMsgCompose::MimeCryptoWriteBlock: stripped trailing whitespaces\n"));
760
if (mLinebreak || (mMatchFrom > 0)) {
762
if (aBuf[j] != FromStr[mMatchFrom]) {
763
// No match; reset count
767
// Increment match count
770
if (mMatchFrom >= strlen(FromStr)) {
771
// Complete match found
772
// Write out characters preceding match
773
writeCount = j+1-offset-mMatchFrom;
775
if (writeCount > 0) {
776
rv = WriteCopy(&aBuf[offset], writeCount);
777
if (NS_FAILED(rv)) return rv;
783
// Write out mangled string
784
rv = WriteCopy(">", 1);
785
if (NS_FAILED(rv)) return rv;
787
rv = WriteCopy(FromStr, strlen(FromStr));
788
if (NS_FAILED(rv)) return rv;
790
DEBUG_LOG(("nsEnigMsgCompose::MimeCryptoWriteBlock: >From\n"));
796
mLinebreak = (aBuf[j] == '\r') || (aBuf[j] == '\n');
797
if (mStripWhitespace && ((aBuf[j] == ' ') || (aBuf[j] == '\t'))) {
805
if ((offset+mMatchFrom) < (PRUint32) aLen) {
806
// Write out characters preceding any match
807
rv = WriteCopy(&aBuf[offset], aLen-offset-mMatchFrom-mSpace);
808
if (NS_FAILED(rv)) return rv;
816
EnigMsgCompose_write(const char *buf, PRInt32 size, void *closure)
818
DEBUG_LOG(("nsEnigMsgCompose::EnigMsgCompose_write: (%p) %d\n", closure, size));
821
return NS_ERROR_FAILURE;
823
nsIEnigMimeWriter* enigMimeWriter = (nsIEnigMimeWriter *) closure;
825
return enigMimeWriter->Write(buf, size);
830
nsEnigMsgCompose::WriteOut(const char *aBuf, PRInt32 aLen)
832
DEBUG_LOG(("nsEnigMsgCompose::WriteOut: %d\n", aLen));
835
return NS_ERROR_FAILURE;
843
// Encode data before transmitting to writer
844
int status = MimeEncoderWrite(mEncoderData, aBuf, aLen);
845
return (status == 0) ? NS_OK : NS_ERROR_FAILURE;
848
return mWriter->Write(aBuf, aLen);
852
nsEnigMsgCompose::WriteToPipe(const char *aBuf, PRInt32 aLen)
855
DEBUG_LOG(("nsEnigMsgCompose::WriteToPipe: %d\n", aLen));
858
tmpStr.Assign(aBuf, aLen);
859
DEBUG_LOG(("nsEnigMimeWriter::WriteToPipe: data: '%s'\n", tmpStr.get()));
861
rv = mPipeTrans->Write(aBuf, aLen);
866
nsEnigMsgCompose::WriteCopy(const char *aBuf, PRInt32 aLen)
870
DEBUG_LOG(("nsEnigMsgCompose::WriteCopy: %d\n", aLen));
879
rv = mMimeListener->Write(aBuf, aLen, NULL, NULL);
880
if (NS_FAILED(rv)) return rv;
882
} else if (mPipeTrans) {
883
// Write to process and copy if multipart/signed
884
rv = WriteToPipe(aBuf, aLen);
885
if (NS_FAILED(rv)) return rv;
887
if (mMultipartSigned) {
888
rv = WriteOut(aBuf, aLen);
889
if (NS_FAILED(rv)) return rv;
896
///////////////////////////////////////////////////////////////////////////////
897
// nsIRequestObserver methods
898
///////////////////////////////////////////////////////////////////////////////
901
nsEnigMsgCompose::OnStartRequest(nsIRequest *aRequest,
902
nsISupports *aContext)
905
DEBUG_LOG(("nsEnigMsgCompose::OnStartRequest:\n"));
907
nsCAutoString contentType;
908
rv = mMimeListener->GetContentType(contentType);
909
if (NS_FAILED(rv)) return rv;
911
nsCAutoString contentEncoding;
912
rv = mMimeListener->GetContentEncoding(contentEncoding);
913
if (NS_FAILED(rv)) return rv;
915
nsCAutoString headers;
916
rv = mMimeListener->GetHeaders(headers);
917
if (NS_FAILED(rv)) return rv;
919
if (headers.IsEmpty())
920
return NS_ERROR_FAILURE;
922
DEBUG_LOG(("nsEnigMsgCompose::OnStartRequest: Content-Type: %s\n", headers.get()));
924
EMBool encapsulate = PR_FALSE;
925
if (mSendFlags & nsIEnigmail::SEND_PGP_MIME) {
926
// RFC2015 crypto encapsulation
927
encapsulate = PR_TRUE;
929
} else if (!contentType.Equals("text/plain", CaseInsensitiveCompare)) {
930
// Force RFC2015 crypto encapsulation for non-plaintext messages
931
encapsulate = PR_TRUE;
932
mSendFlags |= nsIEnigmail::SEND_PGP_MIME;
936
if (NS_FAILED(rv)) return rv;
938
if (!mPipeTrans) return NS_OK;
941
// RFC2015 crypto encapsulation for headers
943
// Send headers to crypto processor
944
rv = WriteToPipe(headers.get(), headers.Length());
945
if (NS_FAILED(rv)) return rv;
947
if (mMultipartSigned) {
948
rv = WriteSignedHeaders1( contentEncoding.Equals("8bit", CaseInsensitiveCompare) );
949
if (NS_FAILED(rv)) return rv;
951
// Copy original headers to output
952
rv = WriteOut(headers.get(), headers.Length());
953
if (NS_FAILED(rv)) return rv;
956
rv = WriteEncryptedHeaders();
957
if (NS_FAILED(rv)) return rv;
961
// No crypto encapsulation for headers
962
DEBUG_LOG(("nsEnigMsgCompose::OnStartRequest: NO CRYPTO ENCAPSULATION\n"));
964
rv = WriteOut(headers.get(), headers.Length());
965
if (NS_FAILED(rv)) return rv;
968
* not supported anymore
969
if (contentEncoding.Equals("base64", CaseInsensitiveCompare)) {
971
mEncoderData = MimeB64EncoderInit(EnigMsgCompose_write, (void*) mWriter);
973
} else if (contentEncoding.Equals("quoted-printable", CaseInsensitiveCompare)) {
975
mEncoderData = MimeQPEncoderInit(EnigMsgCompose_write, (void*) mWriter);
984
nsEnigMsgCompose::OnStopRequest(nsIRequest* aRequest,
985
nsISupports* aContext,
988
DEBUG_LOG(("nsEnigMsgCompose::OnStopRequest:\n"));
990
mRequestStopped = PR_TRUE;
995
///////////////////////////////////////////////////////////////////////////////
996
// nsIStreamListener method
997
///////////////////////////////////////////////////////////////////////////////
1000
nsEnigMsgCompose::OnDataAvailable(nsIRequest* aRequest,
1001
nsISupports* aContext,
1002
nsIInputStream *aInputStream,
1003
#if MOZILLA_MAJOR_VERSION < 18
1004
PRUint32 aSourceOffset,
1006
PRUint64 aSourceOffset,
1012
DEBUG_LOG(("nsEnigMsgCompose::OnDataAVailable: %d\n", aLength));
1015
return NS_ERROR_NOT_INITIALIZED;
1018
PRUint32 readCount, readMax, writeCount;
1020
while (aLength > 0) {
1021
readMax = (aLength < kCharMax) ? aLength : kCharMax;
1022
rv = aInputStream->Read((char *) buf, readMax, &readCount);
1025
DEBUG_LOG(("nsEnigMsgCompose::OnDataAvailable: Error in reading from input stream, %p\n", rv));
1029
if (readCount <= 0) return NS_OK;
1031
writeCount = readCount;
1033
if (mMultipartSigned) {
1036
tmpStr.Assign(buf, readCount);
1038
nsCString left(tmpStr);
1041
if (left.LowerCaseEqualsLiteral("x-mozilla-keys:")) {
1042
DEBUG_LOG(("nsEnigMimeWriter::OnDataAvailable: workaround for 'X-Mozilla-Keys:' header\n"));
1044
tmpStr.StripWhitespace();
1045
if (left == tmpStr) {
1046
if (buf[readCount-2] == '\r' && buf[readCount-1] == '\n') {
1047
tmpStr.Append("\r\n");
1050
tmpStr.Append("\n");
1052
rv = WriteToPipe(tmpStr.get(), tmpStr.Length());
1053
if (NS_FAILED(rv)) return rv;
1055
rv = WriteOut(tmpStr.get(), tmpStr.Length());
1056
if (NS_FAILED(rv)) return rv;
1058
aLength -= readCount;
1066
rv = WriteToPipe(buf, readCount);
1067
if (NS_FAILED(rv)) return rv;
1069
rv = WriteOut(buf, readCount);
1070
if (NS_FAILED(rv)) return rv;
1074
rv = WriteToPipe(buf, readCount);
1075
if (NS_FAILED(rv)) return rv;
1078
aLength -= readCount;