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

« back to all changes in this revision

Viewing changes to mailnews/extensions/enigmail/package/commonFuncs.jsm

  • 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 Patrick Brunschwig.
 
17
 * Portions created by Patrick Brunschwig <patrick@mozilla-enigmail.org> are
 
18
 * Copyright (C) 2011 Patrick Brunschwig. All Rights Reserved.
 
19
 *
 
20
 * Contributor(s):
 
21
 *
 
22
 * Alternatively, the contents of this file may be used under the terms of
 
23
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
24
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
25
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
26
 * of those above. If you wish to allow use of your version of this file only
 
27
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
28
 * use your version of this file under the terms of the MPL, indicate your
 
29
 * decision by deleting the provisions above and replace them with the notice
 
30
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
31
 * the provisions above, a recipient may use your version of this file under
 
32
 * the terms of any one of the MPL, the GPL or the LGPL.
 
33
 * ***** END LICENSE BLOCK ***** */
 
34
 
 
35
 
 
36
/*
 
37
 * Common Enigmail crypto-related GUI functionality
 
38
 *
 
39
 * Import into a JS component using
 
40
 * 'Components.utils.import("resource://enigmail/commonFuncs.jsm");'
 
41
 */
 
42
 
 
43
Components.utils.import("resource://enigmail/enigmailCommon.jsm");
 
44
 
 
45
var EXPORTED_SYMBOLS = [ "EnigmailFuncs" ];
 
46
 
 
47
const Cc = Components.classes;
 
48
const Ci = Components.interfaces;
 
49
 
 
50
const IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
 
51
 
 
52
// field ID's of key list (as described in the doc/DETAILS file in the GnuPG distribution)
 
53
const KEY_TRUST_ID=1;
 
54
const KEY_ID = 4;
 
55
const CREATED_ID = 5;
 
56
const EXPIRY_ID = 6;
 
57
const UID_ID = 7;
 
58
const OWNERTRUST_ID = 8;
 
59
const USERID_ID = 9;
 
60
const SIG_TYPE_ID = 10;
 
61
const KEY_USE_FOR_ID = 11;
 
62
 
 
63
var gTxtConverter = null;
 
64
 
 
65
var EnigmailFuncs = {
 
66
 
 
67
  /**
 
68
   * download key(s) from a keyserver
 
69
   */
 
70
  downloadKeys: function (win, inputObj, resultObj)
 
71
  {
 
72
    EnigmailCommon.DEBUG_LOG("commonFuncs.jsm: downloadKeys: searchList="+inputObj.searchList+"\n");
 
73
 
 
74
    resultObj.importedKeys=0;
 
75
 
 
76
    var ioService = Cc[IOSERVICE_CONTRACTID].getService(Ci.nsIIOService);
 
77
    if (ioService && ioService.offline) {
 
78
      EnigmailCommon.alert(win, EnigmailCommon.getString("needOnline"));
 
79
      return;
 
80
    }
 
81
 
 
82
    var valueObj = {};
 
83
    if (inputObj.searchList) {
 
84
      valueObj = { keyId: "<"+inputObj.searchList.join("> <")+">" };
 
85
    }
 
86
 
 
87
    var keysrvObj = new Object();
 
88
 
 
89
    win.openDialog("chrome://enigmail/content/enigmailKeyserverDlg.xul",
 
90
          "", "dialog,modal,centerscreen", valueObj, keysrvObj);
 
91
    if (! keysrvObj.value) {
 
92
      return;
 
93
    }
 
94
 
 
95
    inputObj.keyserver = keysrvObj.value;
 
96
    if (! inputObj.searchList) {
 
97
      inputObj.searchList = keysrvObj.email.split(/[,; ]+/);
 
98
    }
 
99
 
 
100
    win.openDialog("chrome://enigmail/content/enigmailSearchKey.xul",
 
101
          "", "dialog,modal,centerscreen", inputObj, resultObj);
 
102
  },
 
103
 
 
104
  /**
 
105
   * Format a key fingerprint
 
106
   */
 
107
  formatFpr: function (fingerprint)
 
108
  {
 
109
    // format key fingerprint
 
110
    var r="";
 
111
    var fpr = fingerprint.match(/(....)(....)(....)(....)(....)(....)(....)(....)(....)?(....)?/);
 
112
    if (fpr && fpr.length > 2) {
 
113
      fpr.shift();
 
114
      r=fpr.join(" ");
 
115
    }
 
116
 
 
117
    return r;
 
118
  },
 
119
 
 
120
  /**
 
121
   * get a list of plain email addresses without name or surrounding <>
 
122
   */
 
123
  stripEmail: function (mailAddrs)
 
124
  {
 
125
 
 
126
    var qStart, qEnd;
 
127
    while ((qStart = mailAddrs.indexOf('"')) != -1) {
 
128
       qEnd = mailAddrs.indexOf('"', qStart+1);
 
129
       if (qEnd == -1) {
 
130
         EnigmailCommon.ERROR_LOG("commonFuncs.jsm: stripEmail: Unmatched quote in mail address: "+mailAddrs+"\n");
 
131
         throw Components.results.NS_ERROR_FAILURE;
 
132
       }
 
133
 
 
134
       mailAddrs = mailAddrs.substring(0,qStart) + mailAddrs.substring(qEnd+1);
 
135
    }
 
136
 
 
137
    // Eliminate all whitespace, just to be safe
 
138
    mailAddrs = mailAddrs.replace(/\s+/g,"");
 
139
 
 
140
    // Extract pure e-mail address list (stripping out angle brackets)
 
141
    mailAddrs = mailAddrs.replace(/(^|,)[^,]*<([^>]+)>[^,]*/g,"$1$2");
 
142
 
 
143
    return mailAddrs;
 
144
  },
 
145
 
 
146
  collapseAdvanced: function (obj, attribute, dummy)
 
147
  {
 
148
    EnigmailCommon.DEBUG_LOG("commonFuncs.jsm: collapseAdvanced:\n");
 
149
 
 
150
    var advancedUser = EnigmailCommon.getPref("advancedUser");
 
151
 
 
152
    obj = obj.firstChild;
 
153
    while (obj) {
 
154
      if (obj.getAttribute("advanced") == "true") {
 
155
        if (advancedUser) {
 
156
          obj.removeAttribute(attribute);
 
157
        }
 
158
        else {
 
159
          obj.setAttribute(attribute, "true");
 
160
        }
 
161
      }
 
162
      else if (obj.getAttribute("advanced") == "reverse") {
 
163
        if (advancedUser) {
 
164
          obj.setAttribute(attribute, "true");
 
165
        }
 
166
        else {
 
167
          obj.removeAttribute(attribute);
 
168
        }
 
169
      }
 
170
 
 
171
      obj = obj.nextSibling;
 
172
    }
 
173
  },
 
174
 
 
175
  openSetupWizard: function (win)
 
176
  {
 
177
     win.open("chrome://enigmail/content/enigmailSetupWizard.xul",
 
178
                "", "chrome,centerscreen");
 
179
  },
 
180
 
 
181
  openHelpWindow: function (source)
 
182
  {
 
183
    EnigmailCommon.openWin("enigmail:help",
 
184
                           "chrome://enigmail/content/enigmailHelp.xul?src="+source,
 
185
                           "centerscreen,resizable");
 
186
  },
 
187
 
 
188
  openAboutWindow: function ()
 
189
  {
 
190
    EnigmailCommon.openWin("about:enigmail",
 
191
                           "chrome://enigmail/content/enigmailAbout.xul",
 
192
                           "resizable,centerscreen");
 
193
  },
 
194
 
 
195
  openRulesEditor: function ()
 
196
  {
 
197
    EnigmailCommon.openWin("enigmail:rulesEditor",
 
198
                           "chrome://enigmail/content/enigmailRulesEditor.xul",
 
199
                           "dialog,centerscreen,resizable");
 
200
  },
 
201
 
 
202
  openKeyManager: function (win)
 
203
  {
 
204
    EnigmailCommon.getService(win);
 
205
 
 
206
    EnigmailCommon.openWin("enigmail:KeyManager",
 
207
                           "chrome://enigmail/content/enigmailKeyManager.xul",
 
208
                           "resizable");
 
209
  },
 
210
 
 
211
  openKeyGen: function ()
 
212
  {
 
213
    EnigmailCommon.openWin("enigmail:generateKey",
 
214
                           "chrome://enigmail/content/enigmailKeygen.xul",
 
215
                           "chrome,modal,resizable=yes");
 
216
  },
 
217
 
 
218
  openCardDetails: function ()
 
219
  {
 
220
    EnigmailCommon.openWin("enigmail:cardDetails",
 
221
                           "chrome://enigmail/content/enigmailCardDetails.xul",
 
222
                           "centerscreen");
 
223
  },
 
224
 
 
225
  openConsoleWindow: function ()
 
226
  {
 
227
     EnigmailCommon.openWin("enigmail:console",
 
228
                            "chrome://enigmail/content/enigmailConsole.xul",
 
229
                            "resizable,centerscreen");
 
230
  },
 
231
 
 
232
  openDebugLog: function(win)
 
233
  {
 
234
    var logDirectory = EnigmailCommon.getPref("logDirectory");
 
235
 
 
236
    if (!logDirectory) {
 
237
      EnigmailCommon.alert(win, EnigmailCommon.getString("noLogDir"));
 
238
      return;
 
239
    }
 
240
 
 
241
    var svc = EnigmailCommon.enigmailSvc;
 
242
    if (! svc) {
 
243
      EnigmailCommon.alert(win, EnigmailCommon.getString("noLogFile"));
 
244
      return;
 
245
    }
 
246
 
 
247
    if (! svc.logFileStream) {
 
248
      EnigmailCommon.alert(win, EnigmailCommon.getString("restartForLog"));
 
249
      return;
 
250
    }
 
251
 
 
252
    svc.logFileStream.flush();
 
253
 
 
254
    logDirectory = logDirectory.replace(/\\/g, "/");
 
255
 
 
256
    var logFileURL = "file:///" + logDirectory + "/enigdbug.txt";
 
257
    var opts="fileUrl=" + escape(logFileURL) + "&title=" +
 
258
          escape(EnigmailCommon.getString("debugLog.title"));
 
259
 
 
260
    EnigmailCommon.openWin("enigmail:logFile",
 
261
                           "chrome://enigmail/content/enigmailViewFile.xul?"+opts,
 
262
                           "resizable,centerscreen");
 
263
  },
 
264
 
 
265
  openPrefWindow: function (win, showBasic, selectTab)
 
266
  {
 
267
    EnigmailCommon.DEBUG_LOG("enigmailCommon.js: prefWindow\n");
 
268
 
 
269
    EnigmailCommon.getService(win);
 
270
 
 
271
    win.openDialog("chrome://enigmail/content/pref-enigmail.xul",
 
272
                   "_blank", "chrome,resizable=yes",
 
273
                   {'showBasic': showBasic,
 
274
                   'clientType': 'thunderbird',
 
275
                   'selectTab': selectTab});
 
276
  },
 
277
 
 
278
  createNewRule: function (win, emailAddress)
 
279
  {
 
280
    // make sure the rules database is loaded
 
281
    var enigmailSvc = EnigmailCommon.getService(win);
 
282
    if (!enigmailSvc) return false;
 
283
 
 
284
    var rulesListObj= new Object;
 
285
 
 
286
    // open rule dialog
 
287
    enigmailSvc.getRulesData(rulesListObj);
 
288
    var inputObj=new Object;
 
289
    var resultObj=new Object;
 
290
    inputObj.toAddress="{"+emailAddress+"}";
 
291
    inputObj.options="";
 
292
    inputObj.command = "add";
 
293
    win.openDialog("chrome://enigmail/content/enigmailSingleRcptSettings.xul","",
 
294
                   "dialog,modal,centerscreen,resizable", inputObj, resultObj);
 
295
    return true;
 
296
  },
 
297
 
 
298
  editKeyTrust: function (win, userIdArr, keyIdArr)
 
299
  {
 
300
    var inputObj = {
 
301
      keyId: keyIdArr,
 
302
      userId: userIdArr
 
303
    };
 
304
    var resultObj = { refresh: false };
 
305
    win.openDialog("chrome://enigmail/content/enigmailEditKeyTrustDlg.xul","",
 
306
                   "dialog,modal,centerscreen,resizable", inputObj, resultObj);
 
307
    return resultObj.refresh;
 
308
  },
 
309
 
 
310
  signKey: function (win, userId, keyId, signingKeyHint)
 
311
  {
 
312
    var inputObj = {
 
313
      keyId: keyId,
 
314
      userId: userId,
 
315
      signingKeyHint: signingKeyHint
 
316
    };
 
317
    var resultObj = { refresh: false };
 
318
    win.openDialog("chrome://enigmail/content/enigmailSignKeyDlg.xul","",
 
319
                   "dialog,modal,centerscreen,resizable", inputObj, resultObj);
 
320
    return resultObj.refresh;
 
321
  },
 
322
 
 
323
  showPhoto: function (win, keyId, userId, photoNumber)
 
324
  {
 
325
    var enigmailSvc = EnigmailCommon.getService(win);
 
326
    if (enigmailSvc) {
 
327
 
 
328
      if (photoNumber==null) photoNumber=0;
 
329
 
 
330
      var exitCodeObj = new Object();
 
331
      var errorMsgObj = new Object();
 
332
      var photoPath = enigmailSvc.showKeyPhoto("0x"+keyId, photoNumber, exitCodeObj, errorMsgObj);
 
333
 
 
334
      if (photoPath && exitCodeObj.value==0) {
 
335
 
 
336
        var photoFile = Cc[EnigmailCommon.LOCAL_FILE_CONTRACTID].
 
337
          createInstance(Ci.nsIFile);
 
338
        photoFile.initWithPath(photoPath);
 
339
        if (! (photoFile.isFile() && photoFile.isReadable())) {
 
340
          EnigmailCommon.alert(win, EnigmailCommon.getString("error.photoPathNotReadable", photoPath));
 
341
        }
 
342
        else {
 
343
          var ioServ = Cc[EnigmailCommon.IOSERVICE_CONTRACTID].getService(Ci.nsIIOService);
 
344
          var photoUri = ioServ.newFileURI(photoFile).spec;
 
345
          var argsObj = {
 
346
            photoUri: photoUri,
 
347
            userId: userId,
 
348
            keyId: keyId
 
349
          };
 
350
 
 
351
          win.openDialog("chrome://enigmail/content/enigmailDispPhoto.xul",
 
352
                         photoUri,
 
353
                         "chrome,modal,resizable,dialog,centerscreen",
 
354
                         argsObj);
 
355
          try {
 
356
            // delete the photo file
 
357
            photoFile.remove(false);
 
358
          }
 
359
          catch (ex) {}
 
360
       }
 
361
      }
 
362
      else {
 
363
        EnigmailCommon.alert(win, EnigmailCommon.getString("noPhotoAvailable"));
 
364
      }
 
365
    }
 
366
  },
 
367
 
 
368
  openKeyDetails: function (win, keyId, refresh)
 
369
  {
 
370
    var keyListObj = {};
 
371
 
 
372
    this.loadKeyList(win, refresh, keyListObj);
 
373
 
 
374
    var inputObj = {
 
375
      keyId:  keyId,
 
376
      keyListArr: keyListObj.keyList,
 
377
      secKey: keyListObj.keyList[ keyId ].secretAvailable
 
378
    };
 
379
    var resultObj = { refresh: false };
 
380
    win.openDialog("chrome://enigmail/content/enigmailKeyDetailsDlg.xul", "",
 
381
                   "dialog,modal,centerscreen,resizable", inputObj, resultObj);
 
382
    if (resultObj.refresh) {
 
383
      enigmailRefreshKeys();
 
384
    }
 
385
  },
 
386
 
 
387
  /**
 
388
   * Load the key list into memory
 
389
   * sortDirection: 1 = ascending / -1 = descending
 
390
   */
 
391
  loadKeyList: function (win, refresh, keyListObj, sortColumn, sortDirection)
 
392
  {
 
393
    EnigmailCommon.DEBUG_LOG("enigmailFuncs.jsm: loadKeyList\n");
 
394
 
 
395
    if (! sortColumn) sortColumn = "userid";
 
396
    if (! sortDirection) sortDirection = 1;
 
397
 
 
398
    const TRUSTLEVEL_SORTED="oidreD-qnmfu"; // trust level sorted by increasing level of trust
 
399
 
 
400
    var sortByKeyId = function (a, b) {
 
401
      return (a.keyId < b.keyId) ? -sortDirection : sortDirection;
 
402
    };
 
403
 
 
404
    var sortByKeyIdShort = function (a, b) {
 
405
      return (a.keyId.substr(-8,8) < b.keyId.substr(-8 ,8)) ? -sortDirection : sortDirection;
 
406
    };
 
407
 
 
408
    var sortByUserId = function (a, b) {
 
409
      return (a.userId < b.userId) ? -sortDirection : sortDirection;
 
410
    };
 
411
 
 
412
    var sortByFpr = function (a, b) {
 
413
      return (keyListObj.keyList[a.keyId].fpr < keyListObj.keyList[b.keyId].fpr) ? -sortDirection : sortDirection;
 
414
    };
 
415
 
 
416
    var sortByKeyType = function (a, b) {
 
417
      return (keyListObj.keyList[a.keyId].secretAvailable < keyListObj.keyList[b.keyId].secretAvailable) ? -sortDirection : sortDirection;
 
418
    };
 
419
 
 
420
 
 
421
    var sortByValidity = function (a, b) {
 
422
      return (TRUSTLEVEL_SORTED.indexOf(EnigmailFuncs.getTrustCode(keyListObj.keyList[a.keyId])) < TRUSTLEVEL_SORTED.indexOf(EnigmailFuncs.getTrustCode(keyListObj.keyList[b.keyId]))) ? -sortDirection : sortDirection;
 
423
    };
 
424
 
 
425
    var sortByTrust = function (a, b) {
 
426
      return (TRUSTLEVEL_SORTED.indexOf(keyListObj.keyList[a.keyId].ownerTrust) < TRUSTLEVEL_SORTED.indexOf(keyListObj.keyList[b.keyId].ownerTrust)) ? -sortDirection : sortDirection;
 
427
    };
 
428
 
 
429
    var sortByExpiry = function (a, b) {
 
430
      return (keyListObj.keyList[a.keyId].expiryTime < keyListObj.keyList[b.keyId].expiryTime) ? -sortDirection : sortDirection;
 
431
    };
 
432
 
 
433
    var aGpgUserList = this.obtainKeyList(win, false, refresh);
 
434
    if (!aGpgUserList) return;
 
435
 
 
436
    var aGpgSecretsList = this.obtainKeyList(win, true, refresh);
 
437
    if (!aGpgSecretsList && !refresh) {
 
438
      if (EnigmailCommon.confirmDlg(EnigmailCommon.getString("noSecretKeys"),
 
439
            EnigmailCommon.getString("keyMan.button.generateKey"),
 
440
            EnigmailCommon.getString("keyMan.button.skip"))) {
 
441
        this.openKeyGen();
 
442
        this.loadKeyList(true, keyListObj);
 
443
      }
 
444
    }
 
445
 
 
446
    keyListObj.keyList = new Array();
 
447
    keyListObj.keySortList = new Array();
 
448
 
 
449
    var keyObj = new Object();
 
450
    var i;
 
451
    var uatNum=0; // counter for photos (counts per key)
 
452
 
 
453
    for (i=0; i<aGpgUserList.length; i++) {
 
454
      var listRow=aGpgUserList[i].split(/:/);
 
455
      if (listRow.length>=0) {
 
456
        switch (listRow[0]) {
 
457
        case "pub":
 
458
          keyObj = new Object();
 
459
          uatNum = 0;
 
460
          keyObj.expiry=EnigmailCommon.getDateTime(listRow[EXPIRY_ID], true, false);
 
461
          keyObj.expiryTime = Number(listRow[EXPIRY_ID]);
 
462
          keyObj.created=EnigmailCommon.getDateTime(listRow[CREATED_ID], true, false);
 
463
          keyObj.keyId=listRow[KEY_ID];
 
464
          keyObj.keyTrust=listRow[KEY_TRUST_ID];
 
465
          keyObj.keyUseFor=listRow[KEY_USE_FOR_ID];
 
466
          keyObj.ownerTrust=listRow[OWNERTRUST_ID];
 
467
          keyObj.SubUserIds=new Array();
 
468
          keyObj.fpr="";
 
469
          keyObj.photoAvailable=false;
 
470
          keyObj.secretAvailable=false;
 
471
          keyListObj.keyList[listRow[KEY_ID]] = keyObj;
 
472
          break;
 
473
        case "fpr":
 
474
          keyObj.fpr=listRow[USERID_ID];
 
475
          break;
 
476
        case "uid":
 
477
          if (listRow[USERID_ID].length == 0) {
 
478
            listRow[USERID_ID] = "-";
 
479
          }
 
480
          if (typeof(keyObj.userId) != "string") {
 
481
            keyObj.userId=EnigmailCommon.convertGpgToUnicode(listRow[USERID_ID]);
 
482
            keyListObj.keySortList.push({
 
483
              userId: keyObj.userId.toLowerCase(),
 
484
              keyId: keyObj.keyId
 
485
            });
 
486
            if (TRUSTLEVEL_SORTED.indexOf(listRow[KEY_TRUST_ID]) < TRUSTLEVEL_SORTED.indexOf(keyObj.keyTrust)) {
 
487
              // reduce key trust if primary UID is less trusted than public key
 
488
              keyObj.keyTrust = listRow[KEY_TRUST_ID];
 
489
            }
 
490
          }
 
491
          else {
 
492
            var subUserId = {
 
493
              userId: EnigmailCommon.convertGpgToUnicode(listRow[USERID_ID]),
 
494
              keyTrust: listRow[KEY_TRUST_ID],
 
495
              type: "uid"
 
496
            };
 
497
            keyObj.SubUserIds.push(subUserId);
 
498
          }
 
499
          break;
 
500
        case "uat":
 
501
          if (listRow[USERID_ID].indexOf("1 ")==0) {
 
502
            var userId=EnigmailCommon.getString("userAtt.photo");
 
503
            keyObj.SubUserIds.push({userId: userId,
 
504
                                    keyTrust:listRow[KEY_TRUST_ID],
 
505
                                    type: "uat",
 
506
                                    uatNum: uatNum});
 
507
            keyObj.photoAvailable=true;
 
508
            ++uatNum;
 
509
          }
 
510
        }
 
511
      }
 
512
    }
 
513
 
 
514
    // search and mark keys that have secret keys
 
515
    for (i=0; i<aGpgSecretsList.length; i++) {
 
516
       listRow=aGpgSecretsList[i].split(/:/);
 
517
       if (listRow.length>=0) {
 
518
         if (listRow[0] == "sec") {
 
519
           if (typeof(keyListObj.keyList[listRow[KEY_ID]]) == "object") {
 
520
             keyListObj.keyList[listRow[KEY_ID]].secretAvailable=true;
 
521
           }
 
522
         }
 
523
       }
 
524
    }
 
525
 
 
526
    switch (sortColumn.toLowerCase()) {
 
527
    case "keyid":
 
528
      keyListObj.keySortList.sort(sortByKeyId);
 
529
      break;
 
530
    case "keyidshort":
 
531
      keyListObj.keySortList.sort(sortByKeyIdShort);
 
532
      break;
 
533
    case "fpr":
 
534
      keyListObj.keySortList.sort(sortByFpr);
 
535
      break;
 
536
    case "keytype":
 
537
      keyListObj.keySortList.sort(sortByKeyType);
 
538
      break;
 
539
    case "validity":
 
540
      keyListObj.keySortList.sort(sortByValidity);
 
541
      break;
 
542
    case "trust":
 
543
      keyListObj.keySortList.sort(sortByTrust);
 
544
      break;
 
545
    case "expiry":
 
546
      keyListObj.keySortList.sort(sortByExpiry);
 
547
      break;
 
548
    default:
 
549
      keyListObj.keySortList.sort(sortByUserId);
 
550
    }
 
551
  },
 
552
 
 
553
  getTrustCode: function (keyObj)
 
554
  {
 
555
    // return a merged value of trust level "key disabled"
 
556
    if (keyObj.keyUseFor.indexOf("D")>=0)
 
557
      return "D";
 
558
    else
 
559
      return keyObj.keyTrust;
 
560
  },
 
561
 
 
562
 
 
563
  // Obtain kay list from GnuPG
 
564
  obtainKeyList: function (win, secretOnly, refresh)
 
565
  {
 
566
    EnigmailCommon.DEBUG_LOG("enigmailFuncs.jsm: obtainKeyList\n");
 
567
 
 
568
    var userList = null;
 
569
    try {
 
570
      var exitCodeObj = new Object();
 
571
      var statusFlagsObj = new Object();
 
572
      var errorMsgObj = new Object();
 
573
 
 
574
      var enigmailSvc = EnigmailCommon.getService(win);
 
575
      if (! enigmailSvc) return null;
 
576
 
 
577
      userList = enigmailSvc.getUserIdList(secretOnly,
 
578
                                           refresh,
 
579
                                           exitCodeObj,
 
580
                                           statusFlagsObj,
 
581
                                           errorMsgObj);
 
582
      if (exitCodeObj.value != 0) {
 
583
        EnigmailCommon.alert(win, errorMsgObj.value);
 
584
        return null;
 
585
      }
 
586
    } catch (ex) {
 
587
      EnigmailCommon.ERROR_LOG("ERROR in enigmailFuncs: obtainKeyList"+ex.toString()+"\n");
 
588
    }
 
589
 
 
590
    if (typeof(userList) == "string") {
 
591
      return userList.split(/\n/);
 
592
    }
 
593
    else {
 
594
      return [];
 
595
    }
 
596
  },
 
597
 
 
598
  getSignMsg: function (identity)
 
599
  {
 
600
    EnigmailCommon.DEBUG_LOG("enigmailCommon.jsm: getSignMsg: identity.key="+identity.key+"\n");
 
601
    var sign = null;
 
602
 
 
603
    EnigmailCommon.getPref("configuredVersion"); // dummy call to getPref to ensure initialization
 
604
 
 
605
    var prefRoot = EnigmailCommon.prefRoot;
 
606
 
 
607
    if (prefRoot.getPrefType("mail.identity."+identity.key+".pgpSignPlain")==0) {
 
608
      if (prefRoot.getPrefType("mail.identity."+identity.key+".pgpSignMsg")==0) {
 
609
        sign=identity.getBoolAttribute("pgpAlwaysSign");
 
610
        identity.setBoolAttribute("pgpSignEncrypted", sign);
 
611
        identity.setBoolAttribute("pgpSignPlain", sign);
 
612
      }
 
613
      else {
 
614
        sign = identity.getIntAttribute("pgpSignMsg");
 
615
        identity.setBoolAttribute("pgpSignEncrypted", sign==1);
 
616
        identity.setBoolAttribute("pgpSignPlain", sign>0);
 
617
      }
 
618
      prefRoot.deleteBranch("mail.identity."+identity.key+".pgpSignMsg");
 
619
      prefRoot.deleteBranch("mail.identity."+identity.key+".pgpAlwaysSign");
 
620
    }
 
621
  },
 
622
 
 
623
  // this function tries to mimic the Thunderbird plaintext viewer
 
624
  formatPlaintextMsg: function (plainTxt)
 
625
  {
 
626
    if (! gTxtConverter)
 
627
      gTxtConverter = Cc["@mozilla.org/txttohtmlconv;1"].createInstance(Ci.mozITXTToHTMLConv);
 
628
 
 
629
    if (! EnigmailCommon.prefRoot)
 
630
      EnigmailCommon.getPref("configuredVersion");
 
631
 
 
632
    var prefRoot = EnigmailCommon.prefRoot;
 
633
    var fontStyle = "";
 
634
 
 
635
    // set the style stuff according to perferences
 
636
 
 
637
    switch (prefRoot.getIntPref("mail.quoted_style")) {
 
638
      case 1:
 
639
        fontStyle="font-weight: bold; "; break;
 
640
      case 2:
 
641
        fontStyle="font-style: italic; "; break;
 
642
      case 3:
 
643
        fontStyle="font-weight: bold; font-style: italic; "; break;
 
644
    }
 
645
 
 
646
    switch (prefRoot.getIntPref("mail.quoted_size")) {
 
647
    case 1:
 
648
      fontStyle += "font-size: large; "; break;
 
649
    case 2:
 
650
      fontStyle += "font-size: small; "; break;
 
651
    }
 
652
 
 
653
    fontStyle += "color: "+prefRoot.getCharPref("mail.citation_color")+";";
 
654
 
 
655
    var convFlags = Ci.mozITXTToHTMLConv.kURLs;
 
656
    if (prefRoot.getBoolPref("mail.display_glyph"))
 
657
        convFlags |= Ci.mozITXTToHTMLConv.kGlyphSubstitution;
 
658
    if (prefRoot.getBoolPref("mail.display_struct"))
 
659
        convFlags |= Ci.mozITXTToHTMLConv.kStructPhrase;
 
660
 
 
661
    // start processing the message
 
662
 
 
663
    plainTxt = plainTxt.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
 
664
    var lines = plainTxt.split(/\n/);
 
665
    var oldCiteLevel = 0;
 
666
    var citeLevel = 0;
 
667
    var preface = "";
 
668
    var logLineStart = { value: 0 };
 
669
    var isSignature = false;
 
670
 
 
671
    for (var i=0; i < lines.length; i++) {
 
672
      preface = "";
 
673
      oldCiteLevel = citeLevel;
 
674
      if (lines[i].search(/^[\> \t]*\>$/) == 0)
 
675
        lines[i]+=" ";
 
676
 
 
677
      citeLevel = gTxtConverter.citeLevelTXT(lines[i], logLineStart);
 
678
 
 
679
      if (citeLevel > oldCiteLevel) {
 
680
 
 
681
        preface='</pre>';
 
682
        for (let j=0; j < citeLevel - oldCiteLevel; j++) {
 
683
          preface += '<blockquote type="cite" style="'+fontStyle+'">';
 
684
        }
 
685
        preface += '<pre wrap="">\n';
 
686
      }
 
687
      else if (citeLevel < oldCiteLevel) {
 
688
        preface='</pre>';
 
689
        for (let j = 0; j < oldCiteLevel - citeLevel; j++)
 
690
          preface += "</blockquote>";
 
691
 
 
692
        preface += '<pre wrap="">\n';
 
693
      }
 
694
 
 
695
      if (logLineStart.value > 0) {
 
696
        preface += '<span class="moz-txt-citetags">' +
 
697
            gTxtConverter.scanTXT(lines[i].substr(0, logLineStart.value), convFlags) +
 
698
            '</span>';
 
699
      }
 
700
      else if (lines[i] == "-- ") {
 
701
        preface+='<div class=\"moz-txt-sig\">';
 
702
        isSignature = true;
 
703
      }
 
704
      lines[i] = preface + gTxtConverter.scanTXT(lines[i].substr(logLineStart.value), convFlags);
 
705
 
 
706
    }
 
707
 
 
708
    var r='<pre wrap="">' + lines.join("\n") + (isSignature ? '</div>': '') + '</pre>';
 
709
    //EnigmailCommon.DEBUG_LOG("enigmailFuncs.jsm: r='"+r+"'\n");
 
710
    return r;
 
711
  },
 
712
 
 
713
 
 
714
  /***
 
715
   * extract the data fields following a header.
 
716
   * e.g. ContentType: xyz; Aa=b; cc=d
 
717
   * returns aa=b and cc=d in an array of arrays
 
718
   */
 
719
  getHeaderData: function (data) {
 
720
    EnigmailCommon.DEBUG_LOG("enigmailCommon.jsm: getHeaderData: "+data.substr(0, 100)+"\n");
 
721
    var a = data.split(/\n/);
 
722
    var res = [];
 
723
    for (let i = 0; i < a.length; i++) {
 
724
      if (a[i].length == 0) break;
 
725
      let b = a[i].split(/;/);
 
726
 
 
727
      // extract "abc = xyz" tuples
 
728
      for (let j=0; j < b.length; j++) {
 
729
        let m = b[j].match(/^(\s*)([^=\s;]+)(\s*)(=)(\s*)(.*)(\s*)$/);
 
730
        if (m) {
 
731
          // m[2]: identifier / m[6]: data
 
732
          res[m[2].toLowerCase()] = m[6].replace(/\s*$/, "");
 
733
          EnigmailCommon.DEBUG_LOG("enigmailCommon.jsm: getHeaderData: "+m[2].toLowerCase()+" = "+res[m[2].toLowerCase()] +"\n");
 
734
        }
 
735
      }
 
736
      if (i == 0 && a[i].indexOf(";") < 0) break;
 
737
      if (i > 0 && a[i].search(/^\s/) < 0) break;
 
738
    }
 
739
    return res;
 
740
  }
 
741
};
 
742