1           /**
  2                 @name ConnectionManager
  3                 @class  This class allows handles authentication, connections & notifications between client and server
  4 
  5                 */
  6           /**
  7            * IMPORTANT NOTE ON LOGIN APIs:
  8            *
  9            * A client can be initiated with URL parameters to login (especially when client clones at endpoint
 10            * servers are called after login). So, all clients should first check using
 11            *		var loginIsSuccessful = ConnectionManager.autoLogin();
 12            * before calling ConnectionManager.locateAndLogin();
 13            **/
 14           /**
 15            * Events Dispatched:
 16            *
 17            *	LOADING_CLONE		data: nil
 18            *	LOGIN_SUCCESS		data: nil
 19            *	LOGIN_FAILED		data: {errorType: "HTTP"/"ZEBRA", errorCode, errorMessage}
 20            *	CONNECTION_LOST		data: reason
 21            *	CONNECTION_MADE		data: nil
 22            *	LOGGED_OUT			data: reason
 23            *	ZS_STATE_CHANGED	data: {oldState, state}
 24            *	ZEBRA_ALL			data: zebra
 25            *	ZEBRA(zebraName)	data: zebra. Same as ZEBRA:zebraName Event, e.g. ZEBRA(CONTACTS_UPDATE) = ZEBRA:CONTACTS_UPDATE.
 26            **/
 27           ConnectionManager = EventDispatcher.extendAsSingleton({
 28               build_version: "@BUILD_VERSION@",
 29               build_minor_version: "@BUILD_MINOR_VERSION@",
 30               build_major_version: "@BUILD_MAJOR_VERSION@",
 31               /**
 32                * Configurable Properties
 33                *
 34                * These can be overrided at anytime by setting value as ConnectionManager.<property> = <value>.
 35                **/
 36               LOAD_CLONE_CLIENT_IN_ENDPOINT: true,
 37               AUTOLOGIN_ON_NSDISCONNECT_EXPIRE: false,
 38               POLL_ACTUAL_ENDPOINT: false,
 39               ZEBRA_FMT: "2.0",
 40               service: "saypage",
 41               partner: "home",
 42               CLS: document.location.href.split("/").slice(0, 3).join("/"),
 43               zsPollIsScheduled: false,
 44               stopZSPoll: true,
 45               Brora: "/servlet/com.requestec.smg.servlets.Brora",
 46               ZebraGateway: "/servlet/com.requestec.smg.servlets.ZebraGateway",
 47               ZSServlet: "/zmobile3",
 48               isDisConnected: false,
 49               /**
 50                * Events
 51                **/
 52               Event: {
 53                   LOADING_CLONE: "LOADING_CLONE", //data: nil
 54                   /**
 55                         @name ConnectionManager#Event_LOGIN_SUCCESS
 56                         @description Event fired on login succes
 57                         @type object
 58                   */
 59 
 60                   LOGIN_SUCCESS: "LOGIN_SUCCESS", //data: nil
 61 
 62                   /**
 63                         @name ConnectionManager#Event_LOGIN_FAILED
 64                         @description Event fired on login failed
 65                         @type object
 66                   */
 67                   LOGIN_FAILED: "LOGIN_FAILED", //data: {reason}
 68                   CONNECTION_LOST: "CONNECTION_LOST", //data: reason
 69                   CONNECTION_MADE: "CONNECTION_MADE", //data: nil
 70                   LOGGED_OUT: "LOGGED_OUT", //data: reason
 71                   ZS_STATE_CHANGED: "ZS_STATE_CHANGED", //data: {oldState, state}
 72                   ZS_STATE_UPDATE: "ZS_STATE_UPDATE", //data: { state}
 73                   ZEBRA_ALL: "ZEBRA_ALL", //data: zebra
 74                   ZEBRA: function(zebraEvent) {
 75                       return "ZEBRA:" + zebraEvent;
 76                   } //data: zebra
 77               },
 78               /**
 79                * Constructor
 80                **/
 81               init: function() {
 82                   if (typeof service != "undefined") this.service = service;
 83                   if (typeof partner != "undefined") this.partner = partner;
 84                   this._super();
 85                   //public APIs to add/remove listeners
 86                   this.addListener = this._addListener;
 87                   this.removeListener = this._removeListener;
 88                   this.removeAllListenersForEvent = this._removeAllListenersForEvent;
 89                   this.addListener('LOGIN_SUCCESS', "CONNECTION_MANAGER", function(event) {
 90                       var offset_secs = DataStore.getUserData("epoch_time", "-1"); //(zebra.getZEvent("epoch_time"))? zebra.getZEvent("epoch_time").value: -1;
 91                       if (offset_secs != "-1" && DateTimeUtil) //ofset exist
 92                           DateTimeUtil.setEpochOffset(offset_secs);
 93                   }, true);
 94                   // add listener for avatar update to update datastore.
 95                   this.addListener('ZEBRA:AVATAR_UPDATE', "CONNECTION_MANAGER",
 96                       function(zebra) {
 97                           var avatar_id = zebra.getZEvent('avatar_id').value;
 98                           var vid = DataStore.getUserData("vid");
 99                           DataStore.setUserData('avatar_id', avatar_id);
100                           if (!avatar_id || avatar_id == "" || avatar_id.indexOf('empty') > -1) avatar_id = 'profile_empty';
101                           var avatarurl = "";
102                           if (Platform.spm || Platform.isSayPageApp)
103                               avatarurl = ConnectionManager.getBasePictureURL() + "&pic=1" + "&vid=" + vid + "&avatar_id=" + vid + "_" + avatar_id;
104                           else
105                               avatarurl = ConnectionManager.getBasePictureURL() + "&email=" + DataStore.getUserData("email", "") + "&type=zen&avatar_id=" + vid + "_" + avatar_id;
106                           Platform.downloadURL("GET", avatarurl, function(uri, status, statusText) {
107                               if (uri != "") {
108                                   DataStore.setUserData("avatarurl", uri);
109                                   ConnectionManager._dispatchEvent("AVATAR_UPDATED", {
110                                       "vid": vid,
111                                       "avatar_id": avatar_id,
112                                       "avatarurl": uri
113                                   });
114                               }
115                           }, true);
116                       });
117                   /**
118                    * ZS State - state of the ZS connection. Can be:
119                    *	waiting			Online, and not in a call.
120                    *	busy			In a call.
121                    *	disconnected	Offline.
122                    **/
123                   this.zsState = "disconnected";
124               },
125  /**
126                         @name ConnectionManager#inCall
127                         @function
128                         @description
129                            Returns where user is currently in call or not
130                			@return {boolean} Whether in call or not.
131                 **/
132 
133               inCall: function() {
134                   var isFlashConnected = false;
135                   if (typeof getClientObj != "undefined" && typeof getClientObj == "function" && getClientObj() && getClientObj().getState && getClientObj().getState() == "connected")
136                       isFlashConnected = true;
137                   //return ((Platform.isSayPageApp && MyLiveModel.items.length >0) ||(Platform.spm && ConnectionManager.zsState=="busy"));
138                   return ((Platform.isSayPageApp && ((typeof MyLiveModel!="undefined" && MyLiveModel.items.length > 0) || isFlashConnected)) || (ConnectionManager.zsState == "busy"));
139               },
140               getPartnerLogo: function(partner_) {
141                   return (unescape(this.CLS || "") + "/servlet/com.requestec.smg.servlets.Avatar?command=get_partner_logo&service=" + this.service + "&partner=" + partner_);
142               },
143               /** create baseURL for all avatars */
144               getBasePictureURL: function() {
145                   if (Platform.spm || Platform.isSayPageApp || Platform.mobileWeb)
146                       return (unescape(this.CLS || "") + "/servlet/com.requestec.smg.servlets.Avatar?command=get_picture&service=" + this.service + "&partner=" + this.partner + "&height=" + (Platform.isSayPageApp || Platform.getScreenWidth() > 600 ? 240 : 120) + "&width=" + (Platform.isSayPageApp || Platform.getScreenWidth() > 600 ? 320 : 160) + "&cropToFit=true");
147                   else
148                       return (unescape(this.CLS || "") + "/servlet/com.requestec.smg.servlets.Avatar?command=getAvatar&format=jpg&service=" + this.service + "&username=" + DataStore.getUserData("username", "") + "&height=" + (Platform.isSayPageApp || Platform.getScreenWidth() > 600 ? 240 : 120) + "&width=" + (Platform.isSayPageApp || Platform.getScreenWidth() > 600 ? 320 : 160) + "&cropToFit=true");
149               },
150               //single method to return avatar url for a vid from Contact/AgentsModel/DataStore
151               getAvatarUrlByVid: function(vid) {
152                   var owner = false;
153                   if (DataStore.getUserData('vid') == vid) owner = true;
154                   var url;
155                   if (!owner) {
156                       var agent = (AgentsModel) ? AgentsModel.getAgent(vid) : null;
157                       if (!agent) agent = (ContactModel) ? ContactModel.getContactByVid(vid) : null;
158                       if (agent) url = agent.avatarurl;
159                       else url = ConnectionManager.getBasePictureURL() + "&pic=1&vid=" + vid;
160                   } else
161                       url = DataStore.getUserData("avatarurl");
162                   return url;
163               },
164               /**
165                * Whether the client polling has started
166                *
167                **/
168               isPolling: function() {
169                   return !this.stopZSPoll;
170               },
171               /**
172                * Whether the client is successfully logged in or not.
173                *
174                * This remains "true" after LOGIN_SUCCESS event has been dispatched, even if the client is offline.
175                **/
176               isLoggedIn: function() {
177                   return (DataStore.getUserData("username", "") != "" && DataStore.getUserData("device_id", "") != "");
178               },
179               /**
180                * Whether the client is connected to ZS or not.
181                *
182                * This remains "true" after CONNECTION_MADE event has been dispatched, until CONNECTION_LOST is dispatched.
183                **/
184               isConnectedToZS: function() {
185                   return ConnectionManager.zsState != "disconnected";
186               },
187               /**
188                * To register a new user.
189                **/
190               register: function(loginid, password, screenName, optionalParams) {
191                   var zebra = new Zebra("com.requestec.smg.zebra.Gateway#register")
192                       .setZEvent("login_id", loginid)
193                       .setZEvent("password", password)
194                       .setZEvent("screenName", screenName && screenName != "" ? screenName : loginid)
195                       .setZEvent("zebra_format", ConnectionManager.ZEBRA_FMT);
196                   //send an async HTTP POST Request
197                   Platform.httpRequest(
198                       "POST", (ConnectionManager.CLS || "") + (ConnectionManager.ZebraGateway || ""),
199                       ConnectionManager._loginHandler,
200                       "message=" + escape(zebra.toXML())
201                   );
202               },
203               /**
204                * Locate and Login.
205                *
206                * A client can be initiated with URL parameters to login (especially when client clones at endpoint
207                * servers are called after login). So, all clients should first check using
208                *		var loginIsSuccessful = ConnectionManager.autoLogin();
209                * before calling ConnectionManager.locateAndLogin();
210                **/
211 
212 
213                         /**
214                         @name ConnectionManager#locateAndLogin
215                         @function
216                         @description
217                         @param {String} loginid
218                         @param {String} password
219                         @param {String} optionalParams
220                         @param {String} validSession
221                         @param {String} silentPair
222                         */
223 
224               locateAndLogin: function(loginid, password, optionalParams, validSession, silentPair) {
225                   //persist the last loginid
226                   // check we are trying to login with last sucessful login id otherwice clear all cached data
227                   if ((!loginid || loginid == "") || DataStore.getCommonData("last_loginid") != loginid) {
228                       Platform.log(" CM locateAndLogin " + DataStore.getCommonData("last_loginid") + " " + loginid + " CLEAR STORES ");
229                       DataStore.clearCommonDataStore();
230                       DataStore.clearUserDataStore();
231                   }
232                   DataStore.setCommonData("last_loginid", loginid, true);
233                   DataStore.setCommonData("password", password, true);
234                   var login = function() {
235                       if (validSession) DataStore.setUserData("username", validSession, true);
236                       var loginZebra = new Zebra("com.requestec.smg.zebra.Gateway#login");
237                       loginZebra.setZebraAttribute("partner", ConnectionManager.partner);
238                       if (silentPair) loginZebra.setZEvent("silentPair", silentPair);
239                       loginZebra.setZEvent("login_id", loginid);
240                       loginZebra.setZEvent("offset_mins", DateTimeUtil.getLocalTimeZoneOffsetMinutes());
241                       loginZebra.setZEvent("tz_name", DateTimeUtil.getLocalTimeZoneDisplayString());
242                       loginZebra.setZEvent("password", password);
243                       loginZebra.setZEvent("zebra_format", ConnectionManager.ZEBRA_FMT);
244                       //if(validSession) loginZebra.setZEvent("zebra_format", "2.0");
245                       //send an async HTTP POST Request
246                       Platform.httpRequest(
247                           "POST", (ConnectionManager.CLS || "") + (ConnectionManager.ZebraGateway || ""),
248                           ConnectionManager._loginHandler,
249                           "message=" + escape(loginZebra.toXML())
250                       );
251                   };
252                   login();
253                   // no need for LMS locate
254                   /*
255 		var locateZebra = new Zebra("com.requestec.smg.zebra.Gateway#locate");
256 		locateZebra.setZEvent("reconnect", "false");
257 
258 		//send an async HTTP POST Request
259 		Platform.httpRequest(
260 			"POST",
261 			(ConnectionManager.CLS || "") + (ConnectionManager.ZebraGateway || ""),
262 			function(response, status, statusText) {
263 				if(status == 200) login();
264 				else ConnectionManager._dispatchEvent(ConnectionManager.Event.LOGIN_FAILED,
265 					{
266 						errorType: "HTTP",
267 						errorCode: status,
268 						errorMessage: statusText
269 					});
270 			},
271 			"message="+escape( locateZebra.toXML())
272 		);
273 */
274               },
275               /**
276                * To initiate login (dispatches LOGIN_SUCCESS event, and starts ZS Polling).
277                * Should be called after DataStore.loadedUserStore = true or DataStore.Event.LOADED_DATA_STORE
278                * event has been received.
279                * Returns true if login is successful and initiated, else false.
280                **/
281               autoLogin: function() {
282                   if (!this.isLoggedIn()) return false;
283                   this._dispatchEvent(this.Event.LOGIN_SUCCESS);
284                   DataStore.setUserData('time_format', '12');
285                   DataStore.setUserData('date_format', 'mm-dd-yyyy');
286                   // make username available to JSP
287                   var username = DataStore.getUserData("username", "");
288                   var cookieName = 'zjsdk.username.' + (ConnectionManager.service || "");
289                   this.eraseCookie(cookieName);
290                   this.createCookie(cookieName, username, 1);
291                   //start ZS poll
292                   this.stopZSPoll = false;
293                   this.zsPoll();
294                   return true;
295               },
296               /**
297                * To logout, and stop ZS polling.
298                **/
299               logout: function(reason) {
300                   //stop ZS poll
301                   this.stopZSPoll = true;
302                   //clear all user login related data
303                   DataStore.clearUserDataStore(function(error) {
304                       //set ZS state
305                       ConnectionManager._disconnectZSState(reason);
306                       //dispatch LOGGED_OUT event
307                       ConnectionManager._dispatchEvent(ConnectionManager.Event.LOGGED_OUT, reason);
308                   });
309               },
310               /**
311                * private method to handle login and registration response
312                **/
313               _loginHandler: function(response, status, statusText) {
314                   if (status == 200) {
315                       Platform.log("Zebra parsing start time -   " + new Date());
316                       var zebra = Zebra.parseFromString(response);
317                       Platform.log("Zebra parsing end time -   " + new Date());
318                       if (zebra && (zebra.getZebraAttribute("error_code") || "0") == "0") {
319                           var endpoint = zebra.getZEvent("endpoint").value;
320                           /**
321                            * Save response data in User Data Store, which may contain the following:
322                            *	avatar_id
323                            *	callToken
324                            *	country_code
325                            *	device_id
326                            *	dial_prefix
327                            *	download
328                            *	eas_port
329                            *	eas_url
330                            *	email
331                            *	endpoint
332                            *	error_message
333                            *	fipscode
334                            *  iitvusername
335                            *	macid
336                            *	openfire
337                            *	reg_status
338                            *	screen_name
339                            *	session_id
340                            *	serviceTitle
341                            *	upload
342                            *	username
343                            *	vid
344                            **/
345                           DataStore.setUserData('time_format', '12');
346                           DataStore.setUserData('date_format', 'mm-dd-yyyy');
347                           for (var key in zebra.zEvents) {
348                               if (key != "error_message") {
349                                   if (key == "endpoint") {
350                                       var endp = zebra.getZEventValue(key);
351                                       if (endp.indexOf(":") > -1)
352                                           endp = endp.substring(0, endp.indexOf(":"));
353                                       if (ConnectionManager.CLS.indexOf("https") > -1)
354                                           DataStore.setUserData(key, "https://" + endp, true);
355                                       else
356                                           DataStore.setUserData(key, "http://" + endp, true);
357                                   } else DataStore.setUserData(key, zebra.getZEventValue(key), true);
358                               }
359                           }
360                           var aurl = ConnectionManager.getBasePictureURL();
361                           if (Platform.spm || Platform.isSayPageApp || Platform.mobileWeb) {
362                               aurl += "&pic=1" + "&vid=" + DataStore.getUserData("vid") + "&avatar_id=" + DataStore.getUserData("vid") + "_" + DataStore.getUserData("avatar_id").replace("/", "_");
363                           } else {
364                               aurl += "&avatar_id=" + DataStore.getUserData("avatar_id", "").replace("/", "_") + "&type=zen";
365                           }
366                           if (DataStore.getUserData("avatar_id", "").indexOf("gallery_") > -1) {
367                               if (!parent.rootPath) parent.rootPath = "/";
368                               aurl = parent.rootPath + "assets/images/" + DataStore.getUserData("avatar_id", "") + ".jpg";
369                           }
370                           //store the user's own Avatar's URL
371                           DataStore.setUserData("avatarurl", aurl, true);
372                           // make username available to JSP
373                           var username = DataStore.getUserData("username", "");
374                           var cookieName = 'zjsdk.username.' + (ConnectionManager.service || "");
375                           ConnectionManager.eraseCookie(cookieName);
376                           ConnectionManager.createCookie(cookieName, username, 1);
377                           //if loading clone from endpoint is disabled, or if the endpoint is same, start polling in current page
378                           if (Platform.isSayPageApp || !ConnectionManager.LOAD_CLONE_CLIENT_IN_ENDPOINT || endpoint == ConnectionManager.CLS) {
379                               ConnectionManager.autoLogin();
380                           }
381                           //load the clone of this page from endpoint server, passing all User and Common Data as URL parameters
382                           else {
383                               //dispatch event before loading clone client from the endpoint
384                               ConnectionManager._dispatchEvent(ConnectionManager.Event.LOADING_CLONE);
385                               var params = [];
386                               //pass User Data
387                               for (var key in DataStore.userStoreCache)
388                                   params.push(key + "=" + escape(DataStore.userStoreCache[key]));
389                               //pass Common Data
390                               for (var key in DataStore.commonStoreCache)
391                                   params.push("common-" + key + "=" + escape(DataStore.commonStoreCache[key]));
392                               //load clone client
393                               document.location.href = "http://" + endpoint + "/" + document.location.href.split("?")[0].split("/").slice(3).join("/") + "?" + params.join("&");
394                           }
395                       } else if (zebra) {
396                           ConnectionManager._dispatchEvent(ConnectionManager.Event.LOGIN_FAILED, {
397                               errorType: "ZEBRA",
398                               errorCode: zebra.getZebraAttribute("error_code"),
399                               errorMessage: zebra.getZEventValue("error_message", "")
400                           });
401                       } else ConnectionManager._dispatchEvent(ConnectionManager.Event.LOGIN_FAILED, {
402                           errorType: "ZEBRA",
403                           errorCode: "",
404                           errorMessage: "No Zebra received in response!"
405                       });
406                   } else ConnectionManager._dispatchEvent(ConnectionManager.Event.LOGIN_FAILED, {
407                       errorType: "HTTP",
408                       errorCode: status,
409                       errorMessage: statusText
410                   });
411               },
412               /**
413                * private method to update ZS State
414                **/
415               _updateZSState: function(newState, disconnectReason) {
416                   ConnectionManager._dispatchEvent(ConnectionManager.Event.ZS_STATE_UPDATE, {
417                       state: newState
418                   });
419                   if (ConnectionManager.zsState == newState) {
420                       return;
421                   }
422                   var oldState = ConnectionManager.zsState;
423                   ConnectionManager.zsState = newState;
424                   if (newState == "disconnected")
425                       ConnectionManager.isDisconnected = true;
426                   else
427                       ConnectionManager.isDisconnected = false;
428                   //dispatch event
429                   ConnectionManager._dispatchEvent(ConnectionManager.Event.ZS_STATE_CHANGED, {
430                       oldState: oldState,
431                       state: newState
432                   });
433                   //dispatch CONNECTION_MADE or CONNECTION_LOST
434                   if (newState == "disconnected") {
435                       ConnectionManager._dispatchEvent(ConnectionManager.Event.CONNECTION_LOST, disconnectReason || "");
436                   } else if (oldState == "disconnected") {
437                       ConnectionManager._dispatchEvent(ConnectionManager.Event.CONNECTION_MADE);
438                   }
439               },
440               /**
441                * private utility method to set ZS State as "disconnected".
442                * same as calling _updateZSState("disconnected", disconnectReason)
443                **/
444               _disconnectZSState: function(disconnectReason) {
445                   this._updateZSState("disconnected", disconnectReason);
446               },
447               //local method to process HTTP Message obtained in ZS response.
448               processZSHTTPMessage: function(description, details) {
449                   switch (description) {
450                       /**
451                        * This command is used to exchange Zebra messages between the client and MCU or CLS.
452                        *
453                        * details = zebra XML
454                        **/
455                       case "ZEBRA":
456                           var zebra = Zebra.parseFromString(details);
457                           //broadcast Zebra as an event
458                           if (zebra) {
459                               //Platform.log("ZEBRA " + details);
460                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA_ALL, zebra);
461                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA(zebra.getZebraAttribute("event")), zebra);
462                           }
463                           break;
464                           /**
465                            * This command is sent by notification server to client, to disconnect the connection with ZS.
466                            *
467                            * details = reason. Possible reasons:
468                            *
469                            * EXPIRED	ZS sends this reason, when ZS receives EXPIRED response from CLS or Session Ended is
470                            * received as a reason of CLSDISCONNECT command. On receiving this reason, client disconnects the
471                            * connection with NS and reconnects to NS depending on its configuration. Client have to cache username
472                            * and password so that it can re-login.
473                            *
474                            * DIFFERENT_SESSION_MULTIPLE_CONNECTION	ZS sends this reason when NS receives a new connection
475                            * request from same user but having different session id. This means user is trying to login from
476                            * different places. Here, the client should not perform auto-login. After sending this command, ZS
477                            * closes the last user connection.
478                            *
479                            * DIFFERENT_PROTOCOL_MULTIPLE_CONNECTION	ZS sends this reason when a new connection request is received
480                            * from same user but with different connection protocol, for example, rtmp/ajax. Client should not perform
481                            * auto-login as this will cause flip-flop. After sending this command, ZS closes the last user connection.
482                            **/
483                       case "NSDISCONNECT":
484                           switch (details) {
485                               case "EXPIRED":
486                                   if (ConnectionManager.AUTOLOGIN_ON_NSDISCONNECT_EXPIRE) {
487                                       ConnectionManager._disconnectZSState("Session expired.");
488                                   } else {
489                                       ConnectionManager.logout("Session expired.");
490                                   }
491                                   break;
492                               case "DIFFERENT_SESSION_MULTIPLE_CONNECTION":
493                                   ConnectionManager.logout("You have logged in somewhere else.");
494                                   break;
495                               case "DIFFERENT_PROTOCOL_MULTIPLE_CONNECTION":
496                                   ConnectionManager.logout("You have logged in somewhere else.");
497                                   break;
498                               default:
499                                   ConnectionManager.logout(details);
500                           }
501                           break;
502                           /**
503                            * Redirect a client to connect to a new ZS.
504                            *
505                            * details = ZSIP:CONNECTMODE:DESTINATION
506                            **/
507                       case "ZENONREDIRECT":
508                           break;
509                           /**
510                            * This command is sent by MCU to disconnect an active call with MCU.
511                            *
512                            * details = reason
513                            **/
514                       case "DISCONNECT":
515                           Platform.callDisconnect(details.split("\n")[1]);
516                           break;
517                           /**
518                            * This command is sent by CLS when the caller hangs up an incoming call.
519                            *
520                            * details = N.A.
521                            **/
522                       case "ZENONWAKEFAIL":
523                           ConnectionManager._dispatchEvent("ZENONWAKEFAIL");
524                           break;
525                           /**
526                            * MCU sends this command for different status messages or for displaying the call duration.
527                            *
528                            * details = message
529                            **/
530                       case "SHOWMESSAGE":
531                           break;
532                           /**
533                            * In-call chat or server messages sent by the MCU.
534                            *
535                            * details = sender:message
536                            **/
537                       case "TEXTMESSAGE":
538                           details = details.split(":");
539                           var sender = details.shift();
540                           message = details.join(":");
541                           break;
542                           /**
543                            * Command to clear in-call chats.
544                            *
545                            * details = TXTC:CLEAR
546                            **/
547                       case "TXTC:CLEAR":
548                           break;
549                       default:
550                   }
551               },
552               /**
553                * local method to process ZS response.
554                *
555                * The response ZS comes in the following format:
556                *	line1:		STATUS (waiting, busy or disconnected)
557                *	line2:		COMMAND (EMPTY, HTTP_MESSAGE)
558                *	line3-end:	OPTIONAL MESSAGE
559                **/
560               processZSResponse: function(response) {
561                   if (!response || response == "") return;
562                   //Platform.log("response received is : " + response);
563                   response = response.replace(/^[\s]+/, "").replace(/[\s]+$/, ""); //trim whitespaces
564                   if (response == "") return;
565                   var responseLines = response.split("\n");
566                   //LINE1: read ZS State
567                   var state = responseLines.shift();
568                   
569                   if (response.indexOf("HTTP_MESSAGES") > -1) { //zmobile3 zebra's
570                       var parseValues = Zebra.parseFromStringZMobile3(responseLines[0]);
571                       var zebras = parseValues['zebras'];
572                       if (zebras && zebras.length > 0) {
573                           while (zebras.length > 0) {
574                               var zebra = zebras.shift();
575                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA_ALL, zebra);
576                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA(zebra.getZebraAttribute("event")), zebra);
577                           }
578                       }
579                       var commands = parseValues['commands'];
580                       if (commands && commands.length > 0) {
581                           while (commands.length > 0) {
582                               var cA = commands.shift().split("\n");
583                               if (cA.length > 1) {
584                                   ConnectionManager.processZSHTTPMessage(cA[0], cA[1]);
585                               } else {
586                                   ConnectionManager.processZSHTTPMessage(cA[0], cA[0]);
587                               }
588                           }
589                       }
590                       ConnectionManager._updateZSState(state);
591                       return;
592                   }
593                   //LINE2: process command
594                   switch (responseLines.shift()) {
595                       case "EMPTY":
596                           break;
597                       case "HTTP_MESSAGE":
598                           //the next line is the description, followed by the details
599                           if (responseLines.length > 0) {
600                               var description = responseLines.shift();
601                               var details;
602                               if (responseLines.length == 2) {
603                                   if (responseLines[0] == responseLines[1]) {
604                                       details = responseLines[0];
605                                   } else {
606                                       details = responseLines.join("\n");
607                                   }
608                               } else {
609                                   details = responseLines.join("\n");
610                               }
611                               ConnectionManager.processZSHTTPMessage(description, details);
612                           }
613                           break;
614                   }
615                   //update ZS State
616                   ConnectionManager._updateZSState(state);
617               },
618               /**
619                * Polls the ZS. Called by autoLogin(), and should not be called explicitly.
620                **/
621               zsPoll: function() {
622                   ConnectionManager.zsPollIsScheduled = false;
623                   //Platform.log("********** CM polling ******** Calling getData");
624                   //send an async ZS Command
625                   ConnectionManager.sendZSCommand("getData", "", this,
626                       function(response, status, statusText) {
627                           // Platform.log("********** CM polling Response ******** ConnectionManager.zsPollIsScheduled ="+ConnectionManager.zsPollIsScheduled);
628                           if (ConnectionManager.stopZSPoll) return;
629                           if (ConnectionManager.zsPollIsScheduled) return;
630                           if (response && response.indexOf("DUPLICATE_SESSION_THREAD") > -1) {
631                               Platform.log("DUPLICATE_SESSION_THREAD exit");
632                               return;
633                           }
634                           //if OK
635                           if (status == 200) {
636                               //handle zs response in a separate thread
637                               setTimeout(function() {
638                                   ConnectionManager.processZSResponse(response)
639                               }, 50);
640                               //poll ZS again almost immediately
641                               setTimeout(ConnectionManager.zsPoll, 50);
642                               ConnectionManager.zsPollIsScheduled = true;
643                               //Platform.log("********** CM polling Setup ******** ConnectionManager.zsPollIsScheduled ="+ConnectionManager.zsPollIsScheduled);
644                           } else {
645                               //if(status < 0) {
646                               //update ZS State to reflect the failed connection to ZS
647                               ConnectionManager._disconnectZSState("HTTP ERROR " + status + " (" + statusText + ")");
648                               //poll ZS again after a tiny delay of 1500 millis
649                               setTimeout(ConnectionManager.zsPoll, 1500);
650                               ConnectionManager.zsPollIsScheduled = true;
651                               //}
652                           }
653                       }
654                   );
655               },
656               /**
657                * Send a Zebra to the CLS.
658                *
659                * Arguments:
660                *	zebra					The Zebra object, which is to be sent.
661                *	handlerScopeObject		Optional argument to provide the scope of the handler methods.
662                *							Should be the object which contains the handler methods.
663                *	responseZebraHandler	Optional handler method called with the response zebra as its
664                *							argument (can be null), alongwith a status code and status text
665                *							providing more details on the HTTP Request. This handler should
666                *							have the following signature -
667                *								function(zebra, status, statusText) { //body }
668                *							where, status=200 is OK. For any error, statusText will provide
669                *							a textual representation of the error.
670                *							Other than those provided by Platform.httpRequest, status & statusText
671                *							can also be:
672                *								-10	Client not logged in.
673                *								-11	Client not connected.
674                *	async					Boolean (default true),  whether the request is sent asynchronously,
675                *							or not.
676                *							WARNING: Setting it to false will make it a blocking function,
677                *							causing any dependent UI or sequence to wait till it finishes.
678                **/
679                /**
680             	 @name ConnectionManager#sendZebra
681                         @function
682                         @description
683                            Send a zebra to server
684 	                     @param {object} zebra Zebra object to send.
685 						 @param {object} handlerScopeObject (Optional) Handler scope object
686 						 @param {object} responseZebraHandler Reponse handler for zebra request.
687 						@param {boolean} async Whether request is async or sync.
688 						@param {object} params Extra params to be passed.
689                @return null
690                 **/
691 			sendZebra: function(zebra, handlerScopeObject, responseZebraHandler, async, params) {
692                   if (!zebra) return;
693                   if (!ConnectionManager.isLoggedIn()) {
694                       ConnectionManager.addListener("LOGIN_SUCCESS", this, function() {
695                           var uName = zebra.getZebraAttribute("username");
696                           zebra.setZebraAttribute("username", DataStore.getUserData("username", ""));
697                           ConnectionManager.sendZebra(zebra, handlerScopeObject, responseZebraHandler, async);
698                       });
699                       Platform.log(" !!!!! QUEUE ZEBRA !!!!! AS NOT LOGGED IN !!!! " + zebra.toXML());
700                       if (responseZebraHandler) responseZebraHandler.apply(handlerScopeObject, [null, -10, "Client not logged in."]);
701                       return;
702                   }
703                   if (params && params['fireNoSend']) {
704                       if (ConnectionManager.isDisconnected) {
705                           ConnectionManager._dispatchEvent("CAN_NOT_COMPLETE_REQUEST", {
706                               'error_code_string': 'no_network'
707                           });
708                           return false;
709                       }
710                   }
711                   if (false && !ConnectionManager.isConnectedToZS()) {
712                       if (responseZebraHandler) responseZebraHandler.apply(handlerScopeObject, [null, -11, "Client not connected."]);
713                       return;
714                   }
715                   var recTime = new Date().getTime();
716                   if (zebra.getZebraAttribute('event') == 'com.requestec.smg.apps.zcontact.bookable.BookableZebra#getEvents') {
717                       Platform.log("Time after sending HTTP message getEvents request : ");
718                   }
719                   //send HTTP POST Request
720                   Platform.httpRequest(
721                       "POST",
722                       ConnectionManager.CLS + (ConnectionManager.ZebraGateway || ""),
723                       function(response, status, statusText) {
724                           var responseZebra = status == 200 && response && response != "" ? Zebra.parseFromString(response) : null;
725                           //call responseHandler, if provided
726                           var recTime = new Date().getTime();
727                           Platform.log("zebra.getZebraAttribute('event')" + zebra.getZebraAttribute('event'));
728                           if (zebra.getZebraAttribute('event') == 'com.requestec.smg.apps.zcontact.bookable.BookableZebra#getEvents:response') {
729                               Platform.log("Time after receiving HTTP Mmessage response : ");
730                           }
731                           if (responseZebraHandler) responseZebraHandler.apply(handlerScopeObject, [responseZebra, status, statusText]);
732                           //broadcast Zebra as an event
733                           if (responseZebra) {
734                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA_ALL, responseZebra);
735                               ConnectionManager._dispatchEvent(ConnectionManager.Event.ZEBRA(responseZebra.getZebraAttribute("event")), responseZebra);
736                           }
737                       },
738                       "message=" + encodeURIComponent(zebra.toXML()),
739                       async
740                   );
741               },
742               sendZebraToZC: function(zebra) {
743                   var client = getClientObj();
744                   if (client) {
745                       client.processZebra(zebra.toXML());
746                   }
747               },
748               /**
749                * Send a command to the ZS.
750                *
751                * Arguments:
752                *	command					The command string.
753                *	handlerScopeObject		Optional argument to provide the scope of the handler methods.
754                *							Should be the object which contains the handler methods.
755                *	responseHandler			Optional handler method called with the response as its argument
756                *							(can be null in case of errors), alongwith a status code and status
757                *							text providing more details on the HTTP Request. This handler should
758                *							have the following signature -
759                *								function(response, status, statusText) { //body }
760                *							where, status=200 is OK. For any error, statusText will provide
761                *							a textual representation of the error.
762                *							Other than those provided by Platform.httpRequest, status & statusText
763                *							can also be:
764                *								-10	Client not logged in.
765                *	async					Boolean (default true),  whether the request is sent asynchronously,
766                *							or not.
767                *							WARNING: Setting it to false will make it a blocking function,
768                *							causing any dependent UI or sequence to wait till it finishes.
769                **/
770               getZS: function() {
771                   return (ConnectionManager.POLL_ACTUAL_ENDPOINT) ? DataStore.getUserData("endpoint", "") : ConnectionManager.CLS;
772               },
773               sendZSCommand: function(command, params, handlerScopeObject, responseHandler, async) {
774                   if (!command || command == "") return;
775                   if (!ConnectionManager.isLoggedIn()) {
776                       if (responseHandler) responseHandler.apply(handlerScopeObject, [null, -10, "Client not logged in."]);
777                       return;
778                   }
779                   //send an async HTTP POST Request
780                   Platform.httpRequest(
781                       "POST", ((ConnectionManager.POLL_ACTUAL_ENDPOINT) ? DataStore.getUserData("endpoint", "") : ConnectionManager.CLS) + (ConnectionManager.ZSServlet || ""),
782                       function(response, status, statusText) {
783                           //call responseHandler, if provided
784                           if (responseHandler) responseHandler.apply(handlerScopeObject, [response, status, statusText]);
785                       },
786                       "comm=" + command +
787                       "&username=" + DataStore.getUserData("username", "") +
788                       "&service=" + (ConnectionManager.service || "") +
789                       "&sessionid=" + DataStore.getUserData("session_id", "") +
790                       "&random="+Math.floor(Math.random()*1000000000)+"&" + (params || ""),
791                       async
792                   );
793               },
794               /**
795                * Send a Zebra to the ZS or MCU
796                *  comm=zsMessage | sendMessageToMCU
797                *
798                * Other arguments as above
799                **/
800               sendZSZebraCommand: function(command, zebra, handlerScopeObject, responseHandler, async) {
801                   if (!command || command == "") return;
802                   if (!ConnectionManager.isLoggedIn()) {
803                       if (responseHandler) responseHandler.apply(handlerScopeObject, [null, -10, "Client not logged in."]);
804                       return;
805                   }
806                   //send an async HTTP POST Request
807                   var useSessionId = DataStore.getUserData("session_id", "");
808                   if (zebra.zebraAttributes.username != DataStore.getUserData("username", ""))
809                       useSessionId = "";
810                   Platform.httpRequest(
811                       "POST", (window.zcallerHostname || DataStore.getUserData("endpoint", "") || ConnectionManager.CLS) + (ConnectionManager.ZSServlet || ""),
812                       function(response, status, statusText) {
813                           //call responseHandler, if provided
814                           if (responseHandler) responseHandler.apply(handlerScopeObject, [response, status, statusText]);
815                       },
816                       "comm=" + command +
817                       "&command=zebra" +
818                       "&username=" + (zebra.zebraAttributes.username || DataStore.getUserData("username", "")) +
819                       "&service=" + (ConnectionManager.service || "") +
820                       "&sessionid=" + useSessionId +
821                       "&contents=" + escape(zebra.toXML()),
822                       async
823                   );
824               },
825               createCookie: function(name, value, days) {
826                   if (days) {
827                       var date = new Date();
828                       date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
829                       var expires = "; expires=" + date.toGMTString();
830                   } else var expires = "";
831                   document.cookie = name + "=" + value + expires + "; path=/";
832               },
833               readCookie: function(name) {
834                   var nameEQ = name + "=";
835                   var ca = document.cookie.split(';');
836                   for (var i = 0; i < ca.length; i++) {
837                       var c = ca[i];
838                       while (c.charAt(0) == ' ') c = c.substring(1, c.length);
839                       if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
840                   }
841                   return null;
842               },
843               eraseCookie: function(name) {
844                   this.createCookie(name, "", -1);
845               },
846               sendZebraToZS: function(zebra, handlerScopeObject, responseHandler, async) {
847                   return ConnectionManager.sendZSZebraCommand("zsMessage", zebra, handlerScopeObject, responseHandler, async);
848               },
849               sendZebraToMCU: function(zebra, handlerScopeObject, responseHandler, async) {
850                   return ConnectionManager.sendZSZebraCommand("sendMessageToMCU", zebra, handlerScopeObject, responseHandler, async);
851               },
852               logoutAllOtherDevices: function() {
853                   var zebra = new Zebra("com.requestec.smg.zebra.Gateway#logoutAllOtherDevices", this.service);
854                   ConnectionManager.sendZebra(zebra);
855               }
856           });
857