This is just some static backup of the original site, don't expect every link to work!

source: chrome/content/v_identity/vI_storage.js @ 0f72bb

ng_0.8ng_0.9
Last change on this file since 0f72bb was 0f72bb, checked in by rene <rene@…>, 11 years ago

small bugfixes

  • Property mode set to 100644
File size: 18.8 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15
16    The Original Code is the Virtual Identity Extension.
17
18    The Initial Developer of the Original Code is Rene Ejury.
19    Portions created by the Initial Developer are Copyright (C) 2007
20    the Initial Developer. All Rights Reserved.
21
22    Contributor(s): Mike Krieger, Sebastian Apel
23 * ***** END LICENSE BLOCK ***** */
24 
25/**
26* some code copied and adapted from 'addressContext' and from 'Birthday Reminder'
27* thanks to Mike Krieger and Sebastian Apel
28*/
29
30virtualIdentityExtension.ns(function() { with (virtualIdentityExtension.LIB) {
31var storage = {
32    multipleRecipients : null,
33    focusedElement : null,
34   
35    lastCheckedEmail : {},  // array of last checked emails per row,
36                // to prevent ugly double dialogs and time-consuming double-checks
37   
38    rdfService : Components.classes["@mozilla.org/rdf/rdf-service;1"]
39            .getService(Components.interfaces.nsIRDFService),
40
41    prefroot : Components.classes["@mozilla.org/preferences-service;1"]
42            .getService(Components.interfaces.nsIPrefService)
43            .getBranch(null).QueryInterface(Components.interfaces.nsIPrefBranch2),
44   
45    rdfDatasource : null,    // local storage
46
47    clean: function() {
48        vI.notificationBar.dump("## storage: clean.\n");
49        storage.multipleRecipients = null;
50        storage.lastCheckedEmail = {};
51        storage.firstUsedInputElement = null;
52        awSetInputAndPopupValue = storage.original_functions.awSetInputAndPopupValue;
53        if (storage.rdfDatasource) storage.rdfDatasource.clean();
54    },
55   
56    original_functions : {
57        awSetInputAndPopupValue : null
58    },
59
60    replacement_functions : {
61        awSetInputAndPopupValue : function (inputElem, inputValue, popupElem, popupValue, rowNumber) {
62            vI.notificationBar.dump("## storage: awSetInputAndPopupValue '" + inputElem.id +"'\n");
63            storage.original_functions.awSetInputAndPopupValue(inputElem, inputValue, popupElem, popupValue, rowNumber);
64            storage.updateVIdentityFromStorage(inputElem);
65        }
66    },
67       
68    awOnBlur : function (element) {
69        // only react on events triggered by addressCol2 - textinput Elements
70        if (!element || ! element.id.match(/^addressCol2*/)) return;
71        vI.notificationBar.dump("\n## storage: awOnBlur '" + element.id +"'\n");
72        storage.updateVIdentityFromStorage(element);
73        storage.focusedElement = null;
74    },
75
76    awOnFocus : function (element) {
77        if (!element || ! element.id.match(/^addressCol2*/)) return;
78        storage.focusedElement = element;
79    },
80
81    awPopupOnCommand : function (element) {
82        vI.notificationBar.dump("\n## storage: awPopupOnCommand'" + element.id +"'\n");
83        storage.updateVIdentityFromStorage(document.getElementById(element.id.replace(/^addressCol1/,"addressCol2")));
84        if (element.selectedItem.getAttribute("value") == "addr_reply") // if reply-to is manually entered disable AutoReplyToSelf
85            document.getElementById("autoReplyToSelfLabel").setAttribute("hidden", "true");
86
87    },
88   
89    initialized : null,
90    init: function() {
91        if (!storage.initialized) {
92            storage.rdfDatasource = new vI.rdfDatasource("virtualIdentity.rdf");
93
94            // better approach would be to use te onchange event, but this one is not fired in any change case
95            // see https://bugzilla.mozilla.org/show_bug.cgi?id=355367
96            // same seems to happen with the ondragdrop event
97            if (top.MAX_RECIPIENTS == 0) top.MAX_RECIPIENTS = 1;
98            for (var row = 1; row <= top.MAX_RECIPIENTS ; row ++) {
99                var input = awGetInputElement(row);
100                if (input) {
101                    var oldBlur = input.getAttribute("onblur")
102                    input.setAttribute("onblur", (oldBlur?oldBlur+"; ":"") +
103                        "window.setTimeout(virtualIdentityExtension.storage.awOnBlur, 250, this.parentNode.parentNode.parentNode);")
104                    var oldFocus = input.getAttribute("onfocus")
105                    input.setAttribute("onfocus", (oldFocus?oldFocus+"; ":"") +
106                        "window.setTimeout(virtualIdentityExtension.storage.awOnFocus, 250, this.parentNode.parentNode.parentNode);")
107                }
108                var popup = awGetPopupElement(row);
109                if (popup) {
110                    var oldCommand = popup.getAttribute("oncommand")
111                    popup.setAttribute("oncommand", (oldCommand?oldCommand+"; ":"") +
112                        "window.setTimeout(virtualIdentityExtension.storage.awPopupOnCommand, 250, this);")
113                }
114            }
115            storage.initialized = true;
116        }
117        storage.original_functions.awSetInputAndPopupValue = awSetInputAndPopupValue;
118        awSetInputAndPopupValue = function (inputElem, inputValue, popupElem, popupValue, rowNumber) {
119            storage.replacement_functions.awSetInputAndPopupValue (inputElem, inputValue, popupElem, popupValue, rowNumber) }
120
121        // reset unavailable storageExtras preferences
122        const enigmail_ID="{847b3a00-7ab1-11d4-8f02-006008948af5}"
123        if (!vI.helper.extensionActive(enigmail_ID)) {
124            vI.main.preferences.setBoolPref("storageExtras_openPGP_messageEncryption", false)
125            vI.main.preferences.setBoolPref("storageExtras_openPGP_messageSignature", false)
126            vI.main.preferences.setBoolPref("storageExtras_openPGP_PGPMIME", false)
127        }
128    },
129   
130   
131    firstUsedInputElement : null,   // this stores the first Element for which a Lookup in the Storage was successfull
132    updateVIdentityFromStorage: function(inputElement) {       
133        if (!vI.main.preferences.getBoolPref("storage"))
134            { vI.notificationBar.dump("## storage: Storage deactivated\n"); return; }
135        vI.notificationBar.dump("## storage: updateVIdentityFromStorage()\n");
136
137        var recipientType = document.getElementById(inputElement.id.replace(/^addressCol2/,"addressCol1"))
138            .selectedItem.getAttribute("value");
139        var row = inputElement.id.replace(/^addressCol2#/,"")
140        if (recipientType == "addr_reply" || recipientType == "addr_followup" || storage.__isDoBcc(row)) {
141            // reset firstUsedInputElement if recipientType was changed (and don't care about doBcc fields)
142            if (storage.firstUsedInputElement == inputElement)
143                storage.firstUsedInputElement = null;
144            vI.notificationBar.dump("## storage: field is a 'reply-to' or 'followup-to' or preconfigured 'doBcc'. not searched.\n")
145            return;
146        }
147       
148        if (inputElement.value == "") {
149            vI.notificationBar.dump("## storage: no recipient found, not checked.\n"); return;
150        }
151       
152        var row = inputElement.id.replace(/^addressCol2#/,"")
153        if (storage.lastCheckedEmail[row] && storage.lastCheckedEmail[row] == inputElement.value) {
154            vI.notificationBar.dump("## storage: same email than before, not checked again.\n"); return;
155        }
156        storage.lastCheckedEmail[row] = inputElement.value;
157        var recipient = storage.__getDescriptionAndType(inputElement.value, recipientType);
158
159        var matchResults = { storageData : {}, menuItem : {} };
160        matchResults.storageData[0] = storage.rdfDatasource.readVIdentityFromRDF(recipient.recDesc, recipient.recType);
161        matchResults.storageData[1] = storage.rdfDatasource.findMatchingFilter(recipient.recDesc);
162
163        vI.notificationBar.dump("## storage: updateVIdentityFromStorage add found Identities to CloneMenu.\n");
164        var matchIndex = null;
165        for (var i = 0; i <= 1; i++) {
166            if (matchResults.storageData[i]) {          // check if there is a result in direct match or filter
167                if (matchIndex == null) matchIndex = i;     // prefer direct match instead of filter
168                matchResults.menuItem[i] = document.getElementById("msgIdentity_clone")
169                                .addIdentityToCloneMenu(matchResults.storageData[i]);
170            }
171        }
172        if (matchIndex == null) {
173            vI.notificationBar.dump("## storage: updateVIdentityFromStorage no usable Storage-Data found.\n");
174            return;
175        }
176        else {
177            vI.notificationBar.dump("## storage: using data from " + ((matchIndex == 0)?"direct":"filter") + " match\n");
178        }
179        // found storageData, so store InputElement
180        if (!storage.firstUsedInputElement) storage.firstUsedInputElement = inputElement;
181       
182        vI.notificationBar.dump("## storage: compare with current Identity\n");
183        if (vI.main.preferences.getBoolPref("storage_getOneOnly") &&                    // if requested to retrieve only storageID for first recipient entered
184            storage.firstUsedInputElement &&                        // and the request for the first recipient was already done
185            storage.firstUsedInputElement != inputElement &&                // and it's not the same element we changed now
186            !matchResults.storageData[matchIndex].equalsCurrentIdentity(false).equal)   // and this id is different than the current used one
187                vI.notificationBar.setNote(vI.main.elements.strings
188                    .getString("vident.smartIdentity.vIStorageCollidingIdentity"),  // than drop the potential changes
189                    "storage_notification");
190        // only update fields if new Identity is different than old one.
191        else {
192            vI.notificationBar.dump("## storage: updateVIdentityFromStorage check if storage-data matches current Identity.\n");
193            var compResult = matchResults.storageData[matchIndex].equalsCurrentIdentity(true);
194            if (!compResult.equal) {
195                var warning = storage.__getWarning("replaceVIdentity", recipient, compResult.compareMatrix);
196                var msgIdentityCloneElem = document.getElementById("msgIdentity_clone")
197                if (    !msgIdentityCloneElem.vid ||
198                    !vI.main.preferences.getBoolPref("storage_warn_vI_replace") ||
199                    (storage.__askWarning(warning) == "accept")) {
200                        msgIdentityCloneElem.selectedMenuItem = matchResults.menuItem[matchIndex];
201                        if (msgIdentityCloneElem.vid)
202                            vI.notificationBar.setNote(vI.main.elements.strings.getString("vident.smartIdentity.vIStorageUsage") + ".",
203                            "storage_notification");
204                }
205            }
206            else {
207                vI.notificationBar.dump("## storage: updateVIdentityFromStorage doing nothing - equals current Identity.\n");
208            }
209        }
210    },
211   
212    __getDescriptionAndType : function (recipient, recipientType) {
213        if (recipientType == "addr_newsgroups") return { recDesc : recipient, recType : "newsgroup" }
214        else if (storage.__isMailingList(recipient)) {
215            vI.notificationBar.dump("## __getDescriptionAndType: '" + recipient + "' is MailList\n");
216            return { recDesc : storage.__getMailListName(recipient), recType : "maillist" }
217        }
218        else {
219            vI.notificationBar.dump("## __getDescriptionAndType: '" + recipient + "' is no MailList\n");
220            var localIdentityData = new vI.identityData(recipient, null, null, null, null, null, null);
221            return { recDesc : localIdentityData.combinedName, recType : "email" }
222        }
223    },
224       
225    storeVIdentityToAllRecipients : function(msgType) {
226        if (msgType != nsIMsgCompDeliverMode.Now) return true;
227        vI.notificationBar.dump("## storage: ----------------------------------------------------------\n")
228        if (!vI.main.preferences.getBoolPref("storage"))
229            { vI.notificationBar.dump("## storage: Storage deactivated\n"); return true; }
230       
231        if (vI.statusmenu.objStorageSaveMenuItem.getAttribute("checked") != "true") {
232            vI.notificationBar.dump("## storage: SaveMenuItem not checked.\n")
233            return true;
234        }
235       
236        vI.notificationBar.dump("## storage: storeVIdentityToAllRecipients()\n");
237       
238        // check if there are multiple recipients
239        storage.multipleRecipients = false;
240        var recipients = 0;
241        for (var row = 1; row <= top.MAX_RECIPIENTS; row ++) {
242            var recipientType = awGetPopupElement(row).selectedItem.getAttribute("value");
243            if (recipientType == "addr_reply" || recipientType == "addr_followup" || 
244                storage.__isDoBcc(row) || awGetInputElement(row).value.match(/^\s*$/) ) continue;
245            if (recipients++ == 1) {
246                storage.multipleRecipients = true
247                vI.notificationBar.dump("## storage: multiple recipients found.\n")
248                break;
249            }
250        }           
251       
252        for (var row = 1; row <= top.MAX_RECIPIENTS; row ++) {
253            var recipientType = awGetPopupElement(row).selectedItem.getAttribute("value");
254            if (recipientType == "addr_reply" || recipientType == "addr_followup" || 
255                storage.__isDoBcc(row) || awGetInputElement(row).value.match(/^\s*$/) ) continue;
256            if (!storage.__updateStorageFromVIdentity(awGetInputElement(row).value, recipientType)) {
257                vI.notificationBar.dump("## storage: --------------  aborted  ---------------------------------\n")
258                return false; // abort sending
259            }
260        }
261        vI.notificationBar.dump("## storage: ----------------------------------------------------------\n");
262        return true;
263    },
264   
265    __getWarning : function(warningCase, recipient, compareMatrix) {
266        var warning = { title: null, recLabel : null, recipient : null, warning : null, css: null, query : null, class : null };
267        warning.title = vI.main.elements.strings.getString("vident." + warningCase + ".title")
268        warning.recLabel = vI.main.elements.strings.getString("vident." + warningCase + ".recipient") + " (" + recipient.recType + "):"
269        warning.recipient = recipient.recDesc;
270        warning.warning = 
271            "<table class='" + warningCase + "'><thead><tr><th class='col1'/>" +
272                "<th class='col2'>" + vI.main.elements.strings.getString("vident." + warningCase + ".currentIdentity") + "</th>" +
273                "<th class='col3'>" + vI.main.elements.strings.getString("vident." + warningCase + ".storedIdentity") + "</th>" +
274            "</tr></thead>" +
275            "<tbody>" + compareMatrix + "</tbody>" +
276            "</table>"
277        warning.css = "vI.DialogBrowser.css";
278        warning.query = vI.main.elements.strings.getString("vident." + warningCase + ".query");
279        warning.class = warningCase;
280        return warning;
281    },
282
283    __askWarning : function(warning) {
284        var retVar = { returnValue: null };
285        var answer = window.openDialog("chrome://v_identity/content/vI_Dialog.xul","",
286                    "chrome, dialog, modal, alwaysRaised, resizable=yes",
287                     warning, retVar)
288        return retVar.returnValue;
289    },
290   
291    __updateStorageFromVIdentity : function(recipient, recipientType) {
292        vI.notificationBar.dump("## storage: __updateStorageFromVIdentity.\n")
293        var dontUpdateMultipleNoEqual = (vI.main.preferences.getBoolPref("storage_dont_update_multiple") &&
294                    storage.multipleRecipients)
295        vI.notificationBar.dump("## storage: __updateStorageFromVIdentity dontUpdateMultipleNoEqual='" + dontUpdateMultipleNoEqual + "'\n")
296        recipient = storage.__getDescriptionAndType(recipient, recipientType);
297
298        var storageDataByType = storage.rdfDatasource.readVIdentityFromRDF(recipient.recDesc, recipient.recType);
299        var storageDataByFilter = storage.rdfDatasource.findMatchingFilter(recipient.recDesc);
300       
301        // update (storing) of data by type is required if there is
302        // no data stored by type (or different data stored) and no equal filter found
303        var storageDataByTypeCompResult = storageDataByType?storageDataByType.equalsCurrentIdentity(true):null;
304        var storageDataByTypeEqual = (storageDataByType && storageDataByTypeCompResult.equal);
305        var storageDataByFilterEqual = (storageDataByFilter && storageDataByFilter.equalsCurrentIdentity(false).equal);
306       
307        var doUpdate = "";
308        if (    (!storageDataByType && !storageDataByFilterEqual) ||
309            (!storageDataByTypeEqual && !storageDataByFilterEqual && !dontUpdateMultipleNoEqual) ) {
310            vI.notificationBar.dump("## storage: __updateStorageFromVIdentity updating\n")
311            var doUpdate = "accept";
312            if (storageDataByType && !storageDataByTypeEqual && vI.main.preferences.getBoolPref("storage_warn_update")) {
313                vI.notificationBar.dump("## storage: __updateStorageFromVIdentity overwrite warning\n");
314                doUpdate = storage.__askWarning(storage.__getWarning("updateStorage", recipient, storageDataByTypeCompResult.compareMatrix));
315                if (doUpdate == "takeover") {
316                    var msgIdentityCloneElem = document.getElementById("msgIdentity_clone");
317                    msgIdentityCloneElem.selectedMenuItem = msgIdentityCloneElem.addIdentityToCloneMenu(storageDataByType);
318                    return false;
319                }
320                if (doUpdate == "abort") return false;
321            }
322        }
323        if (doUpdate == "accept") storage.rdfDatasource.updateRDFFromVIdentity(recipient.recDesc, recipient.recType);
324        return true;
325    },
326       
327    // --------------------------------------------------------------------
328    // check if recipient is a mailing list.
329    // Similiar to Thunderbird, if there are muliple cards with the same displayName the mailinglist is preferred
330    // see also https://bugzilla.mozilla.org/show_bug.cgi?id=408575
331    __isMailingList: function(recipient) {
332        let abManager = Components.classes["@mozilla.org/abmanager;1"]
333            .getService(Components.interfaces.nsIAbManager);
334        let allAddressBooks = abManager.directories;
335        while (allAddressBooks.hasMoreElements()) {
336            let ab = allAddressBooks.getNext();
337            if (ab instanceof Components.interfaces.nsIAbDirectory && !ab.isRemote) {
338                let abdirectory = abManager.getDirectory(ab.URI + 
339                    "?(and(DisplayName,=," + encodeURIComponent(storage.__getMailListName(recipient)) + ")(IsMailList,=,TRUE))");
340                if (abdirectory) {
341                    try {   // just try, sometimes there are no childCards at all...
342                        let cards = abdirectory.childCards;
343                        if (cards.hasMoreElements()) return true;   // only interested if there is at least one element...
344                    } catch(e) { }
345                }
346            }
347        }
348        return false;
349    }, 
350   
351    // --------------------------------------------------------------------
352   
353    __getMailListName : function(recipient) {
354        if (recipient.match(/<[^>]*>/) || recipient.match(/$/)) {
355            var mailListName = RegExp.leftContext + RegExp.rightContext
356            mailListName = mailListName.replace(/^\s+|\s+$/g,"")
357        }
358        return mailListName;
359    },
360   
361    __isDoBcc : function(row) {
362        var recipientType = awGetPopupElement(row).selectedItem.getAttribute("value");
363        if (recipientType != "addr_bcc" || !getCurrentIdentity().doBcc) return false
364
365        var doBccArray = gMsgCompose.compFields.splitRecipients(getCurrentIdentity().doBccList, false, {});
366
367        for (var index = 0; index < doBccArray.count; index++ ) {
368            if (doBccArray.StringAt(index) == awGetInputElement(row).value) {
369                vI.notificationBar.dump("## storage: ignoring doBcc field '" +
370                    doBccArray.StringAt(index) + "'.\n");
371                return true;
372            }
373        }       
374        return false
375    },
376
377    getVIdentityFromAllRecipients : function(allIdentities) {
378        if (!vI.main.preferences.getBoolPref("storage"))
379            { vI.notificationBar.dump("## storage: Storage deactivated\n"); return; }
380        vI.notificationBar.dump("## storage: getVIdentityFromAllRecipients()\n");
381
382        for (var row = 1; row <= top.MAX_RECIPIENTS; row ++) {
383            var recipientType = awGetPopupElement(row).selectedItem.getAttribute("value");
384            if (recipientType == "addr_reply" || recipientType == "addr_followup" || storage.__isDoBcc(row)) continue;
385            storage.lastCheckedEmail[row] = awGetInputElement(row).value;
386            var recipient = storage.__getDescriptionAndType(awGetInputElement(row).value, recipientType);
387            var storageData = storage.rdfDatasource.readVIdentityFromRDF(recipient.recDesc, recipient.recType);
388            if (storageData) allIdentities.addWithoutDuplicates(storageData);
389            storageData = storage.rdfDatasource.findMatchingFilter(recipient.recDesc);
390            if (storageData) allIdentities.addWithoutDuplicates(storageData);
391        }
392        vI.notificationBar.dump("## storage: found " + allIdentities.number + " address(es)\n")
393    }
394}
395vI.storage = storage;
396}});
Note: See TracBrowser for help on using the repository browser.