dojo.provide("dojox.xmpp.xmppSession"); dojo.require("dojox.xmpp.TransportSession"); dojo.require("dojox.xmpp.RosterService"); dojo.require("dojox.xmpp.PresenceService"); dojo.require("dojox.xmpp.UserService"); dojo.require("dojox.xmpp.ChatService"); dojo.require("dojox.xmpp.sasl"); dojox.xmpp.xmpp = { STREAM_NS: 'http://etherx.jabber.org/streams', CLIENT_NS: 'jabber:client', STANZA_NS: 'urn:ietf:params:xml:ns:xmpp-stanzas', SASL_NS: 'urn:ietf:params:xml:ns:xmpp-sasl', BIND_NS: 'urn:ietf:params:xml:ns:xmpp-bind', BODY_NS: "http://jabber.org/protocol/httpbind", XHTML_BODY_NS: "http://www.w3.org/1999/xhtml", XHTML_IM_NS: "http://jabber.org/protocol/xhtml-im", INACTIVE: "Inactive", CONNECTED: "Connected", ACTIVE: "Active", TERMINATE: "Terminate", LOGIN_FAILURE: "LoginFailure", INVALID_ID: -1, NO_ID: 0, error:{ BAD_REQUEST: 'bad-request', CONFLICT: 'conflict', FEATURE_NOT_IMPLEMENTED: 'feature-not-implemented', FORBIDDEN: 'forbidden', GONE: 'gone', INTERNAL_SERVER_ERROR: 'internal-server-error', ITEM_NOT_FOUND: 'item-not-found', ID_MALFORMED: 'jid-malformed', NOT_ACCEPTABLE: 'not-acceptable', NOT_ALLOWED: 'not-allowed', NOT_AUTHORIZED: 'not-authorized', SERVICE_UNAVAILABLE: 'service-unavailable', SUBSCRIPTION_REQUIRED: 'subscription-required', UNEXPECTED_REQUEST: 'unexpected-request' } }; dojox.xmpp.xmppSession = function(props){ //mixin any options that we want to provide to this service if (props && dojo.isObject(props)) { dojo.mixin(this, props); } this.session = new dojox.xmpp.TransportSession(props); dojo.connect(this.session, "onReady", this, "onTransportReady"); dojo.connect(this.session, "onTerminate", this, "onTransportTerminate"); dojo.connect(this.session, "onProcessProtocolResponse", this, "processProtocolResponse"); }; dojo.extend(dojox.xmpp.xmppSession, { roster: [], chatRegister: [], _iqId: Math.round(Math.random() * 1000000000), open: function(user, password, resource){ if (!user) { throw new Error("User id cannot be null"); } else { this.jid = user; if(user.indexOf('@') == -1) { this.jid = this.jid + '@' + this.domain; } } //allow null password here as its not needed in the SSO case if (password) { this.password = password; } //normally you should NOT supply a resource and let the server send you one //as part of your jid...see onBindResource() if (resource) { this.resource = resource; } this.session.open(); }, close: function(){ this.state = dojox.xmpp.xmpp.TERMINATE; this.session.close(dojox.xmpp.util.createElement("presence",{type:"unavailable",xmlns:dojox.xmpp.xmpp.CLIENT_NS},true)); }, processProtocolResponse: function(msg){ //console.log("xmppSession::processProtocolResponse() ", msg, msg.nodeName); var type = msg.nodeName; var nsIndex =type.indexOf(":"); if(nsIndex > 0) { type = type.substring(nsIndex+1); } switch(type){ case "iq": case "presence": case "message": case "features": this[type + "Handler"](msg); break; default: //console.log("default action?", msg.getAttribute('xmlns')); if(msg.getAttribute('xmlns')==dojox.xmpp.xmpp.SASL_NS){ this.saslHandler(msg); } } }, //HANDLERS messageHandler: function(msg){ //console.log("xmppSession::messageHandler() ",msg); switch(msg.getAttribute('type')){ case "chat": this.chatHandler(msg); break; case "normal": default: this.simpleMessageHandler(msg); } }, iqHandler: function(msg){ //console.log("xmppSession::iqHandler()", msg); if (msg.getAttribute('type')=="set"){ this.iqSetHandler(msg); return; } else if (msg.getAttribute('type')=='get'){ // this.sendStanzaError('iq', this.domain, msg.getAttribute('from'), 'cancel', 'service-unavailable', 'service not implemented'); return; } }, presenceHandler: function(msg){ //console.log("xmppSession::presenceHandler()"); switch(msg.getAttribute('type')){ case 'subscribe': //console.log("PresenceHandler: ", msg.getAttribute('from')); this.presenceSubscriptionRequest(msg.getAttribute('from')); break; case 'subscribed': case 'unsubscribed': break; case 'error': this.processXmppError(msg); //console.log("xmppService::presenceHandler() Error"); break; default: this.presenceUpdate(msg); break; } }, featuresHandler: function(msg){ //console.log("xmppSession::featuresHandler() ",msg); var authMechanisms = []; var hasBindFeature = false; if(msg.hasChildNodes()){ for(var i=0; i-1 && chatState){ var chat = this.chatRegister[found]; chat.setState(chatState); if (chat.firstMessage){ if (chatState == dojox.xmpp.chat.ACTIVE_STATE) { chat.useChatState = (chatState != null) ? true : false; chat.firstMessage = false; } } } if ((!message.body || message.body=="") && !message.xhtml) {return;} if (found>-1){ var chat = this.chatRegister[found]; chat.recieveMessage(message); }else{ var chatInstance = new dojox.xmpp.ChatService(); chatInstance.uid = this.getBareJid(message.from); chatInstance.chatid = message.chatid; chatInstance.firstMessage = true; if(!chatState || chatState != dojox.xmpp.chat.ACTIVE_STATE){ this.useChatState = false; } this.registerChatInstance(chatInstance, message); } }, simpleMessageHandler: function(msg){ //console.log("xmppSession::simpleMessageHandler() ", msg); }, registerChatInstance: function(chatInstance, message){ chatInstance.setSession(this); this.chatRegister.push(chatInstance); this.onRegisterChatInstance(chatInstance, message); chatInstance.recieveMessage(message,true); }, iqSetHandler: function(msg){ if (msg.hasChildNodes()){ var fn = msg.firstChild; switch(fn.nodeName){ case 'query': if(fn.getAttribute('xmlns') == "jabber:iq:roster"){ this.rosterSetHandler(fn); this.sendIqResult(msg.getAttribute('id'), msg.getAttribute('from')); } break; default: // this.sendStanzaError('iq', this.domain, msg.getAttribute('id'), 'cancel', 'service-unavailable', 'service not implemented'); break; } } }, sendIqResult: function(iqId, to){ var req = { id: iqId, to: to || this.domain, type: 'result', from: this.jid + "/" + this.resource } this.dispatchPacket(dojox.xmpp.util.createElement("iq",req,true)); }, rosterSetHandler: function(elem){ //console.log("xmppSession::rosterSetHandler()", arguments); for (var i=0; i"); var def = this.dispatchPacket(req,"iq", props.id); def.addCallback(this, "onRetrieveRoster"); }, getRosterIndex: function(jid){ if(jid.indexOf('@')==-1){ jid += '@' + this.domain; } for (var i=0; i 0 || re.name ) { re.displayToUser = true; } */ return re; }, bindResource: function(){ var props = { xmlns: "jabber:client", id: this.getNextIqId(), type: "set" } var bindReq = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", props, false)); bindReq.append(dojox.xmpp.util.createElement("bind", {xmlns: dojox.xmpp.xmpp.BIND_NS}, false)); if (this.resource){ bindReq.append(dojox.xmpp.util.createElement("resource")); bindReq.append(this.resource); bindReq.append(""); } bindReq.append(""); var def = this.dispatchPacket(bindReq, "iq", props.id); def.addCallback(this, "onBindResource"); }, getNextIqId: function(){ return "im_" + this._iqId++; }, presenceSubscriptionRequest: function(msg) { this.onSubscriptionRequest(msg); /* this.onSubscriptionRequest({ from: msg, resource:"", show:"", status:"", priority: 5 }); */ }, dispatchPacket: function(msg, type, matchId){ if (this.state != "Terminate") { return this.session.dispatchPacket(msg,type,matchId); }else{ //console.log("xmppSession::dispatchPacket - Session in Terminate state, dropping packet"); } }, setState: function(state, message){ if (this.state != state){ if (this["on"+state]){ this["on"+state](state, this.state, message); } this.state=state; } }, search: function(searchString, service, searchAttribute){ var req={ id: this.getNextIqId(), "xml:lang": this.lang, type: 'set', from: this.jid + '/' + this.resource, to: service } var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false)); request.append(dojox.xmpp.util.createElement('query',{xmlns:'jabber:iq:search'},false)); request.append(dojox.xmpp.util.createElement(searchAttribute,{},false)); request.append(searchString); request.append(""); request.append(""); var def = this.dispatchPacket(request.toString,"iq",req.id); def.addCallback(this, "_onSearchResults"); }, _onSearchResults: function(msg){ if ((msg.getAttribute('type')=='result')&&(msg.hasChildNodes())){ //console.log("xmppSession::_onSearchResults(): ", msg.firstChild); //call the search results event with an array of results this.onSearchResults([]); } }, // EVENTS onLogin: function(){ ////console.log("xmppSession::onLogin()"); this.retrieveRoster(); }, onLoginFailure: function(msg){ //console.log("xmppSession::onLoginFailure ", msg); }, onBindResource: function(msg){ //console.log("xmppSession::onBindResource() ", msg); if (msg.getAttribute('type')=='result'){ //console.log("xmppSession::onBindResource() Got Result Message"); if ((msg.hasChildNodes()) && (msg.firstChild.nodeName=="bind")){ var bindTag = msg.firstChild; if ((bindTag.hasChildNodes()) && (bindTag.firstChild.nodeName=="jid")){ if (bindTag.firstChild.hasChildNodes()){ var fulljid = bindTag.firstChild.firstChild.nodeValue; this.jid = this.getBareJid(fulljid); this.resource = this.getResourceFromJid(fulljid); } } }else{ //console.log("xmppService::onBindResource() No Bind Element Found"); } this.onLogin(); }else if(msg.getAttribute('type')=='error'){ //console.log("xmppSession::onBindResource() Bind Error ", msg); var err = this.processXmppError(msg); this.onLoginFailure(err); } return msg }, onSearchResults: function(results){ //console.log("xmppSession::onSearchResult() ", results); }, onRetrieveRoster: function(msg){ ////console.log("xmppService::onRetrieveRoster() ", arguments); if ((msg.getAttribute('type')=='result') && msg.hasChildNodes()){ var query = msg.getElementsByTagName('query')[0]; if (query.getAttribute('xmlns')=="jabber:iq:roster"){ for (var i=0;i"); } request.append(""); this.dispatchPacket(request.toString()); }, getBareJid: function(jid){ var i = jid.indexOf('/'); if (i != -1){ return jid.substring(0, i); } return jid; }, getResourceFromJid: function(jid){ var i = jid.indexOf('/'); if (i != -1){ return jid.substring((i + 1), jid.length); } return ""; } });