1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the briefcase class. 27 */ 28 29 /** 30 * Creates the briefcase 31 * @class 32 * This class represents a briefcase. A briefcase contains briefcase items. 33 * 34 * @param {Hash} params a hash of parameters 35 * @param {int} params.id the numeric ID 36 * @param {String} params.name the name 37 * @param {ZmOrganizer} params.parent the parent organizer 38 * @param {ZmTree} params.tree the tree model that contains this organizer 39 * @param {constant} params.color the color for this briefcase 40 * @param {String} params.owner the owner of this organizer 41 * @param {String} params.oname the owner's name for this organizer 42 * @param {String} [params.zid] the Zimbra id of owner, if remote share 43 * @param {String} [params.rid] the Remote id of organizer, if remote share 44 * @param {String} [params.restUrl] the REST URL of this organizer. 45 * 46 * @extends ZmFolder 47 */ 48 ZmBriefcase = function(params) { 49 params.type = ZmOrganizer.BRIEFCASE; 50 ZmFolder.call(this, params); 51 } 52 53 ZmBriefcase.prototype = new ZmFolder; 54 ZmBriefcase.prototype.constructor = ZmBriefcase; 55 56 // Constants 57 58 ZmBriefcase.PAGE_INDEX = "_Index"; 59 ZmBriefcase.PAGE_CHROME = "_Template"; 60 ZmBriefcase.PAGE_CHROME_STYLES = "_TemplateStyles"; 61 ZmBriefcase.PAGE_TITLE_BAR = "_TitleBar"; 62 ZmBriefcase.PAGE_HEADER = "_Header"; 63 ZmBriefcase.PAGE_FOOTER = "_Footer"; 64 ZmBriefcase.PAGE_SIDE_BAR = "_SideBar"; 65 ZmBriefcase.PAGE_TOC_BODY_TEMPLATE = "_TocBodyTemplate"; 66 ZmBriefcase.PAGE_TOC_ITEM_TEMPLATE = "_TocItemTemplate"; 67 ZmBriefcase.PATH_BODY_TEMPLATE = "_PathBodyTemplate"; 68 ZmBriefcase.PATH_ITEM_TEMPLATE = "_PathItemTemplate"; 69 ZmBriefcase.PATH_SEPARATOR = "_PathSeparator"; 70 71 // Public methods 72 73 /** 74 * Returns a string representation of the object. 75 * 76 * @return {String} a string representation of the object 77 */ 78 ZmBriefcase.prototype.toString = 79 function() { 80 return "ZmBriefcase"; 81 }; 82 83 ZmBriefcase.prototype.getIcon = 84 function() { 85 if (this.nId == ZmOrganizer.ID_ROOT) { return null; } 86 if (this.link) { return "SharedMailFolder"; } 87 return "Folder"; 88 }; 89 90 ZmBriefcase.prototype.notifyModify = 91 function(obj) { 92 ZmOrganizer.prototype.notifyModify.call(this, obj); 93 94 var doNotify = false; 95 var fields = {}; 96 if (obj.name != null && this.name != obj.name && !obj._isRemote) { 97 this.name = obj.name; 98 fields[ZmOrganizer.F_NAME] = true; 99 doNotify = true; 100 } else if (obj.color != null && this.color != obj.color && !obj._isRemote) { 101 this.color = obj.color; 102 fields[ZmOrganizer.F_COLOR] = true; 103 doNotify = true; 104 } 105 106 if (doNotify) { 107 this._notify(ZmEvent.E_MODIFY, {fields: fields}); 108 } 109 }; 110 111 // Static methods 112 113 /** 114 * Checks the briefcase name for validity. Returns an error message if the 115 * name is invalid and null if the name is valid. 116 * 117 * @param {String} name a briefcase name 118 * @return {String} the name 119 */ 120 ZmBriefcase.checkName = 121 function(name) { 122 return ZmOrganizer.checkName(name); 123 }; 124 125 /** 126 * Returns true if the given object(s) may be placed in this folder. 127 * 128 * If the object is a folder, check that: 129 * <ul> 130 * <li>We are not the immediate parent of the folder</li> 131 * <li>We are not a child of the folder</li> 132 * <li>We are not Spam or Drafts</li> 133 * <li>We don't already have a child with the folder's name (unless we are in Trash)</li> 134 * <li>We are not moving a regular folder into a search folder</li> 135 * <li>We are not moving a search folder into the Folders container</li> 136 * <li>We are not moving a folder into itself</li> 137 * </ul> 138 * 139 * If the object is an item or a list or items, check that: 140 * <ul> 141 * <li>We are not the Folders container</li> 142 * <li>We are not a search folder</li> 143 * <li>The items aren't already in this folder</li> 144 * <li>A contact can only be moved to Trash</li> 145 * <li>A draft can be moved to Trash or Drafts</li> 146 * <li>Non-drafts cannot be moved to Drafts</li> 147 * </ul> 148 * 149 * @param {Object} what the object(s) to possibly move into this briefcase (item or organizer) 150 */ 151 ZmBriefcase.prototype.mayContain = 152 function(what, targetFolderType) { 153 154 if (!what) return true; 155 156 var invalid = false; 157 targetFolderType = targetFolderType || this.type; 158 159 if (what instanceof ZmFolder) { //ZmBriefcase 160 invalid =( 161 what.parent == this || this.isChildOf(what) 162 || targetFolderType == ZmOrganizer.SEARCH || targetFolderType == ZmOrganizer.TAG 163 || (!this.isInTrash() && this.hasChild(what.name)) 164 || (what.id == this.id) 165 || (this.isRemote() && !this._remoteMoveOk(what)) 166 || (what.isRemote() && !this._remoteMoveOk(what)) 167 || this.disallowSubFolder 168 ); 169 } else { //ZmBriefcaseItem 170 var items = AjxUtil.toArray(what); 171 var item = items[0]; 172 if (item.type == ZmItem.BRIEFCASE_ITEM) { 173 invalid = this._checkInvalidFolderItems(items); 174 175 if (!invalid) { 176 for (var i = 0; i < items.length; i++) { 177 if (items[i] instanceof ZmBriefcaseFolderItem && (items[i].id == this.id || // Can't move folder items to themselves 178 this.isChildOf(items[i].folder))) { // Can't move parent folder to child folder 179 invalid = true; 180 break; 181 } 182 } 183 } 184 185 186 // can't move items to folder they're already in; we're okay if 187 // we have one item from another folder 188 if (!invalid && item.folderId) { 189 invalid = true; 190 for (var i = 0; i < items.length; i++) { 191 var tree = appCtxt.getById(items[i].folderId); 192 if (tree != this) { 193 invalid = false; 194 break; 195 } 196 } 197 } 198 } else { 199 invalid = true; 200 } 201 202 // attachments from mail can be moved inside briefcase 203 if (item && item.msgId && item.partId) { 204 invalid = false; 205 } 206 207 } 208 209 if (!invalid && this.link) { 210 invalid = this.isReadOnly(); 211 } 212 213 return !invalid; 214 }; 215 216 ZmBriefcase.prototype._checkInvalidFolderItems = 217 function(items, targetFolderType) { 218 var invalid = false; 219 for (var i=0; i<items.length && !invalid; i++) { 220 if (items[i] instanceof ZmBriefcaseFolderItem) { 221 var item = items[i]; 222 invalid = ( 223 item.parent == this || this.isChildOf(item) 224 || targetFolderType == ZmOrganizer.SEARCH || targetFolderType == ZmOrganizer.TAG 225 || (!this.isInTrash() && this.hasChild(item.name)) 226 || (item.id == this.id) 227 || (item.folder && item.folder.isRemote() && !this.isRemote() && !item.folder.rid) 228 || (item.folder && this.isRemote()) 229 ); 230 } 231 } 232 return invalid; 233 }; 234 235 ZmBriefcase.prototype.supportsPublicAccess = 236 function() { 237 return true; 238 }; 239 240 ZmBriefcase.prototype.isShared = 241 function(){ 242 return this.link ? true : false; 243 }; 244 245 ZmBriefcase.prototype._generateRestUrl = 246 function() { 247 var loc = document.location; 248 var uname = this.getOwner(); 249 var host = loc.host; 250 var m = uname.match(/^(.*)@(.*)$/); 251 252 host = (m && m[2]) || host; 253 254 // REVISIT: What about port? For now assume other host uses same port 255 if (loc.port && loc.port != 80) { 256 host = host + ":" + loc.port; 257 } 258 259 var searchPath = this.getSearchPath(true); 260 var generatedRestURL = [loc.protocol, "//", host, "/service/user/", uname, "/", AjxStringUtil.urlEncode(searchPath)].join(""); 261 var restUrl = this.restUrl; 262 var oname = this.oname; 263 var parent = this.parent; 264 //Get the restUrl and oname from remote share 265 while (parent) { 266 if (parent.restUrl) { 267 restUrl = parent.restUrl; 268 } 269 if (parent.oname) { 270 oname = parent.oname; 271 } 272 parent = parent.parent; 273 } 274 275 if (restUrl) { 276 var index = searchPath.indexOf(oname); //remove oname from searchPath 277 if (index != -1) { 278 searchPath = searchPath.substring(index + oname.length); 279 } 280 generatedRestURL = restUrl + AjxStringUtil.urlEncode(searchPath); 281 } 282 return generatedRestURL; 283 }; 284