xmppSession.js 23 KB

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