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-2009 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 * MailList is an abstraction of a mailing list that facilitates getting the 43 * cards contained within the actual list as well as accessing and modifying the 44 * list and its properties. 45 * 46 * @param aList {Components.interfaces.nsIAbDirectory} The actual nsIAbDirectory 47 * representation of a mailing list. 48 * @param aParentDirectory {AddressBook} The parent directory (as an 49 * AddressBook object) containing this 50 * mailing list. 51 * @param aNew {boolean} Set as true for new mailing lists where 52 * no attempt should be made to fetch the 53 * contacts contained in the list. 54 * @constructor 55 * @class 56 */ 57 com.gContactSync.MailList = function gCS_MailList(aList, aParentDirectory, aNew) { 58 if (!aParentDirectory || 59 !(aParentDirectory instanceof com.gContactSync.AddressBook || 60 aParentDirectory instanceof com.gContactSync.GAddressBook)) 61 throw "Error - invalid address book supplied to the MailList Constructor"; 62 this.mParent = aParentDirectory; 63 this.mParent.checkList(aList, "MailList constructor"); 64 this.mList = aList; 65 this.mList.QueryInterface(Components.interfaces.nsIAbMDBDirectory); 66 this.mNew = aNew; 67 if (!aNew) 68 this.getAllContacts(); 69 }; 70 71 com.gContactSync.MailList.prototype = { 72 /** The contacts in this mailing list (cached) */ 73 mContacts: [], 74 /** This is true whenever the contacts have to be fetched again */ 75 mContactsUpdate: false, 76 /** 77 * Sets the name of this list. The update method must be called in order for 78 * the change to become permanent. 79 * @param aName {string} The new name for the list. 80 */ 81 setName: function MailList_setName(aName) { 82 this.mList.dirName = aName; 83 }, 84 /** 85 * Returns the name of this list. 86 * @returns {string} The name of this list. 87 */ 88 getName: function MailList_getName() { 89 return this.mList.dirName; 90 }, 91 /** 92 * Returns the card in this mail list, if any, with the same (not-null) 93 * value for the GoogleID attribute, or, if the GoogleID is null, if the 94 * display name, primary, and second emails are the same. 95 * @param aContact {TBContact} The contact being searched for. 96 * @param aAttrs {Array} The attributes whose values must be identical in 97 * order for the contact to match. The defaults are 98 * DisplayName, PrimaryEmail, and SecondEmail. 99 * This is only used if the contact doesn't have a 100 * GoogleID 101 * @returns {TBContact} The card in this list, if any, with the same, and 102 * non-null value for its GoogleID attribute, or, if the 103 * GoogleID is null, if the display name, primary, and 104 * second emails are the same. 105 */ 106 hasContact: function MailList_hasContact(aContact, aAttrs) { 107 if (!(aContact instanceof com.gContactSync.TBContact)) { 108 throw "Invalid aContact sent to MailList.hasContact"; 109 } 110 // get all of the cards in this list again, if necessary 111 if (this.mContactsUpdate || this.mContacts.length === 0) { 112 this.getAllContacts(); 113 } 114 // the attributes to check 115 var attrs = aAttrs ? aAttrs : ["DisplayName", "PrimaryEmail", "SecondEmail"]; 116 for (var i = 0, length = this.mContacts.length; i < length; i++) { 117 var contact = this.mContacts[i], 118 aContactID = aContact.getID(); 119 // if it is an old card (has id) compare IDs 120 if (aContactID) { 121 if (aContactID === contact.getID()) { 122 return contact; 123 } 124 } 125 // else check that display name, primary and second email are equal 126 else { 127 for (var j = 0; j < attrs.length; j++) { 128 var aContactVal = aContact.getValue(attrs[j]), 129 contactVal = contact.getValue(attrs[j]); 130 // if a value is non-empty and the two are not equal then return false 131 if ((aContactVal || contactVal) && aContactVal !== contactVal) { 132 return false; 133 } 134 } 135 return contact; 136 } 137 } 138 return null; 139 }, 140 /** 141 * Sets the nick name for this mailing list. The update method must be 142 * called in order for the change to become permanent. 143 * @param aNickName {string} The new nick name for this mailing list. 144 */ 145 setNickName: function MailList_setNickName(aNickName) { 146 this.mList.listNickName = aNickName; 147 }, 148 /** 149 * Returns the nick name of this mailing list. 150 * @returns {string} The nick name of this mailing list. 151 */ 152 getNickName: function MailList_getNickName() { 153 return this.mList.listNickName; 154 }, 155 /** 156 * Sets the description for this mailing list. The update method must be 157 * called in order for the change to become permanent. 158 * @param aDescription {string} The new description for this mailing list. 159 */ 160 setDescription: function MailList_setDescription(aDescription) { 161 this.mList.description = aDescription; 162 }, 163 /** 164 * Returns the description of this mailing list. 165 * @returns {string} The description of this mailing list. 166 */ 167 getDescription: function MailList_getDescription() { 168 return this.mList.description; 169 }, 170 /** 171 * Adds a contact to this mailing list without checking if it already exists. 172 * NOTE: If the contact does not have a primary e-mail address then this 173 * method will add a fake one. 174 * @param aContact {TBContact} The contact to add to this mailing list. 175 * @returns {TBContact} The contact. 176 */ 177 addContact: function MailList_addContact(aContact) { 178 if (!(aContact instanceof com.gContactSync.TBContact)) { 179 throw "Invalid aContact sent to AddressBook.addContact"; 180 } 181 // Add a dummy e-mail address if necessary and ignore the preference 182 // If this was not done then the mailing list would break. 183 if (!(aContact.getValue("PrimaryEmail"))) { 184 aContact.setValue("PrimaryEmail", com.gContactSync.makeDummyEmail(aContact, true)); 185 aContact.update(); // TODO is this necessary 186 } 187 try { 188 var realContact = new com.gContactSync.TBContact(this.mList.addCard(aContact.mContact), 189 this); 190 this.mContacts.push(realContact); 191 return realContact; 192 } 193 catch (e) { 194 com.gContactSync.LOGGER.LOG_ERROR("Unable to add card to the mail list with URI: " + 195 this.getURI(), e); 196 } 197 return null; 198 }, 199 /** 200 * Returns the uniform resource identifier (URI) for this mailing list. 201 * @returns {string} The URI of this list. 202 */ 203 getURI: function MailList_getURI() { 204 if (this.mList.URI) 205 return this.mList.URI; 206 return this.mList.getDirUri(); 207 }, 208 /** 209 * Returns an array of all of the cards in this mailing list. 210 * @returns {array} An array containing all of the cards in this mailing list. 211 */ 212 getAllContacts: function MailList_getAllContacts() { 213 // NOTE: Sometimes hasMoreElements fails if mail lists aren't working 214 this.mContacts = []; 215 var iter = this.mList.childCards, 216 data; 217 if (iter instanceof Components.interfaces.nsISimpleEnumerator) { // Thunderbird 3 218 try { 219 while (iter.hasMoreElements()) { 220 data = iter.getNext(); 221 if (data instanceof Components.interfaces.nsIAbCard) 222 this.mContacts.push(new com.gContactSync.TBContact(data, this)); 223 } 224 } 225 catch (e) { 226 com.gContactSync.LOGGER.LOG_ERROR("A mailing list is not working:", e); 227 if (com.gContactSync.confirm(com.gContactSync.StringBundle.getStr("resetConfirm"))) { 228 if (this.mParent.reset()) { 229 com.gContactSync.alert(com.gContactSync.StringBundle.getStr("pleaseRestart")); 230 } 231 } 232 // Throw an error to stop the sync 233 throw com.gContactSync.StringBundle.getStr("mailListBroken"); 234 } 235 } 236 else if (iter instanceof Components.interfaces.nsIEnumerator) { // TB 2 237 // use nsIEnumerator... 238 try { 239 iter.first(); 240 do { 241 data = iter.currentItem(); 242 if (data instanceof Components.interfaces.nsIAbCard) 243 this.mContacts.push(new com.gContactSync.TBContact(data, this)); 244 iter.next(); 245 } while (Components.lastResult === 0); 246 } 247 catch (ex) { 248 // TODO find a way to distinguish between the usual errors and the 249 // broken list errors 250 // error is expected when finished 251 com.gContactSync.LOGGER.VERBOSE_LOG("This error is expected:\n" + ex); 252 } 253 } 254 else { 255 com.gContactSync.LOGGER.LOG_ERROR("Could not iterate through an address book's contacts"); 256 throw com.gContactSync.StringBundle.getStr("mailListBroken"); 257 } 258 return this.mContacts; 259 }, 260 /** 261 * Deletes all of the cards in the array of cards from this list. 262 * @param aContacts {array} The array of TBContacts to delete from this mailing list. 263 */ 264 deleteContacts: function MailList_deleteContacts(aContacts) { 265 if (!(aContacts && aContacts.length > 0)) 266 return; 267 var arr, 268 i = 0; 269 if (com.gContactSync.AbManager.mVersion === 3) { // TB 3 270 arr = Components.classes["@mozilla.org/array;1"] 271 .createInstance(Components.interfaces.nsIMutableArray); 272 for (; i < aContacts.length; i++) { 273 if (aContacts[i] instanceof com.gContactSync.TBContact) { 274 arr.appendElement(aContacts[i].mContact, false); 275 } 276 else { 277 com.gContactSync.LOGGER.LOG_WARNING("Found an invalid contact sent " + 278 "MailList.deleteContacts"); 279 } 280 } 281 } 282 else { // TB 2 283 arr = Components.classes["@mozilla.org/supports-array;1"] 284 .createInstance(Components.interfaces.nsISupportsArray); 285 for (; i < aContacts.length; i++) { 286 if (aContacts[i] instanceof com.gContactSync.TBContact) { 287 arr.AppendElement(aContacts[i].mContact, false); 288 } 289 else { 290 com.gContactSync.LOGGER.LOG_WARNING("Found an invalid contact sent " + 291 "MailList.deleteContacts"); 292 } 293 } 294 } 295 try { 296 if (arr) { // make sure arr isn't null (mailnews bug 448165) 297 this.mContactsUpdate = true; // update mContacts when used 298 this.mList.deleteCards(arr); 299 } 300 } 301 catch (e) { 302 com.gContactSync.LOGGER.LOG_WARNING("Error while deleting cards from a mailing list", e); 303 } 304 this.mContacts = this.getAllContacts(); 305 }, 306 /** 307 * Deletes this mailing list from its parent address book. 308 */ 309 remove: function MailList_delete() { 310 this.mParent.mDirectory.deleteDirectory(this.mList); 311 this.mContacts = []; 312 // make sure the functions don't do anything 313 for (var i in this) { 314 if (i instanceof Function) 315 i = function () {}; 316 } 317 }, 318 /** 319 * Updates this mail list (commits changes like renaming or changing the 320 * nickname) 321 */ 322 update: function MailList_update() { 323 try { 324 if (com.gContactSync.AbManager.mVersion === 3) 325 this.mList.editMailListToDatabase(null); 326 else 327 this.mList.editMailListToDatabase(this.getURI(), null); 328 } 329 catch (e) { 330 com.gContactSync.LOGGER.LOG_WARNING("Unable to update mail list", e); 331 } 332 } 333 }; 334