~ubuntu-branches/ubuntu/quantal/enigmail/quantal-security

« back to all changes in this revision

Viewing changes to mailnews/extensions/enigmail/ui/content/enigmailMessengerOverlay.js

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-09-13 16:02:15 UTC
  • mfrom: (0.12.16)
  • Revision ID: package-import@ubuntu.com-20130913160215-u3g8nmwa0pdwagwc
Tags: 2:1.5.2-0ubuntu0.12.10.1
* New upstream release v1.5.2 for Thunderbird 24

* Build enigmail using a stripped down Thunderbird 17 build system, as it's
  now quite difficult to build the way we were doing previously, with the
  latest Firefox build system
* Add debian/patches/no_libxpcom.patch - Don't link against libxpcom, as it
  doesn't exist anymore (but exists in the build system)
* Add debian/patches/use_sdk.patch - Use the SDK version of xpt.py and
  friends
* Drop debian/patches/ipc-pipe_rename.diff (not needed anymore)
* Drop debian/patches/makefile_depth.diff (not needed anymore)

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
 
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/
 
8
 *
 
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.
 
13
 *
 
14
 * The Original Code is Enigmail.
 
15
 *
 
16
 * The Initial Developer of the Original Code is Ramalingam Saravanan.
 
17
 * Portions created by Ramalingam Saravanan <svn@xmlterm.org> are
 
18
 * Copyright (C) 2001 Ramalingam Saravanan. All Rights Reserved.
 
19
 *
 
20
 * Contributor(s):
 
21
 *   Patrick Brunschwig <patrick@mozilla-enigmail.org>
 
22
 *
 
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 ***** */
 
35
 
 
36
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
37
 
 
38
try {
 
39
  // TB with omnijar
 
40
  Components.utils.import("resource:///modules/gloda/mimemsg.js");
 
41
}
 
42
catch (ex) {
 
43
  // "old style" TB
 
44
  Components.utils.import("resource://app/modules/gloda/mimemsg.js");
 
45
}
 
46
 
 
47
Components.utils.import("resource://enigmail/enigmailCommon.jsm");
 
48
Components.utils.import("resource://enigmail/commonFuncs.jsm");
 
49
Components.utils.import("resource://enigmail/mimeVerify.jsm");
 
50
 
 
51
if (! Enigmail) var Enigmail = {};
 
52
 
 
53
Enigmail.getEnigmailSvc = function ()
 
54
{
 
55
  return EnigmailCommon.getService(window);
 
56
};
 
57
 
 
58
 
 
59
Enigmail.msg = {
 
60
  createdURIs:      [],
 
61
  decryptedMessage: null,
 
62
  securityInfo:     null,
 
63
  lastSaveDir:      "",
 
64
  messagePane:      null,
 
65
  noShowReload:     false,
 
66
  decryptButton:    null,
 
67
  savedHeaders:     null,
 
68
  removeListener:   false,
 
69
  enableExperiments: false,
 
70
  headersList:      ["content-type", "content-transfer-encoding",
 
71
                     "x-enigmail-version", "x-pgp-encoding-format" ],
 
72
 
 
73
  messengerStartup: function ()
 
74
  {
 
75
 
 
76
    // private function to overwrite attributes
 
77
    function overrideAttribute (elementIdList, attrName, prefix, suffix)
 
78
    {
 
79
      for (var index = 0; index < elementIdList.length; index++) {
 
80
        var elementId = elementIdList[index];
 
81
        var element = document.getElementById(elementId);
 
82
        if (element) {
 
83
          try {
 
84
            var oldValue = element.getAttribute(attrName);
 
85
            EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: overrideAttribute "+attrName+": oldValue="+oldValue+"\n");
 
86
            var newValue = prefix+elementId+suffix;
 
87
 
 
88
            element.setAttribute(attrName, newValue);
 
89
          } catch (ex) {}
 
90
        }
 
91
        else {
 
92
          EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: *** UNABLE to override id="+ elementId+"\n");
 
93
        }
 
94
      }
 
95
    }
 
96
 
 
97
    Enigmail.msg.messagePane = document.getElementById("messagepane");
 
98
 
 
99
    if (Enigmail.msg.messagePane == null) return; // TB on Mac OS X calls this twice -- once far too early
 
100
 
 
101
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: Startup\n");
 
102
 
 
103
    // Override SMIME ui
 
104
    var viewSecurityCmd = document.getElementById("cmd_viewSecurityStatus");
 
105
    if (viewSecurityCmd) {
 
106
      viewSecurityCmd.setAttribute("oncommand", "Enigmail.msg.viewSecurityInfo(null, true);");
 
107
    }
 
108
 
 
109
    // Override print command
 
110
    var printElementIds = ["cmd_print", "cmd_printpreview", "key_print", "button-print",
 
111
                           "mailContext-print", "mailContext-printpreview"];
 
112
 
 
113
    overrideAttribute( printElementIds, "oncommand",
 
114
                       "Enigmail.msg.msgPrint('", "');");
 
115
 
 
116
    Enigmail.msg.overrideLayoutChange();
 
117
 
 
118
    Enigmail.msg.savedHeaders = null;
 
119
 
 
120
    Enigmail.msg.decryptButton = document.getElementById("button-enigmail-decrypt");
 
121
 
 
122
    // Need to add event listener to Enigmail.msg.messagePane to make it work
 
123
    // Adding to msgFrame doesn't seem to work
 
124
    Enigmail.msg.messagePane.addEventListener("unload", Enigmail.msg.messageFrameUnload.bind(Enigmail.msg), true);
 
125
 
 
126
    // override double clicking attachments, but fall back to existing handler if present
 
127
    var attListElem = document.getElementById("attachmentList");
 
128
    if (attListElem) {
 
129
      var newHandler = "Enigmail.msg.enigAttachmentListClick('attachmentList', event)";
 
130
      var oldHandler = attListElem.getAttribute("onclick");
 
131
      if (oldHandler)
 
132
        newHandler = "if (!" + newHandler + ") {" + oldHandler + "}";
 
133
      attListElem.setAttribute("onclick", newHandler);
 
134
    }
 
135
 
 
136
    var treeController = {
 
137
      supportsCommand: function(command) {
 
138
        // EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: treeCtrl: supportsCommand: "+command+"\n");
 
139
        switch(command) {
 
140
        case "button_enigmail_decrypt":
 
141
          return true;
 
142
        }
 
143
        return false;
 
144
      },
 
145
      isCommandEnabled: function(command) {
 
146
        // EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: treeCtrl: isCommandEnabled: "+command+"\n");
 
147
        try {
 
148
          if (gFolderDisplay.messageDisplay.visible) {
 
149
            if (gFolderDisplay.selectedCount != 1) Enigmail.hdrView.statusBarHide();
 
150
            return (gFolderDisplay.selectedCount == 1);
 
151
          }
 
152
          Enigmail.hdrView.statusBarHide();
 
153
        }
 
154
        catch (ex) {}
 
155
        return  false;
 
156
      },
 
157
      doCommand: function(command) {
 
158
        //EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: treeCtrl: doCommand: "+command+"\n");
 
159
        // nothing
 
160
      },
 
161
      onEvent: function(event) {
 
162
        // EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: treeCtrl: onEvent: "+command+"\n");
 
163
        // nothing
 
164
      }
 
165
    };
 
166
 
 
167
    top.controllers.appendController(treeController);
 
168
  },
 
169
 
 
170
  viewSecurityInfo: function (event, displaySmimeMsg)
 
171
  {
 
172
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: viewSecurityInfo\n");
 
173
 
 
174
    if (event && event.button != 0)
 
175
      return;
 
176
 
 
177
    if (gSignatureStatus >= 0 || gEncryptionStatus >= 0) {
 
178
      showMessageReadSecurityInfo();
 
179
    }
 
180
    else {
 
181
      if (Enigmail.msg.securityInfo)
 
182
        this.viewOpenpgpInfo();
 
183
      else
 
184
        showMessageReadSecurityInfo();
 
185
    }
 
186
  },
 
187
 
 
188
  viewOpenpgpInfo: function ()
 
189
  {
 
190
    if (Enigmail.msg.securityInfo) {
 
191
      EnigmailCommon.longAlert(window, EnigmailCommon.getString("securityInfo")+Enigmail.msg.securityInfo.statusInfo);
 
192
    }
 
193
  },
 
194
 
 
195
 
 
196
  messageReload: function (noShowReload)
 
197
  {
 
198
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: this.messageReload: "+noShowReload+"\n");
 
199
 
 
200
    Enigmail.msg.noShowReload = noShowReload;
 
201
 
 
202
    ReloadMessage();
 
203
  },
 
204
 
 
205
 
 
206
  reloadCompleteMsg: function ()
 
207
  {
 
208
    gDBView.reloadMessageWithAllParts();
 
209
  },
 
210
 
 
211
 
 
212
  setAttachmentReveal: function (attachmentList)
 
213
  {
 
214
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: setAttachmentReveal\n");
 
215
 
 
216
    var revealBox = document.getElementById("enigmailRevealAttachments");
 
217
    revealBox.setAttribute("hidden", attachmentList == null ? "true" : "false");
 
218
  },
 
219
 
 
220
 
 
221
  messageCleanup: function () {
 
222
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageCleanup\n");
 
223
 
 
224
    var enigmailBox = document.getElementById("enigmailBox");
 
225
 
 
226
    if (enigmailBox && !enigmailBox.collapsed) {
 
227
      enigmailBox.setAttribute("collapsed", "true");
 
228
 
 
229
      var statusText = document.getElementById("expandedEnigmailStatusText");
 
230
 
 
231
      if (statusText)
 
232
        statusText.value="";
 
233
    }
 
234
 
 
235
    this.setAttachmentReveal(null);
 
236
 
 
237
    if (Enigmail.msg.createdURIs.length) {
 
238
      // Cleanup messages belonging to this window (just in case)
 
239
      var enigmailSvc = Enigmail.getEnigmailSvc();
 
240
      if (enigmailSvc) {
 
241
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: Cleanup: Deleting messages\n");
 
242
        for (var index=0; index < Enigmail.msg.createdURIs.length; index++) {
 
243
          enigmailSvc.deleteMessageURI(Enigmail.msg.createdURIs[index]);
 
244
        }
 
245
        Enigmail.msg.createdURIs = [];
 
246
      }
 
247
    }
 
248
 
 
249
    Enigmail.msg.decryptedMessage = null;
 
250
    Enigmail.msg.securityInfo = null;
 
251
  },
 
252
 
 
253
  messageFrameUnload: function ()
 
254
  {
 
255
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageFrameUnload\n");
 
256
 
 
257
    if (Enigmail.msg.noShowReload) {
 
258
      Enigmail.msg.noShowReload = false;
 
259
 
 
260
    } else {
 
261
      Enigmail.msg.savedHeaders = null;
 
262
 
 
263
      Enigmail.msg.messageCleanup();
 
264
    }
 
265
  },
 
266
 
 
267
  overrideLayoutChange: function ()
 
268
  {
 
269
    // Enigmail needs to listen to some layout changes in order to decrypt
 
270
    // messages in case the user changes the layout
 
271
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: overrideLayoutChange\n");
 
272
    var viewTypeElementIds = ["messagePaneVertical",
 
273
                              "messagePaneClassic",
 
274
                              "messagePaneWide"];
 
275
    var i;
 
276
    for (i = 0; i < viewTypeElementIds.length; i++) {
 
277
      var elementId = viewTypeElementIds[i];
 
278
      var element = document.getElementById(elementId);
 
279
      if (element) {
 
280
        try {
 
281
          var oldValue = element.getAttribute("oncommand").replace(/;/g, "");
 
282
          var arg=oldValue.replace(/^(.*)(\(.*\))/, "$2");
 
283
          element.setAttribute("oncommand", "Enigmail.msg.changeMailLayout"+arg);
 
284
        } catch (ex) {}
 
285
      }
 
286
    }
 
287
 
 
288
    var toggleMsgPaneElementIds = ["cmd_toggleMessagePane"];
 
289
    for (i = 0; i < toggleMsgPaneElementIds.length; i++) {
 
290
      var elementId = toggleMsgPaneElementIds[i];
 
291
      var element = document.getElementById(elementId);
 
292
      if (element) {
 
293
        try {
 
294
          element.setAttribute("oncommand", "Enigmail.msg.toggleMessagePane()");
 
295
        } catch (ex) {}
 
296
      }
 
297
    }
 
298
  },
 
299
 
 
300
  changeMailLayout: function (viewType)
 
301
  {
 
302
    // call the original layout change 1st
 
303
    ChangeMailLayout(viewType);
 
304
 
 
305
    // This event requires that we re-subscribe to these events!
 
306
    Enigmail.msg.messagePane.addEventListener("unload", Enigmail.msg.messageFrameUnload.bind(Enigmail.msg), true);
 
307
    this.messageReload(false);
 
308
  },
 
309
 
 
310
  toggleMessagePane: function () {
 
311
    Enigmail.hdrView.statusBarHide();
 
312
    MsgToggleMessagePane(true);
 
313
 
 
314
    var button=document.getElementById("button_enigmail_decrypt");
 
315
    if (gFolderDisplay.messageDisplay.visible) {
 
316
      button.removeAttribute("disabled");
 
317
    }
 
318
    else {
 
319
      button.setAttribute("disabled", "true");
 
320
    }
 
321
  },
 
322
 
 
323
  getCurrentMsgUriSpec: function ()
 
324
  {
 
325
    try {
 
326
      if (gFolderDisplay.selectedMessages.length != 1)
 
327
        return "";
 
328
 
 
329
      var uriSpec = gFolderDisplay.selectedMessageUris[0];
 
330
      //EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: getCurrentMsgUriSpec: uriSpec="+uriSpec+"\n");
 
331
 
 
332
      return uriSpec;
 
333
 
 
334
    }
 
335
    catch (ex) {
 
336
      return "";
 
337
    }
 
338
  },
 
339
 
 
340
  getCurrentMsgUrl: function ()
 
341
  {
 
342
    var uriSpec = this.getCurrentMsgUriSpec();
 
343
    return this.getUrlFromUriSpec(uriSpec);
 
344
  },
 
345
 
 
346
  getUrlFromUriSpec: function (uriSpec)
 
347
  {
 
348
    try {
 
349
      if (!uriSpec)
 
350
        return null;
 
351
 
 
352
      var msgService = messenger.messageServiceFromURI(uriSpec);
 
353
 
 
354
      var urlObj = new Object();
 
355
      msgService.GetUrlForUri(uriSpec, urlObj, msgWindow);
 
356
 
 
357
      var url = urlObj.value;
 
358
 
 
359
      if (url.scheme=="file") {
 
360
        return url;
 
361
      }
 
362
      else {
 
363
        return url.QueryInterface(Components.interfaces.nsIMsgMailNewsUrl);
 
364
      }
 
365
 
 
366
    }
 
367
    catch (ex) {
 
368
      return null;
 
369
    }
 
370
  },
 
371
 
 
372
  updateOptionsDisplay: function ()
 
373
  {
 
374
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: updateOptionsDisplay: \n");
 
375
    var optList = ["autoDecrypt"];
 
376
 
 
377
    for (var j=0; j<optList.length; j++) {
 
378
      var menuElement = document.getElementById("enigmail_"+optList[j]);
 
379
      menuElement.setAttribute("checked", EnigmailCommon.getPref(optList[j]) ? "true" : "false");
 
380
 
 
381
      menuElement = document.getElementById("enigmail_"+optList[j]+"2");
 
382
      if (menuElement)
 
383
        menuElement.setAttribute("checked", EnigmailCommon.getPref(optList[j]) ? "true" : "false");
 
384
    }
 
385
 
 
386
    optList = ["decryptverify", "importpublickey", "savedecrypted"];
 
387
    for (j=0; j<optList.length; j++) {
 
388
      menuElement = document.getElementById("enigmail_"+optList[j]);
 
389
      if (Enigmail.msg.decryptButton && Enigmail.msg.decryptButton.disabled) {
 
390
         menuElement.setAttribute("disabled", "true");
 
391
      }
 
392
      else {
 
393
         menuElement.removeAttribute("disabled");
 
394
      }
 
395
 
 
396
      menuElement = document.getElementById("enigmail_"+optList[j]+"2");
 
397
      if (menuElement) {
 
398
        if (Enigmail.msg.decryptButton && Enigmail.msg.decryptButton.disabled) {
 
399
           menuElement.setAttribute("disabled", "true");
 
400
        }
 
401
        else {
 
402
           menuElement.removeAttribute("disabled");
 
403
        }
 
404
      }
 
405
    }
 
406
  },
 
407
 
 
408
  displayMainMenu: function(menuPopup) {
 
409
 
 
410
    function traverseTree(currentElement, func)
 
411
    {
 
412
      if (currentElement)
 
413
      {
 
414
        func(currentElement);
 
415
        if (currentElement.id)
 
416
          EnigmailCommon.DEBUG_LOG("traverseTree: "+currentElement.id+"\n");
 
417
 
 
418
        // Traverse the tree
 
419
        var i=0;
 
420
        var currentElementChild=currentElement.childNodes[i];
 
421
        while (currentElementChild)
 
422
        {
 
423
          // Recursively traverse the tree structure of the child node
 
424
          traverseTree(currentElementChild, func);
 
425
          i++;
 
426
          currentElementChild=currentElement.childNodes[i];
 
427
        }
 
428
      }
 
429
    }
 
430
 
 
431
    var p = menuPopup.parentNode;
 
432
    var a = document.getElementById("menu_EnigmailPopup");
 
433
    var c = a.cloneNode(true);
 
434
    p.removeChild(menuPopup);
 
435
 
 
436
 
 
437
    traverseTree(c, function _updNode(node) {
 
438
       if (node.id && node.id.length > 0) node.id += "2";
 
439
    });
 
440
    p.appendChild(c);
 
441
 
 
442
  },
 
443
 
 
444
  toggleAttribute: function (attrName)
 
445
  {
 
446
    EnigmailCommon.DEBUG_LOG("enigmailMsgessengerOverlay.js: toggleAttribute('"+attrName+"')\n");
 
447
 
 
448
    var menuElement = document.getElementById("enigmail_"+attrName);
 
449
 
 
450
    var oldValue = EnigmailCommon.getPref(attrName);
 
451
    EnigmailCommon.setPref(attrName, !oldValue);
 
452
 
 
453
    this.updateOptionsDisplay();
 
454
 
 
455
    if (attrName == "autoDecrypt")
 
456
      this.messageReload(false);
 
457
  },
 
458
 
 
459
  messageImport: function (event)
 
460
  {
 
461
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageImport: "+event+"\n");
 
462
 
 
463
    return this.messageParse(!event, true, "", this.getCurrentMsgUriSpec());
 
464
  },
 
465
 
 
466
  // callback function for automatic decryption
 
467
  messageAutoDecrypt: function (event)
 
468
  {
 
469
    Enigmail.msg.messageDecrypt(event, true);
 
470
  },
 
471
 
 
472
  // analyse message header and decrypt/verify message
 
473
  messageDecrypt: function (event, isAuto)
 
474
  {
 
475
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecrypt: "+event+"\n");
 
476
 
 
477
    var cbObj = {
 
478
      event: event,
 
479
      isAuto: isAuto
 
480
    };
 
481
 
 
482
    let contentType = "text/plain";
 
483
    if ('content-type' in currentHeaderData) contentType=currentHeaderData['content-type'].headerValue;
 
484
 
 
485
 
 
486
    // don't parse message if we know it's a PGP/MIME message
 
487
    if (((contentType.search(/^multipart\/signed(;|$)/i) == 0) && (contentType.search(/application\/pgp-signature/i)>0)) ||
 
488
      ((contentType.search(/^multipart\/encrypted(;|$)/i) == 0) && (contentType.search(/application\/pgp-encrypted/i)>0))) {
 
489
      this.messageDecryptCb(event, isAuto, null);
 
490
      return;
 
491
    }
 
492
 
 
493
    try {
 
494
      if (gFolderDisplay.selectedMessageIsNews) throw "dummy"; // workaround for broken NNTP support in Gloda
 
495
      MsgHdrToMimeMessage(gFolderDisplay.selectedMessage , cbObj, Enigmail.msg.msgDecryptMimeCb, true, {examineEncryptedParts: true, partsOnDemand: false});
 
496
    }
 
497
    catch (ex) {
 
498
      EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: enigMessageDecrypt: cannot use MsgHdrToMimeMessage\n");
 
499
      this.messageDecryptCb(event, isAuto, null);
 
500
    }
 
501
  },
 
502
 
 
503
 
 
504
  msgDecryptMimeCb: function (msg, mimeMsg)
 
505
  {
 
506
    // MsgHdrToMimeMessage is not on the main thread which may lead to problems with
 
507
    // accessing DOM and debugging
 
508
 
 
509
    EnigmailCommon.dispatchEvent(
 
510
      function(argList) {
 
511
        var enigmailSvc=Enigmail.getEnigmailSvc();
 
512
        if (!enigmailSvc) return;
 
513
 
 
514
        var event = argList[0];
 
515
        var isAuto = argList[1];
 
516
        var mimeMsg = argList[2];
 
517
        Enigmail.msg.messageDecryptCb(event, isAuto, mimeMsg);
 
518
      }, 0, [this.event, this.isAuto, mimeMsg]);
 
519
  },
 
520
 
 
521
  enumerateMimeParts: function (mimePart, resultObj)
 
522
  {
 
523
    EnigmailCommon.DEBUG_LOG("enumerateMimeParts: "+mimePart.partName+" - "+mimePart.headers["content-type"]+"\n");
 
524
 
 
525
    try {
 
526
      if (typeof(mimePart.contentType) == "string" &&
 
527
          mimePart.contentType == "multipart/fake-container") {
 
528
        // workaround for wrong content type of signed message
 
529
        let signedPart = mimePart.parts[1];
 
530
        if (typeof(signedPart.headers["content-type"][0]) == "string") {
 
531
          if (signedPart.headers["content-type"][0].search(/application\/pgp-signature/i) >= 0) {
 
532
            resultObj.signed=signedPart.partName.replace(/\.[0-9]+$/, "");
 
533
            EnigmailCommon.DEBUG_LOG("enumerateMimeParts: found signed subpart "+resultObj.signed + "\n");
 
534
          }
 
535
        }
 
536
      }
 
537
 
 
538
      var ct = mimePart.headers["content-type"][0];
 
539
      if (typeof(ct) == "string") {
 
540
        if (ct.search(/multipart\/signed.*application\/pgp-signature/i) >= 0) {
 
541
          resultObj.signed=mimePart.partName;
 
542
        }
 
543
        else if (ct.search(/application\/pgp-encrypted/i) >= 0)
 
544
          resultObj.encrypted=mimePart.partName;
 
545
      }
 
546
    }
 
547
    catch (ex) {
 
548
      // catch exception if no headers or no content-type defined.
 
549
    }
 
550
 
 
551
    var i;
 
552
    for (i in mimePart.parts) {
 
553
      this.enumerateMimeParts(mimePart.parts[i], resultObj);
 
554
    }
 
555
  },
 
556
 
 
557
 
 
558
  messageDecryptCb: function (event, isAuto, mimeMsg)
 
559
  {
 
560
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecryptCb:\n");
 
561
 
 
562
    var enigmailSvc;
 
563
    try {
 
564
      var showHeaders = 0;
 
565
      var contentType = "";
 
566
 
 
567
      if (mimeMsg == null) {
 
568
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecryptCb: mimeMsg is null\n");
 
569
        try {
 
570
          contentType=currentHeaderData['content-type'].headerValue;
 
571
        }
 
572
        catch (ex) {
 
573
          contentType = "text/plain";
 
574
        }
 
575
        mimeMsg = {
 
576
          headers: {'content-type': contentType },
 
577
          contentType: contentType,
 
578
          parts: null
 
579
        };
 
580
      }
 
581
 
 
582
      // Copy selected headers
 
583
      Enigmail.msg.savedHeaders = {};
 
584
 
 
585
      for (var index=0; index < Enigmail.msg.headersList.length; index++) {
 
586
        var headerName = Enigmail.msg.headersList[index];
 
587
        var headerValue = "";
 
588
 
 
589
        if (mimeMsg.headers[headerName] != undefined) {
 
590
          headerValue = mimeMsg.headers[headerName].toString();
 
591
        }
 
592
 
 
593
        Enigmail.msg.savedHeaders[headerName] = headerValue;
 
594
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: header "+headerName+": "+headerValue+"\n");
 
595
      }
 
596
 
 
597
      var embeddedSigned = null;
 
598
      var embeddedEncrypted = null;
 
599
 
 
600
      if (mimeMsg.parts != null && Enigmail.msg.savedHeaders["content-type"].search(/^multipart\/encrypted(;|$)/i) != 0) {
 
601
        // TB >= 8.0
 
602
        var resultObj={ encrypted: "", signed: "" };
 
603
        this.enumerateMimeParts(mimeMsg, resultObj);
 
604
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: embedded objects: "+resultObj.encrypted+" / "+resultObj.signed+"\n");
 
605
 
 
606
        // ignore mime parts on top level (regular messages)
 
607
        if (resultObj.signed.indexOf(".") < 0) resultObj.signed = null;
 
608
        if (resultObj.encrypted.indexOf(".") < 0) resultObj.encrypted = null;
 
609
 
 
610
        if (resultObj.encrypted || resultObj.signed) {
 
611
          let mailUrl = this.getCurrentMsgUrl();
 
612
          if (mailUrl) {
 
613
            if (resultObj.signed) embeddedSigned = mailUrl.spec+"?part="+resultObj.signed.replace(/\.\d+$/, "");
 
614
            if (resultObj.encrypted) embeddedEncrypted = mailUrl.spec+"?part="+resultObj.encrypted.replace(/\.\d+$/, "");
 
615
          }
 
616
        }
 
617
      }
 
618
 
 
619
      var contentEncoding = "";
 
620
      var xEnigmailVersion = "";
 
621
      var msgUriSpec = this.getCurrentMsgUriSpec();
 
622
 
 
623
      if (Enigmail.msg.savedHeaders) {
 
624
        contentType      = Enigmail.msg.savedHeaders["content-type"];
 
625
        contentEncoding  = Enigmail.msg.savedHeaders["content-transfer-encoding"];
 
626
        xEnigmailVersion = Enigmail.msg.savedHeaders["x-enigmail-version"];
 
627
      }
 
628
 
 
629
      if (isAuto && (! EnigmailCommon.getPref("autoDecrypt"))) {
 
630
        var signedMsg = ((contentType.search(/^multipart\/signed(;|$)/i) == 0) && (contentType.search(/application\/pgp-signature/i)>0));
 
631
        var encrypedMsg = ((contentType.search(/^multipart\/encrypted(;|$)/i) == 0) && (contentType.search(/application\/pgp-encrypted/i)>0));
 
632
        if (embeddedSigned || embeddedEncrypted ||
 
633
            encrypedMsg || signedMsg) {
 
634
          enigmailSvc = Enigmail.getEnigmailSvc();
 
635
          if (!enigmailSvc)
 
636
            return;
 
637
 
 
638
          if (signedMsg ||
 
639
              ((!encrypedMsg) && (embeddedSigned || embeddedEncrypted))) {
 
640
            Enigmail.hdrView.updateHdrIcons(EnigmailCommon.POSSIBLE_PGPMIME, 0, "", "", "", EnigmailCommon.getString("possiblyPgpMime"));
 
641
          }
 
642
        }
 
643
        return;
 
644
      }
 
645
 
 
646
      if (contentType.search(/^multipart\/encrypted(;|$)/i) == 0) {
 
647
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: multipart/encrypted\n");
 
648
 
 
649
        enigmailSvc = Enigmail.getEnigmailSvc();
 
650
        if (!enigmailSvc)
 
651
          return;
 
652
      }
 
653
 
 
654
      if (((contentType.search(/^multipart\/encrypted(;|$)/i) == 0) ||
 
655
          (embeddedEncrypted && contentType.search(/^multipart\/mixed(;|$)/i) == 0))
 
656
           && (!embeddedSigned)) {
 
657
 
 
658
        enigmailSvc = Enigmail.getEnigmailSvc();
 
659
        if (!enigmailSvc)
 
660
          return;
 
661
 
 
662
        if (! isAuto) {
 
663
          Enigmail.msg.messageReload(false);
 
664
        }
 
665
        else if (embeddedEncrypted && (! encrypedMsg)) {
 
666
          var mailNewsUrl = this.getCurrentMsgUrl();
 
667
          if (mailNewsUrl) {
 
668
            mailNewsUrl.spec = embeddedEncrypted;
 
669
            Enigmail.msg.verifyEmbeddedMsg(window, mailNewsUrl, msgWindow, msgUriSpec, contentEncoding, event);
 
670
          }
 
671
        }
 
672
 
 
673
        return;
 
674
      }
 
675
 
 
676
      var tryVerify = false;
 
677
      var enableSubpartTreatment = false;
 
678
      // special treatment for embedded signed messages
 
679
      if (embeddedSigned) {
 
680
        if (contentType.search(/^multipart\/encrypted(;|$)/i) == 0) {
 
681
          tryVerify = true;
 
682
        }
 
683
        if (contentType.search(/^multipart\/mixed(;|$)/i) == 0) {
 
684
          tryVerify = true;
 
685
          enableSubpartTreatment = true;
 
686
        }
 
687
      }
 
688
 
 
689
      if ((contentType.search(/^multipart\/signed(;|$)/i) == 0) &&
 
690
           (contentType.search(/application\/pgp-signature/i) >= 0)) {
 
691
        tryVerify=true;
 
692
      }
 
693
      if (tryVerify) {
 
694
        // multipart/signed
 
695
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecryptCb: multipart/signed\n");
 
696
 
 
697
        var mailNewsUrl = this.getCurrentMsgUrl();
 
698
        if (mailNewsUrl) {
 
699
            EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecryptCb: mailNewsUrl:"+mailNewsUrl+"\n");
 
700
            EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageDecryptCb: msgUriSpec:"+msgUriSpec+"\n");
 
701
          if (embeddedSigned) {
 
702
            mailNewsUrl.spec = embeddedSigned;
 
703
            Enigmail.msg.verifyEmbeddedMsg(window, mailNewsUrl, msgWindow, msgUriSpec, contentEncoding, event);
 
704
          }
 
705
          else {
 
706
            var verifier = EnigmailVerify.newVerfier(false, mailNewsUrl);
 
707
            verifier.startStreaming(window, msgWindow, msgUriSpec);
 
708
 
 
709
          }
 
710
          return;
 
711
        }
 
712
      }
 
713
 
 
714
      this.messageParse(!event, false, contentEncoding, msgUriSpec);
 
715
    }
 
716
    catch (ex) {
 
717
      EnigmailCommon.writeException("enigmailMessengerOverlay.js: messageDecryptCb", ex);
 
718
    }
 
719
  },
 
720
 
 
721
 
 
722
  messageParse: function (interactive, importOnly, contentEncoding, msgUriSpec)
 
723
  {
 
724
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParse: "+interactive+"\n");
 
725
    var msgFrame = EnigmailCommon.getFrame(window, "messagepane");
 
726
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgFrame="+msgFrame+"\n");
 
727
 
 
728
    var bodyElement = msgFrame.document.getElementsByTagName("body")[0];
 
729
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: bodyElement="+bodyElement+"\n");
 
730
 
 
731
    var findStr = /* interactive ? null : */ "-----BEGIN PGP";
 
732
    var msgText = null;
 
733
    var foundIndex = -1;
 
734
 
 
735
 
 
736
    if (bodyElement.firstChild) {
 
737
      let node = bodyElement.firstChild;
 
738
      while (node) {
 
739
        if (node.nodeName == "DIV") {
 
740
          foundIndex = node.textContent.indexOf(findStr);
 
741
 
 
742
          if (foundIndex >= 0) {
 
743
            if (node.textContent.indexOf(findStr+" LICENSE AUTHORIZATION") == foundIndex)
 
744
              foundIndex = -1;
 
745
          }
 
746
          if (foundIndex >= 0) {
 
747
            bodyElement = node;
 
748
            break;
 
749
          }
 
750
        }
 
751
        node = node.nextSibling;
 
752
      }
 
753
    }
 
754
 
 
755
    if (foundIndex >= 0) {
 
756
      msgText = bodyElement.textContent;
 
757
    }
 
758
 
 
759
    if (!msgText) {
 
760
      // No PGP content
 
761
      return;
 
762
    }
 
763
 
 
764
    var charset = msgWindow ? msgWindow.mailCharacterSet : "";
 
765
 
 
766
    // Encode ciphertext to charset from unicode
 
767
    msgText = EnigmailCommon.convertFromUnicode(msgText, charset);
 
768
 
 
769
    var mozPlainText = bodyElement.innerHTML.search(/class=\"moz-text-plain\"/);
 
770
 
 
771
    if ((mozPlainText >= 0) && (mozPlainText < 40)) {
 
772
      // workaround for too much expanded emoticons in plaintext msg
 
773
      var r = new RegExp(/( )(;-\)|:-\)|;\)|:\)|:-\(|:\(|:-\\|:-P|:-D|:-\[|:-\*|\>:o|8-\)|:-\$|:-X|\=-O|:-\!|O:-\)|:\'\()( )/g);
 
774
      if (msgText.search(r) >= 0) {
 
775
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParse: performing emoticons fixing\n");
 
776
        msgText = msgText.replace(r, "$2");
 
777
      }
 
778
    }
 
779
 
 
780
    // extract text preceeding and/or following armored block
 
781
    var head="";
 
782
    var tail="";
 
783
    if (findStr) {
 
784
      head=msgText.substring(0,msgText.indexOf(findStr)).replace(/^[\n\r\s]*/,"");
 
785
      head=head.replace(/[\n\r\s]*$/,"");
 
786
      var endStart=msgText.indexOf("-----END PGP");
 
787
      var nextLine=msgText.substring(endStart).search(/[\n\r]/);
 
788
      if (nextLine>0) {
 
789
        tail=msgText.substring(endStart+nextLine).replace(/^[\n\r\s]*/,"");
 
790
      }
 
791
    }
 
792
 
 
793
    //EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgText='"+msgText+"'\n");
 
794
 
 
795
    var mailNewsUrl = this.getUrlFromUriSpec(msgUriSpec);
 
796
 
 
797
    var urlSpec = mailNewsUrl ? mailNewsUrl.spec : "";
 
798
 
 
799
    let retry = (charset != "UTF-8" ? 1 : 2);
 
800
 
 
801
    Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset, interactive,
 
802
                                      importOnly, urlSpec, "", retry, head, tail,
 
803
                                      msgUriSpec);
 
804
  },
 
805
 
 
806
 
 
807
  messageParseCallback: function (msgText, contentEncoding, charset, interactive,
 
808
                                  importOnly, messageUrl, signature, retry,
 
809
                                  head, tail, msgUriSpec)
 
810
  {
 
811
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParseCallback: "+interactive+", "+interactive+", importOnly="+importOnly+", charset="+charset+", msgUrl="+messageUrl+", retry="+retry+", signature='"+signature+"'\n");
 
812
 
 
813
    const nsIEnigmail = Components.interfaces.nsIEnigmail;
 
814
 
 
815
    if (!msgText)
 
816
      return;
 
817
 
 
818
    var enigmailSvc = Enigmail.getEnigmailSvc();
 
819
    if (!enigmailSvc)
 
820
      return;
 
821
 
 
822
    var plainText;
 
823
    var exitCode;
 
824
    var newSignature = "";
 
825
    var statusFlags = 0;
 
826
 
 
827
    var errorMsgObj = new Object();
 
828
    var keyIdObj    = new Object();
 
829
    var blockSeparationObj = { value: "" };
 
830
 
 
831
 
 
832
    if (importOnly) {
 
833
      // Import public key
 
834
      var importFlags = nsIEnigmail.UI_INTERACTIVE;
 
835
      exitCode = enigmailSvc.importKey(window, importFlags, msgText, "",
 
836
                                       errorMsgObj);
 
837
 
 
838
    }
 
839
    else {
 
840
 
 
841
      if (msgText.indexOf("\nCharset:") > 0) {
 
842
        // Check if character set needs to be overridden
 
843
        var startOffset = msgText.indexOf("-----BEGIN PGP ");
 
844
 
 
845
        if (startOffset >= 0) {
 
846
          var subText = msgText.substr(startOffset);
 
847
 
 
848
          subText = subText.replace(/\r\n/g, "\n");
 
849
          subText = subText.replace(/\r/g,   "\n");
 
850
 
 
851
          var endOffset = subText.search(/\n\n/);
 
852
          if (endOffset > 0) {
 
853
            subText = subText.substr(0,endOffset) + "\n";
 
854
 
 
855
            var matches = subText.match(/\nCharset: *(.*) *\n/i);
 
856
            if (matches && (matches.length > 1)) {
 
857
              // Override character set
 
858
              charset = matches[1];
 
859
              EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParseCallback: OVERRIDING charset="+charset+"\n");
 
860
            }
 
861
          }
 
862
        }
 
863
      }
 
864
 
 
865
      var exitCodeObj    = new Object();
 
866
      var statusFlagsObj = new Object();
 
867
      var userIdObj      = new Object();
 
868
      var sigDetailsObj  = new Object();
 
869
 
 
870
      var signatureObj = new Object();
 
871
      signatureObj.value = signature;
 
872
 
 
873
      var uiFlags = interactive ? (nsIEnigmail.UI_INTERACTIVE |
 
874
                                   nsIEnigmail.UI_ALLOW_KEY_IMPORT |
 
875
                                   nsIEnigmail.UI_UNVERIFIED_ENC_OK) : 0;
 
876
 
 
877
 
 
878
      plainText = enigmailSvc.decryptMessage(window, uiFlags, msgText,
 
879
                                   signatureObj, exitCodeObj, statusFlagsObj,
 
880
                                   keyIdObj, userIdObj, sigDetailsObj, errorMsgObj, blockSeparationObj);
 
881
 
 
882
      //EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParseCallback: plainText='"+plainText+"'\n");
 
883
 
 
884
      exitCode = exitCodeObj.value;
 
885
      newSignature = signatureObj.value;
 
886
 
 
887
      if (plainText == "" && exitCode == 0) {
 
888
        plainText = " ";
 
889
      }
 
890
 
 
891
      statusFlags = statusFlagsObj.value;
 
892
 
 
893
      EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageParseCallback: newSignature='"+newSignature+"'\n");
 
894
    }
 
895
 
 
896
    var errorMsg = errorMsgObj.value;
 
897
 
 
898
    if (importOnly) {
 
899
       if (interactive && errorMsg)
 
900
         EnigmailCommon.longAlert(window, errorMsg);
 
901
       return;
 
902
    }
 
903
 
 
904
    var displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
 
905
    if (!msgUriSpec || (displayedUriSpec == msgUriSpec)) {
 
906
      Enigmail.hdrView.updateHdrIcons(exitCode, statusFlags, keyIdObj.value, userIdObj.value, sigDetailsObj.value, errorMsg, null);
 
907
    }
 
908
 
 
909
    var noSecondTry = nsIEnigmail.GOOD_SIGNATURE |
 
910
          nsIEnigmail.EXPIRED_SIGNATURE |
 
911
          nsIEnigmail.EXPIRED_KEY_SIGNATURE |
 
912
          nsIEnigmail.EXPIRED_KEY |
 
913
          nsIEnigmail.REVOKED_KEY |
 
914
          nsIEnigmail.NO_PUBKEY |
 
915
          nsIEnigmail.NO_SECKEY |
 
916
          nsIEnigmail.IMPORTED_KEY |
 
917
          nsIEnigmail.MISSING_PASSPHRASE |
 
918
          nsIEnigmail.BAD_PASSPHRASE |
 
919
          nsIEnigmail.UNKNOWN_ALGO |
 
920
          nsIEnigmail.DECRYPTION_OKAY |
 
921
          nsIEnigmail.OVERFLOWED;
 
922
 
 
923
    if ((exitCode !=0) && (! (statusFlags & noSecondTry))) {
 
924
      // Bad signature/armor
 
925
      if (retry == 1) {
 
926
        msgText = EnigmailCommon.convertFromUnicode(msgText, "UTF-8");
 
927
        Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset,
 
928
                                          interactive, importOnly, messageUrl,
 
929
                                          signature, retry + 1,
 
930
                                          head, tail, msgUriSpec);
 
931
        return;
 
932
      }
 
933
      else if (retry == 2) {
 
934
        // Try to verify signature by accessing raw message text directly
 
935
        // (avoid recursion by setting retry parameter to false on callback)
 
936
        newSignature = "";
 
937
        Enigmail.msg.msgDirectDecrypt(interactive, importOnly, contentEncoding, charset,
 
938
                                      newSignature, 0, head, tail, msgUriSpec,
 
939
                                      Enigmail.msg.messageParseCallback);
 
940
        return;
 
941
      }
 
942
      else if (retry == 3) {
 
943
        msgText = EnigmailCommon.convertToUnicode(msgText, "UTF-8");
 
944
        Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset, interactive,
 
945
                                          importOnly, messageUrl, null, retry + 1,
 
946
                                          head, tail, msgUriSpec);
 
947
        return;
 
948
      }
 
949
    }
 
950
 
 
951
    if (!plainText) {
 
952
       if (interactive && Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.statusInfo)
 
953
         EnigmailCommon.longAlert(window, Enigmail.msg.securityInfo.statusInfo);
 
954
       return;
 
955
    }
 
956
 
 
957
    if (retry >= 2) {
 
958
      plainText = EnigmailCommon.convertFromUnicode(EnigmailCommon.convertToUnicode(plainText, "UTF-8"), charset);
 
959
    }
 
960
 
 
961
    if (blockSeparationObj.value.indexOf(" ")>=0) {
 
962
      var blocks = blockSeparationObj.value.split(/ /);
 
963
      var blockInfo = blocks[0].split(/:/);
 
964
      plainText = EnigmailCommon.convertFromUnicode(EnigmailCommon.getString("notePartEncrypted"), charset)
 
965
          + "\n\n" + plainText.substr(0, blockInfo[1]) + "\n\n" + EnigmailCommon.getString("noteCutMessage");
 
966
    }
 
967
 
 
968
    // Save decrypted message status, headers, and content
 
969
    var headerList = {"subject":"", "from":"", "date":"", "to":"", "cc":""};
 
970
 
 
971
    var index, headerName;
 
972
 
 
973
    if (!gViewAllHeaders) {
 
974
      for (index = 0; index < headerList.length; index++) {
 
975
        headerList[index] = "";
 
976
      }
 
977
 
 
978
    } else {
 
979
      for (index = 0; index < gExpandedHeaderList.length; index++) {
 
980
        headerList[gExpandedHeaderList[index].name] = "";
 
981
      }
 
982
 
 
983
      for (headerName in currentHeaderData) {
 
984
        headerList[headerName] = "";
 
985
      }
 
986
    }
 
987
 
 
988
    for (headerName in headerList) {
 
989
      if (currentHeaderData[headerName])
 
990
        headerList[headerName] = currentHeaderData[headerName].headerValue;
 
991
    }
 
992
 
 
993
    // WORKAROUND
 
994
    if (headerList["cc"] == headerList["to"])
 
995
      headerList["cc"] = "";
 
996
 
 
997
    var hasAttachments = currentAttachments && currentAttachments.length;
 
998
    var attachmentsEncrypted=true;
 
999
 
 
1000
    for (index in currentAttachments) {
 
1001
      if (! Enigmail.msg.checkEncryptedAttach(currentAttachments[index])) {
 
1002
        if (!Enigmail.msg.checkSignedAttachment(currentAttachments, index)) attachmentsEncrypted=false;
 
1003
      }
 
1004
    }
 
1005
 
 
1006
    var msgRfc822Text = "";
 
1007
    if (head || tail) {
 
1008
      if (head) {
 
1009
        // print a warning if the signed or encrypted part doesn't start
 
1010
        // quite early in the message
 
1011
        matches=head.match(/(\n)/g);
 
1012
        if (matches && matches.length >10) {
 
1013
          msgRfc822Text=EnigmailCommon.convertFromUnicode(EnigmailCommon.getString("notePartEncrypted"), charset)+"\n\n";
 
1014
        }
 
1015
        msgRfc822Text+=head+"\n\n";
 
1016
      }
 
1017
      msgRfc822Text += EnigmailCommon.convertFromUnicode(EnigmailCommon.getString("beginPgpPart"), charset)+"\n\n";
 
1018
    }
 
1019
    msgRfc822Text+=plainText;
 
1020
    if (head || tail) {
 
1021
      msgRfc822Text+="\n\n"+ EnigmailCommon.convertFromUnicode(EnigmailCommon.getString("endPgpPart"), charset)+"\n\n"+tail;
 
1022
    }
 
1023
 
 
1024
    Enigmail.msg.decryptedMessage = {url:messageUrl,
 
1025
                             uri:msgUriSpec,
 
1026
                             headerList:headerList,
 
1027
                             hasAttachments:hasAttachments,
 
1028
                             attachmentsEncrypted:attachmentsEncrypted,
 
1029
                             charset:charset,
 
1030
                             plainText:msgRfc822Text};
 
1031
 
 
1032
    var msgFrame = EnigmailCommon.getFrame(window, "messagepane");
 
1033
    var bodyElement = msgFrame.document.getElementsByTagName("body")[0];
 
1034
 
 
1035
    // don't display decrypted message if message selection has changed
 
1036
    displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
 
1037
    if (msgUriSpec && displayedUriSpec && (displayedUriSpec != msgUriSpec)) return;
 
1038
 
 
1039
 
 
1040
    // Create and load one-time message URI
 
1041
    var messageContent = Enigmail.msg.getDecryptedMessage("message/rfc822", false);
 
1042
 
 
1043
    Enigmail.msg.noShowReload = true;
 
1044
 
 
1045
    bodyElement = msgFrame.document.getElementsByTagName("body")[0];
 
1046
    if (bodyElement.firstChild) {
 
1047
      var node = bodyElement.firstChild;
 
1048
      var foundIndex = -1;
 
1049
      var findStr = "-----BEGIN PGP";
 
1050
 
 
1051
      while (node) {
 
1052
        if (node.nodeName == "DIV") {
 
1053
          foundIndex = node.textContent.indexOf(findStr);
 
1054
 
 
1055
          if (foundIndex >= 0) {
 
1056
            if (node.textContent.indexOf(findStr+" LICENSE AUTHORIZATION") == foundIndex)
 
1057
              foundIndex = -1;
 
1058
          }
 
1059
          if (foundIndex >= 0) {
 
1060
            node.innerHTML = EnigmailFuncs.formatPlaintextMsg(EnigmailCommon.convertToUnicode(messageContent, charset));
 
1061
            return;
 
1062
          }
 
1063
        }
 
1064
        node = node.nextSibling;
 
1065
      }
 
1066
 
 
1067
      // if no <DIV> node is found, try with <PRE> (bug 24762)
 
1068
      node = bodyElement.firstChild;
 
1069
      foundIndex = -1;
 
1070
      while (node) {
 
1071
        if (node.nodeName == "PRE") {
 
1072
          foundIndex = node.textContent.indexOf(findStr);
 
1073
 
 
1074
          if (foundIndex >= 0) {
 
1075
            if (node.textContent.indexOf(findStr+" LICENSE AUTHORIZATION") == foundIndex)
 
1076
              foundIndex = -1;
 
1077
          }
 
1078
          if (foundIndex >= 0) {
 
1079
            node.innerHTML = EnigmailFuncs.formatPlaintextMsg(EnigmailCommon.convertToUnicode(messageContent, charset));
 
1080
            return;
 
1081
          }
 
1082
        }
 
1083
        node = node.nextSibling;
 
1084
      }
 
1085
 
 
1086
    }
 
1087
 
 
1088
    EnigmailCommon.ERROR_LOG("enigmailMessengerOverlay.js: no node found to replace message display\n");
 
1089
 
 
1090
    return;
 
1091
  },
 
1092
 
 
1093
 
 
1094
  // check if an attachment could be signed
 
1095
  checkSignedAttachment: function (attachmentObj, index)
 
1096
  {
 
1097
    var attachmentList;
 
1098
    if (index != null) {
 
1099
      attachmentList = attachmentObj;
 
1100
    }
 
1101
    else {
 
1102
      attachmentList=currentAttachments;
 
1103
      for (var i=0; i < attachmentList.length; i++) {
 
1104
        if (attachmentList[i].url == attachmentObj.url) {
 
1105
          index = i;
 
1106
          break;
 
1107
        }
 
1108
      }
 
1109
      if (index == null) return false;
 
1110
    }
 
1111
 
 
1112
    var signed = false;
 
1113
    var findFile;
 
1114
 
 
1115
    var attName = this.getAttachmentName(attachmentList[index]).toLowerCase().replace(/\+/g, "\\+");
 
1116
 
 
1117
    // check if filename is a signature
 
1118
    if ((this.getAttachmentName(attachmentList[index]).search(/\.(sig|asc)$/i) > 0) ||
 
1119
       (attachmentList[index].contentType.match(/^application\/pgp\-signature/i))) {
 
1120
      findFile = new RegExp(attName.replace(/\.(sig|asc)$/, ""));
 
1121
    }
 
1122
    else
 
1123
      findFile = new RegExp(attName+".(sig|asc)$");
 
1124
 
 
1125
    var i;
 
1126
    for (i in attachmentList) {
 
1127
      if ((i != index) &&
 
1128
          (this.getAttachmentName(attachmentList[i]).toLowerCase().search(findFile) == 0))
 
1129
        signed=true;
 
1130
    }
 
1131
 
 
1132
    return signed;
 
1133
  },
 
1134
 
 
1135
  // check if the attachment could be encrypted
 
1136
  checkEncryptedAttach: function (attachment)
 
1137
  {
 
1138
    return (this.getAttachmentName(attachment).match(/\.(gpg|pgp|asc)$/i) ||
 
1139
      (attachment.contentType.match(/^application\/pgp(\-.*)?$/i)) &&
 
1140
       (attachment.contentType.search(/^application\/pgp\-signature/i) < 0));
 
1141
  },
 
1142
 
 
1143
  getAttachmentName: function (attachment) {
 
1144
    if (typeof(attachment.displayName) == "undefined") {
 
1145
      // TB >=  7.0
 
1146
      return attachment.name;
 
1147
    }
 
1148
    else
 
1149
      // TB <= 6.0
 
1150
      return attachment.displayName;
 
1151
  },
 
1152
 
 
1153
  escapeTextForHTML: function (text, hyperlink)
 
1154
  {
 
1155
    // Escape special characters
 
1156
    if (text.indexOf("&") > -1)
 
1157
      text = text.replace(/&/g, "&amp;");
 
1158
 
 
1159
    if (text.indexOf("<") > -1)
 
1160
      text = text.replace(/</g, "&lt;");
 
1161
 
 
1162
    if (text.indexOf(">") > -1)
 
1163
      text = text.replace(/>/g, "&gt;");
 
1164
 
 
1165
    if (text.indexOf("\"") > -1)
 
1166
      text = text.replace(/"/g, "&quot;");
 
1167
 
 
1168
    if (!hyperlink)
 
1169
      return text;
 
1170
 
 
1171
    // Hyperlink email addresses
 
1172
    var addrs = text.match(/\b[A-Za-z0-9_+\-\.]+@[A-Za-z0-9\-\.]+\b/g);
 
1173
 
 
1174
    var newText, offset, loc;
 
1175
    if (addrs && addrs.length) {
 
1176
      newText = "";
 
1177
      offset = 0;
 
1178
 
 
1179
      for (var j=0; j < addrs.length; j++) {
 
1180
        var addr = addrs[j];
 
1181
 
 
1182
        loc = text.indexOf(addr, offset);
 
1183
        if (loc < offset)
 
1184
          break;
 
1185
 
 
1186
        if (loc > offset)
 
1187
          newText += text.substr(offset, loc-offset);
 
1188
 
 
1189
        // Strip any period off the end of address
 
1190
        addr = addr.replace(/[\.]$/, "");
 
1191
 
 
1192
        if (!addr.length)
 
1193
          continue;
 
1194
 
 
1195
        newText += "<a href=\"mailto:"+addr+"\">" + addr + "</a>";
 
1196
 
 
1197
        offset = loc + addr.length;
 
1198
      }
 
1199
 
 
1200
      newText += text.substr(offset, text.length-offset);
 
1201
 
 
1202
      text = newText;
 
1203
    }
 
1204
 
 
1205
    // Hyperlink URLs
 
1206
    var urls = text.match(/\b(http|https|ftp):\S+\s/g);
 
1207
 
 
1208
    if (urls && urls.length) {
 
1209
      newText = "";
 
1210
      offset = 0;
 
1211
 
 
1212
      for (var k=0; k < urls.length; k++) {
 
1213
        var url = urls[k];
 
1214
 
 
1215
        loc = text.indexOf(url, offset);
 
1216
        if (loc < offset)
 
1217
          break;
 
1218
 
 
1219
        if (loc > offset)
 
1220
          newText += text.substr(offset, loc-offset);
 
1221
 
 
1222
        // Strip delimiters off the end of URL
 
1223
        url = url.replace(/\s$/, "");
 
1224
        url = url.replace(/([\),\.']|&gt;|&quot;)$/, "");
 
1225
 
 
1226
        if (!url.length)
 
1227
          continue;
 
1228
 
 
1229
        newText += "<a href=\""+url+"\">" + url + "</a>";
 
1230
 
 
1231
        offset = loc + url.length;
 
1232
      }
 
1233
 
 
1234
      newText += text.substr(offset, text.length-offset);
 
1235
 
 
1236
      text = newText;
 
1237
    }
 
1238
 
 
1239
    return text;
 
1240
  },
 
1241
 
 
1242
  getDecryptedMessage: function (contentType, includeHeaders)
 
1243
  {
 
1244
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: getDecryptedMessage: "+contentType+", "+includeHeaders+"\n");
 
1245
 
 
1246
    if (!Enigmail.msg.decryptedMessage)
 
1247
      return "No decrypted message found!\n";
 
1248
 
 
1249
    var enigmailSvc = Enigmail.getEnigmailSvc();
 
1250
    if (!enigmailSvc)
 
1251
      return "";
 
1252
 
 
1253
    var headerList = Enigmail.msg.decryptedMessage.headerList;
 
1254
 
 
1255
    var statusLine = Enigmail.msg.securityInfo ? Enigmail.msg.securityInfo.statusLine : "";
 
1256
 
 
1257
    var contentData = "";
 
1258
 
 
1259
    var headerName;
 
1260
 
 
1261
    if (contentType == "message/rfc822") {
 
1262
      // message/rfc822
 
1263
 
 
1264
      if (includeHeaders) {
 
1265
        try {
 
1266
 
 
1267
          var msg = gFolderDisplay.selectedMessage;
 
1268
          if (msg) {
 
1269
            msgHdr = { "From": msg.author,
 
1270
                       "Subject": msg.subject,
 
1271
                       "To": msg.recipients,
 
1272
                       "Cc": msg.ccList,
 
1273
                       "Date": EnigmailCommon.getDateTime(msg.dateInSeconds, true, true) };
 
1274
 
 
1275
 
 
1276
            if(gFolderDisplay.selectedMessageIsNews) {
 
1277
              if (typeof (currentHeaderData.newsgroups)) {
 
1278
                msgHdr.Newsgroups = currentHeaderData.newsgroups.headerValue;
 
1279
              }
 
1280
            }
 
1281
 
 
1282
            for (headerName in msgHdr) {
 
1283
              if (msgHdr[headerName] && msgHdr[headerName].length>0)
 
1284
                contentData += headerName + ": " + msgHdr[headerName] + "\r\n";
 
1285
            }
 
1286
 
 
1287
          }
 
1288
        } catch (ex) {
 
1289
          // the above seems to fail every now and then
 
1290
          // so, here is the fallback
 
1291
          for (headerName in headerList) {
 
1292
            headerValue = headerList[headerName];
 
1293
            contentData += headerName + ": " + headerValue + "\r\n";
 
1294
          }
 
1295
        }
 
1296
 
 
1297
        contentData += "Content-Type: text/plain";
 
1298
 
 
1299
        if (Enigmail.msg.decryptedMessage.charset) {
 
1300
          contentData += "; charset="+Enigmail.msg.decryptedMessage.charset;
 
1301
        }
 
1302
 
 
1303
        contentData += "\r\n";
 
1304
      }
 
1305
 
 
1306
      contentData += "\r\n";
 
1307
 
 
1308
      if (Enigmail.msg.decryptedMessage.hasAttachments && (! Enigmail.msg.decryptedMessage.attachmentsEncrypted)) {
 
1309
        contentData += EnigmailCommon.convertFromUnicode(EnigmailCommon.getString("enigContentNote"), Enigmail.msg.decryptedMessage.charset);
 
1310
      }
 
1311
 
 
1312
      contentData += Enigmail.msg.decryptedMessage.plainText;
 
1313
 
 
1314
    } else {
 
1315
      // text/html or text/plain
 
1316
 
 
1317
      if (contentType == "text/html") {
 
1318
        contentData += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset="+Enigmail.msg.decryptedMessage.charset+"\">\r\n";
 
1319
 
 
1320
        contentData += "<html><head></head><body>\r\n";
 
1321
      }
 
1322
 
 
1323
      if (statusLine) {
 
1324
        if (contentType == "text/html") {
 
1325
          contentData += "<b>"+EnigmailCommon.getString("enigHeader")+"</b> " +
 
1326
                         this.escapeTextForHTML(statusLine, false) + "<br>\r\n<hr>\r\n";
 
1327
        } else{
 
1328
          contentData += EnigmailCommon.getString("enigHeader")+" " + statusLine + "\r\n\r\n";
 
1329
        }
 
1330
      }
 
1331
 
 
1332
      if (includeHeaders) {
 
1333
        for (headerName in headerList) {
 
1334
          headerValue = headerList[headerName];
 
1335
 
 
1336
          if (headerValue) {
 
1337
            if (contentType == "text/html") {
 
1338
              contentData += "<b>"+this.escapeTextForHTML(headerName, false)+":</b> "+
 
1339
                                   this.escapeTextForHTML(headerValue, false)+"<br>\r\n";
 
1340
            } else {
 
1341
              contentData += headerName + ": " + headerValue + "\r\n";
 
1342
            }
 
1343
          }
 
1344
        }
 
1345
      }
 
1346
 
 
1347
      if (contentType == "text/html") {
 
1348
        contentData += "<pre>"+this.escapeTextForHTML(Enigmail.msg.decryptedMessage.plainText, false)+"</pre>\r\n";
 
1349
 
 
1350
        contentData += "</body></html>\r\n";
 
1351
 
 
1352
      } else {
 
1353
 
 
1354
        contentData += "\r\n"+Enigmail.msg.decryptedMessage.plainText;
 
1355
      }
 
1356
 
 
1357
      if (!(EnigmailCommon.isDosLike())) {
 
1358
        contentData = contentData.replace(/\r\n/g, "\n");
 
1359
      }
 
1360
    }
 
1361
 
 
1362
    return contentData;
 
1363
  },
 
1364
 
 
1365
 
 
1366
  msgDefaultPrint: function (elementId)
 
1367
  {
 
1368
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: this.msgDefaultPrint: "+elementId+"\n");
 
1369
 
 
1370
    goDoCommand(elementId.indexOf("printpreview")>=0 ? "cmd_printpreview" : "cmd_print");
 
1371
  },
 
1372
 
 
1373
  msgPrint: function (elementId)
 
1374
  {
 
1375
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgPrint: "+elementId+"\n");
 
1376
 
 
1377
    var contextMenu = (elementId.search("Context") > -1);
 
1378
 
 
1379
    if (!Enigmail.msg.decryptedMessage || typeof(Enigmail.msg.decryptedMessage) == "undefined") {
 
1380
      this.msgDefaultPrint(elementId);
 
1381
      return;
 
1382
    }
 
1383
 
 
1384
    var mailNewsUrl = this.getCurrentMsgUrl();
 
1385
 
 
1386
    if (!mailNewsUrl) {
 
1387
      this.msgDefaultPrint(elementId);
 
1388
      return;
 
1389
    }
 
1390
 
 
1391
    if (Enigmail.msg.decryptedMessage.url != mailNewsUrl.spec) {
 
1392
      Enigmail.msg.decryptedMessage = null;
 
1393
      this.msgDefaultPrint(elementId);
 
1394
      return;
 
1395
    }
 
1396
 
 
1397
    var enigmailSvc = Enigmail.getEnigmailSvc();
 
1398
    if (!enigmailSvc) {
 
1399
      this.msgDefaultPrint(elementId);
 
1400
      return;
 
1401
    }
 
1402
 
 
1403
    // Note: Trying to print text/html content does not seem to work with
 
1404
    //       non-ASCII chars
 
1405
    var msgContent = this.getDecryptedMessage("message/rfc822", true);
 
1406
 
 
1407
    var uri = enigmailSvc.createMessageURI(Enigmail.msg.decryptedMessage.url,
 
1408
                                           "message/rfc822",
 
1409
                                           "",
 
1410
                                           msgContent,
 
1411
                                           false);
 
1412
 
 
1413
    Enigmail.msg.createdURIs.push(uri);
 
1414
 
 
1415
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgPrint: uri="+uri+"\n");
 
1416
 
 
1417
    var messageList = [uri];
 
1418
 
 
1419
    var printPreview = (elementId.indexOf("printpreview")>=0);
 
1420
 
 
1421
    window.openDialog("chrome://messenger/content/msgPrintEngine.xul",
 
1422
                      "",
 
1423
                      "chrome,dialog=no,all,centerscreen",
 
1424
                      1, messageList, statusFeedback,
 
1425
                      printPreview, Components.interfaces.nsIMsgPrintEngine.MNAB_PRINTPREVIEW_MSG,
 
1426
                      window);
 
1427
 
 
1428
    return true;
 
1429
  },
 
1430
 
 
1431
  messageSave: function ()
 
1432
  {
 
1433
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageSave: \n");
 
1434
 
 
1435
    if (!Enigmail.msg.decryptedMessage) {
 
1436
      EnigmailCommon.alert(window, EnigmailCommon.getString("noDecrypted"));
 
1437
      return;
 
1438
    }
 
1439
 
 
1440
    var mailNewsUrl = this.getCurrentMsgUrl();
 
1441
 
 
1442
    if (!mailNewsUrl) {
 
1443
      EnigmailCommon.alert(window, EnigmailCommon.getString("noMessage"));
 
1444
      return;
 
1445
    }
 
1446
 
 
1447
    if (Enigmail.msg.decryptedMessage.url != mailNewsUrl.spec) {
 
1448
      Enigmail.msg.decryptedMessage = null;
 
1449
      EnigmailCommon.alert(window, EnigmailCommon.getString("useButton"));
 
1450
      return;
 
1451
    }
 
1452
 
 
1453
    var saveFile = EnigmailCommon.filePicker(window, EnigmailCommon.getString("saveHeader"),
 
1454
                                  Enigmail.msg.lastSaveDir, true, "txt",
 
1455
                                  null, ["Text files", "*.txt"]);
 
1456
    if (!saveFile) return;
 
1457
 
 
1458
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: messageSave: path="+saveFile.path+"\n");
 
1459
 
 
1460
    if (saveFile.parent)
 
1461
      Enigmail.msg.lastSaveDir = EnigmailCommon.getFilePath(saveFile.parent);
 
1462
 
 
1463
    var textContent = this.getDecryptedMessage("text/plain", true);
 
1464
 
 
1465
    if (!Enigmail.msg.writeFileContents(saveFile.path, textContent, null)) {
 
1466
      EnigmailCommon.alert(window, "Error in saving to file "+saveFile.path);
 
1467
      return;
 
1468
    }
 
1469
 
 
1470
    return;
 
1471
  },
 
1472
 
 
1473
  msgDirectDecrypt: function (interactive, importOnly, contentEncoding, charset, signature,
 
1474
                           bufferSize, head, tail, msgUriSpec, callbackFunction)
 
1475
  {
 
1476
    EnigmailCommon.WRITE_LOG("enigmailMessengerOverlay.js: msgDirectDecrypt: contentEncoding="+contentEncoding+", signature="+signature+"\n");
 
1477
    var mailNewsUrl = this.getCurrentMsgUrl();
 
1478
    if (!mailNewsUrl)
 
1479
      return;
 
1480
 
 
1481
    var callbackArg = { interactive:interactive,
 
1482
                        importOnly:importOnly,
 
1483
                        contentEncoding:contentEncoding,
 
1484
                        charset:charset,
 
1485
                        messageUrl:mailNewsUrl.spec,
 
1486
                        msgUriSpec:msgUriSpec,
 
1487
                        signature:signature,
 
1488
                        data: "",
 
1489
                        head:head,
 
1490
                        tail:tail,
 
1491
                        callbackFunction: callbackFunction };
 
1492
 
 
1493
    var msgSvc = messenger.messageServiceFromURI(msgUriSpec);
 
1494
 
 
1495
    var listener = {
 
1496
      QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIStreamListener]),
 
1497
      onStartRequest: function() {
 
1498
        this.data = "";
 
1499
        this.inStream = Components.classes["@mozilla.org/scriptableinputstream;1"].
 
1500
          createInstance(Components.interfaces.nsIScriptableInputStream);
 
1501
 
 
1502
      },
 
1503
      onDataAvailable: function(req, sup, stream, offset, count) {
 
1504
        this.inStream.init(stream);
 
1505
        this.data += this.inStream.read(count);
 
1506
      },
 
1507
      onStopRequest: function() {
 
1508
        var start = this.data.indexOf("-----BEGIN PGP");
 
1509
        var end = this.data.indexOf("-----END PGP");
 
1510
 
 
1511
        if (start >= 0 && end > start) {
 
1512
          var tStr = this.data.substr(end);
 
1513
          var n = tStr.indexOf("\n");
 
1514
          var r = tStr.indexOf("\r");
 
1515
          var lEnd = -1;
 
1516
          if (n >= 0 && r >= 0) {
 
1517
            lEnd = Math.min(r, n);
 
1518
          }
 
1519
          else if (r >= 0) {
 
1520
            lEnd = r;
 
1521
          }
 
1522
          else if (n >= 0)
 
1523
            lEnd = n;
 
1524
 
 
1525
          if (lEnd >= 0) {
 
1526
            end += lEnd;
 
1527
          }
 
1528
 
 
1529
          callbackArg.data = this.data.substring(start, end+1);
 
1530
          EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: data: >"+callbackArg.data+"<\n");
 
1531
          Enigmail.msg.msgDirectCallback(callbackArg);
 
1532
        }
 
1533
      }
 
1534
    };
 
1535
 
 
1536
    msgSvc.streamMessage(msgUriSpec,
 
1537
                    listener,
 
1538
                    msgWindow,
 
1539
                    null,
 
1540
                    false,
 
1541
                    null,
 
1542
                    false);
 
1543
 
 
1544
  },
 
1545
 
 
1546
 
 
1547
  msgDirectCallback: function (callbackArg)
 
1548
  {
 
1549
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgDirectCallback: \n");
 
1550
 
 
1551
    var mailNewsUrl = Enigmail.msg.getCurrentMsgUrl();
 
1552
    var urlSpec = mailNewsUrl ? mailNewsUrl.spec : "";
 
1553
    var newBufferSize = 0;
 
1554
 
 
1555
    var l = urlSpec.length;
 
1556
 
 
1557
    if (urlSpec.substr(0, l) != callbackArg.messageUrl.substr(0, l)) {
 
1558
      EnigmailCommon.ERROR_LOG("enigmailMessengerOverlay.js: msgDirectCallback: Message URL mismatch "+mailNewsUrl.spec+" vs. "+callbackArg.messageUrl+"\n");
 
1559
      return;
 
1560
    }
 
1561
 
 
1562
    var msgText = callbackArg.data;
 
1563
    msgText = EnigmailCommon.convertFromUnicode(msgText, "UTF-8");
 
1564
 
 
1565
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: msgDirectCallback: msgText='"+msgText+"'\n");
 
1566
 
 
1567
    var f = function (argList) {
 
1568
      var msgText = argList[0];
 
1569
      var cb = argList[1];
 
1570
      cb.callbackFunction(msgText, cb.contentEncoding,
 
1571
                           cb.charset,
 
1572
                           cb.interactive,
 
1573
                           cb.importOnly,
 
1574
                           cb.messageUrl,
 
1575
                           cb.signature,
 
1576
                           3,
 
1577
                           cb.head,
 
1578
                           cb.tail,
 
1579
                           cb.msgUriSpec);
 
1580
    };
 
1581
 
 
1582
    EnigmailCommon.dispatchEvent(f, 0, [msgText, callbackArg ]);
 
1583
  },
 
1584
 
 
1585
 
 
1586
  verifyEmbeddedMsg: function (window, msgUrl, msgWindow, msgUriSpec, contentEncoding, event)
 
1587
  {
 
1588
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: verifyEmbeddedMsg: msgUrl"+msgUrl+"\n");
 
1589
 
 
1590
    var callbackArg = { data: "",
 
1591
                        window: window,
 
1592
                        msgUrl: msgUrl,
 
1593
                        msgWindow: msgWindow,
 
1594
                        msgUriSpec: msgUriSpec,
 
1595
                        contentEncoding: contentEncoding,
 
1596
                        event: event };
 
1597
 
 
1598
    var requestCallback = function _cb (data) {
 
1599
      callbackArg.data = data;
 
1600
      Enigmail.msg.verifyEmbeddedCallback(callbackArg);
 
1601
    };
 
1602
 
 
1603
    var bufferListener = EnigmailCommon.newStringStreamListener(requestCallback);
 
1604
 
 
1605
    var ioServ = Components.classes[EnigmailCommon.IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
 
1606
 
 
1607
    var channel = ioServ.newChannelFromURI(msgUrl);
 
1608
 
 
1609
    channel.asyncOpen(bufferListener, msgUrl);
 
1610
  },
 
1611
 
 
1612
  verifyEmbeddedCallback: function (callbackArg)
 
1613
  {
 
1614
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: verifyEmbeddedCallback: \n");
 
1615
 
 
1616
    if (callbackArg.data.length > 0) {
 
1617
      let msigned=callbackArg.data.search(/content\-type:[ \t]*multipart\/signed/i);
 
1618
      if(msigned >= 0) {
 
1619
 
 
1620
        // Real multipart/signed message; let's try to verify it
 
1621
        EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: verifyEmbeddedCallback: detected multipart/signed. msigned: "+msigned+"\n");
 
1622
 
 
1623
        let enableSubpartTreatment=(msigned > 0);
 
1624
 
 
1625
        var verifier = EnigmailVerify.newVerfier(enableSubpartTreatment, callbackArg.mailNewsUrl);
 
1626
        verifier.verifyData(callbackArg.window, callbackArg.msgWindow, callbackArg.msgUriSpec, callbackArg.data);
 
1627
 
 
1628
        return;
 
1629
      }
 
1630
    }
 
1631
 
 
1632
    // try inline PGP
 
1633
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: verifyEmbeddedCallback: try inline PGP\n");
 
1634
 
 
1635
    Enigmail.msg.messageParse(!callbackArg.event, false, callbackArg.contentEncoding, callbackArg.msgUriSpec);
 
1636
  },
 
1637
 
 
1638
 
 
1639
  revealAttachments: function (index)
 
1640
  {
 
1641
    if (!index) index = 0;
 
1642
 
 
1643
    if (index < currentAttachments.length) {
 
1644
      this.handleAttachment("revealName/"+index.toString(), currentAttachments[index]);
 
1645
    }
 
1646
  },
 
1647
 
 
1648
 
 
1649
  // handle a selected attachment (decrypt & open or save)
 
1650
  handleAttachmentSel: function (actionType)
 
1651
  {
 
1652
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: handleAttachmentSel: actionType="+actionType+"\n");
 
1653
 
 
1654
    // Thunderbird
 
1655
    var contextMenu = document.getElementById('attachmentItemContext');
 
1656
    var selectedAttachments = contextMenu.attachments;
 
1657
 
 
1658
    if (! contextMenu) {
 
1659
      // SeaMonkey
 
1660
      contextMenu = document.getElementById('attachmentListContext');
 
1661
      selectedAttachments = attachmentList.selectedItems;
 
1662
    }
 
1663
    var anAttachment = selectedAttachments[0];
 
1664
 
 
1665
    switch (actionType) {
 
1666
      case "saveAttachment":
 
1667
      case "openAttachment":
 
1668
      case "importKey":
 
1669
      case "revealName":
 
1670
        this.handleAttachment(actionType, anAttachment);
 
1671
        break;
 
1672
      case "verifySig":
 
1673
        this.verifyDetachedSignature(anAttachment);
 
1674
        break;
 
1675
    }
 
1676
  },
 
1677
 
 
1678
  /**
 
1679
   * save the original file plus the signature file to disk and then verify the signature
 
1680
   */
 
1681
  verifyDetachedSignature: function (anAttachment)
 
1682
  {
 
1683
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: verifyDetachedSignature: url="+anAttachment.url+"\n");
 
1684
 
 
1685
    var enigmailSvc = Enigmail.getEnigmailSvc();
 
1686
    if (! enigmailSvc) return;
 
1687
 
 
1688
    var origAtt, signatureAtt;
 
1689
 
 
1690
    if ((this.getAttachmentName(anAttachment).search(/\.sig$/i) > 0) ||
 
1691
        (anAttachment.contentType.search(/^application\/pgp\-signature/i) == 0)) {
 
1692
      // we have the .sig file; need to know the original file;
 
1693
 
 
1694
      signatureAtt = anAttachment;
 
1695
      var origName = this.getAttachmentName(anAttachment).replace(/\.sig$/i, "");
 
1696
 
 
1697
      for (let i=0; i < currentAttachments.length; i++) {
 
1698
        if (origName == this.getAttachmentName(currentAttachments[i])) {
 
1699
          origAtt = currentAttachments[i];
 
1700
          break;
 
1701
        }
 
1702
      }
 
1703
    }
 
1704
    else {
 
1705
      // we have a supposedly original file; need to know the .sig file;
 
1706
 
 
1707
      origAtt = anAttachment;
 
1708
      var sigName = this.getAttachmentName(anAttachment)+".sig";
 
1709
 
 
1710
      for (let i=0; i < currentAttachments.length; i++) {
 
1711
        if (sigName == this.getAttachmentName(currentAttachments[i])) {
 
1712
          signatureAtt = currentAttachments[i];
 
1713
          break;
 
1714
        }
 
1715
      }
 
1716
    }
 
1717
 
 
1718
    if (! signatureAtt) {
 
1719
      EnigmailCommon.alert(window, EnigmailCommon.getString("attachment.noMatchToSignature", [ this.getAttachmentName(origAtt) ]));
 
1720
      return;
 
1721
    }
 
1722
    if (! origAtt) {
 
1723
      EnigmailCommon.alert(window, EnigmailCommon.getString("attachment.noMatchFromSignature", [ this.getAttachmentName(signatureAtt) ]));
 
1724
      return;
 
1725
    }
 
1726
 
 
1727
    // open
 
1728
    var tmpDir = EnigmailCommon.getTempDir();
 
1729
    var outFile1, outFile2;
 
1730
    outFile1 = Components.classes[EnigmailCommon.LOCAL_FILE_CONTRACTID].
 
1731
      createInstance(EnigmailCommon.getLocalFileApi());
 
1732
    outFile1.initWithPath(tmpDir);
 
1733
    if (!(outFile1.isDirectory() && outFile1.isWritable())) {
 
1734
      EnigmailCommon.alert(window, EnigmailCommon.getString("noTempDir"));
 
1735
      return;
 
1736
    }
 
1737
    outFile1.append(this.getAttachmentName(origAtt));
 
1738
    outFile1.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
 
1739
    this.writeUrlToFile(origAtt.url, outFile1);
 
1740
 
 
1741
    outFile2 = Components.classes[EnigmailCommon.LOCAL_FILE_CONTRACTID].
 
1742
      createInstance(EnigmailCommon.getLocalFileApi());
 
1743
    outFile2.initWithPath(tmpDir);
 
1744
    outFile2.append(this.getAttachmentName(signatureAtt));
 
1745
    outFile2.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
 
1746
    this.writeUrlToFile(signatureAtt.url, outFile2);
 
1747
 
 
1748
    var statusFlagsObj = {};
 
1749
    var errorMsgObj = {};
 
1750
    var r = enigmailSvc.verifyAttachment(window, outFile1, outFile2, statusFlagsObj, errorMsgObj);
 
1751
 
 
1752
    if (r == 0)
 
1753
      EnigmailCommon.alert(window, EnigmailCommon.getString("signature.verifiedOK", [ this.getAttachmentName(origAtt) ]) +"\n\n"+ errorMsgObj.value);
 
1754
    else
 
1755
      EnigmailCommon.alert(window, EnigmailCommon.getString("signature.verifyFailed", [ this.getAttachmentName(origAtt) ])+"\n\n"+
 
1756
        errorMsgObj.value);
 
1757
 
 
1758
    outFile1.remove(false);
 
1759
    outFile2.remove(false);
 
1760
  },
 
1761
 
 
1762
  writeUrlToFile: function(srcUrl, outFile) {
 
1763
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: writeUrlToFile: outFile="+outFile.path+"\n");
 
1764
     var ioServ = Components.classes[EnigmailCommon.IOSERVICE_CONTRACTID].
 
1765
      getService(Components.interfaces.nsIIOService);
 
1766
    var msgUri = ioServ.newURI(srcUrl, null, null);
 
1767
    var channel = ioServ.newChannelFromURI(msgUri);
 
1768
    var istream = channel.open();
 
1769
 
 
1770
    var fstream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"]
 
1771
                          .createInstance(Components.interfaces.nsIFileOutputStream);
 
1772
    var buffer  = Components.classes["@mozilla.org/network/buffered-output-stream;1"]
 
1773
                            .createInstance(Components.interfaces.nsIBufferedOutputStream);
 
1774
    fstream.init(outFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate
 
1775
    buffer.init(fstream, 8192);
 
1776
 
 
1777
    buffer.writeFrom(istream, istream.available());
 
1778
 
 
1779
    // Close the output streams
 
1780
    if (buffer instanceof Components.interfaces.nsISafeOutputStream)
 
1781
      buffer.finish();
 
1782
    else
 
1783
      buffer.close();
 
1784
 
 
1785
    if (fstream instanceof Components.interfaces.nsISafeOutputStream)
 
1786
      fstream.finish();
 
1787
    else
 
1788
      fstream.close();
 
1789
 
 
1790
    // Close the input stream
 
1791
    istream.close();
 
1792
  },
 
1793
 
 
1794
  handleAttachment: function (actionType, anAttachment)
 
1795
  {
 
1796
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: handleAttachment: actionType="+actionType+", anAttachment(url)="+anAttachment.url+"\n");
 
1797
 
 
1798
    var argumentsObj = { actionType: actionType,
 
1799
                         attachment: anAttachment,
 
1800
                         forceBrowser: false,
 
1801
                         data: ""
 
1802
                       };
 
1803
 
 
1804
    var f = function _cb(data) {
 
1805
      argumentsObj.data = data;
 
1806
      Enigmail.msg.decryptAttachmentCallback([argumentsObj]);
 
1807
    };
 
1808
 
 
1809
    var bufferListener = EnigmailCommon.newStringStreamListener(f);
 
1810
    var ioServ = Components.classes[EnigmailCommon.IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
 
1811
    var msgUri = ioServ.newURI(argumentsObj.attachment.url, null, null);
 
1812
 
 
1813
    var channel = ioServ.newChannelFromURI(msgUri);
 
1814
    channel.asyncOpen(bufferListener, msgUri);
 
1815
  },
 
1816
 
 
1817
  setAttachmentName: function (attachment, newLabel, index)
 
1818
  {
 
1819
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: setAttachmentName ("+newLabel+"):\n");
 
1820
 
 
1821
    var attList=document.getElementById("attachmentList");
 
1822
    if (attList) {
 
1823
      var attNode = attList.firstChild;
 
1824
      while (attNode) {
 
1825
        // TB <= 9
 
1826
        if (attNode.getAttribute("attachmentUrl") == attachment.url)
 
1827
          attNode.setAttribute("label", newLabel);
 
1828
        // TB >= 10
 
1829
        if (attNode.getAttribute("name") == attachment.name)
 
1830
          attNode.setAttribute("name", newLabel);
 
1831
        attNode=attNode.nextSibling;
 
1832
      }
 
1833
    }
 
1834
 
 
1835
    if (typeof(attachment.displayName) == "undefined") {
 
1836
      attachment.name = newLabel;
 
1837
    }
 
1838
    else
 
1839
      attachment.displayName = newLabel;
 
1840
 
 
1841
    if (index && index.length > 0) {
 
1842
      this.revealAttachments(parseInt(index)+1);
 
1843
    }
 
1844
  },
 
1845
 
 
1846
  decryptAttachmentCallback: function (cbArray)
 
1847
  {
 
1848
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: decryptAttachmentCallback:\n");
 
1849
 
 
1850
    var callbackArg = cbArray[0];
 
1851
    const nsIEnigmail = Components.interfaces.nsIEnigmail;
 
1852
 
 
1853
    var exitCodeObj = new Object();
 
1854
    var statusFlagsObj = new Object();
 
1855
    var errorMsgObj= new Object();
 
1856
    var exitStatus = -1;
 
1857
 
 
1858
    var enigmailSvc =  Enigmail.getEnigmailSvc();
 
1859
    var outFile;
 
1860
    var origFilename;
 
1861
    var rawFileName=Enigmail.msg.getAttachmentName(callbackArg.attachment).replace(/\.(asc|pgp|gpg)$/i,"");
 
1862
 
 
1863
    if (callbackArg.actionType != "importKey") {
 
1864
      origFilename = EnigmailCommon.getAttachmentFileName(window, callbackArg.data);
 
1865
      if (origFilename && origFilename.length > rawFileName.length) rawFileName = origFilename;
 
1866
    }
 
1867
 
 
1868
    if (callbackArg.actionType == "saveAttachment") {
 
1869
      outFile = EnigmailCommon.filePicker(window, EnigmailCommon.getString("saveAttachmentHeader"),
 
1870
                                  Enigmail.msg.lastSaveDir, true, "",
 
1871
                                  rawFileName, null);
 
1872
      if (! outFile) return;
 
1873
    }
 
1874
    else if (callbackArg.actionType.substr(0,10) == "revealName") {
 
1875
      if (origFilename && origFilename.length > 0) {
 
1876
        Enigmail.msg.setAttachmentName(callbackArg.attachment, origFilename+".pgp", callbackArg.actionType.substr(11,10));
 
1877
      }
 
1878
      Enigmail.msg.setAttachmentReveal(null);
 
1879
      return;
 
1880
    }
 
1881
    else {
 
1882
      // open
 
1883
      var tmpDir = EnigmailCommon.getTempDir();
 
1884
      try {
 
1885
        outFile = Components.classes[EnigmailCommon.LOCAL_FILE_CONTRACTID].createInstance(EnigmailCommon.getLocalFileApi());
 
1886
        outFile.initWithPath(tmpDir);
 
1887
        if (!(outFile.isDirectory() && outFile.isWritable())) {
 
1888
          errorMsgObj.value=EnigmailCommon.getString("noTempDir");
 
1889
          return;
 
1890
        }
 
1891
        outFile.append(rawFileName);
 
1892
        outFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
 
1893
      }
 
1894
      catch (ex) {
 
1895
        errorMsgObj.value=EnigmailCommon.getString("noTempDir");
 
1896
        return;
 
1897
      }
 
1898
    }
 
1899
 
 
1900
    if (callbackArg.actionType == "importKey") {
 
1901
      try {
 
1902
        exitStatus = enigmailSvc.importKey(parent, 0, callbackArg.data, "", errorMsgObj);
 
1903
      }
 
1904
      catch (ex) {}
 
1905
      if (exitStatus == 0) {
 
1906
        EnigmailCommon.longAlert(window, EnigmailCommon.getString("successKeyImport")+"\n\n"+errorMsgObj.value);
 
1907
      }
 
1908
      else {
 
1909
        EnigmailCommon.alert(window, EnigmailCommon.getString("failKeyImport")+"\n"+errorMsgObj.value);
 
1910
      }
 
1911
 
 
1912
      return;
 
1913
    }
 
1914
 
 
1915
    exitStatus=enigmailSvc.decryptAttachment(window, outFile,
 
1916
                                  Enigmail.msg.getAttachmentName(callbackArg.attachment),
 
1917
                                  callbackArg.data,
 
1918
                                  exitCodeObj, statusFlagsObj,
 
1919
                                  errorMsgObj);
 
1920
 
 
1921
    if ((! exitStatus) || exitCodeObj.value != 0) {
 
1922
      exitStatus=false;
 
1923
      if ((statusFlagsObj.value & nsIEnigmail.DECRYPTION_OKAY) &&
 
1924
         (statusFlagsObj.value & nsIEnigmail.UNVERIFIED_SIGNATURE)) {
 
1925
 
 
1926
        if (callbackArg.actionType == "openAttachment") {
 
1927
          exitStatus = EnigmailCommon.confirmDlg(window, EnigmailCommon.getString("decryptOkNoSig"), EnigmailCommon.getString("msgOvl.button.contAnyway"));
 
1928
        }
 
1929
        else {
 
1930
          EnigmailCommon.alert(window, EnigmailCommon.getString("decryptOkNoSig"));
 
1931
        }
 
1932
      }
 
1933
      else {
 
1934
        EnigmailCommon.alert(window, EnigmailCommon.getString("failedDecrypt")+"\n\n"+errorMsgObj.value);
 
1935
        exitStatus=false;
 
1936
      }
 
1937
    }
 
1938
    if (exitStatus) {
 
1939
      if (statusFlagsObj.value & nsIEnigmail.IMPORTED_KEY) {
 
1940
        EnigmailCommon.longAlert(window, EnigmailCommon.getString("successKeyImport")+"\n\n"+errorMsgObj.value);
 
1941
      }
 
1942
      else if (statusFlagsObj.value & nsIEnigmail.DISPLAY_MESSAGE) {
 
1943
        HandleSelectedAttachments('open');
 
1944
      }
 
1945
      else if ((statusFlagsObj.value & nsIEnigmail.DISPLAY_MESSAGE) ||
 
1946
               (callbackArg.actionType == "openAttachment")) {
 
1947
        var ioServ = Components.classes[EnigmailCommon.IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
 
1948
        var outFileUri = ioServ.newFileURI(outFile);
 
1949
        var fileExt = outFile.leafName.replace(/(.*\.)(\w+)$/, "$2");
 
1950
        if (fileExt && ! callbackArg.forceBrowser) {
 
1951
          var extAppLauncher = Components.classes[EnigmailCommon.MIME_CONTRACTID].getService(Components.interfaces.nsPIExternalAppLauncher);
 
1952
          extAppLauncher.deleteTemporaryFileOnExit(outFile);
 
1953
 
 
1954
          try {
 
1955
            var mimeService = Components.classes[EnigmailCommon.MIME_CONTRACTID].getService(Components.interfaces.nsIMIMEService);
 
1956
            var fileMimeType = mimeService.getTypeFromFile(outFile);
 
1957
            var fileMimeInfo = mimeService.getFromTypeAndExtension(fileMimeType, fileExt);
 
1958
 
 
1959
            fileMimeInfo.launchWithFile(outFile);
 
1960
          }
 
1961
          catch (ex) {
 
1962
            // if the attachment file type is unknown, an exception is thrown,
 
1963
            // so let it be handled by a browser window
 
1964
            Enigmail.msg.loadExternalURL(outFileUri.asciiSpec);
 
1965
          }
 
1966
        }
 
1967
 
 
1968
        // open the attachment using an external application
 
1969
        Enigmail.msg.loadExternalURL(outFileUri.asciiSpec);
 
1970
      }
 
1971
    }
 
1972
  },
 
1973
 
 
1974
  loadExternalURL: function (url) {
 
1975
    if (EnigmailCommon.isSuite()) {
 
1976
      Enigmail.msg.loadURLInNavigatorWindow(url, true);
 
1977
    }
 
1978
    else {
 
1979
      messenger.launchExternalURL(url);
 
1980
    }
 
1981
  },
 
1982
 
 
1983
  // retrieves the most recent navigator window (opens one if need be)
 
1984
  loadURLInNavigatorWindow: function (url, aOpenFlag)
 
1985
  {
 
1986
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: loadURLInNavigatorWindow: "+url+", "+aOpenFlag+"\n");
 
1987
 
 
1988
    var navWindow;
 
1989
 
 
1990
    // if this is a browser window, just use it
 
1991
    if ("document" in top) {
 
1992
      var possibleNavigator = top.document.getElementById("main-window");
 
1993
      if (possibleNavigator &&
 
1994
          possibleNavigator.getAttribute("windowtype") == "navigator:browser")
 
1995
        navWindow = top;
 
1996
    }
 
1997
 
 
1998
    // if not, get the most recently used browser window
 
1999
    if (!navWindow) {
 
2000
      var wm;
 
2001
      wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(
 
2002
            Components.interfaces.nsIWindowMediator);
 
2003
      navWindow = wm.getMostRecentWindow("navigator:browser");
 
2004
    }
 
2005
 
 
2006
    if (navWindow) {
 
2007
 
 
2008
      if ("loadURI" in navWindow)
 
2009
        navWindow.loadURI(url);
 
2010
      else
 
2011
        navWindow._content.location.href = url;
 
2012
 
 
2013
    } else if (aOpenFlag) {
 
2014
      // if no browser window available and it's ok to open a new one, do so
 
2015
      navWindow = window.open(url, "Enigmail");
 
2016
    }
 
2017
 
 
2018
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: loadURLInNavigatorWindow: navWindow="+navWindow+"\n");
 
2019
 
 
2020
    return navWindow;
 
2021
  },
 
2022
 
 
2023
  // handle double click events on Attachments
 
2024
  enigAttachmentListClick: function (elementId, event)
 
2025
  {
 
2026
    EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay.js: enigAttachmentListClick: event="+event+"\n");
 
2027
 
 
2028
    var attachment=event.target.attachment;
 
2029
    if (this.checkEncryptedAttach(attachment)) {
 
2030
      if (event.button == 0 && event.detail == 2) { // double click
 
2031
        this.handleAttachment("openAttachment", attachment);
 
2032
        event.stopPropagation();
 
2033
        return true;
 
2034
      }
 
2035
    }
 
2036
    return false;
 
2037
  },
 
2038
 
 
2039
  // download keys
 
2040
  handleUnknownKey: function ()
 
2041
  {
 
2042
    var pubKeyId = "0x" + Enigmail.msg.securityInfo.keyId.substr(8, 8);
 
2043
 
 
2044
    var mesg =  EnigmailCommon.getString("pubKeyNeeded") + EnigmailCommon.getString("keyImport", [pubKeyId]);
 
2045
 
 
2046
    if (EnigmailCommon.confirmDlg(window, mesg, EnigmailCommon.getString("keyMan.button.import"))) {
 
2047
      var inputObj = {
 
2048
        searchList : [ pubKeyId ]
 
2049
      };
 
2050
      var resultObj = new Object();
 
2051
 
 
2052
      EnigmailFuncs.downloadKeys(window, inputObj, resultObj);
 
2053
 
 
2054
      if (resultObj.importedKeys > 0) {
 
2055
        this.messageReload(false);
 
2056
      }
 
2057
    }
 
2058
  },
 
2059
 
 
2060
  createFileStream: function (filePath, permissions)
 
2061
  {
 
2062
    const DEFAULT_FILE_PERMS = 0600;
 
2063
    const WRONLY             = 0x02;
 
2064
    const CREATE_FILE        = 0x08;
 
2065
    const TRUNCATE           = 0x20;
 
2066
 
 
2067
    try {
 
2068
      var localFile = Components.classes[EnigmailCommon.LOCAL_FILE_CONTRACTID].
 
2069
        createInstance(EnigmailCommon.getLocalFileApi());
 
2070
 
 
2071
      localFile.initWithPath(filePath);
 
2072
 
 
2073
      if (localFile.exists()) {
 
2074
 
 
2075
        if (localFile.isDirectory() || !localFile.isWritable())
 
2076
           throw Components.results.NS_ERROR_FAILURE;
 
2077
 
 
2078
        if (!permissions)
 
2079
          permissions = localFile.permissions;
 
2080
      }
 
2081
 
 
2082
      if (!permissions)
 
2083
        permissions = DEFAULT_FILE_PERMS;
 
2084
 
 
2085
      var flags = WRONLY | CREATE_FILE | TRUNCATE;
 
2086
 
 
2087
      var fileStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
 
2088
                        createInstance(Components.interfaces.nsIFileOutputStream);
 
2089
 
 
2090
      fileStream.init(localFile, flags, permissions, 0);
 
2091
 
 
2092
      return fileStream;
 
2093
 
 
2094
    } catch (ex) {
 
2095
      EnigmailCommon.ERROR_LOG("enigmailMessengerOverlay.js: createFileStream: Failed to create "+filePath+"\n");
 
2096
      return null;
 
2097
    }
 
2098
  },
 
2099
 
 
2100
  writeFileContents: function (filePath, data, permissions)
 
2101
  {
 
2102
 
 
2103
    try {
 
2104
      var fileOutStream = this.createFileStream(filePath, permissions);
 
2105
 
 
2106
      if (data.length) {
 
2107
        if (fileOutStream.write(data, data.length) != data.length)
 
2108
          throw Components.results.NS_ERROR_FAILURE;
 
2109
 
 
2110
        fileOutStream.flush();
 
2111
      }
 
2112
      fileOutStream.close();
 
2113
 
 
2114
    } catch (ex) {
 
2115
      EnigmailCommon.ERROR_LOG("enigmailMessengerOverlay.js: writeFileContents: Failed to write to "+filePath+"\n");
 
2116
      return false;
 
2117
    }
 
2118
 
 
2119
    return true;
 
2120
  }
 
2121
};
 
2122
 
 
2123
window.addEventListener("load",   Enigmail.msg.messengerStartup.bind(Enigmail.msg), false);
 
2124