1 /* ***** BEGIN LICENSE BLOCK ***** 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 * 4 * The contents of this file are subject to the Mozilla Public License Version 5 * 1.1 (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * http://www.mozilla.org/MPL/ 8 * 9 * Software distributed under the License is distributed on an "AS IS" basis, 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 * for the specific language governing rights and limitations under the 12 * License. 13 * 14 * The Original Code is gContactSync. 15 * 16 * The Initial Developer of the Original Code is 17 * Josh Geenen <gcontactsync@pirules.org>. 18 * Portions created by the Initial Developer are Copyright (C) 2008-2010 19 * the Initial Developer. All Rights Reserved. 20 * 21 * Contributor(s): 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 * 35 * ***** END LICENSE BLOCK ***** */ 36 37 if (!com) var com = {}; // A generic wrapper variable 38 // A wrapper for all GCS functions and variables 39 if (!com.gContactSync) com.gContactSync = {}; 40 41 /** 42 * An extension of AddressBook that adds functionality specific to gContactSync. 43 * @param aDirectory {nsIAbDirectory} The actual directory. 44 * @param aNoPrefs {boolean} Set this to true to skip fetching the 45 * preferences. 46 * @constructor 47 * @class 48 * @extends com.gContactSync.AddressBook 49 */ 50 com.gContactSync.GAddressBook = function gCS_GAddressBook(aDirectory, aNoPrefs) { 51 // call the AddressBook constructor using this object 52 com.gContactSync.AddressBook.call(this, aDirectory); 53 54 // Preferences for this address book 55 // If these aren't set the global preference with the same name, if any, is used 56 // NOTE: All these preferences are converted to strings 57 this.mPrefs = { 58 Plugin: "", // The name of the plugin to use 59 Username: "", // The username of the acct synced with 60 Disabled: "", // Temporarily disable synchronization with this AB 61 // NOTE: These three prefs aren't combined into a single pref for backwards 62 // compatibility with 0.2.x 63 myContacts: "", // true if only one group should be synced 64 myContactsName: "", // The name of the group to sync 65 syncGroups: "", // Synchronize groups 66 // NOTE: These two prefs aren't combined into a single pref for backwards 67 // compatibility with 0.2.x 68 readOnly: "", // Fetch updates from Google but don't send any changes 69 writeOnly: "", // Send changes to the server, but don't fetch any changes 70 updateGoogleInConflicts: "", // If a contact was updated in Google and TB then 71 // this pref determines which contact to update 72 lastSync: "", // The last time this AB was synchronized 73 lastBackup: "", // The last time this AB was backed up 74 reset: "" // Whether this AB has been reset since the last sync 75 }; 76 if (!aNoPrefs) 77 this.getPrefs(); 78 }; 79 80 // Copy the AB prototype (methods and member variables) 81 com.gContactSync.GAddressBook.prototype = com.gContactSync.AddressBook.prototype; 82 83 // A prefix for all preferences used to prevent conflicts with other extensions 84 com.gContactSync.GAddressBook.prototype.prefPrefix = "gContactSync"; 85 86 /** 87 * Fetches all of this directory's preferences. If the directory does not have 88 * any given preferences this function will use the global preference's value, 89 * if any. 90 */ 91 com.gContactSync.GAddressBook.prototype.getPrefs = function GAddressBook_getPrefs() { 92 com.gContactSync.LOGGER.VERBOSE_LOG("\nGetting Prefs for AB '" + this.getName() + "':"); 93 var i, val, pref; 94 for (i in this.mPrefs) { 95 var isLastSync = (i === "lastSync") 96 // all prefs except lastSync have the prefPrefix in from of them 97 val = this.getStringPref(isLastSync ? i : this.prefPrefix + i); 98 // getStringPref returns 0 iff the pref doesn't exist 99 // if the pref doesn't exist, then use the global gContactSync pref 100 // AND set this AB's pref so this doesn't fall through next time 101 // this behavior is mostly for backwards compatibility 102 if (val === 0) { 103 com.gContactSync.LOGGER.VERBOSE_LOG("getPrefs fell through on " + i); 104 pref = com.gContactSync.Preferences.mSyncPrefs[i]; 105 val = pref ? String(pref.value) : ""; 106 this.savePref(i, val); 107 } 108 // Bug 22817 - Unexpected behavior when lastSync is NaN 109 // Make sure that lastSync isn't set to NaN 110 else if (isLastSync && isNaN(val)) { 111 val = 0; 112 } 113 com.gContactSync.LOGGER.VERBOSE_LOG(" * " + i + " = " + val); 114 this.mPrefs[i] = val; 115 } 116 com.gContactSync.LOGGER.VERBOSE_LOG("\n"); 117 }; 118 119 /** 120 * Save the value of a given preference for this address book. 121 * 122 * @param aName {string} The name of the preference to set. 123 * @param aValue {string} The value to set the preference to. 124 */ 125 com.gContactSync.GAddressBook.prototype.savePref = function GAddressBook_savePref(aName, aValue) { 126 com.gContactSync.LOGGER.VERBOSE_LOG(" * Setting pref '" + aName + "' to value '" + aValue + "'"); 127 // all prefs except lastSync have the prefPrefix in from of them 128 this.setStringPref((aName === "lastSync" ? aName : this.prefPrefix + aName), aValue); 129 // in theory (and in testing) the preferences listener should already take 130 // care of setting the preference in this.mPrefs... 131 this.mPrefs[aName] = aValue; 132 }; 133 134 /** 135 * Sets the last time this address book was synchronized, in milliseconds 136 * since the epoch. 137 * @param aLastSync {integer} The last sync time. 138 */ 139 com.gContactSync.GAddressBook.prototype.setLastSyncDate = function GAddressBook_setLastSyncDate(aLastSync) { 140 this.setStringPref("lastSync", aLastSync); 141 // in theory (and in testing) the preferences listener should already take 142 // care of setting the preference in this.mPrefs... 143 this.mPrefs.lastSync = aLastSync; 144 }; 145 146 /** 147 * 'Resets' this address book making it appear to be brand new and never 148 * synchronized. 149 * The username is NOT erased. 150 * 151 * This includes: 152 * - Creating a backup 153 * - Deleting all mailing lists 154 * - Deleting all contacts 155 * - Setting primary to true 156 * - Setting the last sync date to 0 157 * @returns {boolean} True if the AB was reset, false otherwise. 158 */ 159 com.gContactSync.GAddressBook.prototype.reset = function GAddressBook_reset() { 160 com.gContactSync.LOGGER.LOG("Resetting the " + this.getName() + " directory."); 161 var lists, i, dt; 162 if (this.mPrefs.reset === "true") { 163 com.gContactSync.LOGGER.LOG_WARNING("An attempt was made to reset an AB which was already reset. Ignoring request."); 164 return false; 165 } 166 dt = new Date().toLocaleFormat("%Y_%m_%d_"); 167 com.gContactSync.GAbManager.backupAB(this, "reset_" + dt, ".bak"); 168 try { 169 lists = this.getAllLists(true); 170 } 171 catch (e) { 172 com.gContactSync.LOGGER.LOG_ERROR("Unable to get all lists", e); 173 lists = {}; 174 } 175 com.gContactSync.LOGGER.VERBOSE_LOG(" * Deleting all lists"); 176 for (i in lists) { 177 if (lists[i] instanceof com.gContactSync.GMailList) { 178 com.gContactSync.LOGGER.VERBOSE_LOG(" - Deleting list " + lists[i].getName()); 179 lists[i].remove(); 180 } 181 } 182 com.gContactSync.LOGGER.VERBOSE_LOG(" * Finished deleting lists"); 183 com.gContactSync.LOGGER.VERBOSE_LOG(" * Deleting all contacts"); 184 this.deleteContacts(this.getAllContacts()); 185 com.gContactSync.LOGGER.VERBOSE_LOG(" * Setting Last Sync Date to 0"); 186 this.setLastSyncDate(0); 187 com.gContactSync.LOGGER.LOG("Finished resetting the directory."); 188 // mark the AB as having been reset 189 this.savePref("reset", true); 190 return true; 191 }; 192 193 /** 194 * Updates the LastModifiedDate of every contact in this address book so 195 * it gets updated during the next sync. 196 */ 197 com.gContactSync.GAddressBook.prototype.replaceToServer = function GAddressBook_replaceToServer() { 198 var contacts = this.getAllContacts(), 199 time = (new Date()).getTime(); 200 201 // Set the LastModifiedDate to right now so each contact will get sent to 202 // Google during the next sync. Also update the card in the AB. 203 for (var i = 0; i < contacts.length; i++) { 204 contacts[i].setValue("LastModifiedDate", time, true); 205 } 206 }; 207 208 /** 209 * Returns a new GMailList object given the same parameters as the GMailList 210 * constructor. 211 * 212 * See the GMailList constructor for the most recent comments. 213 * 214 * @param aList {Ci.nsIAbDirectory} The actual nsIAbDirectory 215 * representation of a mailing list. 216 * @param aParentDirectory {GAddressBook} The parent directory (as an 217 * AddressBook object) containing this 218 * mailing list. 219 * @param aNew {boolean} Set as true for new mailing lists where 220 * no attempt should be made to fetch the 221 * contacts contained in the list. 222 * @returns {GMailList} A new GMailList. 223 */ 224 com.gContactSync.GAddressBook.prototype.newListObj = function GAddressBook_newListObj(aList, aParentDirectory, aNew) { 225 return new com.gContactSync.GMailList(aList, aParentDirectory, aNew); 226 }; 227 228 /** 229 * Returns an an object containing GMailList objects whose attribute name is 230 * the name of the mail list. 231 * @param skipGetCards {boolean} True to skip getting the cards of each list. 232 * @returns {object} An object containing GMailList objects. 233 */ 234 com.gContactSync.GAddressBook.prototype.getAllLists = function GAddressBook_getAllLists(skipGetCards) { 235 // same in Thunderbird 2 and 3 236 com.gContactSync.LOGGER.VERBOSE_LOG("Searching for mailing lists:"); 237 var iter = this.mDirectory.childNodes, 238 obj = {}, 239 list, 240 id, 241 data; 242 while (iter.hasMoreElements()) { 243 data = iter.getNext(); 244 if (data instanceof Components.interfaces.nsIAbDirectory && data.isMailList) { 245 list = this.newListObj(data, this, skipGetCards); 246 id = list.getGroupID(); 247 obj[id] = list; 248 com.gContactSync.LOGGER.VERBOSE_LOG(" * " + list.getName() + " - " + id); 249 } 250 } 251 return obj; 252 }; 253