1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  * This file contains the zimbra account class.
 27  */
 28 
 29 /**
 30  * Creates an account object containing meta info about the account.
 31  * @class
 32  * This class represents an account. This object is created primarily if a user has added sub-accounts
 33  * to manage (i.e. a family mailbox).
 34  *
 35  * @author Parag Shah
 36  *
 37  * @param {String}		id			the unique ID for this account
 38  * @param {String}		name		the email address
 39  * @param {Boolean}		visible		if <code>true</code>, make this account available in the overview (i.e. child accounts)
 40  *
 41  * @extends	ZmAccount
 42  */
 43 ZmZimbraAccount = function(id, name, visible) {
 44 
 45 	ZmAccount.call(this, null, id, name);
 46 
 47 	this.visible = (visible !== false);
 48 	/**
 49 	 * The account settings.
 50 	 * @type	ZmSettings
 51 	 */
 52 	this.settings = null;
 53 	this.trees = {};
 54 	this.loaded = false;
 55 	/**
 56 	 * The account Access Control List.
 57 	 * @type	ZmAccessControlList
 58 	 */
 59 	this.acl = new ZmAccessControlList();
 60 	this.metaData = new ZmMetaData(this);
 61 };
 62 
 63 ZmZimbraAccount.prototype = new ZmAccount;
 64 ZmZimbraAccount.prototype.constructor = ZmZimbraAccount;
 65 
 66 ZmZimbraAccount.prototype.isZmZimbraAccount = true;
 67 ZmZimbraAccount.prototype.toString = function() { return "ZmZimbraAccount"; };
 68 
 69 
 70 //
 71 // Constants
 72 //
 73 
 74 /**
 75  * Defines the "unknown" status.
 76  */
 77 ZmZimbraAccount.STATUS_UNKNOWN	= "unknown";
 78 /**
 79  * Defines the "offline" status.
 80  */
 81 ZmZimbraAccount.STATUS_OFFLINE	= "offline";
 82 /**
 83  * Defines the "online" status.
 84  */
 85 ZmZimbraAccount.STATUS_ONLINE	= "online";
 86 /**
 87  * Defines the "running" status.
 88  */
 89 ZmZimbraAccount.STATUS_RUNNING	= "running";
 90 /**
 91  * Defines the "authentication fail" status.
 92  */
 93 ZmZimbraAccount.STATUS_AUTHFAIL	= "authfail";
 94 /**
 95  * Defines the "error" status.
 96  */
 97 ZmZimbraAccount.STATUS_ERROR	= "error";
 98 
 99 //
100 // Public methods
101 //
102 
103 /**
104  * Sets the name of the account.
105  * 
106  * @param		{String}	name	the account name
107  */
108 ZmZimbraAccount.prototype.setName =
109 function(name) {
110 	var identity = this.getIdentity();
111 	// TODO: If no identity and name is set, should create one!
112 	if (!identity) return;
113 	identity.name = name;
114 };
115 
116 /**
117  * Gets the name of the account.
118  * 
119  * @return		{String}		the account name
120  */
121 ZmZimbraAccount.prototype.getName =
122 function() {
123 	var identity = this.getIdentity();
124 	var name = (!identity)
125 		? this.settings.get(ZmSetting.DISPLAY_NAME)
126 		: identity.name;
127 
128 	if (!name) {
129 		name = this.getDisplayName();
130 	}
131 	return identity.isDefault && name == ZmIdentity.DEFAULT_NAME ? ZmMsg.accountDefault : name;
132 };
133 
134 /**
135  * Sets the email address for this account. This method does nothing. The email address is set
136  * when the object is created.
137  * 
138  * @param	{String}	email 	the email address (ignored)
139  */
140 ZmZimbraAccount.prototype.setEmail =
141 function(email) {}; // IGNORE
142 
143 /**
144  * Gets the email address for this account.
145  * 
146  * @return	{String}	the email address
147  */
148 ZmZimbraAccount.prototype.getEmail =
149 function() {
150 	return this.name;
151 };
152 
153 /**
154  * Gets the display name.
155  * 
156  * @return	{String}	the display name
157  */
158 ZmZimbraAccount.prototype.getDisplayName =
159 function() {
160 	if (!this.displayName) {
161 		var dispName = this.isMain
162 			? this.settings.get(ZmSetting.DISPLAY_NAME)
163 			: this._displayName;
164 		this.displayName = (this._accountName || dispName || this.name);
165 	}
166 	return this.displayName;
167 };
168 
169 /**
170  * Gets the identity.
171  * 
172  * @return	{ZmIdentity}	the identity
173  */
174 ZmZimbraAccount.prototype.getIdentity =
175 function() {
176 	var defaultIdentity = appCtxt.getIdentityCollection(this).defaultIdentity;
177 	if (!appCtxt.isFamilyMbox || this.isMain) {
178 		return defaultIdentity;
179 	}
180 
181 	// for family mbox, create dummy identities for child accounts
182 	if (!this.dummyIdentity) {
183 		this.dummyIdentity = new ZmIdentity(this.name);
184 		AjxUtil.hashUpdate(this.dummyIdentity, defaultIdentity, true, ["name","isDefault"]);
185 	}
186 	return this.dummyIdentity;
187 };
188 
189 /**
190  * Gets the tool tip.
191  * 
192  * @return	{String}		the tool tip
193  */
194 ZmZimbraAccount.prototype.getToolTip =
195 function() {
196 	if (this.status || this.lastSync || this.isMain) {
197 		var lastSyncDate = (this.lastSync && this.lastSync != 0)
198 			? (new Date(parseInt(this.lastSync))) : null;
199 
200 		var quota = appCtxt.get(ZmSetting.QUOTA_USED, null, this);
201 		var lastSync;
202 		if (!lastSyncDate) {
203 			// this means, we've synced but server lost the last sync timestamp
204 			if (quota > 0 && !this.isMain) {
205 				lastSync = ZmMsg.unknown;
206 			}
207 		} else {
208 			lastSync = AjxDateUtil.computeWordyDateStr(new Date(), lastSyncDate);
209 		}
210 
211 		var params = {
212 			lastSync: lastSync,
213 			hasNotSynced: this.hasNotSynced(),
214 			status: this.getStatusMessage(),
215 			quota: AjxUtil.formatSize(quota, false, 1)
216 		};
217 
218 		return AjxTemplate.expand("share.App#ZimbraAccountTooltip", params);
219 	}
220 	return "";
221 };
222 
223 /**
224  * Gets the default color.
225  * 
226  * @return	{String}		the default color
227  * @see		ZmOrganizer
228  */
229 ZmZimbraAccount.prototype.getDefaultColor =
230 function() {
231 	if (this.isMain) {
232 		return ZmOrganizer.C_GRAY;
233 	}
234 
235 	switch (this.type) {
236 		case ZmAccount.TYPE_GMAIL:		return ZmOrganizer.C_RED;
237 		case ZmAccount.TYPE_MSE:		return ZmOrganizer.C_GREEN;
238 		case ZmAccount.TYPE_EXCHANGE:	return ZmOrganizer.C_GREEN;
239 		case ZmAccount.TYPE_YMP:		return ZmOrganizer.C_PURPLE;
240 	}
241 
242 	return null;
243 };
244 
245 /**
246  * Checks if the account has sync'd.
247  * 
248  * @return	{Boolean}	if <code>true</code>, this account has never been sync'd
249  */
250 ZmZimbraAccount.prototype.hasNotSynced =
251 function() {
252 	return (this.isOfflineInitialSync() && 
253 			this.status == ZmZimbraAccount.STATUS_UNKNOWN &&
254 			appCtxt.get(ZmSetting.QUOTA_USED, null, this) == 0);
255 };
256 
257 /**
258  * Check is this account is currently sync'ing for the first time.
259  * 
260  * @return	{Boolean}	if <code>true</code>, this account is currently sync'ing for the first time
261  */
262 ZmZimbraAccount.prototype.isOfflineInitialSync =
263 function() {
264 	return (appCtxt.isOffline && (!this.lastSync || (this.lastSync && this.lastSync == 0)));
265 };
266 
267 /**
268  * Checks if this account is CalDAV based.
269  * 
270  * @return	{Boolean}	if <code>true</code>, account is CalDAV based
271  */
272 ZmZimbraAccount.prototype.isCalDavBased =
273 function() {
274 	return (this.type == ZmAccount.TYPE_GMAIL ||
275 			this.type == ZmAccount.TYPE_YMP);
276 };
277 
278 /**
279  * Gets the default calendar. For CalDAV based accounts, the default calendar is hidden;
280  * therefore, this method returns the first non-default calendar.
281  * 
282  * @return	{Object}		the calendar
283  * @see		ZmZimbraAccount.isCalDavBased
284  */
285 ZmZimbraAccount.prototype.getDefaultCalendar =
286 function() {
287 	var tree = appCtxt.getFolderTree(this);
288 	if (this.isCalDavBased()) {
289 		var calendars = tree.getByType(ZmOrganizer.CALENDAR);
290 		for (var i = 0; i < calendars.length; i++) {
291 			if (calendars[i].nId == ZmOrganizer.ID_CALENDAR) { continue; }
292 			return calendars[i];
293 		}
294 	}
295 	return tree.getById(ZmOrganizer.ID_CALENDAR);
296 };
297 
298 /**
299  * Updates the account status.
300  * 
301  * @private
302  */
303 ZmZimbraAccount.prototype.updateState =
304 function(acctInfo) {
305 	if (this.isMain) { return; } // main account doesn't sync
306 
307 	// update last sync timestamp
308 	var updateTooltip = false;
309 	if (this.lastSync != acctInfo.lastsync) {
310 		this.lastSync = acctInfo.lastsync;
311 		if (this.visible) {
312 			updateTooltip = true;
313 		}
314 	}
315 
316 	// set to update account (offline) status if changed
317 	var updateStatus = false;
318 	if (this.status != acctInfo.status) {
319 		this.status = acctInfo.status;
320 		if (this.visible) {
321 			updateStatus = true;
322 		}
323 	}
324 
325 	// for all overview containers, update status/tooltip
326 	var container = appCtxt.getOverviewController()._overviewContainer;
327 	for (var i in container) {
328 		var c = container[i];
329 		if (updateStatus || updateTooltip) {
330 			c.updateAccountInfo(this, updateStatus, updateTooltip);
331 		}
332 	}
333 
334 	if (this.visible && acctInfo.unread != this.unread) {
335 		this.unread = acctInfo.unread;
336 	}
337 
338 	this.code = acctInfo.code;
339 	if (acctInfo.error) {
340 		var error = acctInfo.error[0];
341 		this.errorDetail = error.exception[0]._content;
342 		this.errorMessage = error.message;
343 	}
344 };
345 
346 /**
347  * Gets the status icon.
348  * 
349  * @return	{String}	the status icon
350  */
351 ZmZimbraAccount.prototype.getStatusIcon =
352 function() {
353 	if (this.inNewMailMode) {
354 		return "NewMailAlert";
355 	}
356 
357 	switch (this.status) {
358 //		case ZmZimbraAccount.STATUS_UNKNOWN:	return "Offline"; 				// bug: 42403 - remove
359 		case ZmZimbraAccount.STATUS_OFFLINE:	return "ImAway";
360 //		case ZmZimbraAccount.STATUS_ONLINE:		return "";						// no icon for "online"
361 //		case ZmZimbraAccount.STATUS_RUNNING:	// animated, so cannot be set using AjxImg
362 		case ZmZimbraAccount.STATUS_AUTHFAIL:	return "ImDnd";
363 		case ZmZimbraAccount.STATUS_ERROR:		return "Critical";
364 	}
365 	return null;
366 };
367 
368 /**
369  * Checks if this account is in error status.
370  * 
371  * @return	{Boolean}	if <code>true</code>, the account is in error status
372  */
373 ZmZimbraAccount.prototype.isError =
374 function() {
375 	return (this.status == ZmZimbraAccount.STATUS_AUTHFAIL ||
376 			this.status == ZmZimbraAccount.STATUS_ERROR);
377 };
378 
379 /**
380  * Gets the icon.
381  * 
382  * @return	{String}	the icon
383  */
384 ZmZimbraAccount.prototype.getIcon =
385 function() {
386 	return (this.isMain && appCtxt.isOffline) ? "LocalFolders" : this.icon;
387 };
388 
389 /**
390  * Gets the Zd message.
391  * 
392  * @private
393  */
394 ZmZimbraAccount.prototype.getZdMsg =
395 function(code) {
396 	var msg = ((ZdMsg["client." + code]) || (ZdMsg["exception." + code]));
397 	if (!msg && code) {
398 		msg = ZdMsg["exception.offline.UNEXPECTED"];
399 	}
400 	return msg;
401 };
402 
403 /**
404  * Gets the status message.
405  * 
406  * @return	{String}		the status message
407  */
408 ZmZimbraAccount.prototype.getStatusMessage =
409 function() {
410 	if (this.inNewMailMode) {
411 		return AjxMessageFormat.format(ZmMsg.unreadCount, this.unread);
412 	}
413 
414 	switch (this.status) {
415 //		case ZmZimbraAccount.STATUS_UNKNOWN:	return ZmMsg.unknown;
416 		case ZmZimbraAccount.STATUS_OFFLINE:	return ZmMsg.netStatusOffline;
417 		case ZmZimbraAccount.STATUS_ONLINE:		return ZmMsg.netStatusOnline;
418 		case ZmZimbraAccount.STATUS_RUNNING:	return ZmMsg.running;
419 		case ZmZimbraAccount.STATUS_AUTHFAIL:	return this.code ? this.getZdMsg(this.code) : AjxMessageFormat.format(ZmMsg.authFailure, this.getEmail());
420 		case ZmZimbraAccount.STATUS_ERROR:		return this.code ? this.getZdMsg(this.code) : ZmMsg.error;
421 	}
422 	return "";
423 };
424 
425 /**
426  * Shows an error message.
427  * 
428  * Offline use only.
429  * 
430  * @private
431  */
432 ZmZimbraAccount.prototype.showErrorMessage =
433 function() {
434 	if (!this.isError()) { return; }
435 
436 	var dialog = (this.status == ZmZimbraAccount.STATUS_ERROR)
437 		? appCtxt.getErrorDialog() : appCtxt.getMsgDialog();
438 
439 	// short message
440 	var msg = this.getZdMsg(this.code);
441 	if (msg == "") {
442 		msg = this.getStatusMessage();
443 	}
444 	dialog.setMessage(msg);
445 
446 	if (this.status == ZmZimbraAccount.STATUS_ERROR) {
447 		// detailed message
448 		var html = [];
449 		var i = 0;
450 		if (this.errorMessage) {
451 			html[i++] = "<p><b>";
452 			html[i++] = ZdMsg.DebugMsg;
453 			html[i++] = "</b>: ";
454 			html[i++] = this.errorMessage;
455 			html[i++] = "</p>";
456 		}
457 
458 		if (this.errorDetail) {
459 			html[i++] = "<p><b>";
460 			html[i++] = ZdMsg.DebugStack;
461 			html[i++] = "</b>:</p><p><pre>";
462 			html[i++] = this.errorDetail;
463 			html[i++] = "</pre></p>";
464 		}
465 
466 		html[i++] = "<p><b>";
467 		html[i++] = ZdMsg.DebugActionNote;
468 		html[i++] = "</b></p>";
469 
470 		dialog.setDetailString(html.join(""));
471 	}
472 
473 	dialog.popup(null, true);
474 };
475 
476 /**
477  * @private
478  */
479 ZmZimbraAccount.createFromDom =
480 function(node) {
481 	var acct = new ZmZimbraAccount();
482 	acct._loadFromDom(node);
483 	return acct;
484 };
485 
486 /**
487  * Loads the account.
488  * 
489  * @param	{AjxCallback}	callback		the callback
490  */
491 ZmZimbraAccount.prototype.load =
492 function(callback) {
493 	if (!this.loaded) {
494 		// create new ZmSetting for this account
495 		this.settings = new ZmSettings();
496 
497 		// check "{APP}_ENABLED" state against main account's settings
498 		var mainAcct = appCtxt.accountList.mainAccount;
499 
500 		// for all *loaded* apps, add their app-specific settings
501 		for (var i = 0; i < ZmApp.APPS.length; i++) {
502 			var appName = ZmApp.APPS[i];
503 			var setting = ZmApp.SETTING[appName];
504 			if (setting && appCtxt.get(setting, null, mainAcct)) {
505 				var app = appCtxt.getApp(appName);
506 				if (app) {
507 					app._registerSettings(this.settings);
508 				}
509 			}
510 		}
511 
512 		var command = new ZmBatchCommand(null, this.name);
513 
514 		// load user settings retrieved from server now
515 		var loadCallback = new AjxCallback(this, this._handleLoadSettings);
516 		this.settings.loadUserSettings(loadCallback, null, this.name, null, command);
517 
518 		// get tag info for this account *FIRST* - otherwise, root ID get overridden
519 		var tagDoc = AjxSoapDoc.create("GetTagRequest", "urn:zimbraMail");
520 		var tagCallback = new AjxCallback(this, this._handleLoadTags);
521 		command.addNewRequestParams(tagDoc, tagCallback);
522 
523 		// get meta data for this account
524 		this.loadMetaData(null, command);
525 
526 		// get folder info for this account
527 		var folderDoc = AjxSoapDoc.create("GetFolderRequest", "urn:zimbraMail");
528 		folderDoc.getMethod().setAttribute("visible", "1");
529 		var folderCallback = new AjxCallback(this, this._handleLoadFolders);
530 		command.addNewRequestParams(folderDoc, folderCallback);
531 
532 		var respCallback = new AjxCallback(this, this._handleLoadUserInfo, callback);
533 		var errCallback = new AjxCallback(this, this._handleErrorLoad, callback);
534 		command.run(respCallback, errCallback);
535 	}
536 	else if (callback) {
537 		callback.run();
538 	}
539 };
540 
541 ZmZimbraAccount.prototype.loadMetaData =
542 function(callback, batchCommand) {
543 	var metaDataCallback = new AjxCallback(this, this._handleLoadMetaData, [callback]);
544 	var sections = [ZmSetting.M_IMPLICIT, ZmSetting.M_OFFLINE];
545 	this.metaData.load(sections, metaDataCallback, batchCommand);
546 };
547 
548 /**
549  * Unloads the account and removes any account-specific data stored globally.
550  * 
551  */
552 ZmZimbraAccount.prototype.unload =
553 function() {
554 	if (!appCtxt.inStartup) {
555 		// unset account-specific shortcuts
556 		this.settings.loadShortcuts(true);
557 	}
558 };
559 
560 /**
561  * Sync the account.
562  * 
563  * @param	{AjxCallback}	callback		the callback
564  */
565 ZmZimbraAccount.prototype.sync =
566 function(callback) {
567 	var soapDoc = AjxSoapDoc.create("SyncRequest", "urn:zimbraOffline");
568 	if (appCtxt.get(ZmSetting.OFFLINE_DEBUG_TRACE)) {
569 		var method = soapDoc.getMethod();
570 		method.setAttribute("debug", 1);
571 	}
572 	appCtxt.getAppController().sendRequest({
573 		soapDoc:soapDoc,
574 		asyncMode:true,
575 		noBusyOverlay:true,
576 		callback:callback,
577 		accountName:this.name
578 	});
579 };
580 
581 /**
582  * Saves the account.
583  * 
584  * @param	{AjxCallback}	callback		the callback
585  * @param	{AjxCallback}	errorCallback		the error callback
586  * @param	{Object}	batchCmd		the batch command
587  */
588 ZmZimbraAccount.prototype.save =
589 function(callback, errorCallback, batchCmd) {
590 	return (this.getIdentity().save(callback, errorCallback, batchCmd));
591 };
592 
593 /**
594  * Saves implicit prefs. Because it's done onunload, the save is sync.
595  * 
596  * @private
597  */
598 ZmZimbraAccount.prototype.saveImplicitPrefs =
599 function() {
600     var isExternal = this.settings ? this.settings.get(ZmSetting.IS_EXTERNAL) : false;
601     if (isExternal) {
602         return;
603     }
604 	var list = [];
605 	for (var id in ZmSetting.CHANGED_IMPLICIT) {
606 		var setting = this.settings ? this.settings.getSetting(id) : null;
607 		if (ZmSetting.IS_GLOBAL[setting.id] && !this.isMain) { continue; }
608 		if (setting && (setting.getValue(null, true) != setting.getOrigValue(null, true))) {
609 			list.push(setting);
610 		}
611 	}
612 
613 	if (list.length > 0) {
614 		this.settings.save(list, null, null, this);
615 	}
616 };
617 
618 /**
619  * Checks if this account supports the given application name
620  *
621  * @param {String}		appName		the name of the application
622  * @return	{Boolean}	<code>true</code> if account supports the application
623  */
624 ZmZimbraAccount.prototype.isAppEnabled =
625 function(appName) {
626 	switch (appName) {
627 		case ZmApp.BRIEFCASE: 	return appCtxt.get(ZmSetting.BRIEFCASE_ENABLED, null, this);
628 		case ZmApp.CALENDAR:	return appCtxt.get(ZmSetting.CALENDAR_ENABLED, 	null, this);
629 		case ZmApp.CONTACTS:	return appCtxt.get(ZmSetting.CONTACTS_ENABLED, 	null, this);
630 		case ZmApp.MAIL:		return appCtxt.get(ZmSetting.MAIL_ENABLED, 		null, this);
631 		case ZmApp.PREFERENCES:	return appCtxt.get(ZmSetting.OPTIONS_ENABLED, 	null, this);
632 		case ZmApp.TASKS:		return appCtxt.get(ZmSetting.TASKS_ENABLED, 	null, this);
633 	}
634 	return false;
635 };
636 
637 
638 //
639 // Protected methods
640 //
641 
642 /**
643  * @private
644  */
645 ZmZimbraAccount.prototype._handleLoadSettings =
646 function(result) {
647 	DBG.println(AjxDebug.DBG1, "Account settings successfully loaded for " + this.name);
648 
649 	// set account type
650 	this.type = appCtxt.isOffline
651 		? appCtxt.get(ZmSetting.OFFLINE_ACCOUNT_FLAVOR, null, this)
652 		: ZmAccount.TYPE_ZIMBRA;
653 
654 	this.isZimbraAccount = this.type == ZmAccount.TYPE_ZIMBRA;
655 
656 	// set icon now that we know the type
657 	switch (this.type) {
658 		case ZmAccount.TYPE_AOL:		this.icon = "AccountAOL"; break;
659 		case ZmAccount.TYPE_GMAIL:		this.icon = "AccountGmail"; break;
660 		case ZmAccount.TYPE_IMAP:		this.icon = "AccountIMAP"; break;
661 		case ZmAccount.TYPE_LIVE:		this.icon = "AccountMSN"; break;
662 		case ZmAccount.TYPE_MSE:		this.icon = "AccountExchange"; break;
663 		case ZmAccount.TYPE_EXCHANGE:	this.icon = "AccountExchange"; break;
664 		case ZmAccount.TYPE_POP:		this.icon = "AccountPOP"; break;
665 		case ZmAccount.TYPE_YMP:		this.icon = "AccountYahoo"; break;
666 		case ZmAccount.TYPE_ZIMBRA:		this.icon = "AccountZimbra"; break;
667 	}
668 
669 	// initialize identities/data-sources/signatures for this account
670 	var obj = result.getResponse().GetInfoResponse;
671 	appCtxt.getIdentityCollection(this).initialize(obj.identities);
672 	appCtxt.getDataSourceCollection(this).initialize(obj.dataSources);
673 	appCtxt.getSignatureCollection(this).initialize(obj.signatures);
674 
675 };
676 
677 /**
678  * @private
679  */
680 ZmZimbraAccount.prototype._handleLoadFolders =
681 function(result) {
682 	var resp = result.getResponse().GetFolderResponse;
683 	var folders = resp ? resp.folder[0] : null;
684 	if (folders) {
685 		appCtxt.getRequestMgr()._loadTree(ZmOrganizer.FOLDER, null, resp.folder[0], "folder", this);
686 	}
687 };
688 
689 /**
690  * @private
691  */
692 ZmZimbraAccount.prototype._handleLoadTags =
693 function(result) {
694 	var resp = result.getResponse().GetTagResponse;
695 	appCtxt.getRequestMgr()._loadTree(ZmOrganizer.TAG, null, resp, null, this);
696 };
697 
698 /**
699  * @private
700  */
701 ZmZimbraAccount.prototype._handleLoadUserInfo =
702 function(callback) {
703 	this.loaded = true;
704 
705 	// bug fix #33168 - get perms for all mountpoints in account
706 	var folderTree = appCtxt.getFolderTree(this);
707 	if (folderTree) {
708 		folderTree.getPermissions({noBusyOverlay:true, accountName:this.name});
709 	}
710 
711 	if (callback) {
712 		callback.run();
713 	}
714 };
715 
716 /**
717  * @private
718  */
719 ZmZimbraAccount.prototype._handleLoadMetaData =
720 function(callback, sections) {
721 	for (var i in sections) {
722 		this.settings.createFromJs(sections[i]);
723 	}
724 
725 	if (callback) {
726 		callback.run();
727 	}
728 };
729 
730 /**
731  * @private
732  */
733 ZmZimbraAccount.prototype._handleErrorLoad =
734 function(callback, ev) {
735 	DBG.println(AjxDebug.DBG1, "------- ERROR loading account settings for " + this.name);
736 	if (callback) {
737 		callback.run();
738 	}
739 };
740 
741 /**
742  * @private
743  */
744 ZmZimbraAccount.prototype._loadFromDom =
745 function(node) {
746 	this.id = node.id;
747 	this.name = node.name;
748 	this.visible = node.visible;
749 	this.active = node.active;
750 
751 	var data = node.attrs && node.attrs._attrs;
752 	this._displayName = data ? data.displayName : this.email;
753 	this._accountName = data && data.zimbraPrefLabel;
754 };
755