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 License
5
* Version 1.1 (the "MPL"); you may not use this file except in
6
* compliance with the MPL. You may obtain a copy of the MPL at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the MPL is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
11
* for the specific language governing rights and limitations under the
14
* The Original Code is Enigmail.
16
* The Initial Developer of the Original Code is
17
* Ramalingam Saravanan <sarava@sarava.net>
18
* Portions created by the Initial Developer are Copyright (C) 2002
19
* the Initial Developer. All Rights Reserved.
22
* Patrick Brunschwig <patrick.brunschwig@gmx.net>
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
38
// Logging of debug output
39
// The following define statement should occur before any include statements
40
#define FORCE_PR_LOG /* Allow logging even in release build */
46
#include "nsXPIDLString.h"
47
#include "nsNetUtil.h"
49
#include "nsIPrompt.h"
50
#include "nsIMsgWindow.h"
51
#include "nsIDOMWindow.h"
52
#include "nsIMimeMiscStatus.h"
53
#include "nsIEnigMimeHeaderSink.h"
54
#include "nsIThread.h"
55
#include "nsEnigMimeVerify.h"
56
#include "nsIPipeTransport.h"
57
#include "nsIIPCBuffer.h"
58
#include "nsIEnigmail.h"
59
#include "nsIUnicharOutputStream.h"
61
#undef MOZILLA_INTERNAL_API
63
PRLogModuleInfo* gEnigMimeVerifyLog = NULL;
66
#define ERROR_LOG(args) PR_LOG(gEnigMimeVerifyLog,PR_LOG_ERROR,args)
67
#define WARNING_LOG(args) PR_LOG(gEnigMimeVerifyLog,PR_LOG_WARNING,args)
68
#define DEBUG_LOG(args) PR_LOG(gEnigMimeVerifyLog,PR_LOG_DEBUG,args)
70
#define MAX_BUFFER_BYTES 32000
71
#define MAX_HEADER_BYTES 16000
73
static const PRUint32 kCharMax = 1024;
75
// nsEnigMimeVerify implementation
77
// nsISupports implementation
78
NS_IMPL_THREADSAFE_ISUPPORTS3(nsEnigMimeVerify,
83
// nsEnigMimeVerify implementation
84
nsEnigMimeVerify::nsEnigMimeVerify()
85
: mInitialized(PR_FALSE),
87
mRequestStopped(PR_FALSE),
88
mLastLinebreak(PR_TRUE),
101
mArmorListener(nsnull),
102
mSecondPartListener(nsnull),
103
mFirstPartListener(nsnull),
104
mOuterMimeListener(nsnull),
105
mInnerMimeListener(nsnull)
112
if (gEnigMimeVerifyLog == nsnull) {
113
gEnigMimeVerifyLog = PR_NewLogModule("nsEnigMimeVerify");
118
nsCOMPtr<nsIThread> myThread;
119
rv = ENIG_GET_THREAD(myThread);
120
DEBUG_LOG(("nsEnigMimeVerify:: <<<<<<<<< CTOR(%p): myThread=%p\n",
121
this, myThread.get()));
126
nsEnigMimeVerify::~nsEnigMimeVerify()
130
nsCOMPtr<nsIThread> myThread;
131
rv = ENIG_GET_THREAD(myThread);
132
DEBUG_LOG(("nsEnigMimeVerify:: >>>>>>>>> DTOR(%p): myThread=%p\n",
133
this, myThread.get()));
140
///////////////////////////////////////////////////////////////////////////////
141
// nsIEnigMimeVerify methods:
142
///////////////////////////////////////////////////////////////////////////////
145
nsEnigMimeVerify::Init(nsIDOMWindow* window,
147
nsIMsgWindow* msgWindow,
148
const nsACString& msgUriSpec,
154
DEBUG_LOG(("nsEnigMimeVerify::Init: pgpMime=%d\n", (int) pgpMime));
157
return NS_ERROR_NULL_POINTER;
159
mMsgWindow = msgWindow;
160
mURISpec = msgUriSpec;
163
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
164
if (NS_FAILED(rv)) return rv;
166
nsCOMPtr<nsIChannel> channel;
167
rv = ioService->NewChannelFromURI(aURI, getter_AddRefs(channel));
168
if (NS_FAILED(rv)) return rv;
170
// Listener to parse PGP block armor
171
mArmorListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
172
if (NS_FAILED(rv)) return rv;
174
const char* pgpHeader = "-----BEGIN PGP ";
175
const char* pgpFooter = "-----END PGP ";
177
rv = mArmorListener->Init((nsIStreamListener*) this, nsnull,
178
pgpHeader, pgpFooter,
179
0, PR_TRUE, PR_FALSE, nsnull);
180
if (NS_FAILED(rv)) return rv;
182
// Inner mime listener to parse second part
183
mInnerMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
184
if (NS_FAILED(rv)) return rv;
186
rv = mInnerMimeListener->Init(mArmorListener, nsnull,
187
MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
188
if (NS_FAILED(rv)) return rv;
190
// Create PipeFilterListener to extract second MIME part
191
mSecondPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
192
if (NS_FAILED(rv)) return rv;
194
// Create PipeFilterListener to extract first MIME part
195
mFirstPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
196
if (NS_FAILED(rv)) return rv;
198
rv = mFirstPartListener->Init((nsIStreamListener*) this,
199
nsnull, "", "", 0, PR_FALSE, PR_TRUE,
200
mSecondPartListener);
201
if (NS_FAILED(rv)) return rv;
203
// Outer mime listener to capture URI content
204
mOuterMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
205
if (NS_FAILED(rv)) return rv;
208
mOuterMimeListener->SetSubPartTreatment(PR_TRUE);
210
rv = mOuterMimeListener->Init(mFirstPartListener, nsnull,
211
MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
213
if (NS_FAILED(rv)) return rv;
215
// Initiate asynchronous loading of URI
216
rv = channel->AsyncOpen( mOuterMimeListener, nsnull );
220
mInitialized = PR_TRUE;
226
nsEnigMimeVerify::InitWithChannel(nsIDOMWindow* window,
227
nsIChannel* aChannel,
228
nsIMsgWindow* msgWindow,
229
const nsACString& msgUriSpec,
235
DEBUG_LOG(("nsEnigMimeVerify::Init: pgpMime=%d\n", (int) pgpMime));
237
mMsgWindow = msgWindow;
238
mURISpec = msgUriSpec;
241
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
242
if (NS_FAILED(rv)) return rv;
244
// Listener to parse PGP block armor
245
mArmorListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
246
if (NS_FAILED(rv)) return rv;
248
const char* pgpHeader = "-----BEGIN PGP ";
249
const char* pgpFooter = "-----END PGP ";
251
rv = mArmorListener->Init((nsIStreamListener*) this, nsnull,
252
pgpHeader, pgpFooter,
253
0, PR_TRUE, PR_FALSE, nsnull);
254
if (NS_FAILED(rv)) return rv;
256
// Inner mime listener to parse second part
257
mInnerMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
258
if (NS_FAILED(rv)) return rv;
260
rv = mInnerMimeListener->Init(mArmorListener, nsnull,
261
MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
262
if (NS_FAILED(rv)) return rv;
264
// Create PipeFilterListener to extract second MIME part
265
mSecondPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
266
if (NS_FAILED(rv)) return rv;
268
// Create PipeFilterListener to extract first MIME part
269
mFirstPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
270
if (NS_FAILED(rv)) return rv;
272
rv = mFirstPartListener->Init((nsIStreamListener*) this,
273
nsnull, "", "", 0, PR_FALSE, PR_TRUE,
274
mSecondPartListener);
275
if (NS_FAILED(rv)) return rv;
277
// Outer mime listener to capture URI content
278
mOuterMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
279
if (NS_FAILED(rv)) return rv;
282
mOuterMimeListener->SetSubPartTreatment(PR_TRUE);
284
rv = mOuterMimeListener->Init(mFirstPartListener, nsnull,
285
MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
287
if (NS_FAILED(rv)) return rv;
289
// Initiate asynchronous loading of URI
290
rv = aChannel->AsyncOpen( mOuterMimeListener, nsnull );
294
mInitialized = PR_TRUE;
300
nsEnigMimeVerify::Finalize()
302
DEBUG_LOG(("nsEnigMimeVerify::Finalize:\n"));
305
mPipeTrans->Terminate();
310
mOutBuffer->Shutdown();
316
mArmorListener = nsnull;
317
mFirstPartListener = nsnull;
318
mSecondPartListener = nsnull;
319
mOuterMimeListener = nsnull;
320
mInnerMimeListener = nsnull;
326
nsEnigMimeVerify::Finish()
331
if (!mInitialized || !mPipeTrans)
332
return NS_ERROR_NOT_INITIALIZED;
334
if (!mRequestStopped)
335
return NS_ERROR_FAILURE;
337
// Wait for STDOUT to close
338
rv = mPipeTrans->Join();
339
if (NS_FAILED(rv)) return rv;
341
// Count of STDOUT bytes
343
rv = mOutBuffer->GetTotalBytes(&outputLen);
344
if (NS_FAILED(rv)) return rv;
346
// Shutdown STDOUT console
347
mOutBuffer->Shutdown();
349
// Check input data consistency
350
if (mStartCount < 2) {
351
ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR mStartCount=%d\n", mStartCount));
352
return NS_ERROR_FAILURE;
355
nsCAutoString armorTail;
356
rv = mArmorListener->GetEndLine(armorTail);
357
if (NS_FAILED(rv)) return rv;
359
if (armorTail.IsEmpty()) {
360
ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR No armor tail found\n"));
361
return NS_ERROR_FAILURE;
364
nsCAutoString endBoundary;
365
rv = mSecondPartListener->GetEndLine(endBoundary);
366
if (NS_FAILED(rv)) return rv;
368
// Trim leading/trailing whitespace
369
endBoundary.Trim(" \t\r\n", PR_TRUE, PR_TRUE);
371
nsCAutoString temBoundary("--");
372
temBoundary += mContentBoundary;
375
if (!endBoundary.Equals(temBoundary)) {
376
ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR endBoundary=%s\n", endBoundary.get()));
377
return NS_ERROR_FAILURE;
381
PRUint32 statusFlags;
384
nsXPIDLString userId;
385
nsXPIDLString sigDate;
386
nsXPIDLString errorMsg;
387
nsXPIDLString blockSeparation;
389
nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
390
if (NS_FAILED(rv)) return rv;
392
PRUint32 uiFlags = nsIEnigmail::UI_PGP_MIME;
393
PRBool verifyOnly = PR_TRUE;
394
PRBool noOutput = PR_TRUE;
396
rv = enigmailSvc->DecryptMessageEnd(uiFlags,
402
getter_Copies(keyId),
403
getter_Copies(userId),
404
getter_Copies(sigDate),
405
getter_Copies(errorMsg),
406
getter_Copies(blockSeparation),
408
if (NS_FAILED(rv)) return rv;
410
nsCOMPtr<nsISupports> securityInfo;
412
nsCOMPtr<nsIMsgHeaderSink> headerSink;
413
mMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
415
headerSink->GetSecurityInfo(getter_AddRefs(securityInfo));
418
DEBUG_LOG(("nsEnigMimeVerify::Finish: securityInfo=%p\n", securityInfo.get()));
421
nsCOMPtr<nsIEnigMimeHeaderSink> enigHeaderSink = do_QueryInterface(securityInfo);
422
if (enigHeaderSink) {
423
rv = enigHeaderSink->UpdateSecurityStatus(mURISpec, exitCode, statusFlags, keyId, userId, sigDate, errorMsg, blockSeparation);
428
DEBUG_LOG(("nsEnigMimeVerify::Finish: ERROR EXIT %d\n", exitCode));
429
return NS_ERROR_FAILURE;
436
///////////////////////////////////////////////////////////////////////////////
437
// nsIRequestObserver methods
438
///////////////////////////////////////////////////////////////////////////////
441
nsEnigMimeVerify::OnStartRequest(nsIRequest *aRequest,
442
nsISupports *aContext)
448
DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: %d\n", mStartCount));
451
return NS_ERROR_NOT_INITIALIZED;
454
return NS_ERROR_FAILURE;
456
if (mStartCount == 2) {
457
// Second start request
458
nsCAutoString innerContentType;
459
rv = mInnerMimeListener->GetContentType(innerContentType);
460
if (NS_FAILED(rv)) return rv;
462
if (!innerContentType.EqualsIgnoreCase("application/pgp-signature")) {
463
DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR innerContentType=%s\n", innerContentType.get()));
464
return NS_ERROR_FAILURE;
467
// Output Linebreak after signed content (IMPORTANT)
468
rv = mInnerMimeListener->GetLinebreak(mLinebreak);
469
if (NS_FAILED(rv)) return rv;
471
if (mLinebreak.IsEmpty())
472
return NS_ERROR_FAILURE;
474
mPipeTrans->WriteSync(mLinebreak.get(), mLinebreak.Length());
479
// First start request
480
nsCAutoString contentType;
481
rv = mOuterMimeListener->GetContentType(contentType);
482
if (NS_FAILED(rv)) return rv;
484
if (!contentType.EqualsIgnoreCase("multipart/signed")) {
485
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentType=%s\n", contentType.get()));
486
return NS_ERROR_FAILURE;
489
nsCAutoString contentProtocol;
490
rv = mOuterMimeListener->GetContentProtocol(contentProtocol);
491
if (NS_FAILED(rv)) return rv;
493
if (!contentProtocol.EqualsIgnoreCase("application/pgp-signature")) {
494
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentProtocol=%s\n", contentProtocol.get()));
495
return NS_ERROR_FAILURE;
498
nsCAutoString contentMicalg;
499
rv = mOuterMimeListener->GetContentMicalg(contentMicalg);
500
if (NS_FAILED(rv)) return rv;
502
nsCAutoString hashSymbol;
503
if (contentMicalg.EqualsIgnoreCase("pgp-md5")) {
506
} else if (contentMicalg.EqualsIgnoreCase("pgp-sha1")) {
509
} else if (contentMicalg.EqualsIgnoreCase("pgp-ripemd160")) {
510
hashSymbol = "RIPEMD160";
512
} else if (contentMicalg.EqualsIgnoreCase("pgp-sha224")) {
513
hashSymbol = "SHA224";
515
} else if (contentMicalg.EqualsIgnoreCase("pgp-sha256")) {
516
hashSymbol = "SHA256";
518
} else if (contentMicalg.EqualsIgnoreCase("pgp-sha384")) {
519
hashSymbol = "SHA384";
521
} else if (contentMicalg.EqualsIgnoreCase("pgp-sha512")) {
522
hashSymbol = "SHA512";
525
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentMicalg='%s'\n", contentMicalg.get()));
526
return NS_ERROR_FAILURE;
529
nsCAutoString linebreak;
530
rv = mOuterMimeListener->GetLinebreak(linebreak);
531
if (NS_FAILED(rv)) return rv;
533
rv = mOuterMimeListener->GetContentBoundary(mContentBoundary);
534
if (NS_FAILED(rv)) return rv;
536
if (mContentBoundary.IsEmpty()) {
537
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR no content boundary\n"));
538
return NS_ERROR_FAILURE;
541
nsCAutoString mimeSeparator("--");
542
mimeSeparator += mContentBoundary;
544
nsCAutoString startDelimiter;
545
rv = mFirstPartListener->GetStartDelimiter(startDelimiter);
546
if (NS_FAILED(rv)) return rv;
548
if (!startDelimiter.Equals(mimeSeparator)) {
549
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR startDelimiter=%s\n", startDelimiter.get()));
550
return NS_ERROR_FAILURE;
553
nsCAutoString endBoundary;
554
rv = mFirstPartListener->GetEndDelimiter(endBoundary);
555
if (NS_FAILED(rv)) return rv;
557
endBoundary.Trim(" \t\r\n", PR_TRUE, PR_TRUE);
559
if (!endBoundary.Equals(mimeSeparator)) {
560
ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR endBoundary=%s\n", endBoundary.get()));
561
return NS_ERROR_FAILURE;
564
// Initialize second part listener with content boundary
565
rv = mSecondPartListener->Init(mInnerMimeListener,
566
nsnull, "", mimeSeparator.get(),
567
0, PR_FALSE, PR_FALSE, nsnull);
568
if (NS_FAILED(rv)) return rv;
571
// Create null buffer to capture verification output
572
mOutBuffer = do_CreateInstance(NS_IPCBUFFER_CONTRACTID, &rv);
573
if (NS_FAILED(rv)) return rv;
575
rv = mOutBuffer->Open(0, PR_FALSE);
576
if (NS_FAILED(rv)) return rv;
578
nsCOMPtr<nsIPrompt> prompter;
580
mMsgWindow->GetPromptDialog(getter_AddRefs(prompter));
583
DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: prompter=%p\n", prompter.get()));
585
nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
586
if (NS_FAILED(rv)) return rv;
588
nsXPIDLString errorMsg;
589
PRBool verifyOnly = PR_TRUE;
590
PRBool noOutput = PR_TRUE;
591
PRBool noProxy = PR_TRUE;
592
PRUint32 statusFlags;
593
rv = enigmailSvc->DecryptMessageStart(nsnull,
600
getter_Copies(errorMsg),
601
getter_AddRefs(mPipeTrans) );
602
if (NS_FAILED(rv)) return rv;
605
nsCOMPtr<nsISupports> securityInfo;
607
nsCOMPtr<nsIMsgHeaderSink> headerSink;
608
mMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
610
headerSink->GetSecurityInfo(getter_AddRefs(securityInfo));
614
nsCOMPtr<nsIEnigMimeHeaderSink> enigHeaderSink = do_QueryInterface(securityInfo);
615
if (enigHeaderSink) {
616
NS_NAMED_LITERAL_STRING(nullString, "");
617
rv = enigHeaderSink->UpdateSecurityStatus(mURISpec, -1, statusFlags, nullString.get(), nullString.get(), nullString.get(), errorMsg, nullString.get());
621
return NS_ERROR_FAILURE;
624
// Write clearsigned message header
625
const char* clearsignHeader = "-----BEGIN PGP SIGNED MESSAGE-----";
627
rv = mPipeTrans->WriteSync(clearsignHeader, strlen(clearsignHeader));
628
if (NS_FAILED(rv)) return rv;
630
rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
631
if (NS_FAILED(rv)) return rv;
633
// Write out hash symbol
634
const char* hashHeader = "Hash: ";
636
rv = mPipeTrans->WriteSync(hashHeader, strlen(hashHeader));
637
if (NS_FAILED(rv)) return rv;
639
rv = mPipeTrans->WriteSync(hashSymbol.get(), hashSymbol.Length());
640
if (NS_FAILED(rv)) return rv;
642
rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
643
if (NS_FAILED(rv)) return rv;
645
rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
646
if (NS_FAILED(rv)) return rv;
648
// Initialize for dash-escaping
649
mLastLinebreak = PR_TRUE;
655
nsEnigMimeVerify::OnStopRequest(nsIRequest* aRequest,
656
nsISupports* aContext,
660
DEBUG_LOG(("nsEnigMimeVerify::OnStopRequest:\n"));
665
if (!mInitialized || !mPipeTrans)
666
return NS_ERROR_NOT_INITIALIZED;
668
mRequestStopped = PR_TRUE;
670
rv = mPipeTrans->CloseStdin();
685
///////////////////////////////////////////////////////////////////////////////
686
// nsIStreamListener method
687
///////////////////////////////////////////////////////////////////////////////
690
nsEnigMimeVerify::OnDataAvailable(nsIRequest* aRequest,
691
nsISupports* aContext,
692
nsIInputStream *aInputStream,
693
PRUint32 aSourceOffset,
698
DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: %d\n", aLength));
700
if (!mInitialized || !mPipeTrans)
701
return NS_ERROR_NOT_INITIALIZED;
703
const char* dashEscape = " -";
705
PRUint32 readCount, readMax;
707
while (aLength > 0) {
708
readMax = (aLength < kCharMax) ? aLength : kCharMax;
709
rv = aInputStream->Read((char *) buf, readMax, &readCount);
711
DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: Error in reading from input stream, %p\n", rv));
715
if (readCount <= 0) return NS_OK;
717
if (mStartCount == 1) {
718
// Dash escaping for first part only (RFC 2440)
721
for (PRUint32 j=0; j < readCount; j++) {
723
if ((ch == '-') && mLastLinebreak) {
724
rv = mPipeTrans->WriteSync(buf+offset, j-offset+1);
725
if (NS_FAILED(rv)) return rv;
728
rv = mPipeTrans->WriteSync(dashEscape, strlen(dashEscape));
729
if (NS_FAILED(rv)) return rv;
731
DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: DASH ESCAPED\n"));
734
mLastLinebreak = (ch == '\r') || (ch == '\n');
737
if (offset < readCount) {
738
rv = mPipeTrans->WriteSync(buf+offset, readCount-offset);
739
if (NS_FAILED(rv)) return rv;
744
rv = mPipeTrans->WriteSync(buf, readCount);
745
if (NS_FAILED(rv)) return rv;
748
aLength -= readCount;