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 ZmMiniCalCache = function(calViewController) {
 25 	this._calViewController = calViewController;
 26 	this.clearCache();
 27 };
 28 
 29 ZmMiniCalCache.prototype.toString =
 30 function() {
 31 	return "ZmMiniCalCache";
 32 };
 33 
 34 ZmMiniCalCache.prototype.clearCache =
 35 function() {
 36 	this._miniCalData = {};
 37 };
 38 
 39 ZmMiniCalCache.prototype.updateCache =
 40 function(params, data) {
 41 	var key = this._getCacheKey(params);
 42 	this._miniCalData[key] = data;	
 43 };
 44 
 45 ZmMiniCalCache.prototype._getCacheKey =
 46 function(params) {
 47 	var sortedFolderIds = [];
 48 	sortedFolderIds = sortedFolderIds.concat(params.folderIds);
 49 	sortedFolderIds.sort();
 50 	return (params.start + ":" + params.end + ":" + sortedFolderIds.join(":"));
 51 };
 52 
 53 ZmMiniCalCache.prototype._getMiniCalData =
 54 function(params) {
 55 	var cacheKey = this._getCacheKey(params);
 56 	var cachedData = this._miniCalData[cacheKey];
 57 	if (cachedData) {
 58 		this.highlightMiniCal(cachedData);
 59 		if (params.callback) {
 60 			params.callback.run(cachedData);
 61 			return;
 62 		}
 63 		return cachedData;
 64 	}	
 65 
 66 	var jsonObj = {GetMiniCalRequest:{_jsns:"urn:zimbraMail"}};
 67 	var request = jsonObj.GetMiniCalRequest;
 68 
 69 	this._setSoapParams(request, params);
 70 
 71 	appCtxt.getAppController().sendRequest({
 72 		jsonObj: jsonObj,
 73 		asyncMode: true,
 74         offlineCache: true,
 75 		callback: (new AjxCallback(this, this._getMiniCalResponse, [params])),
 76 		errorCallback: (new AjxCallback(this, this._handleMiniCalResponseError, [params])),
 77         offlineCallback: this._getMiniCalOfflineResponse.bind(this, params),
 78 		noBusyOverlay: params.noBusyOverlay,
 79 		accountName: (appCtxt.multiAccounts ? appCtxt.accountList.mainAccount.name : null)
 80 	});
 81 };
 82 
 83 ZmMiniCalCache.prototype.getCacheData =
 84 function(params) {
 85 	var cacheKey = this._getCacheKey(params);
 86 	var cachedData = this._miniCalData[cacheKey];
 87 	if (cachedData) {
 88 		return cachedData;
 89 	}
 90 };
 91 
 92 ZmMiniCalCache.prototype._handleMiniCalResponseError =
 93 function(params, result) {
 94 	var code = result ? result.code : null;
 95 	if (code == ZmCsfeException.ACCT_NO_SUCH_ACCOUNT ||
 96 		code == ZmCsfeException.MAIL_NO_SUCH_MOUNTPOINT)
 97 	{
 98 		var data = (result && result.data) ? result.data : null;
 99 		var id = (data && data.itemId && (data.itemId.length>0)) ? data.itemId[0] : null;
100 		if (id && appCtxt.getById(id) && this._faultHandler) {
101 			var folder = appCtxt.getById(id);
102 			folder.noSuchFolder = true;
103 			this._faultHandler.run(folder);
104 			return true;
105 		}
106 	}
107 
108 	//continue with callback operation
109 	if(params.callback) {
110 		params.callback.run([]);
111 	}
112 
113 	return true;
114 };
115 
116 ZmMiniCalCache.prototype._setSoapParams = 
117 function(request, params) {
118 	request.s = params.start;
119 	request.e = params.end;
120     request.tz = params.tz;
121 
122 	var folderNode = null;
123 	if (params.folderIds && params.folderIds.length) {
124 		request.folder = [];
125 		for (var i = 0; i < params.folderIds.length; i++) {
126 			request.folder.push({id:params.folderIds[i]});
127 		}
128 	}
129     if(params.tz){
130         request.tz = [];
131         var timezone = AjxTimezone.getRule(params.tz);
132         request.tz.push({id:params.tz,stdoff: timezone ? timezone.standard.offset : 0});
133     }
134 
135 };
136 
137 ZmMiniCalCache.prototype.setFaultHandler =
138 function(faultHandler) {
139 	this._faultHandler = faultHandler;
140 };
141 
142 ZmMiniCalCache.prototype._getMiniCalResponse =
143 function(params, result) {
144 	var data = [];
145 	if (!result) { return data; }
146 
147 	var callback = params.callback;
148 	var resp = result && result._data && result._data;
149 	var miniCalResponse = resp.GetMiniCalResponse;
150 
151 	if (miniCalResponse && miniCalResponse.date) {
152 		var dates = miniCalResponse.date;
153 		if (dates) {
154 			for (var i = 0; i < dates.length; i++) {
155 				if (dates[i]._content) {
156 					data.push(dates[i]._content);
157 				}
158 			}
159 		}	
160 		this.highlightMiniCal(data);
161 	} else {
162 		// always reset hiliting if empty response returned
163 		this.highlightMiniCal([]);
164 	}
165 
166     var errors = (miniCalResponse && miniCalResponse.error);
167     this.handleError(errors);
168 
169 	this.updateCache(params, data);
170 
171 	if (params.callback) {
172 		params.callback.run(data);
173 		return;
174 	}
175 
176 	return data;
177 };
178 
179 ZmMiniCalCache.prototype._getMiniCalOfflineResponse =
180 function(params) {
181 
182     var calMgr = appCtxt.getCalManager();
183     var calViewController = calMgr && calMgr.getCalViewController();
184     if (calViewController) {
185         var apptCache = calViewController.getApptCache();
186         if (apptCache) {
187             var folderIds = calViewController.getMainAccountCheckedCalendarIds();
188             var searchParams = { folderIds: folderIds,
189                                  start: params.start,
190                                  end: params.end
191                                };
192             var apptList = apptCache.setSearchParams(searchParams);
193             if (apptList) {
194                 apptCache.processOfflineMiniCal(params, apptList);
195             } else {
196                 apptCache.offlineSearchAppts(searchParams, params, null);
197             }
198         }
199     }
200 }
201 
202 ZmMiniCalCache.prototype.processBatchResponse =
203 function(miniCalResponse, data) {
204 	if (!miniCalResponse) { return; }
205 
206 	for (var i = 0; i < miniCalResponse.length; i++) {
207 		var dates = (miniCalResponse[i] && miniCalResponse[i].date);
208 		if (dates) {
209 			for (var j = 0; j < dates.length; j++) {
210 				if (dates[j]._content) {
211 					data.push(dates[j]._content);
212 				}
213 			}
214 		}
215 
216         var errors = (miniCalResponse[i] && miniCalResponse[i].error);
217         this.handleError(errors);
218 	}
219 };
220 
221 ZmMiniCalCache.prototype.handleError =
222 function(errors) {
223     if (errors && errors.length) {
224         for (var i = 0; i < errors.length; i++) {
225             if (errors[i].code == ZmCsfeException.MAIL_NO_SUCH_FOLDER || errors[i].code == ZmCsfeException.MAIL_NO_SUCH_MOUNTPOINT || errors[i].code == ZmCsfeException.ACCT_NO_SUCH_ACCOUNT || errors[i].code == ZmCsfeException.SVC_PERM_DENIED) {
226                 var id = errors[i].id;
227                 if (id && appCtxt.getById(id)) {
228                     var folder = appCtxt.getById(id);
229                     folder.noSuchFolder = true;
230                 }
231             }
232         }
233     }
234 };
235 
236 ZmMiniCalCache.prototype.highlightMiniCal =
237 function(dateArr) {
238 	var highlight = {};
239 	for (var i = 0; i < dateArr.length; i++) {
240 		if (dateArr[i]) {
241 			highlight[dateArr[i]] = AjxDateFormat.parse("yyyyMMdd", dateArr[i]);
242 		}
243 	}
244 	if (this._calViewController && this._calViewController._miniCalendar) {
245 		this._calViewController._miniCalendar.setHilite(highlight, true, true);
246 	}
247 };
248