xmppSession.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.xmpp.xmppSession"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.xmpp.xmppSession"] = true;
  8. dojo.provide("dojox.xmpp.xmppSession");
  9. dojo.require("dojox.xmpp.TransportSession");
  10. dojo.require("dojox.xmpp.RosterService");
  11. dojo.require("dojox.xmpp.PresenceService");
  12. dojo.require("dojox.xmpp.UserService");
  13. dojo.require("dojox.xmpp.ChatService");
  14. dojo.require("dojox.xmpp.sasl");
  15. dojox.xmpp.xmpp = {
  16. STREAM_NS: 'http://etherx.jabber.org/streams',
  17. CLIENT_NS: 'jabber:client',
  18. STANZA_NS: 'urn:ietf:params:xml:ns:xmpp-stanzas',
  19. SASL_NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
  20. BIND_NS: 'urn:ietf:params:xml:ns:xmpp-bind',
  21. SESSION_NS: 'urn:ietf:params:xml:ns:xmpp-session',
  22. BODY_NS: "http://jabber.org/protocol/httpbind",
  23. XHTML_BODY_NS: "http://www.w3.org/1999/xhtml",
  24. XHTML_IM_NS: "http://jabber.org/protocol/xhtml-im",
  25. INACTIVE: "Inactive",
  26. CONNECTED: "Connected",
  27. ACTIVE: "Active",
  28. TERMINATE: "Terminate",
  29. LOGIN_FAILURE: "LoginFailure",
  30. INVALID_ID: -1,
  31. NO_ID: 0,
  32. error:{
  33. BAD_REQUEST: 'bad-request',
  34. CONFLICT: 'conflict',
  35. FEATURE_NOT_IMPLEMENTED: 'feature-not-implemented',
  36. FORBIDDEN: 'forbidden',
  37. GONE: 'gone',
  38. INTERNAL_SERVER_ERROR: 'internal-server-error',
  39. ITEM_NOT_FOUND: 'item-not-found',
  40. ID_MALFORMED: 'jid-malformed',
  41. NOT_ACCEPTABLE: 'not-acceptable',
  42. NOT_ALLOWED: 'not-allowed',
  43. NOT_AUTHORIZED: 'not-authorized',
  44. SERVICE_UNAVAILABLE: 'service-unavailable',
  45. SUBSCRIPTION_REQUIRED: 'subscription-required',
  46. UNEXPECTED_REQUEST: 'unexpected-request'
  47. }
  48. };
  49. dojox.xmpp.xmppSession = function(props){
  50. this.roster = [];
  51. this.chatRegister = [];
  52. this._iqId = Math.round(Math.random() * 1000000000);
  53. //mixin any options that we want to provide to this service
  54. if (props && dojo.isObject(props)) {
  55. dojo.mixin(this, props);
  56. }
  57. this.session = new dojox.xmpp.TransportSession(props);
  58. dojo.connect(this.session, "onReady", this, "onTransportReady");
  59. dojo.connect(this.session, "onTerminate", this, "onTransportTerminate");
  60. dojo.connect(this.session, "onProcessProtocolResponse", this, "processProtocolResponse");
  61. };
  62. dojo.extend(dojox.xmpp.xmppSession, {
  63. roster: [],
  64. chatRegister: [],
  65. _iqId: 0,
  66. open: function(user, password, resource){
  67. if (!user) {
  68. throw new Error("User id cannot be null");
  69. } else {
  70. this.jid = user;
  71. if(user.indexOf('@') == -1) {
  72. this.jid = this.jid + '@' + this.domain;
  73. }
  74. }
  75. //allow null password here as its not needed in the SSO case
  76. if (password) {
  77. this.password = password;
  78. }
  79. //normally you should NOT supply a resource and let the server send you one
  80. //as part of your jid...see onBindResource()
  81. if (resource) {
  82. this.resource = resource;
  83. }
  84. this.session.open();
  85. },
  86. close: function(){
  87. this.state = dojox.xmpp.xmpp.TERMINATE;
  88. this.session.close(dojox.xmpp.util.createElement("presence",{type:"unavailable",xmlns:dojox.xmpp.xmpp.CLIENT_NS},true));
  89. },
  90. processProtocolResponse: function(msg){
  91. //console.log("xmppSession::processProtocolResponse() ", msg, msg.nodeName);
  92. var type = msg.nodeName;
  93. var nsIndex =type.indexOf(":");
  94. if(nsIndex > 0) {
  95. type = type.substring(nsIndex+1);
  96. }
  97. switch(type){
  98. case "iq":
  99. case "presence":
  100. case "message":
  101. case "features":
  102. this[type + "Handler"](msg);
  103. break;
  104. default:
  105. //console.log("default action?", msg.getAttribute('xmlns'));
  106. if(msg.getAttribute('xmlns')==dojox.xmpp.xmpp.SASL_NS){
  107. this.saslHandler(msg);
  108. }
  109. }
  110. },
  111. //HANDLERS
  112. messageHandler: function(msg){
  113. //console.log("xmppSession::messageHandler() ",msg);
  114. switch(msg.getAttribute('type')){
  115. case "chat":
  116. this.chatHandler(msg);
  117. break;
  118. case "normal":
  119. default:
  120. this.simpleMessageHandler(msg);
  121. }
  122. },
  123. iqHandler: function(msg){
  124. //console.log("xmppSession::iqHandler()", msg);
  125. if (msg.getAttribute('type')=="set"){
  126. this.iqSetHandler(msg);
  127. return;
  128. } else if (msg.getAttribute('type')=='get'){
  129. // this.sendStanzaError('iq', this.domain, msg.getAttribute('from'), 'cancel', 'service-unavailable', 'service not implemented');
  130. return;
  131. }
  132. },
  133. presenceHandler: function(msg){
  134. //console.log("xmppSession::presenceHandler()");
  135. switch(msg.getAttribute('type')){
  136. case 'subscribe':
  137. //console.log("PresenceHandler: ", msg.getAttribute('from'));
  138. this.presenceSubscriptionRequest(msg.getAttribute('from'));
  139. break;
  140. case 'subscribed':
  141. case 'unsubscribed':
  142. break;
  143. case 'error':
  144. this.processXmppError(msg);
  145. //console.log("xmppService::presenceHandler() Error");
  146. break;
  147. default:
  148. this.presenceUpdate(msg);
  149. break;
  150. }
  151. },
  152. featuresHandler: function(msg){
  153. //console.log("xmppSession::featuresHandler() ",msg);
  154. var authMechanisms = [];
  155. var hasBindFeature = false;
  156. var hasSessionFeature = false;
  157. if(msg.hasChildNodes()){
  158. for(var i=0; i<msg.childNodes.length;i++){
  159. var n = msg.childNodes[i];
  160. //console.log("featuresHandler::node", n);
  161. switch(n.nodeName){
  162. case 'mechanisms':
  163. for (var x=0; x<n.childNodes.length; x++){
  164. //console.log("featuresHandler::node::mechanisms", n.childNodes[x].firstChild.nodeValue);
  165. authMechanisms.push(n.childNodes[x].firstChild.nodeValue);
  166. }
  167. break;
  168. case 'bind':
  169. //if (n.getAttribute('xmlns')==dojox.xmpp.xmpp.BIND_NS) {
  170. hasBindFeature = true;
  171. // }
  172. break;
  173. case 'session':
  174. hasSessionFeature = true;
  175. }
  176. }
  177. }
  178. //console.log("Has connected/bind?", this.state, hasBindFeature, authMechanisms);
  179. if(this.state == dojox.xmpp.xmpp.CONNECTED){
  180. if(!this.auth){
  181. // start the login
  182. for(var i=0; i<authMechanisms.length; i++){
  183. try{
  184. this.auth = dojox.xmpp.sasl.registry.match(authMechanisms[i], this);
  185. break;
  186. }catch(e){
  187. console.warn("No suitable auth mechanism found for: ", authMechanisms[i]);
  188. }
  189. }
  190. }else if(hasBindFeature){
  191. this.bindResource(hasSessionFeature);
  192. }
  193. }
  194. },
  195. saslHandler: function(msg){
  196. //console.log("xmppSession::saslHandler() ", msg);
  197. if(msg.nodeName=="success"){
  198. this.auth.onSuccess();
  199. return;
  200. }
  201. if(msg.nodeName=="challenge"){
  202. this.auth.onChallenge(msg);
  203. return;
  204. }
  205. if(msg.hasChildNodes()){
  206. this.onLoginFailure(msg.firstChild.nodeName);
  207. this.session.setState('Terminate', msg.firstChild.nodeName);
  208. }
  209. },
  210. sendRestart: function(){
  211. this.session._sendRestart();
  212. },
  213. //SUB HANDLERS
  214. chatHandler: function(msg){
  215. //console.log("xmppSession::chatHandler() ", msg);
  216. var message = {
  217. from: msg.getAttribute('from'),
  218. to: msg.getAttribute('to')
  219. }
  220. var chatState = null;
  221. //console.log("chat child node ", msg.childNodes, msg.childNodes.length);
  222. for (var i=0; i<msg.childNodes.length; i++){
  223. var n = msg.childNodes[i];
  224. if (n.hasChildNodes()){
  225. //console.log("chat child node ", n);
  226. switch(n.nodeName){
  227. case 'thread':
  228. message.chatid = n.firstChild.nodeValue;
  229. break;
  230. case 'body':
  231. if (!n.getAttribute('xmlns') || (n.getAttribute('xmlns')=="")){
  232. message.body = n.firstChild.nodeValue;
  233. }
  234. break;
  235. case 'subject':
  236. message.subject = n.firstChild.nodeValue;
  237. case 'html':
  238. if (n.getAttribute('xmlns')==dojox.xmpp.xmpp.XHTML_IM_NS){
  239. message.xhtml = n.getElementsByTagName("body")[0];
  240. }
  241. break;
  242. case 'x':
  243. break;
  244. default:
  245. //console.log("xmppSession::chatHandler() Unknown node type: ",n.nodeName);
  246. }
  247. }
  248. /*//console.log("Foo", n, n.nodeName);
  249. if(n.getAttribute('xmlns')==dojox.xmpp.chat.CHAT_STATE_NS){
  250. chatState = n.nodeName;
  251. }*/
  252. }
  253. var found = -1;
  254. if (message.chatid){
  255. for (var i=0; i< this.chatRegister.length; i++){
  256. var ci = this.chatRegister[i];
  257. ////console.log("ci.chatid: ", ci.chatid, message.chatid);
  258. if (ci && ci.chatid == message.chatid) {
  259. found = i;
  260. break;
  261. }
  262. }
  263. } else {
  264. for (var i=0; i< this.chatRegister.length; i++){
  265. var ci = this.chatRegister[i];
  266. if(ci){
  267. if (ci.uid==this.getBareJid(message.from)){
  268. found = i;
  269. }
  270. }
  271. }
  272. }
  273. if (found>-1 && chatState){
  274. var chat = this.chatRegister[found];
  275. chat.setState(chatState);
  276. if (chat.firstMessage){
  277. if (chatState == dojox.xmpp.chat.ACTIVE_STATE) {
  278. chat.useChatState = (chatState != null) ? true : false;
  279. chat.firstMessage = false;
  280. }
  281. }
  282. }
  283. if ((!message.body || message.body=="") && !message.xhtml) {return;}
  284. if (found>-1){
  285. var chat = this.chatRegister[found];
  286. chat.recieveMessage(message);
  287. }else{
  288. var chatInstance = new dojox.xmpp.ChatService();
  289. chatInstance.uid = this.getBareJid(message.from);
  290. chatInstance.chatid = message.chatid;
  291. chatInstance.firstMessage = true;
  292. if(!chatState || chatState != dojox.xmpp.chat.ACTIVE_STATE){
  293. this.useChatState = false;
  294. }
  295. this.registerChatInstance(chatInstance, message);
  296. }
  297. },
  298. simpleMessageHandler: function(msg){
  299. //console.log("xmppSession::simpleMessageHandler() ", msg);
  300. },
  301. registerChatInstance: function(chatInstance, message){
  302. chatInstance.setSession(this);
  303. this.chatRegister.push(chatInstance);
  304. this.onRegisterChatInstance(chatInstance, message);
  305. chatInstance.recieveMessage(message,true);
  306. },
  307. iqSetHandler: function(msg){
  308. if (msg.hasChildNodes()){
  309. var fn = msg.firstChild;
  310. switch(fn.nodeName){
  311. case 'query':
  312. if(fn.getAttribute('xmlns') == "jabber:iq:roster"){
  313. this.rosterSetHandler(fn);
  314. this.sendIqResult(msg.getAttribute('id'), msg.getAttribute('from'));
  315. }
  316. break;
  317. default:
  318. // this.sendStanzaError('iq', this.domain, msg.getAttribute('id'), 'cancel', 'service-unavailable', 'service not implemented');
  319. break;
  320. }
  321. }
  322. },
  323. sendIqResult: function(iqId, to){
  324. var req = {
  325. id: iqId,
  326. to: to || this.domain,
  327. type: 'result',
  328. from: this.jid + "/" + this.resource
  329. }
  330. this.dispatchPacket(dojox.xmpp.util.createElement("iq",req,true));
  331. },
  332. rosterSetHandler: function(elem){
  333. //console.log("xmppSession::rosterSetHandler()", arguments);
  334. for (var i=0; i<elem.childNodes.length;i++){
  335. var n = elem.childNodes[i];
  336. if (n.nodeName=="item"){
  337. var found = false;
  338. var state = -1;
  339. var rosterItem = null;
  340. var previousCopy = null;
  341. for(var x=0; x<this.roster.length;x++){
  342. var r = this.roster[x];
  343. if(n.getAttribute('jid')==r.jid){
  344. found = true;
  345. if(n.getAttribute('subscription')=='remove'){
  346. //remove the item
  347. rosterItem = {
  348. id: r.jid,
  349. name: r.name,
  350. groups:[]
  351. }
  352. for (var y=0;y<r.groups.length;y++){
  353. rosterItem.groups.push(r.groups[y]);
  354. }
  355. this.roster.splice(x,1);
  356. state = dojox.xmpp.roster.REMOVED;
  357. } else { //update
  358. previousCopy = dojo.clone(r);
  359. var itemName = n.getAttribute('name');
  360. if (itemName){
  361. this.roster[x].name = itemName;
  362. }
  363. r.groups = [];
  364. if (n.getAttribute('subscription')){
  365. r.status = n.getAttribute('subscription');
  366. }
  367. r.substatus = dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE;
  368. if(n.getAttribute('ask')=='subscribe'){
  369. r.substatus = dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
  370. }
  371. for(var y=0;y<n.childNodes.length;y++){
  372. var groupNode = n.childNodes[y];
  373. if ((groupNode.nodeName=='group')&&(groupNode.hasChildNodes())){
  374. var gname = groupNode.firstChild.nodeValue;
  375. r.groups.push(gname);
  376. }
  377. }
  378. rosterItem = r;
  379. state = dojox.xmpp.roster.CHANGED;
  380. }
  381. break;
  382. }
  383. }
  384. if(!found && (n.getAttribute('subscription')!='remove')){
  385. r = this.createRosterEntry(n);
  386. rosterItem = r;
  387. state = dojox.xmpp.roster.ADDED;
  388. }
  389. switch(state){
  390. case dojox.xmpp.roster.ADDED:
  391. this.onRosterAdded(rosterItem);
  392. break;
  393. case dojox.xmpp.roster.REMOVED:
  394. this.onRosterRemoved(rosterItem);
  395. break;
  396. case dojox.xmpp.roster.CHANGED:
  397. this.onRosterChanged(rosterItem, previousCopy);
  398. break;
  399. }
  400. }
  401. }
  402. },
  403. presenceUpdate: function(msg){
  404. if(msg.getAttribute('to')){
  405. var jid = this.getBareJid(msg.getAttribute('to'));
  406. if(jid != this.jid) {
  407. //console.log("xmppService::presenceUpdate Update Recieved with wrong address - ",jid);
  408. return;
  409. }
  410. }
  411. var fromRes = this.getResourceFromJid(msg.getAttribute('from'));
  412. var p = {
  413. from: this.getBareJid(msg.getAttribute('from')),
  414. resource: fromRes,
  415. show: dojox.xmpp.presence.STATUS_ONLINE,
  416. priority: 5,
  417. hasAvatar: false
  418. }
  419. if(msg.getAttribute('type')=='unavailable'){
  420. p.show=dojox.xmpp.presence.STATUS_OFFLINE
  421. }
  422. for (var i=0; i<msg.childNodes.length;i++){
  423. var n=msg.childNodes[i];
  424. if (n.hasChildNodes()){
  425. switch(n.nodeName){
  426. case 'status':
  427. case 'show':
  428. p[n.nodeName]=n.firstChild.nodeValue;
  429. break;
  430. case 'status':
  431. p.priority=parseInt(n.firstChild.nodeValue);
  432. break;
  433. case 'x':
  434. if(n.firstChild && n.firstChild.firstChild && n.firstChild.firstChild.nodeValue != "") {
  435. p.avatarHash= n.firstChild.firstChild.nodeValue;
  436. p.hasAvatar = true;
  437. }
  438. break;
  439. }
  440. }
  441. }
  442. this.onPresenceUpdate(p);
  443. },
  444. retrieveRoster: function(){
  445. ////console.log("xmppService::retrieveRoster()");
  446. var props={
  447. id: this.getNextIqId(),
  448. from: this.jid + "/" + this.resource,
  449. type: "get"
  450. }
  451. var req = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
  452. req.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:roster"},true));
  453. req.append("</iq>");
  454. var def = this.dispatchPacket(req,"iq", props.id);
  455. def.addCallback(this, "onRetrieveRoster");
  456. },
  457. getRosterIndex: function(jid){
  458. if(jid.indexOf('@')==-1){
  459. jid += '@' + this.domain;
  460. }
  461. for (var i=0; i<this.roster.length;i++){
  462. if(jid == this.roster[i].jid) { return i; }
  463. }
  464. return -1;
  465. },
  466. createRosterEntry: function(elem){
  467. ////console.log("xmppService::createRosterEntry()");
  468. var re = {
  469. name: elem.getAttribute('name'),
  470. jid: elem.getAttribute('jid'),
  471. groups: [],
  472. status: dojox.xmpp.presence.SUBSCRIPTION_NONE,
  473. substatus: dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE
  474. // displayToUser: false
  475. }
  476. if (!re.name){
  477. re.name = re.id;
  478. }
  479. for(var i=0; i<elem.childNodes.length;i++){
  480. var n = elem.childNodes[i];
  481. if (n.nodeName=='group' && n.hasChildNodes()){
  482. re.groups.push(n.firstChild.nodeValue);
  483. }
  484. }
  485. if (elem.getAttribute('subscription')){
  486. re.status = elem.getAttribute('subscription');
  487. }
  488. if (elem.getAttribute('ask')=='subscribe'){
  489. re.substatus = dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
  490. }
  491. //Display contact rules from http://www.xmpp.org/extensions/xep-0162.html#contacts
  492. /* if(re.status == dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING ||
  493. re.status == dojox.xmpp.presence.SUBSCRIPTION_TO ||
  494. re.status == dojox.xmpp.presence.SUBSCRIPTION_BOTH ||
  495. re.groups.length > 0 ||
  496. re.name
  497. ) {
  498. re.displayToUser = true;
  499. }
  500. */
  501. return re;
  502. },
  503. bindResource: function(hasSession){
  504. var props = {
  505. id: this.getNextIqId(),
  506. type: "set"
  507. }
  508. var bindReq = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", props, false));
  509. bindReq.append(dojox.xmpp.util.createElement("bind", {xmlns: dojox.xmpp.xmpp.BIND_NS}, false));
  510. if (this.resource){
  511. bindReq.append(dojox.xmpp.util.createElement("resource"));
  512. bindReq.append(this.resource);
  513. bindReq.append("</resource>");
  514. }
  515. bindReq.append("</bind></iq>");
  516. var def = this.dispatchPacket(bindReq, "iq", props.id);
  517. def.addCallback(this, function(msg){
  518. this.onBindResource(msg, hasSession);
  519. return msg;
  520. });
  521. },
  522. getNextIqId: function(){
  523. return "im_" + this._iqId++;
  524. },
  525. presenceSubscriptionRequest: function(msg) {
  526. this.onSubscriptionRequest(msg);
  527. /*
  528. this.onSubscriptionRequest({
  529. from: msg,
  530. resource:"",
  531. show:"",
  532. status:"",
  533. priority: 5
  534. });
  535. */
  536. },
  537. dispatchPacket: function(msg, type, matchId){
  538. if (this.state != "Terminate") {
  539. return this.session.dispatchPacket(msg,type,matchId);
  540. }else{
  541. //console.log("xmppSession::dispatchPacket - Session in Terminate state, dropping packet");
  542. }
  543. },
  544. setState: function(state, message){
  545. if (this.state != state){
  546. if (this["on"+state]){
  547. this["on"+state](state, this.state, message);
  548. }
  549. this.state=state;
  550. }
  551. },
  552. search: function(searchString, service, searchAttribute){
  553. var req={
  554. id: this.getNextIqId(),
  555. "xml:lang": this.lang,
  556. type: 'set',
  557. from: this.jid + '/' + this.resource,
  558. to: service
  559. }
  560. var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
  561. request.append(dojox.xmpp.util.createElement('query',{xmlns:'jabber:iq:search'},false));
  562. request.append(dojox.xmpp.util.createElement(searchAttribute,{},false));
  563. request.append(searchString);
  564. request.append("</").append(searchAttribute).append(">");
  565. request.append("</query></iq>");
  566. var def = this.dispatchPacket(request.toString,"iq",req.id);
  567. def.addCallback(this, "_onSearchResults");
  568. },
  569. _onSearchResults: function(msg){
  570. if ((msg.getAttribute('type')=='result')&&(msg.hasChildNodes())){
  571. //console.log("xmppSession::_onSearchResults(): ", msg.firstChild);
  572. //call the search results event with an array of results
  573. this.onSearchResults([]);
  574. }
  575. },
  576. // EVENTS
  577. onLogin: function(){
  578. ////console.log("xmppSession::onLogin()");
  579. this.retrieveRoster();
  580. },
  581. onLoginFailure: function(msg){
  582. //console.log("xmppSession::onLoginFailure ", msg);
  583. },
  584. onBindResource: function(msg, hasSession){
  585. //console.log("xmppSession::onBindResource() ", msg);
  586. if (msg.getAttribute('type')=='result'){
  587. //console.log("xmppSession::onBindResource() Got Result Message");
  588. if ((msg.hasChildNodes()) && (msg.firstChild.nodeName=="bind")){
  589. var bindTag = msg.firstChild;
  590. if ((bindTag.hasChildNodes()) && (bindTag.firstChild.nodeName=="jid")){
  591. if (bindTag.firstChild.hasChildNodes()){
  592. var fulljid = bindTag.firstChild.firstChild.nodeValue;
  593. this.jid = this.getBareJid(fulljid);
  594. this.resource = this.getResourceFromJid(fulljid);
  595. }
  596. }
  597. if(hasSession){
  598. var props = {
  599. id: this.getNextIqId(),
  600. type: "set"
  601. }
  602. var bindReq = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", props, false));
  603. bindReq.append(dojox.xmpp.util.createElement("session", {xmlns: dojox.xmpp.xmpp.SESSION_NS}, true));
  604. bindReq.append("</iq>");
  605. var def = this.dispatchPacket(bindReq, "iq", props.id);
  606. def.addCallback(this, "onBindSession");
  607. return;
  608. }
  609. }else{
  610. //console.log("xmppService::onBindResource() No Bind Element Found");
  611. }
  612. this.onLogin();
  613. }else if(msg.getAttribute('type')=='error'){
  614. //console.log("xmppSession::onBindResource() Bind Error ", msg);
  615. var err = this.processXmppError(msg);
  616. this.onLoginFailure(err);
  617. }
  618. },
  619. onBindSession: function(msg){
  620. if(msg.getAttribute('type')=='error'){
  621. //console.log("xmppSession::onBindSession() Bind Error ", msg);
  622. var err = this.processXmppError(msg);
  623. this.onLoginFailure(err);
  624. }else{
  625. this.onLogin();
  626. }
  627. },
  628. onSearchResults: function(results){
  629. //console.log("xmppSession::onSearchResult() ", results);
  630. },
  631. onRetrieveRoster: function(msg){
  632. ////console.log("xmppService::onRetrieveRoster() ", arguments);
  633. if ((msg.getAttribute('type')=='result') && msg.hasChildNodes()){
  634. var query = msg.getElementsByTagName('query')[0];
  635. if (query.getAttribute('xmlns')=="jabber:iq:roster"){
  636. for (var i=0;i<query.childNodes.length;i++){
  637. if (query.childNodes[i].nodeName=="item"){
  638. this.roster[i] = this.createRosterEntry(query.childNodes[i]);
  639. }
  640. }
  641. }
  642. }else if(msg.getAttribute('type')=="error"){
  643. //console.log("xmppService::storeRoster() Error recieved on roster get");
  644. }
  645. ////console.log("Roster: ", this.roster);
  646. this.setState(dojox.xmpp.xmpp.ACTIVE);
  647. this.onRosterUpdated();
  648. return msg;
  649. },
  650. onRosterUpdated: function() {},
  651. onSubscriptionRequest: function(req){},
  652. onPresenceUpdate: function(p){},
  653. onTransportReady: function(){
  654. this.setState(dojox.xmpp.xmpp.CONNECTED);
  655. this.rosterService = new dojox.xmpp.RosterService(this);
  656. this.presenceService= new dojox.xmpp.PresenceService(this);
  657. this.userService = new dojox.xmpp.UserService(this);
  658. ////console.log("xmppSession::onTransportReady()");
  659. },
  660. onTransportTerminate: function(newState, oldState, message){
  661. this.setState(dojox.xmpp.xmpp.TERMINATE, message);
  662. },
  663. onConnected: function(){
  664. ////console.log("xmppSession::onConnected()");
  665. },
  666. onTerminate: function(newState, oldState, message){
  667. //console.log("xmppSession::onTerminate()", newState, oldState, message);
  668. },
  669. onActive: function(){
  670. ////console.log("xmppSession::onActive()");
  671. //this.presenceService.publish({show: dojox.xmpp.presence.STATUS_ONLINE});
  672. },
  673. onRegisterChatInstance: function(chatInstance, message){
  674. ////console.log("xmppSession::onRegisterChatInstance()");
  675. },
  676. onRosterAdded: function(ri){},
  677. onRosterRemoved: function(ri){},
  678. onRosterChanged: function(ri, previousCopy){},
  679. //Utilities
  680. processXmppError: function(msg){
  681. ////console.log("xmppSession::processXmppError() ", msg);
  682. var err = {
  683. stanzaType: msg.nodeName,
  684. id: msg.getAttribute('id')
  685. }
  686. for (var i=0; i<msg.childNodes.length; i++){
  687. var n = msg.childNodes[i];
  688. switch(n.nodeName){
  689. case 'error':
  690. err.errorType = n.getAttribute('type');
  691. for (var x=0; x< n.childNodes.length; x++){
  692. var cn = n.childNodes[x];
  693. if ((cn.nodeName=="text") && (cn.getAttribute('xmlns') == dojox.xmpp.xmpp.STANZA_NS) && cn.hasChildNodes()) {
  694. err.message = cn.firstChild.nodeValue;
  695. } else if ((cn.getAttribute('xmlns') == dojox.xmpp.xmpp.STANZA_NS) &&(!cn.hasChildNodes())){
  696. err.condition = cn.nodeName;
  697. }
  698. }
  699. break;
  700. default:
  701. break;
  702. }
  703. }
  704. return err;
  705. },
  706. sendStanzaError: function(stanzaType,to,id,errorType,condition,text){
  707. ////console.log("xmppSession: sendStanzaError() ", arguments);
  708. var req = {type:'error'};
  709. if (to) { req.to=to; }
  710. if (id) { req.id=id; }
  711. var request = new dojox.string.Builder(dojox.xmpp.util.createElement(stanzaType,req,false));
  712. request.append(dojox.xmpp.util.createElement('error',{type:errorType},false));
  713. request.append(dojox.xmpp.util.createElement('condition',{xmlns:dojox.xmpp.xmpp.STANZA_NS},true));
  714. if(text){
  715. var textAttr={
  716. xmlns: dojox.xmpp.xmpp.STANZA_NS,
  717. "xml:lang":this.lang
  718. }
  719. request.append(dojox.xmpp.util.createElement('text',textAttr,false));
  720. request.append(text).append("</text>");
  721. }
  722. request.append("</error></").append(stanzaType).append(">");
  723. this.dispatchPacket(request.toString());
  724. },
  725. getBareJid: function(jid){
  726. var i = jid.indexOf('/');
  727. if (i != -1){
  728. return jid.substring(0, i);
  729. }
  730. return jid;
  731. },
  732. getResourceFromJid: function(jid){
  733. var i = jid.indexOf('/');
  734. if (i != -1){
  735. return jid.substring((i + 1), jid.length);
  736. }
  737. return "";
  738. }
  739. });
  740. }