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 mozilla.org code. 15 * 16 * The Initial Developer of the Original Code is 17 * Netscape Communications Corporation. 18 * Portions created by the Initial Developer are Copyright (C) 1998 19 * the Initial Developer. All Rights Reserved. 20 * 21 * Contributor(s): 22 * Seth Spitzer <sspitzer@netscape.com> 23 * Mark Banner <mark@standard8.demon.co.uk> 24 * Josh Geenen <gcontactsync@pirules.org> 25 * 26 * Alternatively, the contents of this file may be used under the terms of 27 * either of the GNU General Public License Version 2 or later (the "GPL"), 28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 * in which case the provisions of the GPL or the LGPL are applicable instead 30 * of those above. If you wish to allow use of your version of this file only 31 * under the terms of either the GPL or the LGPL, and not to allow others to 32 * use your version of this file under the terms of the MPL, indicate your 33 * decision by deleting the provisions above and replace them with the notice 34 * and other provisions required by the GPL or the LGPL. If you do not delete 35 * the provisions above, a recipient may use your version of this file under 36 * the terms of any one of the MPL, the GPL or the LGPL. 37 * 38 * ***** END LICENSE BLOCK ***** */ 39 40 if (!com) var com = {}; // A generic wrapper variable 41 // A wrapper for all GCS functions and variables 42 if (!com.gContactSync) com.gContactSync = {}; 43 44 /** 45 * Meant to override the code in the onDrop method of abDirTreeObserver (an 46 * instance of nsIXULTreeBuilderObserver), which is called when the user drops 47 * one or more cards. The code is a modified version of onDrop found in 48 * mailnews/addrbook/resources/abDragDrop.js 49 * It's purpose is to copy over extra attributes that this extension adds to 50 * address book cards and to work around bugs. 51 * 52 * @param row The row 53 * @param orientation {int} An integer specifying on/after/before the given row 54 */ 55 com.gContactSync.myOnDrop = function gCS_myOnDrop(row, orientation) { 56 var dragSession = dragService.getCurrentSession(); 57 if (!dragSession) 58 return; 59 // get the attributes added by this extension 60 var attributes = com.gContactSync.ContactConverter.getExtraSyncAttributes(false, true), 61 attributesLen = attributes.length, 62 trans = Components.classes["@mozilla.org/widget/transferable;1"] 63 .createInstance(Components.interfaces.nsITransferable); 64 trans.addDataFlavor("moz/abcard"); 65 66 var targetResource = dirTree.builderView.getResourceAtIndex(row), 67 // get the source and target directory information 68 targetURI = targetResource.Value, 69 srcURI = GetSelectedDirectory(), 70 toDirectory = GetDirectoryFromURI(targetURI), 71 srcDirectory = GetDirectoryFromURI(srcURI), 72 ab = new com.gContactSync.GAddressBook(toDirectory); 73 // iterate through each dropped item from the session 74 for (var i = 0, dropItems = dragSession.numDropItems; i < dropItems; i++) { 75 dragSession.getData(trans, i); 76 var dataObj = {}, 77 flavor = {}, 78 len = {}, 79 needToRefresh = false; 80 try { 81 trans.getAnyTransferData(flavor, dataObj, len); 82 dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString); 83 } 84 catch (ex) { continue; } 85 var transData = dataObj.data.split("\n"), 86 rows = transData[0].split(","), 87 numrows = rows.length, 88 result, 89 // needToCopyCard is used for whether or not we should be creating 90 // copies of the cards in a mailing list in a different address book 91 // - it's not for if we are moving or not. 92 needToCopyCard = true; 93 if (srcURI.length > targetURI.length) { 94 result = srcURI.split(targetURI); 95 if (result[0] !== srcURI) { 96 // src directory is a mailing list on target directory, no need to copy card 97 needToCopyCard = false; 98 // workaround for a mailnews bug, get the childCards enumerator to 99 // update the mIsMailingList variable in the directory 100 // https://www.mozdev.org/bugs/show_bug.cgi?id=19733 101 toDirectory.childCards || toDirectory.childNodes; 102 } 103 } 104 else { 105 result = targetURI.split(srcURI); 106 if (result[0] !== targetURI) { 107 // target directory is a mailing list on src directory, no need to copy card 108 needToCopyCard = false; 109 // workaround for a mailnews bug, get the childCards enumerator to 110 // update the mIsMailingList variable in the directory 111 // https://www.mozdev.org/bugs/show_bug.cgi?id=19733 112 toDirectory.childCards || toDirectory.childNodes; 113 needToRefresh = true; 114 } 115 } 116 // if we still think we have to copy the card, 117 // check if srcURI and targetURI are mailing lists on same directory 118 // if so, we don't have to copy the card 119 if (needToCopyCard) { 120 var targetParentURI = GetParentDirectoryFromMailingListURI(targetURI); 121 if (targetParentURI && (targetParentURI === 122 GetParentDirectoryFromMailingListURI(srcURI))) { 123 needToCopyCard = false; 124 } 125 } 126 // Only move if we are not transferring to a mail list 127 var actionIsMoving = (dragSession.dragAction & dragSession.DRAGDROP_ACTION_MOVE) && 128 !toDirectory.isMailList; 129 // get the cards first 130 var cards = []; 131 for (var j = 0; j < numrows; j++) { 132 cards.push(gAbView.getCardFromRow(rows[j])); 133 } 134 // iterate through each card and copy/move it 135 for (j = 0; j < numrows; j++) { 136 var card = cards[j]; 137 if (!card) 138 continue; 139 if (card.isMailList) { 140 // This check ensures we haven't slipped through by mistake 141 if (needToCopyCard && actionIsMoving) 142 toDirectory.addMailList(GetDirectoryFromURI(card.mailListURI)); 143 } 144 else { 145 var values = []; 146 // put in a try/catch block in case the card can't be QI'd to nsIAbMDBCard 147 var isMDBCard = false; 148 // only copy over the extra attributes if this is before Bug 413260 and 149 // if the card is an MDB Card (not an LDAP or different card) 150 try { 151 if (!card.getProperty) { 152 // MDB card was removed in 413260, but after that patch it is no 153 // longer necessary to copy the extra attributes manually 154 // the card may also be an LDAP card in which case it won't have 155 // extra attributes to copy 156 card.QueryInterface(Components.interfaces.nsIAbMDBCard); 157 isMDBCard = true; 158 for (var k = 0; k < attributesLen; k++) { 159 values[k] = card.getStringAttribute(attributes[k]); 160 } 161 } 162 } 163 catch (e) { 164 // ignore the error if the card wasn't an MDB card, otherwise log it 165 if (isMDBCard) 166 com.gContactSync.LOGGER.LOG_WARNING("Error while getting extra card attributes.", e); 167 } 168 // delete the card if the user chose to move it (rather than copy it) 169 if (actionIsMoving) 170 com.gContactSync.deleteCard(srcDirectory, card); 171 if (toDirectory.isMailList) { 172 needToRefresh = true; 173 var contact = new com.gContactSync.TBContact(card); 174 if (!contact.getValue("PrimaryEmail")) { 175 com.gContactSync.LOGGER.VERBOSE_LOG("Forcing dummy email"); 176 // force a dummy e-mail address 177 var dummyEmail = com.gContactSync.makeDummyEmail(contact, true); 178 contact.setValue("PrimaryEmail", dummyEmail, false); 179 } 180 } 181 var newCard = toDirectory.addCard(card); 182 if (isMDBCard) { // copy the attributes if this is an MDB card 183 try { 184 newCard.QueryInterface(Components.interfaces.nsIAbMDBCard); 185 if (isMDBCard) { 186 for (var k = 0; k < attributesLen; k++) { 187 var value = values[k] ? values[k] : ""; 188 newCard.setStringAttribute(attributes[k], value); 189 } 190 } 191 } catch (e) { com.gContactSync.LOGGER.LOG_WARNING("Error while copying card", e); } 192 } 193 try { 194 var now = (new Date()).getTime()/1000, 195 newContact = new com.gContactSync.TBContact(newCard, ab); 196 // now set the new card's last modified date and update it 197 newContact.setValue("LastModifiedDate", now); 198 newContact.update(); 199 } catch (e) { com.gContactSync.LOGGER.LOG_WARNING('copy card error: ' + e); } 200 } 201 } 202 var cardsTransferredText; 203 204 // set the status bar text 205 if (actionIsMoving) 206 cardsTransferredText = 207 numrows == 1 ? gAddressBookBundle.getString("cardMoved") 208 : gAddressBookBundle.getFormattedString("cardsMoved", 209 [numrows]); 210 else 211 cardsTransferredText = 212 numrows == 1 ? gAddressBookBundle.getString("cardCopied") 213 : gAddressBookBundle.getFormattedString("cardsCopied", 214 [numrows]); 215 // update the address book view so it doesn't show the card twice 216 SetAbView(GetSelectedDirectory(), false); 217 // select the first card, if any 218 if (gAbView && gAbView.getCardFromRow(0)) 219 SelectFirstCard(); 220 // set the status text 221 document.getElementById("statusText").label = cardsTransferredText; 222 } 223 } 224 /** 225 * Deletes the given card from the given directory. 226 * @param aDirectory {nsIAbDirectory} The directory from which the card is 227 * deleted. 228 * @param aCard {nsIAbCard} The card that is deleted from the 229 * directory. 230 */ 231 com.gContactSync.deleteCard = function gCS_deleteCard(aDirectory, aCard) { 232 if (!aCard || !aDirectory) 233 return; 234 var arr; 235 // Thunderbird 2 and 3 differ in the type of array that must be passed to 236 // the deleteCards method 237 if (aDirectory.modifyCard) { // TB 3 238 arr = Components.classes["@mozilla.org/array;1"] 239 .createInstance(Components.interfaces.nsIMutableArray); 240 arr.appendElement(aCard, false); 241 } 242 else { // TB 2 243 arr = Components.classes["@mozilla.org/supports-array;1"] 244 .createInstance(Components.interfaces.nsISupportsArray); 245 arr.AppendElement(aCard, false); 246 } 247 aDirectory.deleteCards(arr); 248 }; 249