1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Creates a doclet manager. 26 * @class 27 * This class represents a doclet manager. 28 * 29 */ 30 ZmDocletMgr = function() { 31 }; 32 33 ZmDocletMgr.prototype.saveDocument = 34 function(item) { 35 this._uploadSaveDocs2([{id: item.id, name: item.name, version: (item.version ? item.version :1), folderId: item.folderId}], null, null, item.name, item.content, item.contentType, item.descEnabled, item.desc); 36 }; 37 38 ZmDocletMgr.prototype._uploadSaveDocs2 = 39 function(files, status, guids, name, content, ct, enableDesc, desc) { 40 // create document wrappers 41 var soapDoc = AjxSoapDoc.create("BatchRequest", "urn:zimbra", null); 42 soapDoc.setMethodAttribute("onerror", "continue"); 43 for (var i = 0; i < files.length; i++) { 44 var file = files[i]; 45 if (file.done) continue; 46 47 var saveDocNode = soapDoc.set("SaveDocumentRequest", null, null, "urn:zimbraMail"); 48 saveDocNode.setAttribute("requestId", i); 49 50 var docNode = soapDoc.set("doc", null, saveDocNode); 51 if (file.id) { 52 docNode.setAttribute("id", file.id); 53 docNode.setAttribute("ver", file.version); 54 } 55 else { 56 docNode.setAttribute("l", file.folderId); 57 } 58 59 if(ct){ 60 docNode.setAttribute("ct", ct); 61 } 62 63 if(file.guid) { 64 var uploadNode = soapDoc.set("upload", null, docNode); 65 uploadNode.setAttribute("id", file.guid); 66 } 67 68 if(name!=null && content!=null) { 69 var contentNode = soapDoc.set("content", content, docNode); 70 docNode.setAttribute("name", name); 71 } 72 73 docNode.setAttribute("descEnabled", enableDesc ? "true" : "false"); 74 if(desc){ 75 docNode.setAttribute("desc", desc); 76 } 77 } 78 79 var args = [ files, status, guids ]; 80 var callback = new AjxCallback(this, this._uploadSaveDocsResponse, args); 81 var params = { 82 soapDoc:soapDoc, 83 asyncMode:true, 84 callback:callback 85 }; 86 87 var parentAppCtxt = window.opener && window.opener.appCtxt; 88 if (parentAppCtxt) { 89 var acct = parentAppCtxt.getActiveAccount(); 90 params.accountName = (acct && acct.id != ZmAccountList.DEFAULT_ID) ? acct.name : null; 91 } 92 this.sendRequest(params); 93 }; 94 95 /** 96 * Sends the request. 97 * 98 * @param {Hash} params a hash of parameters 99 * 100 * @see ZmRequestMgr 101 * @see ZmRequestMgr.sendRequest 102 */ 103 ZmDocletMgr.prototype.sendRequest = 104 function(params) { 105 if(!this._requestMgr) { 106 this._requestMgr = new ZmRequestMgr(this); 107 } 108 params.noSession = true; 109 return this._requestMgr.sendRequest(params); 110 }; 111 112 ZmDocletMgr.prototype._uploadSaveDocsResponse = 113 function(files, status, guids, response) { 114 var resp = response && response._data && response._data.BatchResponse; 115 116 var folderIds = []; 117 118 // mark successful uploads 119 if (resp && resp.SaveDocumentResponse) { 120 for (var i = 0; i < resp.SaveDocumentResponse.length; i++) { 121 var saveDocResp = resp.SaveDocumentResponse[i]; 122 files[saveDocResp.requestId].done = true; 123 files[saveDocResp.requestId].rest = saveDocResp.doc[0].rest; 124 files[saveDocResp.requestId].ver = saveDocResp.doc[0].ver; 125 files[saveDocResp.requestId].id = saveDocResp.doc[0].id; 126 if(files[saveDocResp.requestId].folderId) { 127 folderIds.push(files[saveDocResp.requestId].folderId); 128 } 129 } 130 } 131 132 // check for conflicts 133 var conflicts = null; 134 if (resp && resp.Fault) { 135 var errors = []; 136 conflicts = []; 137 for (var i = 0; i < resp.Fault.length; i++) { 138 var fault = resp.Fault[i]; 139 var error = fault.Detail.Error; 140 var code = error.Code; 141 var attrs = error.a; 142 if (code == ZmCsfeException.MAIL_ALREADY_EXISTS || 143 code == ZmCsfeException.MODIFY_CONFLICT) { 144 var file = files[fault.requestId]; 145 for (var p in attrs) { 146 var attr = attrs[p]; 147 switch (attr.n) { 148 case "id": { file.id = attr._content; break; } 149 case "ver": { file.version = attr._content; break; } 150 case "rest": { file.rest = attr._content; break; } 151 152 } 153 } 154 conflicts.push(file); 155 } 156 else { 157 DBG.println("Unknown error occurred: "+code); 158 errors[fault.requestId] = fault; 159 } 160 } 161 // TODO: What to do about other errors? 162 } 163 164 // poke parent window to get notifications 165 var parentAppCtxt = window.opener && window.opener.appCtxt; 166 var parentAppCtlr = parentAppCtxt && parentAppCtxt.getAppController(); 167 if (parentAppCtlr && !parentAppCtlr.getInstantNotify()) { 168 parentAppCtlr.sendNoOp(); 169 } 170 171 if (this._saveCallback) { 172 //Pass on the conflicts to callback 173 this._saveCallback.run(files, conflicts); 174 } 175 }; 176 177 ZmDocletMgr.prototype.setSaveCallback = 178 function(callback) { 179 this._saveCallback = callback; 180 181 }; 182 183 ZmDocletMgr.prototype._kickPolling = 184 function(resetBackoff) { 185 186 }; 187 188 ZmDocletMgr.prototype._handleException = 189 function(ex, continuation) { 190 //todo: handle exceptions 191 }; 192 193 ZmDocletMgr.prototype.runAppFunction = 194 function(funcName, force) { 195 //not needed in new function 196 }; 197 198 ZmDocletMgr.prototype.fetchDocumentContent = 199 function(item) { 200 var restURL = item.rest; 201 var urlParts = AjxStringUtil.parseURL(restURL); 202 if(urlParts && urlParts.path) { 203 var result = AjxRpc.invoke("", urlParts.path + "?fmt=native&ver=" + item.version, {}, null, true); 204 var docContent = ""; 205 if(result && result.success) { 206 docContent = this._pendingContent = result.text; 207 } 208 return docContent; 209 } 210 return ""; 211 }; 212 213 214 ZmDocletMgr.prototype.getItemInfo = 215 function(params) 216 { 217 var soapDoc = AjxSoapDoc.create("GetItemRequest", "urn:zimbraMail"); 218 var folderNode = soapDoc.set("item"); 219 220 if(params.path){ 221 folderNode.setAttribute("path", params.path); 222 }else if(params.folderId && params.id){ //bug:19658 223 folderNode.setAttribute("l", params.folderId); 224 folderNode.setAttribute("id", params.id); 225 }else if(params.folderId && params.name){ 226 folderNode.setAttribute("l", params.folderId); 227 folderNode.setAttribute("name", params.name); 228 }else if(params.id){ 229 folderNode.setAttribute("id", params.id); 230 } 231 232 var args = []; 233 var asyncMode = (params.callback?true:false); 234 235 var handleResponse = null; 236 if(asyncMode){ 237 handleResponse = new AjxCallback(this, this.handleGetItemResponse,[params]); 238 } 239 240 var parentAppCtxt = window.opener && window.opener.appCtxt; 241 if (parentAppCtxt && parentAppCtxt.multiAccounts) { 242 var acct = parentAppCtxt.getActiveAccount(); 243 params.accountName = acct && acct.name; 244 } 245 246 var reqParams = { 247 soapDoc: soapDoc, 248 asyncMode: asyncMode, 249 callback: handleResponse, 250 accountName: params.accountName 251 }; 252 253 var response = this.sendRequest(reqParams); 254 255 if(!asyncMode && response){ 256 var item = this.handleGetItemResponse(params,response.GetItemResponse); 257 return item; 258 } 259 260 return null; 261 }; 262 263 ZmDocletMgr.prototype.handleGetItemResponse = 264 function(params,response) 265 { 266 267 var path = params.path; 268 var callback = params.callback; 269 270 var getItemResponse = response; 271 if(response && response._data){ 272 getItemResponse = response && response._data && response._data.GetItemResponse; 273 } 274 275 var docResp = getItemResponse && getItemResponse.doc && getItemResponse.doc[0]; 276 277 var item = null; 278 279 if(docResp){ 280 item = new ZmItem(); 281 var data = docResp; 282 if (data.id) item.id = data.id; 283 if (data.rest) item.rest = data.rest; 284 if (data.l) item.folderId = data.l; 285 if (data.name) item.name = data.name; 286 if (data.cr) item.creator = data.cr; 287 if (data.d) item.createDate = new Date(Number(data.d)); 288 if (data.md) item.modifyDate = new Date(Number(data.md)); 289 if (data.leb) item.modifier = data.leb; 290 if (data.s) item.size = Number(data.s); 291 if (data.ver) item.version = Number(data.ver); 292 if (data.ct) item.contentType = data.ct.split(";")[0]; 293 item.folderId = docResp.l || ZmOrganizer.ID_BRIEFCASE; 294 item.locked = false; 295 if (data.loid) { 296 item.locked = true; 297 item.lockId = data.loid; 298 item.lockUser = data.loe; 299 item.lockTime = new Date(Number(data.lt)); 300 } 301 item.descEnabled = data.descEnabled; 302 } 303 304 if(callback){ 305 callback.run(item); 306 } 307 308 return item; 309 }; 310 311 ZmDocletMgr.createItem = function(response) { 312 var docletMgr = new ZmDocletMgr(); 313 return docletMgr.handleGetItemResponse({}, response); 314 }; 315 316 ZmDocletMgr.prototype.getThemeContent = 317 function(themePath) 318 { 319 if(!themePath) return ''; 320 321 var result = AjxRpc.invoke("", themePath, {}, null, true); 322 var docContent = ""; 323 if(result && result.success) { 324 docContent = result.text; 325 } 326 return docContent; 327 }; 328 329 ZmDocletMgr.prototype.checkInvalidDocName = function(fileName) { 330 331 var message; 332 fileName = fileName.replace(/^\s+/,"").replace(/\s+$/,""); 333 334 if(fileName == ""){ 335 message = ZmMsg.emptyDocName; 336 }else if (!ZmOrganizer.VALID_NAME_RE.test(fileName) || ZmAppCtxt.INVALID_NAME_CHARS_RE.test(fileName)) { 337 //Bug fix # 79986 - < > , ? | / \ * : are invalid filenames 338 message = AjxMessageFormat.format(ZmMsg.errorInvalidName, AjxStringUtil.htmlEncode(fileName)); 339 } else if ( fileName.length > ZmOrganizer.MAX_NAME_LENGTH){ 340 message = AjxMessageFormat.format(ZmMsg.nameTooLong, ZmOrganizer.MAX_NAME_LENGTH); 341 } 342 343 return message; 344 }; 345 346 ZmDocletMgr.prototype.unlock = 347 function(item, callback, errorCallback, accountName){ 348 349 var json = { 350 ItemActionRequest: { 351 _jsns: "urn:zimbraMail", 352 action: { 353 id: item.id, 354 op: "unlock" 355 } 356 } 357 }; 358 359 var params = { 360 jsonObj: json, 361 asyncMode: Boolean(callback), 362 callback: callback, 363 errorCallback: errorCallback, 364 accountName: accountName 365 }; 366 return this.sendRequest(params); 367 368 }; 369