~ubuntu-branches/ubuntu/oneiric/enigmail/oneiric-updates

« back to all changes in this revision

Viewing changes to extensions/enigmail/src/nsEnigMimeVerify.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2010-04-10 01:42:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100410014224-fbq9ui5x3b0h2t36
Tags: 2:1.0.1-0ubuntu1
* First releaase of enigmail 1.0.1 for tbird/icedove 3
  (LP: #527138)
* redo packaging from scratch 
  + add debian/make-orig target that uses xulrunner provided
    buildsystem + enigmail tarball to produce a proper orig.tar.gz
  + use debhelper 7 with mozilla-devscripts
  + use debian source format 3.0 (quilt)
  + patch enigmail to use frozen API only
    - add debian/patches/frozen_api.diff
  + patch build system to not link against -lxul - which isnt
    available for sdks produced by all-static apps like tbird
    - add debian/patches/build_system_dont_link_libxul.diff
  + add minimal build-depends to control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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
 
12
 * MPL.
 
13
 *
 
14
 * The Original Code is Enigmail.
 
15
 *
 
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.
 
20
 *
 
21
 * Contributor(s):
 
22
 * Patrick Brunschwig <patrick.brunschwig@gmx.net>
 
23
 *
 
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.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
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 */
 
41
 
 
42
#include "enigmail.h"
 
43
#include "nspr.h"
 
44
#include "nsCOMPtr.h"
 
45
#include "nsString.h"
 
46
#include "nsXPIDLString.h"
 
47
#include "nsNetUtil.h"
 
48
#include "nsNetCID.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"
 
60
 
 
61
#undef MOZILLA_INTERNAL_API
 
62
#ifdef PR_LOGGING
 
63
PRLogModuleInfo* gEnigMimeVerifyLog = NULL;
 
64
#endif
 
65
 
 
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)
 
69
 
 
70
#define MAX_BUFFER_BYTES 32000
 
71
#define MAX_HEADER_BYTES 16000
 
72
 
 
73
static const PRUint32 kCharMax = 1024;
 
74
 
 
75
// nsEnigMimeVerify implementation
 
76
 
 
77
// nsISupports implementation
 
78
NS_IMPL_THREADSAFE_ISUPPORTS3(nsEnigMimeVerify,
 
79
                              nsIEnigMimeVerify,
 
80
                              nsIRequestObserver,
 
81
                              nsIStreamListener)
 
82
 
 
83
// nsEnigMimeVerify implementation
 
84
nsEnigMimeVerify::nsEnigMimeVerify()
 
85
  : mInitialized(PR_FALSE),
 
86
    mPgpMime(PR_FALSE),
 
87
    mRequestStopped(PR_FALSE),
 
88
    mLastLinebreak(PR_TRUE),
 
89
 
 
90
    mStartCount(0),
 
91
 
 
92
    mContentBoundary(""),
 
93
    mLinebreak(""),
 
94
 
 
95
    mURISpec(""),
 
96
    mMsgWindow(nsnull),
 
97
 
 
98
    mOutBuffer(nsnull),
 
99
    mPipeTrans(nsnull),
 
100
 
 
101
    mArmorListener(nsnull),
 
102
    mSecondPartListener(nsnull),
 
103
    mFirstPartListener(nsnull),
 
104
    mOuterMimeListener(nsnull),
 
105
    mInnerMimeListener(nsnull)
 
106
{
 
107
  nsresult rv;
 
108
 
 
109
  NS_INIT_ISUPPORTS();
 
110
 
 
111
#ifdef PR_LOGGING
 
112
  if (gEnigMimeVerifyLog == nsnull) {
 
113
    gEnigMimeVerifyLog = PR_NewLogModule("nsEnigMimeVerify");
 
114
  }
 
115
#endif
 
116
 
 
117
#ifdef FORCE_PR_LOG
 
118
  nsCOMPtr<nsIThread> myThread;
 
119
  rv = ENIG_GET_THREAD(myThread);
 
120
  DEBUG_LOG(("nsEnigMimeVerify:: <<<<<<<<< CTOR(%p): myThread=%p\n",
 
121
         this, myThread.get()));
 
122
#endif
 
123
}
 
124
 
 
125
 
 
126
nsEnigMimeVerify::~nsEnigMimeVerify()
 
127
{
 
128
  nsresult rv;
 
129
#ifdef FORCE_PR_LOG
 
130
  nsCOMPtr<nsIThread> myThread;
 
131
  rv = ENIG_GET_THREAD(myThread);
 
132
  DEBUG_LOG(("nsEnigMimeVerify:: >>>>>>>>> DTOR(%p): myThread=%p\n",
 
133
         this, myThread.get()));
 
134
#endif
 
135
 
 
136
  Finalize();
 
137
}
 
138
 
 
139
 
 
140
///////////////////////////////////////////////////////////////////////////////
 
141
// nsIEnigMimeVerify methods:
 
142
///////////////////////////////////////////////////////////////////////////////
 
143
 
 
144
NS_IMETHODIMP
 
145
nsEnigMimeVerify::Init(nsIDOMWindow* window,
 
146
                       nsIURI* aURI,
 
147
                       nsIMsgWindow* msgWindow,
 
148
                       const nsACString& msgUriSpec,
 
149
                       PRBool pgpMime,
 
150
                       PRBool isSubPart)
 
151
{
 
152
  nsresult rv;
 
153
 
 
154
  DEBUG_LOG(("nsEnigMimeVerify::Init: pgpMime=%d\n", (int) pgpMime));
 
155
 
 
156
  if (!aURI)
 
157
    return NS_ERROR_NULL_POINTER;
 
158
 
 
159
  mMsgWindow = msgWindow;
 
160
  mURISpec = msgUriSpec;
 
161
  mPgpMime = pgpMime;
 
162
 
 
163
  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
 
164
  if (NS_FAILED(rv)) return rv;
 
165
 
 
166
  nsCOMPtr<nsIChannel> channel;
 
167
  rv = ioService->NewChannelFromURI(aURI, getter_AddRefs(channel));
 
168
  if (NS_FAILED(rv)) return rv;
 
169
 
 
170
  // Listener to parse PGP block armor
 
171
  mArmorListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
172
  if (NS_FAILED(rv)) return rv;
 
173
 
 
174
  const char* pgpHeader = "-----BEGIN PGP ";
 
175
  const char* pgpFooter = "-----END PGP ";
 
176
 
 
177
  rv = mArmorListener->Init((nsIStreamListener*) this, nsnull,
 
178
                            pgpHeader, pgpFooter,
 
179
                            0, PR_TRUE, PR_FALSE, nsnull);
 
180
  if (NS_FAILED(rv)) return rv;
 
181
 
 
182
  // Inner mime listener to parse second part
 
183
  mInnerMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
 
184
  if (NS_FAILED(rv)) return rv;
 
185
 
 
186
  rv = mInnerMimeListener->Init(mArmorListener, nsnull,
 
187
                                MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
 
188
  if (NS_FAILED(rv)) return rv;
 
189
 
 
190
  // Create PipeFilterListener to extract second MIME part
 
191
  mSecondPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
192
  if (NS_FAILED(rv)) return rv;
 
193
 
 
194
  // Create PipeFilterListener to extract first MIME part
 
195
  mFirstPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
196
  if (NS_FAILED(rv)) return rv;
 
197
 
 
198
  rv = mFirstPartListener->Init((nsIStreamListener*) this,
 
199
                               nsnull, "", "", 0, PR_FALSE, PR_TRUE,
 
200
                               mSecondPartListener);
 
201
  if (NS_FAILED(rv)) return rv;
 
202
 
 
203
  // Outer mime listener to capture URI content
 
204
  mOuterMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
 
205
  if (NS_FAILED(rv)) return rv;
 
206
 
 
207
  if (isSubPart)
 
208
    mOuterMimeListener->SetSubPartTreatment(PR_TRUE);
 
209
 
 
210
  rv = mOuterMimeListener->Init(mFirstPartListener, nsnull,
 
211
                                MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
 
212
 
 
213
  if (NS_FAILED(rv)) return rv;
 
214
 
 
215
  // Initiate asynchronous loading of URI
 
216
  rv = channel->AsyncOpen( mOuterMimeListener, nsnull );
 
217
  if (NS_FAILED(rv))
 
218
    return rv;
 
219
 
 
220
  mInitialized = PR_TRUE;
 
221
 
 
222
  return NS_OK;
 
223
}
 
224
 
 
225
NS_IMETHODIMP
 
226
nsEnigMimeVerify::InitWithChannel(nsIDOMWindow* window,
 
227
                       nsIChannel* aChannel,
 
228
                       nsIMsgWindow* msgWindow,
 
229
                       const nsACString& msgUriSpec,
 
230
                       PRBool pgpMime,
 
231
                       PRBool isSubPart)
 
232
{
 
233
  nsresult rv;
 
234
 
 
235
  DEBUG_LOG(("nsEnigMimeVerify::Init: pgpMime=%d\n", (int) pgpMime));
 
236
 
 
237
  mMsgWindow = msgWindow;
 
238
  mURISpec = msgUriSpec;
 
239
  mPgpMime = pgpMime;
 
240
 
 
241
  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
 
242
  if (NS_FAILED(rv)) return rv;
 
243
 
 
244
  // Listener to parse PGP block armor
 
245
  mArmorListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
246
  if (NS_FAILED(rv)) return rv;
 
247
 
 
248
  const char* pgpHeader = "-----BEGIN PGP ";
 
249
  const char* pgpFooter = "-----END PGP ";
 
250
 
 
251
  rv = mArmorListener->Init((nsIStreamListener*) this, nsnull,
 
252
                            pgpHeader, pgpFooter,
 
253
                            0, PR_TRUE, PR_FALSE, nsnull);
 
254
  if (NS_FAILED(rv)) return rv;
 
255
 
 
256
  // Inner mime listener to parse second part
 
257
  mInnerMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
 
258
  if (NS_FAILED(rv)) return rv;
 
259
 
 
260
  rv = mInnerMimeListener->Init(mArmorListener, nsnull,
 
261
                                MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
 
262
  if (NS_FAILED(rv)) return rv;
 
263
 
 
264
  // Create PipeFilterListener to extract second MIME part
 
265
  mSecondPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
266
  if (NS_FAILED(rv)) return rv;
 
267
 
 
268
  // Create PipeFilterListener to extract first MIME part
 
269
  mFirstPartListener = do_CreateInstance(NS_PIPEFILTERLISTENER_CONTRACTID, &rv);
 
270
  if (NS_FAILED(rv)) return rv;
 
271
 
 
272
  rv = mFirstPartListener->Init((nsIStreamListener*) this,
 
273
                               nsnull, "", "", 0, PR_FALSE, PR_TRUE,
 
274
                               mSecondPartListener);
 
275
  if (NS_FAILED(rv)) return rv;
 
276
 
 
277
  // Outer mime listener to capture URI content
 
278
  mOuterMimeListener = do_CreateInstance(NS_ENIGMIMELISTENER_CONTRACTID, &rv);
 
279
  if (NS_FAILED(rv)) return rv;
 
280
 
 
281
  if (isSubPart)
 
282
    mOuterMimeListener->SetSubPartTreatment(PR_TRUE);
 
283
 
 
284
  rv = mOuterMimeListener->Init(mFirstPartListener, nsnull,
 
285
                                MAX_HEADER_BYTES, PR_TRUE, PR_FALSE, PR_FALSE);
 
286
 
 
287
  if (NS_FAILED(rv)) return rv;
 
288
 
 
289
  // Initiate asynchronous loading of URI
 
290
  rv = aChannel->AsyncOpen( mOuterMimeListener, nsnull );
 
291
  if (NS_FAILED(rv))
 
292
    return rv;
 
293
 
 
294
  mInitialized = PR_TRUE;
 
295
 
 
296
  return NS_OK;
 
297
}
 
298
 
 
299
nsresult
 
300
nsEnigMimeVerify::Finalize()
 
301
{
 
302
  DEBUG_LOG(("nsEnigMimeVerify::Finalize:\n"));
 
303
 
 
304
  if (mPipeTrans) {
 
305
    mPipeTrans->Terminate();
 
306
    mPipeTrans = nsnull;
 
307
  }
 
308
 
 
309
  if (mOutBuffer) {
 
310
    mOutBuffer->Shutdown();
 
311
    mOutBuffer = nsnull;
 
312
  }
 
313
 
 
314
  mMsgWindow = nsnull;
 
315
 
 
316
  mArmorListener = nsnull;
 
317
  mFirstPartListener = nsnull;
 
318
  mSecondPartListener = nsnull;
 
319
  mOuterMimeListener = nsnull;
 
320
  mInnerMimeListener = nsnull;
 
321
 
 
322
  return NS_OK;
 
323
}
 
324
 
 
325
NS_IMETHODIMP
 
326
nsEnigMimeVerify::Finish()
 
327
{
 
328
  // Enigmail stuff
 
329
  nsresult rv;
 
330
 
 
331
  if (!mInitialized || !mPipeTrans)
 
332
    return NS_ERROR_NOT_INITIALIZED;
 
333
 
 
334
  if (!mRequestStopped)
 
335
    return NS_ERROR_FAILURE;
 
336
 
 
337
  // Wait for STDOUT to close
 
338
  rv = mPipeTrans->Join();
 
339
  if (NS_FAILED(rv)) return rv;
 
340
 
 
341
  // Count of STDOUT bytes
 
342
  PRUint32 outputLen;
 
343
  rv = mOutBuffer->GetTotalBytes(&outputLen);
 
344
  if (NS_FAILED(rv)) return rv;
 
345
 
 
346
  // Shutdown STDOUT console
 
347
  mOutBuffer->Shutdown();
 
348
 
 
349
  // Check input data consistency
 
350
  if (mStartCount < 2) {
 
351
    ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR mStartCount=%d\n", mStartCount));
 
352
    return NS_ERROR_FAILURE;
 
353
  }
 
354
 
 
355
  nsCAutoString armorTail;
 
356
  rv = mArmorListener->GetEndLine(armorTail);
 
357
  if (NS_FAILED(rv)) return rv;
 
358
 
 
359
  if (armorTail.IsEmpty()) {
 
360
    ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR No armor tail found\n"));
 
361
    return NS_ERROR_FAILURE;
 
362
  }
 
363
 
 
364
  nsCAutoString endBoundary;
 
365
  rv = mSecondPartListener->GetEndLine(endBoundary);
 
366
  if (NS_FAILED(rv)) return rv;
 
367
 
 
368
  // Trim leading/trailing whitespace
 
369
  endBoundary.Trim(" \t\r\n", PR_TRUE, PR_TRUE);
 
370
 
 
371
  nsCAutoString temBoundary("--");
 
372
  temBoundary += mContentBoundary;
 
373
temBoundary += "--";
 
374
 
 
375
  if (!endBoundary.Equals(temBoundary)) {
 
376
    ERROR_LOG(("nsEnigMimeVerify::Finish: ERROR endBoundary=%s\n", endBoundary.get()));
 
377
    return NS_ERROR_FAILURE;
 
378
  }
 
379
 
 
380
  PRInt32 exitCode;
 
381
  PRUint32 statusFlags;
 
382
 
 
383
  nsXPIDLString keyId;
 
384
  nsXPIDLString userId;
 
385
  nsXPIDLString sigDate;
 
386
  nsXPIDLString errorMsg;
 
387
  nsXPIDLString blockSeparation;
 
388
 
 
389
  nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
 
390
  if (NS_FAILED(rv)) return rv;
 
391
 
 
392
  PRUint32 uiFlags = nsIEnigmail::UI_PGP_MIME;
 
393
  PRBool verifyOnly = PR_TRUE;
 
394
  PRBool noOutput = PR_TRUE;
 
395
 
 
396
  rv = enigmailSvc->DecryptMessageEnd(uiFlags,
 
397
                                      outputLen,
 
398
                                      mPipeTrans,
 
399
                                      verifyOnly,
 
400
                                      noOutput,
 
401
                                      &statusFlags,
 
402
                                      getter_Copies(keyId),
 
403
                                      getter_Copies(userId),
 
404
                                      getter_Copies(sigDate),
 
405
                                      getter_Copies(errorMsg),
 
406
                                      getter_Copies(blockSeparation),
 
407
                                      &exitCode);
 
408
  if (NS_FAILED(rv)) return rv;
 
409
 
 
410
  nsCOMPtr<nsISupports> securityInfo;
 
411
  if (mMsgWindow) {
 
412
    nsCOMPtr<nsIMsgHeaderSink> headerSink;
 
413
    mMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
 
414
    if (headerSink)
 
415
        headerSink->GetSecurityInfo(getter_AddRefs(securityInfo));
 
416
  }
 
417
 
 
418
  DEBUG_LOG(("nsEnigMimeVerify::Finish: securityInfo=%p\n", securityInfo.get()));
 
419
 
 
420
  if (securityInfo) {
 
421
    nsCOMPtr<nsIEnigMimeHeaderSink> enigHeaderSink = do_QueryInterface(securityInfo);
 
422
    if (enigHeaderSink) {
 
423
      rv = enigHeaderSink->UpdateSecurityStatus(mURISpec, exitCode, statusFlags, keyId, userId, sigDate, errorMsg, blockSeparation);
 
424
    }
 
425
  }
 
426
 
 
427
  if (exitCode != 0) {
 
428
    DEBUG_LOG(("nsEnigMimeVerify::Finish: ERROR EXIT %d\n", exitCode));
 
429
    return NS_ERROR_FAILURE;
 
430
  }
 
431
 
 
432
  return NS_OK;
 
433
}
 
434
 
 
435
 
 
436
///////////////////////////////////////////////////////////////////////////////
 
437
// nsIRequestObserver methods
 
438
///////////////////////////////////////////////////////////////////////////////
 
439
 
 
440
NS_IMETHODIMP
 
441
nsEnigMimeVerify::OnStartRequest(nsIRequest *aRequest,
 
442
                                   nsISupports *aContext)
 
443
{
 
444
  nsresult rv;
 
445
 
 
446
  mStartCount++;
 
447
 
 
448
  DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: %d\n", mStartCount));
 
449
 
 
450
  if (!mInitialized)
 
451
    return NS_ERROR_NOT_INITIALIZED;
 
452
 
 
453
  if (mStartCount > 2)
 
454
    return NS_ERROR_FAILURE;
 
455
 
 
456
  if (mStartCount == 2) {
 
457
    // Second start request
 
458
    nsCAutoString innerContentType;
 
459
    rv = mInnerMimeListener->GetContentType(innerContentType);
 
460
    if (NS_FAILED(rv)) return rv;
 
461
 
 
462
    if (!innerContentType.EqualsIgnoreCase("application/pgp-signature")) {
 
463
      DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR innerContentType=%s\n", innerContentType.get()));
 
464
      return NS_ERROR_FAILURE;
 
465
    }
 
466
 
 
467
    // Output Linebreak after signed content (IMPORTANT)
 
468
    rv = mInnerMimeListener->GetLinebreak(mLinebreak);
 
469
    if (NS_FAILED(rv)) return rv;
 
470
 
 
471
    if (mLinebreak.IsEmpty())
 
472
      return NS_ERROR_FAILURE;
 
473
 
 
474
    mPipeTrans->WriteSync(mLinebreak.get(), mLinebreak.Length());
 
475
 
 
476
    return NS_OK;
 
477
  }
 
478
 
 
479
  // First start request
 
480
  nsCAutoString contentType;
 
481
  rv = mOuterMimeListener->GetContentType(contentType);
 
482
  if (NS_FAILED(rv)) return rv;
 
483
 
 
484
  if (!contentType.EqualsIgnoreCase("multipart/signed")) {
 
485
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentType=%s\n", contentType.get()));
 
486
    return NS_ERROR_FAILURE;
 
487
  }
 
488
 
 
489
  nsCAutoString contentProtocol;
 
490
  rv = mOuterMimeListener->GetContentProtocol(contentProtocol);
 
491
  if (NS_FAILED(rv)) return rv;
 
492
 
 
493
  if (!contentProtocol.EqualsIgnoreCase("application/pgp-signature")) {
 
494
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentProtocol=%s\n", contentProtocol.get()));
 
495
    return NS_ERROR_FAILURE;
 
496
  }
 
497
 
 
498
  nsCAutoString contentMicalg;
 
499
  rv = mOuterMimeListener->GetContentMicalg(contentMicalg);
 
500
  if (NS_FAILED(rv)) return rv;
 
501
 
 
502
  nsCAutoString hashSymbol;
 
503
  if (contentMicalg.EqualsIgnoreCase("pgp-md5")) {
 
504
    hashSymbol = "MD5";
 
505
 
 
506
  } else if (contentMicalg.EqualsIgnoreCase("pgp-sha1")) {
 
507
    hashSymbol = "SHA1";
 
508
 
 
509
  } else if (contentMicalg.EqualsIgnoreCase("pgp-ripemd160")) {
 
510
    hashSymbol = "RIPEMD160";
 
511
 
 
512
  } else if (contentMicalg.EqualsIgnoreCase("pgp-sha224")) {
 
513
    hashSymbol = "SHA224";
 
514
 
 
515
  } else if (contentMicalg.EqualsIgnoreCase("pgp-sha256")) {
 
516
    hashSymbol = "SHA256";
 
517
 
 
518
  } else if (contentMicalg.EqualsIgnoreCase("pgp-sha384")) {
 
519
    hashSymbol = "SHA384";
 
520
 
 
521
  } else if (contentMicalg.EqualsIgnoreCase("pgp-sha512")) {
 
522
    hashSymbol = "SHA512";
 
523
 
 
524
  } else {
 
525
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR contentMicalg='%s'\n", contentMicalg.get()));
 
526
    return NS_ERROR_FAILURE;
 
527
  }
 
528
 
 
529
  nsCAutoString linebreak;
 
530
  rv = mOuterMimeListener->GetLinebreak(linebreak);
 
531
  if (NS_FAILED(rv)) return rv;
 
532
 
 
533
  rv = mOuterMimeListener->GetContentBoundary(mContentBoundary);
 
534
  if (NS_FAILED(rv)) return rv;
 
535
 
 
536
  if (mContentBoundary.IsEmpty()) {
 
537
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR no content boundary\n"));
 
538
    return NS_ERROR_FAILURE;
 
539
  }
 
540
 
 
541
  nsCAutoString mimeSeparator("--");
 
542
  mimeSeparator += mContentBoundary;
 
543
 
 
544
  nsCAutoString startDelimiter;
 
545
  rv = mFirstPartListener->GetStartDelimiter(startDelimiter);
 
546
  if (NS_FAILED(rv)) return rv;
 
547
 
 
548
  if (!startDelimiter.Equals(mimeSeparator)) {
 
549
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR startDelimiter=%s\n", startDelimiter.get()));
 
550
    return NS_ERROR_FAILURE;
 
551
  }
 
552
 
 
553
  nsCAutoString endBoundary;
 
554
  rv = mFirstPartListener->GetEndDelimiter(endBoundary);
 
555
  if (NS_FAILED(rv)) return rv;
 
556
 
 
557
  endBoundary.Trim(" \t\r\n", PR_TRUE, PR_TRUE);
 
558
 
 
559
  if (!endBoundary.Equals(mimeSeparator)) {
 
560
    ERROR_LOG(("nsEnigMimeVerify::OnStartRequest: ERROR endBoundary=%s\n", endBoundary.get()));
 
561
    return NS_ERROR_FAILURE;
 
562
  }
 
563
 
 
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;
 
569
 
 
570
 
 
571
  // Create null buffer to capture verification output
 
572
  mOutBuffer = do_CreateInstance(NS_IPCBUFFER_CONTRACTID, &rv);
 
573
  if (NS_FAILED(rv)) return rv;
 
574
 
 
575
  rv = mOutBuffer->Open(0, PR_FALSE);
 
576
  if (NS_FAILED(rv)) return rv;
 
577
 
 
578
  nsCOMPtr<nsIPrompt> prompter;
 
579
  if (mMsgWindow) {
 
580
    mMsgWindow->GetPromptDialog(getter_AddRefs(prompter));
 
581
  }
 
582
 
 
583
  DEBUG_LOG(("nsEnigMimeVerify::OnStartRequest: prompter=%p\n", prompter.get()));
 
584
 
 
585
  nsCOMPtr<nsIEnigmail> enigmailSvc = do_GetService(NS_ENIGMAIL_CONTRACTID, &rv);
 
586
  if (NS_FAILED(rv)) return rv;
 
587
 
 
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,
 
594
                                        prompter,
 
595
                                        verifyOnly,
 
596
                                        noOutput,
 
597
                                        mOutBuffer,
 
598
                                        noProxy,
 
599
                                        &statusFlags,
 
600
                                        getter_Copies(errorMsg),
 
601
                                        getter_AddRefs(mPipeTrans) );
 
602
  if (NS_FAILED(rv)) return rv;
 
603
 
 
604
  if (!mPipeTrans) {
 
605
    nsCOMPtr<nsISupports> securityInfo;
 
606
    if (mMsgWindow) {
 
607
      nsCOMPtr<nsIMsgHeaderSink> headerSink;
 
608
      mMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
 
609
      if (headerSink)
 
610
          headerSink->GetSecurityInfo(getter_AddRefs(securityInfo));
 
611
    }
 
612
 
 
613
    if (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());
 
618
      }
 
619
    }
 
620
 
 
621
    return NS_ERROR_FAILURE;
 
622
  }
 
623
  
 
624
  // Write clearsigned message header
 
625
  const char* clearsignHeader = "-----BEGIN PGP SIGNED MESSAGE-----";
 
626
 
 
627
  rv = mPipeTrans->WriteSync(clearsignHeader, strlen(clearsignHeader));
 
628
  if (NS_FAILED(rv)) return rv;
 
629
 
 
630
  rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
 
631
  if (NS_FAILED(rv)) return rv;
 
632
 
 
633
  // Write out hash symbol
 
634
  const char* hashHeader = "Hash: ";
 
635
 
 
636
  rv = mPipeTrans->WriteSync(hashHeader, strlen(hashHeader));
 
637
  if (NS_FAILED(rv)) return rv;
 
638
 
 
639
  rv = mPipeTrans->WriteSync(hashSymbol.get(), hashSymbol.Length());
 
640
  if (NS_FAILED(rv)) return rv;
 
641
 
 
642
  rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
 
643
  if (NS_FAILED(rv)) return rv;
 
644
 
 
645
  rv = mPipeTrans->WriteSync(linebreak.get(), linebreak.Length());
 
646
  if (NS_FAILED(rv)) return rv;
 
647
 
 
648
  // Initialize for dash-escaping
 
649
  mLastLinebreak = PR_TRUE;
 
650
 
 
651
  return NS_OK;
 
652
}
 
653
 
 
654
NS_IMETHODIMP
 
655
nsEnigMimeVerify::OnStopRequest(nsIRequest* aRequest,
 
656
                                nsISupports* aContext,
 
657
                                nsresult aStatus)
 
658
{
 
659
  nsresult rv;
 
660
  DEBUG_LOG(("nsEnigMimeVerify::OnStopRequest:\n"));
 
661
 
 
662
  if (mRequestStopped)
 
663
    return NS_OK;
 
664
 
 
665
  if (!mInitialized || !mPipeTrans)
 
666
    return NS_ERROR_NOT_INITIALIZED;
 
667
 
 
668
  mRequestStopped = PR_TRUE;
 
669
 
 
670
  rv = mPipeTrans->CloseStdin();
 
671
  if (NS_FAILED(rv)) {
 
672
    Finalize();
 
673
    return rv;
 
674
  }
 
675
 
 
676
  rv = Finish();
 
677
  if (NS_FAILED(rv)) {
 
678
    Finalize();
 
679
    return rv;
 
680
  }
 
681
 
 
682
  return NS_OK;
 
683
}
 
684
 
 
685
///////////////////////////////////////////////////////////////////////////////
 
686
// nsIStreamListener method
 
687
///////////////////////////////////////////////////////////////////////////////
 
688
 
 
689
NS_IMETHODIMP
 
690
nsEnigMimeVerify::OnDataAvailable(nsIRequest* aRequest,
 
691
                                  nsISupports* aContext,
 
692
                                  nsIInputStream *aInputStream,
 
693
                                  PRUint32 aSourceOffset,
 
694
                                  PRUint32 aLength)
 
695
{
 
696
  nsresult rv = NS_OK;
 
697
 
 
698
  DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: %d\n", aLength));
 
699
 
 
700
  if (!mInitialized || !mPipeTrans)
 
701
    return NS_ERROR_NOT_INITIALIZED;
 
702
 
 
703
  const char* dashEscape = " -";
 
704
  char buf[kCharMax];
 
705
  PRUint32 readCount, readMax;
 
706
 
 
707
  while (aLength > 0) {
 
708
    readMax = (aLength < kCharMax) ? aLength : kCharMax;
 
709
    rv = aInputStream->Read((char *) buf, readMax, &readCount);
 
710
    if (NS_FAILED(rv)){
 
711
      DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: Error in reading from input stream, %p\n", rv));
 
712
      return rv;
 
713
    }
 
714
 
 
715
    if (readCount <= 0) return NS_OK;
 
716
 
 
717
    if (mStartCount == 1) {
 
718
      // Dash escaping for first part only (RFC 2440)
 
719
 
 
720
      PRUint32 offset = 0;
 
721
      for (PRUint32 j=0; j < readCount; j++) {
 
722
        char ch = buf[j];
 
723
        if ((ch == '-') && mLastLinebreak) {
 
724
          rv = mPipeTrans->WriteSync(buf+offset, j-offset+1);
 
725
          if (NS_FAILED(rv)) return rv;
 
726
          offset = j+1;
 
727
 
 
728
          rv = mPipeTrans->WriteSync(dashEscape, strlen(dashEscape));
 
729
          if (NS_FAILED(rv)) return rv;
 
730
 
 
731
          DEBUG_LOG(("nsEnigMimeVerify::OnDataAvailable: DASH ESCAPED\n"));
 
732
        }
 
733
 
 
734
        mLastLinebreak = (ch == '\r') || (ch == '\n');
 
735
      }
 
736
 
 
737
      if (offset < readCount) {
 
738
        rv = mPipeTrans->WriteSync(buf+offset, readCount-offset);
 
739
        if (NS_FAILED(rv)) return rv;
 
740
      }
 
741
 
 
742
    } else {
 
743
      // No dash escaping
 
744
      rv = mPipeTrans->WriteSync(buf, readCount);
 
745
      if (NS_FAILED(rv)) return rv;
 
746
    }
 
747
 
 
748
    aLength -= readCount;
 
749
  }
 
750
 
 
751
  return NS_OK;
 
752
}