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