/** * This program is distributed under the terms of the MIT license. * Please see the LICENSE file for details. * * Copyright 2008 Michael Garvin */ var TROPHYIM_BOSH_SERVICE = "/proxy/ejabberd"; //Change to suit var TROPHYIM_LOG_LINES = 200; var TROPHYIM_LOGLEVEL = 0; //0=debug, 1=info, 2=warn, 3=error, 4=fatal var TROPHYIM_VERSION = "0.3"; var TROPHYIM_RESOURCE = "/JABBERITWEB"; var TROPHYIM_CHATROOM = "conference.im.pr.gov.br"; //Uncomment to make session reattachment work //var TROPHYIM_JSON_STORE = "json_store.php"; /** Object: DOMObjects * This class contains builders for all the DOM objects needed by TrophyIM */ DOMObjects = { /** Function: xmlParse * Cross-browser alternative to using innerHTML * Parses given string, returns valid DOM HTML object * * Parameters: * (String) xml - the xml string to parse */ xmlParse : function(xmlString) { var xmlObj = this.xmlRender(xmlString); if(xmlObj) { try { //Firefox, Gecko, etc if (this.processor == undefined) { this.processor = new XSLTProcessor(); this.processor.importStylesheet(this.xmlRender( '\ \ ')); } var htmlObj = this.processor.transformToDocument(xmlObj).documentElement; //Safari has a quirk where it wraps dom elements in if (htmlObj.tagName.toLowerCase() == 'html') { htmlObj = htmlObj.firstChild.firstChild; } return document.importNode(htmlObj, true); } catch(e) { try { //IE is so very very special var htmlObj = document.importNode(xmlObj.documentElement, true); if (htmlObj.tagName.toLowerCase() == "div") { var div_wrapper = document.createElement('div'); div_wrapper.appendChild(htmlObj); if(div_wrapper.innerHTML) { div_wrapper.innerHTML = div_wrapper.innerHTML; } htmlObj = div_wrapper.firstChild; } return htmlObj; } catch(e) { alert("TrophyIM Error: Cannot add html to page " + e.message); } } } }, /** Function: xmlRender * Uses browser-specific methods to turn given string into xml object * * Parameters: * (String) xml - the xml string to parse */ xmlRender : function(xmlString) { try {//IE var renderObj = new ActiveXObject("Microsoft.XMLDOM"); renderObj.async="false"; if(xmlString) { renderObj.loadXML(xmlString); } } catch (e) { try { //Firefox, Gecko, etc if (this.parser == undefined) { this.parser = new DOMParser(); } var renderObj = this.parser.parseFromString(xmlString, "application/xml"); } catch(e) { alert("TrophyIM Error: Cannot create new html for page"); } } return renderObj; }, /** Function: getHTML * Returns named HTML snippet as DOM object * * Parameters: * (String) name - name of HTML snippet to retrieve (see HTMLSnippets * object) */ getHTML : function(page) { return this.xmlParse(HTMLSnippets[page]); }, /** Function: getScript * Returns script object with src to given script * * Parameters: * (String) script - name of script to put in src attribute of script * element */ getScript : function(script) { var newscript = document.createElement('script'); newscript.setAttribute('src', script); newscript.setAttribute('type', 'text/javascript'); return newscript; } }; /** Object: TrophyIM * * This is the actual TrophyIM application. It searches for the * 'trophyimclient' element and inserts itself into that. */ TrophyIM = { controll : { notificationNewUsers : 0 }, /** AutoConnection * */ autoConnection : { connect : true }, /** Object: chatHistory * * Stores chat history (last 10 message) and current presence of active * chat tabs. Indexed by jid. */ chatHistory : {}, /** Constants: * * (Boolean) stale_roster - roster is stale and needs to be rewritten. */ constants : {stale_roster: false}, /** PosWindow * */ posWindow : { left : 400, top : 100 }, /** StatusConnection * */ statusConn : { connected : false }, /** TimeOut Render Roster * * */ _timeOut : { renderRoster : null }, /** Function: setCookie * * Sets cookie name/value pair. Date and path are auto-selected. * * Parameters: * (String) name - the name of the cookie variable * (String) value - the value of the cookie variable */ setCookie : function(name, value) { var expire = new Date(); expire.setDate(expire.getDate() + 365); document.cookie = name + "=" + value + "; expires=" + expire.toGMTString(); }, /** Function: delCookie * * Deletes cookie * * Parameters: * (String) name) - the name of the cookie to delete */ delCookie : function(name) { var expire = new Date(); expire.setDate(expire.getDate() - 365); document.cookie = name + "= ; expires=" + expire.toGMTString(); delete TrophyIM.cookies[name]; }, /** Function: getCookies * * Retrieves all trophyim cookies into an indexed object. Inteneded to be * called once, at which time the app refers to the returned object instead * of re-parsing the cookie string every time. * * Each cookie is also re-applied so as to refresh the expiry date. */ getCookies : function() { var cObj = {}; var cookies = document.cookie.split(';'); for(var i = 0 ; i < cookies.length; i++ ) { while ( cookies[i].charAt(0) == ' ') { cookies[i] = cookies[i].substring(1,cookies[i].length); } if (cookies[i].substr(0, 8) == "trophyim") { var nvpair = cookies[i].split("=", 2); cObj[nvpair[0]] = nvpair[1]; TrophyIM.setCookie(nvpair[0], nvpair[1]); } } return cObj; }, /** Function: load * * This function searches for the trophyimclient div and loads the client * into it. */ load : function() { if( loadscript.getUserCurrent() == null ) { loadscript.setUserCurrent(); } if ( !TrophyIM.statusConn.connected ) { TrophyIM.cookies = TrophyIM.getCookies(); //Wait a second to give scripts time to load setTimeout( "TrophyIM.showLogin()", 550 ); } else { loadscript.rosterDiv(); } }, /** Function: storeData * * Store all our data in the JSONStore, if it is active */ storeData : function() { if ( TrophyIM.connection && TrophyIM.connection.connected ) { TrophyIM.setCookie('trophyim_bosh_xid', TrophyIM.connection.jid + "|" + TrophyIM.connection.sid + "|" + TrophyIM.connection.rid); TrophyIM.rosterObj.save(); } }, /** Function: showlogin * * This function clears out the IM box and either redisplays the login * page, or re-attaches to Strophe, preserving the logging div if it * exists, or creating a new one of we are re-attaching. */ showLogin : function() { /** * * JSON is the last script to load, so we wait on it * Added Strophe check too because of bug where it's sometimes missing * */ if ( typeof(JSON) != undefined && typeof(Strophe) != undefined ) { TrophyIM.JSONStore = new TrophyIMJSONStore(); if ( TrophyIM.JSONStore.store_working && TrophyIM.cookies['trophyim_bosh_xid'] ) { var xids = TrophyIM.cookies['trophyim_bosh_xid'].split("|"); TrophyIM.delCookie('trophyim_bosh_xid'); TrophyIM.constants.stale_roster = true; TrophyIM.connection = new Strophe.Connection(TROPHYIM_BOSH_SERVICE); TrophyIM.connection.rawInput = TrophyIM.rawInput; TrophyIM.connection.rawOutput = TrophyIM.rawOutput; //Strophe.log = TrophyIM.log; Strophe.info('Attempting Strophe attach.'); TrophyIM.connection.attach(xids[0], xids[1], xids[2], TrophyIM.onConnect); TrophyIM.onConnect(Strophe.Status.CONNECTED); } else { // List Contact loadscript.rosterDiv(); // Get User Current; var _getUserCurrent = null; var _flag = 0; do { _getUserCurrent = loadscript.getUserCurrent(); _flag++; }while( ( _getUserCurrent == null || _flag > 3 ) ) TrophyIM.login( Base64.decode( _getUserCurrent.jid ), Base64.decode( _getUserCurrent.password )); } } else { setTimeout("TrophyIM.showLogin()", 500); } }, /** Function: log * * This function logs the given message in the trophyimlog div * * Parameter: (String) msg - the message to log */ log : function(level, msg) { if (TrophyIM.logging_div && level >= TROPHYIM_LOGLEVEL) { while(TrophyIM.logging_div.childNodes.length > TROPHYIM_LOG_LINES) { TrophyIM.logging_div.removeChild( TrophyIM.logging_div.firstChild ); } var msg_div = document.createElement('div'); msg_div.className = 'trophyimlogitem'; msg_div.appendChild(document.createTextNode(msg)); TrophyIM.logging_div.appendChild(msg_div); TrophyIM.logging_div.scrollTop = TrophyIM.logging_div.scrollHeight; } }, /** Function: rawInput * * This logs the packets actually recieved by strophe at the debug level */ rawInput : function (data) { Strophe.debug("RECV: " + data); }, /** Function: rawInput * * This logs the packets actually recieved by strophe at the debug level */ rawOutput : function (data) { Strophe.debug("SEND: " + data); }, /** Function: login * * This function logs into server using information given on login page. * Since the login page is where the logging checkbox is, it makes or * removes the logging div and cookie accordingly. * */ login : function() { if ( TrophyIM.JSONStore.store_working ) { //In case they never logged out TrophyIM.JSONStore.delData(['groups','roster', 'active_chat', 'chat_history']); } TrophyIM.connection = new Strophe.Connection(TROPHYIM_BOSH_SERVICE); TrophyIM.connection.rawInput = TrophyIM.rawInput; TrophyIM.connection.rawOutput = TrophyIM.rawOutput; //Strophe.log = TrophyIM.log; if ( arguments.length > 0 ) { var barejid = arguments[0]; var password = arguments[1]; TrophyIM.connection.connect( barejid + TROPHYIM_RESOURCE, password, TrophyIM.onConnect ); } else { var barejid = document.getElementById('trophyimjid').value var fulljid = barejid + TROPHYIM_RESOURCE; var password = document.getElementById('trophyimpass').value; var button = document.getElementById('trophyimconnect'); loadscript.setUserCurrent( barejid, password); if ( button.value == 'connect' ) { button.value = 'disconnect'; //TrophyIM.connection.connect( fulljid , password, TrophyIM.onConnect ); TrophyIM.login( barejid, password ); _winBuild('window_login_page', 'remove'); } } TrophyIM.setCookie('trophyimjid', barejid); }, /** Function: logout * * Logs into fresh session through Strophe, purging any old data. */ logout : function() { TrophyIM.autoConnection.connect = false; TrophyIM.delCookie('trophyim_bosh_xid'); delete TrophyIM['cookies']['trophyim_bosh_xid']; TrophyIM.connection.disconnect(); }, /** Function onConnect * * Callback given to Strophe upon connection to BOSH proxy. */ onConnect : function(status) { var loading_gif = document.getElementById("JabberIMRosterLoadingGif"); if( status == Strophe.Status.CONNECTING ) { loading_gif.style.display = "block"; Strophe.info('Strophe is connecting.'); } if( status == Strophe.Status.CONNFAIL ) { TrophyIM.delCookie('trophyim_bosh_xid'); TrophyIM.statusConn.connected = false; loading_gif.style.display = "block"; } if( status == Strophe.Status.DISCONNECTING ) { TrophyIM.statusConn.connected = false; } if( status == Strophe.Status.DISCONNECTED ) { if( TrophyIM.autoConnection.connect ) { loading_gif.style.display = "block"; TrophyIM.delCookie('trophyim_bosh_xid'); TrophyIM.statusConn.connected = false; setTimeout(function() { TrophyIM.showLogin(); },10000); loadscript.clrAllContacts(); loadscript.setStatusJabber(i18n.STATUS_ANAVAILABLE,"unavailable"); delete TrophyIM.rosterObj.roster; delete TrophyIM.rosterObj.groups; } } if( status == Strophe.Status.CONNECTED ) { loadscript.setStatusJabber(i18n.STATUS_AVAILABLE,'available'); TrophyIM.statusConn.connected = true; TrophyIM.showClient(); } }, /** Function: showClient * * This clears out the main div and puts in the main client. It also * registers all the handlers for Strophe to call in the client. */ showClient : function() { TrophyIM.setCookie('trophyim_bosh_xid', TrophyIM.connection.jid + "|" + TrophyIM.connection.sid + "|" + TrophyIM.connection.rid); TrophyIM.rosterObj = new TrophyIMRoster(); TrophyIM.connection.addHandler(TrophyIM.onVersion, Strophe.NS.VERSION, 'iq', null, null, null); TrophyIM.connection.addHandler(TrophyIM.onRoster, Strophe.NS.ROSTER, 'iq', null, null, null); TrophyIM.connection.addHandler(TrophyIM.onPresence, null, 'presence', null, null, null); TrophyIM.connection.addHandler(TrophyIM.onMessage, null, 'message', null, null, null); //Get roster then announce presence. TrophyIM.connection.send($iq({type: 'get', xmlns: Strophe.NS.CLIENT}).c('query', {xmlns: Strophe.NS.ROSTER}).tree()); TrophyIM.connection.send($pres().tree()); setTimeout( TrophyIM.renderRoster, 1000); }, /** Function: clearClient * * Clears out client div, preserving and returning existing logging_div if * one exists */ clearClient : function() { if(TrophyIM.logging_div) { var logging_div = TrophyIM.client_div.removeChild(document.getElementById('trophyimlog')); } else { var logging_div = null; } while(TrophyIM.client_div.childNodes.length > 0) { TrophyIM.client_div.removeChild(TrophyIM.client_div.firstChild); } return logging_div; }, /** Function: onVersion * * jabber:iq:version query handler */ onVersion : function(msg) { Strophe.debug("Version handler"); if (msg.getAttribute('type') == 'get') { var from = msg.getAttribute('from'); var to = msg.getAttribute('to'); var id = msg.getAttribute('id'); var reply = $iq({type: 'result', to: from, from: to, id: id}).c('query', {name: "TrophyIM", version: TROPHYIM_VERSION, os: "Javascript-capable browser"}); TrophyIM.connection.send(reply.tree()); } return true; }, /** Function: onRoster * * Roster iq handler */ onRoster : function(msg) { var roster_items = msg.firstChild.getElementsByTagName('item'); for (var i = 0; i < roster_items.length; i++) { with(roster_items[i]) { var groups = getElementsByTagName('group'); var group_array = []; for( var g = 0 ; g < groups.length; g++ ) { if( groups[g].hasChildNodes() ) group_array[group_array.length] = groups[g].firstChild.nodeValue; } if( getAttribute('ask') && getAttribute('ask').toString() === "subscribe" ) { if( getAttribute('subscription').toString() === "none" ) { TrophyIM.rosterObj.addContact( getAttribute('jid'), getAttribute('ask'), getAttribute('name'), group_array ); } if( getAttribute('subscription').toString() === "remove" ) { TrophyIM.rosterObj.removeContact( getAttribute('jid').toString() ); } } else { if( ( getAttribute('ask') == null && getAttribute('subscription').toString() === "remove" ) || getAttribute('subscription').toString() === "remove" ) { TrophyIM.rosterObj.removeContact( getAttribute('jid').toString() ); } else { TrophyIM.rosterObj.addContact( getAttribute('jid'), getAttribute('subscription'), getAttribute('name'), group_array ); } } } } if ( msg.getAttribute('type') == 'set' ) { var _iq = $iq({type: 'reply', id: msg.getAttribute('id'), to: msg.getAttribute('from')}); TrophyIM.connection.send( _iq.tree()); } return true; }, /** Function: onPresence * * Presence Handler */ onPresence : function(msg) { // Get Presences ChatRoom TrophyIM.onPresenceChatRoom( msg ); var type = msg.getAttribute('type') ? msg.getAttribute('type') : 'available'; var show = msg.getElementsByTagName('show').length ? Strophe.getText(msg.getElementsByTagName('show')[0]) : type; var status = msg.getElementsByTagName('status').length ? Strophe.getText(msg.getElementsByTagName('status')[0]) : ''; var priority = msg.getElementsByTagName('priority').length ? parseInt(Strophe.getText(msg.getElementsByTagName('priority')[0])) : 0; if( msg.getAttribute('from').toString().indexOf( TROPHYIM_CHATROOM ) < 0 ) { TrophyIM.rosterObj.setPresence( msg.getAttribute('from'), priority, show, status ); } return true; }, /** Function : onPresenceChatRoom * * Presence ChatRoom Handler */ onPresenceChatRoom : function(msg) { var xquery = msg.getElementsByTagName("x"); if ( xquery.length > 0 ) { for ( var i = 0; i < xquery.length; i++ ) { var xmlns = xquery[i].getAttribute("xmlns"); if( xmlns.indexOf("http://jabber.org/protocol/muc#user") == 0 ) { var _from = xquery[i].parentNode.getAttribute('from'); var _to = xquery[i].parentNode.getAttribute('to'); // Get NameChatRoom var nameChatRoom = Strophe.getBareJidFromJid( _from ); // Get nickName var nickName = Strophe.getResourceFromJid( _from ); var type = ( xquery[i].parentNode.getAttribute('type') != null ) ? xquery[i].parentNode.getAttribute('type') : 'available' ; var show = type; // Get Jid/From = idElement var _idElement = ( xquery[i].firstChild.getAttribute('jid') != null ) ? xquery[i].firstChild.getAttribute('jid') : xquery[i].parentNode.getAttribute('from') ; _idElement = nameChatRoom + "_UserChatRoom__" + _idElement; var _UserChatRoom = document.createElement("div"); _UserChatRoom.id = _idElement; _UserChatRoom.setAttribute("style","padding-left:18px ; margin:3px 0px 0px 2px; background: url('"+path_jabberit+"templates/default/images/" + show + ".gif')no-repeat center left"); _UserChatRoom.appendChild( document.createTextNode(nickName) ); var nodeUser = document.getElementById( _idElement ); if( nodeUser == null && xquery[i].firstChild.getAttribute('jid') ) { if( document.getElementById( nameChatRoom + '__roomChat__participants' ) != null ) { nameChatRoom = document.getElementById( nameChatRoom + '__roomChat__participants' ); nameChatRoom.appendChild( _UserChatRoom ); } else { TrophyIM.makeChatRoom( nameChatRoom, nameChatRoom.substring(0, nameChatRoom.indexOf('@')) ); nameChatRoom = document.getElementById( nameChatRoom + '__roomChat__participants' ); nameChatRoom.appendChild( _UserChatRoom ); } } else { if( type == 'unavailable' ) { var nodeUser = ""; if( xquery[i].firstChild.getAttribute('jid') != null ) nodeUser = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid') ); else nodeUser = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].parentNode.getAttribute('to') ); nodeUser.parentNode.removeChild( nodeUser ); } else if( show ) { var _UserChatRoom = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid') ) _UserChatRoom.setAttribute("style","padding-left:18px ; margin:3px 0px 0px 2px; background: url('"+path_jabberit+"templates/default/images/" + show + ".gif')no-repeat center left"); } } } /*if( xmlns.indexOf("http://jabber.org/protocol/muc#user") == 0 ) { var nameChatRoom = xquery[i].parentNode.getAttribute('from'); nameChatRoom = Strophe.getBareJidFromJid(nameChatRoom); var nickName = xquery[i].parentNode.getAttribute('from'); nickName = Strophe.getResourceFromJid(nickName); var type = ( xquery[i].parentNode.getAttribute('type') != null ) ? xquery[i].parentNode.getAttribute('type') : 'available' ; var show = ( xquery[i].parentNode.firstChild.firstChild.nodeName.toLowerCase() == "show" ) ? xquery[i].parentNode.firstChild.firstChild.nodeValue : type ; if( xquery[i].firstChild.getAttribute('jid') ) { if ( Strophe.getBareJidFromJid( xquery[i].firstChild.getAttribute('jid') ) == Strophe.getBareJidFromJid( TrophyIM.connection.jid ) ) show = loadscript.getStatusUserIM(); } var _UserChatRoom = document.createElement("div"); _UserChatRoom.id = nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid'); _UserChatRoom.setAttribute("style","padding-left:18px ; margin:3px 0px 0px 2px; background: url('"+path_jabberit+"templates/default/images/" + show + ".gif')no-repeat center left"); _UserChatRoom.appendChild( document.createTextNode(nickName) ); var nodeUser = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid') ); if( nodeUser == null && xquery[i].firstChild.getAttribute('jid') ) { if( document.getElementById( nameChatRoom + '__roomChat__participants' ) != null ) { nameChatRoom = document.getElementById( nameChatRoom + '__roomChat__participants' ); nameChatRoom.appendChild( _UserChatRoom ); } else { TrophyIM.makeChatRoom( nameChatRoom, nameChatRoom ); nameChatRoom = document.getElementById( nameChatRoom + '__roomChat__participants' ); nameChatRoom.appendChild( _UserChatRoom ); } } else { if( type == 'unavailable' ) { var nodeUser = ""; if( xquery[i].firstChild.getAttribute('jid') != null ) nodeUser = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid') ); else nodeUser = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].parentNode.getAttribute('to') ); nodeUser.parentNode.removeChild( nodeUser ); } else if( show ) { var _UserChatRoom = document.getElementById( nameChatRoom + "_UserChatRoom__" + xquery[i].firstChild.getAttribute('jid') ) _UserChatRoom.setAttribute("style","padding-left:18px ; margin:3px 0px 0px 2px; background: url('"+path_jabberit+"templates/default/images/" + show + ".gif')no-repeat center left"); } } }*/ } } }, /** Function: onMessage * * Message handler */ onMessage : function(msg) { var checkTime = function(i) { if ( i < 10 ) i= "0" + i; return i; }; var messageDate = function( _date ) { var _dt = _date.substr( 0, _date.indexOf( 'T' ) ).split( '-' ); var _hr = _date.substr( _date.indexOf( 'T' ) + 1, _date.length - _date.indexOf( 'T' ) - 2 ).split( ':' ); ( _date = new Date ).setTime( Date.UTC( _dt[0], _dt[1] - 1, _dt[2], _hr[0], _hr[1], _hr[2] ) ); return ( _date.toLocaleDateString( ).replace( /-/g, '/' ) + ' ' + _date.toLocaleTimeString( ) ); }; var data = new Date(); var dtNow = checkTime(data.getHours()) + ":" + checkTime(data.getMinutes()) + ":" + checkTime(data.getSeconds()); var from = msg.getAttribute('from'); var type = msg.getAttribute('type'); var elems = msg.getElementsByTagName('body'); var delay = ( msg.getElementsByTagName('delay') ) ? msg.getElementsByTagName('delay') : null; var stamp = ( delay[0] != null ) ? "" + messageDate(delay[0].getAttribute('stamp')) + "" : dtNow; var barejid = Strophe.getBareJidFromJid(from); var jidChatRoom = Strophe.getResourceFromJid(from); var jid_lower = barejid.toLowerCase(); var contact = ""; var state = ""; var chatBox = document.getElementById(jid_lower + "__chatState"); var chatStateOnOff = null; var active = msg.getElementsByTagName('active'); contact = barejid.toLowerCase(); contact = contact.substring(0, contact.indexOf('@')); if( TrophyIM.rosterObj.roster[barejid] ) { if( TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'] ) { contact = TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name']; } } // Message with body are "content message", this means state active if ( elems.length > 0 ) { state = ""; // Set notify chat state capability on when sender notify it themself chatStateOnOff = document.getElementById(jid_lower + "__chatStateOnOff"); if (active.length > 0 & chatStateOnOff != null ) { chatStateOnOff.value = 'on'; } // Get Message var _message = document.createElement("div"); _message.innerHTML = Strophe.getText(elems[0]); var scripts = _message.getElementsByTagName('script'); for (var i = 0; i < scripts.length; i++) _message.removeChild(scripts[i--]); _message.innerHTML = _message.innerHTML.replace(/^\s+|\s+$|^\n|\n$/g, ""); // Get Smiles _message.innerHTML = loadscript.getSmiles( _message.innerHTML ); if (type == 'chat' || type == 'normal') { if ( _message.hasChildNodes() ) { var message = { contact : "[" + stamp + "] " + contact + "", msg : "
" + _message.innerHTML }; TrophyIM.addMessage( TrophyIM.makeChat( from ), jid_lower, message ); } } else if( type == 'groupchat') { if ( _message.hasChildNodes() ) { var message = { contact : "[" + stamp + "] " + jidChatRoom + "", msg : "
" + _message.innerHTML }; TrophyIM.addMessage( TrophyIM.makeChatRoom( barejid ), jid_lower, message ); } } } // Message without body are "content message", this mean state is not active else { if( chatBox != null ) state = TrophyIM.getChatState(msg); } // Clean chat status message some time later var clearChatState = function() { chatBox.innerHTML=''; } if (chatBox != null) { var clearChatStateTimer; chatBox.innerHTML = "" + state + ""; var _composing = msg.getElementsByTagName('composing'); if ( _composing.length == 0 ) clearChatStateTimer = setTimeout(clearChatState, 2000); else clearTimeout(clearChatStateTimer); } return true; }, /** Function: getChatState * * Parameters: * (string) msg - the message to get chat state * (string) jid - the jid of chat box to update the chat state to. */ getChatState : function(msg) { var state = msg.getElementsByTagName('inactive'); if ( state.length > 0 ) { return i18n.INACTIVE; } else { state = msg.getElementsByTagName('gone'); if ( state.length > 0 ) { return i18n.GONE; } else { state = msg.getElementsByTagName('composing'); if ( state.length > 0 ) { return i18n.COMPOSING; } else { state = msg.getElementsByTagName('paused'); if ( state.length > 0 ) { return i18n.PAUSED; } } } } return ''; }, /** Function: makeChat * * Make sure chat window to given fulljid exists, switching chat context to * given resource. */ makeChat : function(fulljid) { var barejid = Strophe.getBareJidFromJid(fulljid); var titleWindow = ""; var paramsChatBox = { 'enabledPopUp' : ( ( loadscript.getIsIE() ) ? "none" : "block" ), 'idChatBox' : barejid + "__chatBox", 'jidTo' : barejid, 'path_jabberit' : path_jabberit }; titleWindow = barejid.toLowerCase(); titleWindow = titleWindow.substring(0, titleWindow.indexOf('@')); if( TrophyIM.rosterObj.roster[barejid] ) { if( TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'] ) { titleWindow = TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name']; } } // Position Top TrophyIM.posWindow.top = TrophyIM.posWindow.top + 10; if( TrophyIM.posWindow.top > 200 ) TrophyIM.posWindow.top = 100; // Position Left TrophyIM.posWindow.left = TrophyIM.posWindow.left + 5; if( TrophyIM.posWindow.left > 455 ) TrophyIM.posWindow.left = 400; var _content = document.createElement( 'div' ); _content.innerHTML = loadscript.parse( "chat_box", "chatBox.xsl", paramsChatBox); _content = _content.firstChild; var _messages = _content.firstChild.firstChild; var _textarea = _content.getElementsByTagName( 'textarea' ).item( 0 ); var _send = _content.getElementsByTagName( 'input' ).item( 0 ); var _chatStateOnOff = _content.getElementsByTagName( 'input' ).item( 1 ); var _send_message = function( ) { if ( ! TrophyIM.sendMessage( barejid, _textarea.value ) ) return false; // Add Message in chatBox; TrophyIM.addMessage( _messages, barejid, { contact : "" + i18n.ME + "", msg : "
" + _textarea.value } ); _textarea.value = ''; _textarea.focus( ); }; var composingTimer_ = 0; var isComposing_ = 0; var timeCounter; var setComposing = function( ) { var checkComposing = function() { if (!isComposing_) { // User stopped composing composingTimer_ = 0; clearInterval(timeCounter); TrophyIM.sendContentMessage(barejid, 'paused'); } else { TrophyIM.sendContentMessage(barejid, 'composing'); } isComposing_ = 0; // Reset composing } if (!composingTimer_) { /* User (re)starts composing */ composingTimer_ = 1; timeCounter = setInterval(checkComposing,4000); } isComposing_ = 1; }; loadscript.configEvents( _send, 'onclick', _send_message ); loadscript.configEvents( _textarea, 'onkeyup', function( e ) { if ( e.keyCode == 13 ){ _send_message( ); // User stopped composing composingTimer_ = 0; clearInterval(timeCounter); }else{ if (_chatStateOnOff.value == 'on') setComposing(); } } ); var winChatBox = { id_window : "window_chat_area_" + barejid, barejid : barejid, width : 387, height : 375, top : TrophyIM.posWindow.top, left : TrophyIM.posWindow.left, draggable : true, visible : "display", resizable : true, zindex : loadscript.getZIndex(), title : titleWindow, closeAction : "hidden", content : _content } _win = _winBuild(winChatBox); // Notification New Message loadscript.notification(barejid); // Photo User; loadscript.getPhotoUser(barejid); _textarea.focus( ); return ( _messages = _win.content( ).firstChild ); }, /** Function: makeChatRoom * * * */ makeChatRoom : function() { var jidChatRoom = arguments[0]; var titleWindow = "ChatRoom - " + arguments[1]; var paramsChatRoom = { 'idChatRoom' : jidChatRoom + "__roomChat", 'jidTo' : jidChatRoom, 'lang_Send' : i18n.SEND, 'lang_Leave_ChatRoom' : i18n.LEAVE_CHATROOM, 'path_jabberit' : path_jabberit }; // Position Top TrophyIM.posWindow.top = TrophyIM.posWindow.top + 10; if( TrophyIM.posWindow.top > 200 ) TrophyIM.posWindow.top = 100; // Position Left TrophyIM.posWindow.left = TrophyIM.posWindow.left + 5; if( TrophyIM.posWindow.left > 455 ) TrophyIM.posWindow.left = 400; var _content = document.createElement( 'div' ); _content.innerHTML = loadscript.parse( "chat_room", "chatRoom.xsl", paramsChatRoom ); _content = _content.firstChild; var _messages = _content.firstChild.firstChild; var _textarea = _content.getElementsByTagName( 'textarea' ).item( 0 ); var _send = _content.getElementsByTagName( 'input' ).item( 0 ); var _leaveChatRoom = _content.getElementsByTagName( 'input' ).item( 1 ); var _send_message = function( ) { if ( ! TrophyIM.sendMessageChatRoom( jidChatRoom, _textarea.value ) ) return false; _textarea.value = ''; _textarea.focus( ); }; loadscript.configEvents( _send, 'onclick', _send_message ); loadscript.configEvents( _leaveChatRoom, 'onclick', function( ) { TrophyIM.leaveChatRoom( jidChatRoom ); setTimeout( function() { _winBuild('window_chat_room_' + jidChatRoom, 'remove'); }, 500 ); }); loadscript.configEvents( _textarea, 'onkeyup', function( e ) { if ( e.keyCode == 13 ) { _send_message( ); } }); var winChatRoom = { id_window : "window_chat_room_" + arguments[0], barejid : jidChatRoom, width : 500, height : 450, top : TrophyIM.posWindow.top, left : TrophyIM.posWindow.left, draggable : true, visible : "display", resizable : true, zindex : loadscript.getZIndex(), title : titleWindow, closeAction : "hidden", content : _content } _win = _winBuild(winChatRoom); return ( _messages = _win.content( ).firstChild ); }, /** Function addContacts * * Parameters: * (string) jidFrom * (string) jidTo * (string) name * (string) group */ addContact : function( jidTo, name, group ) { // Add Contact var _id = TrophyIM.connection.getUniqueId('add'); var newContact = $iq({type: 'set', id: _id }); newContact = newContact.c('query').attrs({xmlns : 'jabber:iq:roster'}); newContact = newContact.c('item').attrs({jid: jidTo, name:name }); newContact = newContact.c('group').t(group).tree(); TrophyIM.connection.send(newContact); }, /** Function: add * * Parameters: * (string) msg - the message to add * (string) jid - the jid of chat box to add the message to. */ addMessage : function( chatBox, jid, msg ) { // Get Smiles msg.msg = loadscript.getSmiles( msg.msg ); var messageDiv = document.createElement("div"); messageDiv.style.margin = "3px 0px 1em 3px"; messageDiv.innerHTML = msg.contact + " : " + msg.msg ; chatBox.appendChild(messageDiv); chatBox.scrollTop = chatBox.scrollHeight; }, /** Function : renameContact * * */ renameContact : function( jid ) { // Name var name = TrophyIM.rosterObj.roster[jid].contact.name; if(( name = prompt(i18n.ASK_NEW_NAME_QUESTION + name + "!", name ))) if(( name = name.replace(/^\s+|\s+$|^\n|\n$/g,"")) == "" ) name = ""; if( name == null || name == "") name = ""; var jidTo = jid var name = ( name ) ? name : TrophyIM.rosterObj.roster[jid].contact.name; var group = TrophyIM.rosterObj.roster[jid].contact.groups[0]; TrophyIM.addContact( jidTo, name, group ); document.getElementById('itenContact_' + jid ).innerHTML = name; }, /** Function : renameGroup * * */ renameGroup : function( jid ) { var group = TrophyIM.rosterObj.roster[jid].contact.groups[0]; var presence = TrophyIM.rosterObj.roster[jid].presence; // Group if(( group = prompt( i18n.ASK_NEW_GROUP_QUESTION, group ))) if(( group = group.replace(/^\s+|\s+$|^\n|\n$/g,"")) == "" ) group = ""; if( group == null || group == "") group = ""; var jidTo = TrophyIM.rosterObj.roster[jid].contact.jid; var name = TrophyIM.rosterObj.roster[jid].contact.name; var group = ( group ) ? group : TrophyIM.rosterObj.roster[jid].contact.groups[0]; TrophyIM.rosterObj.removeContact( jid ); TrophyIM.addContact( jidTo, name, group ); document.getElementById("JabberIMRoster").innerHTML = ""; TrophyIM.renderRoster(); setTimeout(function() { for( var i in presence ) { if ( presence[ i ].constructor == Function ) continue; TrophyIM.rosterObj.setPresence( jid, presence[i].priority, presence[i].show, presence[i].status); } },500); }, /** Function createChatRooms * * */ createChatRooms : function() { var nickName = document.getElementById('nickName_chatRoom_jabberit').value; var nameChatRoom = document.getElementById('name_ChatRoom_jabberit').value; var _from = Base64.decode( loadscript.getUserCurrent().jid ) + TROPHYIM_RESOURCE; var _to = escape( nameChatRoom ) + "@" + TROPHYIM_CHATROOM + "/" + nickName ; var new_room = $pres( {from: _from, to: _to } ).c( "x", { xmlns: Strophe.NS.MUC } ); TrophyIM.connection.send( new_room.tree() ); }, /** Function : joinRoom * * */ joinChatRoom : function( roomName ) { var presence = $pres( {from: TrophyIM.connection.jid, to: roomName} ).c("x",{xmlns: Strophe.NS.MUC}); TrophyIM.connection.send( presence ); }, /** Function : Leave Chat Room * * */ leaveChatRoom : function( roomName ) { var room_nick = roomName; var presenceid = TrophyIM.connection.getUniqueId(); var presence = $pres( {type: "unavailable", id: presenceid, from: TrophyIM.connection.jid, to: room_nick} ).c("x",{xmlns: Strophe.NS.MUC}); TrophyIM.connection.send( presence ); }, /** Function : getlistRooms * * */ getListRooms : function() { var _error_return = function(element) { alert( " ERROR : " + element ); }; var iq = $iq({to: "conference.im.pr.gov.br", type: "get"}).c("query",{xmlns: Strophe.NS.DISCO_ITEMS}); TrophyIM.connection.sendIQ( iq, loadscript.listRooms, _error_return, 500 ); }, /** Function: removeContact * * Parameters: * (string) jidTo */ removeContact : function( jidTo ) { var divItenContact = null; if( ( divItenContact = document.getElementById('itenContact_' + jidTo ))) { // Remove Contact var _id = TrophyIM.connection.getUniqueId(); var delContact = $iq({type: 'set', id: _id}) delContact = delContact.c('query').attrs({xmlns : 'jabber:iq:roster'}); delContact = delContact.c('item').attrs({jid: jidTo, subscription:'remove'}).tree(); TrophyIM.connection.send( delContact ); loadscript.removeElement( document.getElementById('itenContactNotification_' + jidTo ) ); var spanShow = document.getElementById('span_show_itenContact_' + jidTo ) spanShow.parentNode.removeChild(spanShow); loadscript.removeGroup( divItenContact.parentNode ); divItenContact.parentNode.removeChild(divItenContact); } }, /** Function: renderRoster * * Renders roster, looking only for jids flagged by setPresence as having * changed. */ renderRoster : function() { var roster_div = document.getElementById('JabberIMRoster'); if( roster_div ) { var users = new Array(); var loading_gif = document.getElementById("JabberIMRosterLoadingGif"); if( loading_gif.style.display == "block" ) loading_gif.style.display = "none"; for( var user in TrophyIM.rosterObj.roster ) { if ( TrophyIM.rosterObj.roster[ user ].constructor == Function ) continue; users[users.length] = TrophyIM.rosterObj.roster[user].contact.jid; } users.sort(); var groups = new Array(); var flagGeral = false; for (var group in TrophyIM.rosterObj.groups) { if ( TrophyIM.rosterObj.groups[ group ].constructor == Function ) continue; if( group ) groups[groups.length] = group; if( group == "Geral" ) flagGeral = true; } if( !flagGeral && users.length > 0 ) groups[groups.length] = "Geral"; groups.sort(); for ( var i = 0; i < groups.length; i++ ) { TrophyIM.renderGroups( groups[i] , roster_div ); } TrophyIM.renderItensGroup( users, roster_div ); } TrophyIM._timeOut.renderRoster = setTimeout("TrophyIM.renderRoster()", 1000 ); }, /** Function: renderGroups * * */ renderGroups: function( nameGroup, element ) { var _addGroup = function() { var _nameGroup = nameGroup; var _element = element; var paramsGroup = { 'nameGroup' : _nameGroup, 'path_jabberit' : path_jabberit } _element.innerHTML += loadscript.parse("group","groups.xsl", paramsGroup); } if( !element.hasChildNodes() ) { _addGroup(); } else { var _NodeChild = element.firstChild; var flagAdd = false; while( _NodeChild ) { if( _NodeChild.childNodes[0].nodeName.toLowerCase() === "span" ) { if( _NodeChild.childNodes[0].childNodes[0].nodeValue === nameGroup ) { flagAdd = true; } } _NodeChild = _NodeChild.nextSibling; } if( !flagAdd ) { _addGroup(); } } }, /** Function: renderItensGroup * * */ renderItensGroup : function( users, element ) { var addItem = function() { if( arguments.length > 0 ) { // Get Arguments var objContact = arguments[0]; var group = arguments[1]; var element = arguments[2]; var showOffline = loadscript.getShowContactsOffline(); // Presence e Status var presence = "unavailable"; var status = ""; var statusColor = "black"; var statusDisplay = "none"; var _resource = ""; // Set Presence var _presence = function(objContact) { if (objContact.presence) { for (var resource in objContact.presence) { if ( objContact.presence[resource].constructor == Function ) continue; if( objContact.presence[resource].show != 'invisible' ) presence = objContact.presence[resource].show; if( objContact.contact.subscription != "both") presence = 'subscription'; if( objContact.presence[resource].status ) { status = " ( " + objContact.presence[resource].status + " ) "; statusDisplay = "block"; } } } }; // Set Subscription var _subscription = function( objContact ) { if( objContact.contact.subscription != "both" ) { switch( objContact.contact.subscription ) { case "none" : status = " (( " + i18n.ASK_FOR_AUTH + " )) "; statusColor = "red"; break; case "to" : status = " (( " + i18n.CONTACT_ASK_FOR_AUTH + " )) "; statusColor = "orange"; break; case "from" : status = " (( " + i18n.AUTHORIZED + " )) "; statusColor = "green"; break; case "subscribe" : status = " (( " + i18n.AUTH_SENT + " )) "; statusColor = "red"; break; case "not-in-roster" : status = " (( " + i18n.ASK_FOR_AUTH_QUESTION + " )) "; statusColor = "orange"; break; default : break; } statusDisplay = "block"; } }; if( objContact.contact.subscription != "remove") { var itensJid = document.getElementById( "itenContact_" + objContact.contact.jid ); if( itensJid == null ) { // Name var nameContact = ""; if ( objContact.contact.name ) nameContact = objContact.contact.name; else { nameContact = objContact.contact.jid; nameContact = nameContact.substring(0, nameContact.indexOf('@')); } // Get Presence _presence(objContact); var paramsContact = { divDisplay : "block", id : 'itenContact_' + objContact.contact.jid , jid : objContact.contact.jid, nameContact : nameContact, path_jabberit : path_jabberit, presence : presence, spanDisplay : statusDisplay, status : status, statusColor : "black", subscription : objContact.contact.subscription, resource : _resource } // Get Authorization _subscription( objContact ); if( group != "") { var _NodeChild = element.firstChild; while( _NodeChild ) { if( _NodeChild.childNodes[0].nodeName.toLowerCase() === "span" ) { if( _NodeChild.childNodes[0].childNodes[0].nodeValue === group ) { _NodeChild.innerHTML += loadscript.parse("itens_group", "itensGroup.xsl", paramsContact); } } _NodeChild = _NodeChild.nextSibling; } } } else { // Get Presence _presence(objContact); var is_open = itensJid.parentNode.childNodes[0].style.backgroundImage; is_open = is_open.indexOf("arrow_down.gif"); // Get Authorization _subscription( objContact ); // Set subscription itensJid.setAttribute('subscription', objContact.contact.subscription ); with ( document.getElementById('span_show_' + 'itenContact_' + objContact.contact.jid ) ) { if( presence == "unavailable" && !showOffline ) { style.display = "none"; } else { if( is_open > 0 ) { style.display = statusDisplay; style.color = statusColor; innerHTML = status; } } } if( presence == "unavailable" && !showOffline ) { itensJid.style.display = "none"; } else { if( is_open > 0 ) { itensJid.style.display = "block"; } } itensJid.style.background = "url('"+path_jabberit+"templates/default/images/" + presence + ".gif') no-repeat center left"; } // Contact OffLine if( !objContact.presence && !showOffline ) { if( objContact.contact.subscription != "remove" ) { with ( document.getElementById('span_show_' + 'itenContact_' + objContact.contact.jid )) { style.display = "none"; } with ( document.getElementById('itenContact_' + objContact.contact.jid ) ) { style.display = "none"; } } } } } }; var flag = false; for( var i = 0 ; i < users.length; i++ ) { if( TrophyIM.rosterObj.roster[users[i]].contact.jid != Base64.decode( loadscript.getUserCurrent().jid) ) { var _subscription = TrophyIM.rosterObj.roster[users[i]].contact.subscription; if( _subscription === "to" ) { flag = true; } if( _subscription === "not-in-roster") { flag = true; } if( TrophyIM.rosterObj.roster[users[i]].contact.groups ) { var groups = TrophyIM.rosterObj.roster[users[i]].contact.groups; if( groups.length > 0 ) { for( var j = 0; j < groups.length; j++ ) { addItem( TrophyIM.rosterObj.roster[users[i]], groups[j], element ); } } else { addItem( TrophyIM.rosterObj.roster[users[i]], "Geral", element ); } } else { addItem( TrophyIM.rosterObj.roster[users[i]], "Geral", element ); } } } if( flag ) { if ( TrophyIM.controll.notificationNewUsers == 0 ) { loadscript.enabledNotificationNewUsers(); TrophyIM.controll.notificationNewUsers++; } } else { loadscript.disabledNotificationNewUsers(); TrophyIM.controll.notificationNewUsers = 0; } }, /** Function: rosterClick * * Handles actions when a roster item is clicked */ rosterClick : function(fulljid) { TrophyIM.makeChat(fulljid); }, /** Function SetAutorization * */ setAutorization : function( jidTo, jidFrom, _typeSubscription ) { var _id = TrophyIM.connection.getUniqueId(); TrophyIM.connection.send($pres( ).attrs({ from: jidFrom, to: jidTo, type: _typeSubscription, id: _id }).tree()); }, /** Function: setPresence * */ setPresence : function( _type ) { if( _type != 'status') { if( _type == "unavailable" && TrophyIM.statusConn.connected ) { var loading_gif = document.getElementById("JabberIMRosterLoadingGif"); if( TrophyIM._timeOut.renderRoster != null ) clearTimeout(TrophyIM._timeOut.renderRoster); if( TrophyIM.statusConn.connected ) TrophyIM.connection.send($pres({type : _type}).tree()); for( var i = 0; i < TrophyIM.connection._requests.length; i++ ) { if( TrophyIM.connection._requests[i] ) TrophyIM.connection._removeRequest(TrophyIM.connection._requests[i]); } TrophyIM.logout(); loadscript.clrAllContacts(); delete TrophyIM.rosterObj.roster; delete TrophyIM.rosterObj.groups; setTimeout(function() { if( loading_gif.style.display == "block" ) loading_gif.style.display = "none"; }, 1000); } else { if( !TrophyIM.autoConnection.connect ) { TrophyIM.autoConnection.connect = true; TrophyIM.load(); } else { if( TrophyIM.statusConn.connected ) { if( loadscript.getStatusMessage() != "" ) { var _presence = $pres( ); _presence.node.appendChild( Strophe.xmlElement( 'show' ) ).appendChild( Strophe.xmlTextNode( _type ) ); _presence.node.appendChild( Strophe.xmlElement( 'status' ) ).appendChild( Strophe.xmlTextNode( loadscript.getStatusMessage() )); TrophyIM.connection.send( _presence.tree() ); } else { TrophyIM.connection.send($pres( ).c('show').t(_type).tree()); } } } } } else { var _show = "available"; var _status = ""; if( arguments.length < 2 ) { if( loadscript.getStatusMessage() != "" ) _status = prompt(i18n.TYPE_YOUR_MSG, loadscript.getStatusMessage()); else _status = prompt(i18n.TYPE_YOUR_MSG); var _divStatus = document.getElementById("JabberIMStatusMessage"); if( ( _status = _status.replace(/^\s+|\s+$|^\n|\n$/g,"") ) != "") _divStatus.firstChild.innerHTML = "( " + _status + " )"; } else { _status = arguments[1]; } for( var resource in TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence ) { if ( TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence[ resource ].constructor == Function ) continue; if ( TROPHYIM_RESOURCE === ("/" + resource) ) _show = TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence[resource].show; } if ( TrophyIM.statusConn.connected ) { var _presence = $pres( ); _presence.node.appendChild( Strophe.xmlElement( 'show' ) ).appendChild( Strophe.xmlTextNode( _show ) ); _presence.node.appendChild( Strophe.xmlElement( 'status' ) ).appendChild( Strophe.xmlTextNode( _status ) ); TrophyIM.connection.send( _presence.tree() ); } } }, /** Function: sendMessage * * Send message from chat input to user */ sendMessage : function() { if (arguments.length > 0) { var jidTo = arguments[0]; var message_input = arguments[1]; message_input = message_input.replace(/^\s+|\s+$|^\n|\n$/g, ""); if (message_input != "") { // Send Message var newMessage = $msg({ to: jidTo, from: TrophyIM.connection.jid, type: 'chat' }); newMessage = newMessage.c('body').t(message_input); newMessage.up(); newMessage = newMessage.c('active').attrs({ xmlns: 'http://jabber.org/protocol/chatstates' }); // Send Message TrophyIM.connection.send(newMessage.tree()); return true; } } return false; }, /** Function: sendMessage * * Send message to ChatRoom */ sendMessageChatRoom : function( room ) { if( arguments.length > 0 ) { var room_nick = arguments[0]; var message = arguments[1]; var msgid = TrophyIM.connection.getUniqueId(); var msg = $msg({to: room_nick, type: "groupchat", id: msgid}).c("body",{xmlns: Strophe.NS.CLIENT}).t(message); msg.up();//.c("x", {xmlns: "jabber:x:event"}).c("composing"); TrophyIM.connection.send(msg); return true; } }, /** Function: sendContentMessage * * Send a content message from chat input to user */ sendContentMessage : function() { if( arguments.length > 0 ) { var jidTo = arguments[0]; var state = arguments[1]; var newMessage = $msg({to: jidTo, from: TrophyIM.connection.jid, type: 'chat'}); newMessage = newMessage.c(state).attrs({xmlns : 'http://jabber.org/protocol/chatstates'}); // Send content message TrophyIM.connection.send(newMessage.tree()); } } }; /** Class: TrophyIMRoster * * * This object stores the roster and presence info for the TrophyIMClient * * roster[jid_lower]['contact'] * roster[jid_lower]['presence'][resource] */ function TrophyIMRoster() { /** Constants: internal arrays * (Object) roster - the actual roster/presence information * (Object) groups - list of current groups in the roster * (Array) changes - array of jids with presence changes */ if (TrophyIM.JSONStore.store_working) { var data = TrophyIM.JSONStore.getData(['roster', 'groups']); this.roster = (data['roster'] != null) ? data['roster'] : {}; this.groups = (data['groups'] != null) ? data['groups'] : {}; } else { this.roster = {}; this.groups = {}; } this.changes = new Array(); if (TrophyIM.constants.stale_roster) { for (var jid in this.roster) { this.changes[this.changes.length] = jid; } } /** Function: addChange * * Adds given jid to this.changes, keeping this.changes sorted and * preventing duplicates. * * Parameters * (String) jid : jid to add to this.changes */ this.addChange = function(jid) { for (var c = 0; c < this.changes.length; c++) { if (this.changes[c] == jid) { return; } } this.changes[this.changes.length] = jid; this.changes.sort(); } /** Function: addContact * * Adds given contact to roster * * Parameters: * (String) jid - bare jid * (String) subscription - subscription attribute for contact * (String) name - name attribute for contact * (Array) groups - array of groups contact is member of */ this.addContact = function(jid, subscription, name, groups ) { if( subscription === "remove" ) { this.removeContact(jid); } else { var contact = { jid:jid, subscription:subscription, name:name, groups:groups } var jid_lower = jid.toLowerCase(); if ( this.roster[jid_lower] ) { this.roster[jid_lower]['contact'] = contact; } else { this.roster[jid_lower] = {contact:contact}; } groups = groups ? groups : ['']; for ( var g = 0; g < groups.length; g++ ) { if ( !this.groups[groups[g]] ) { this.groups[groups[g]] = {}; } this.groups[groups[g]][jid_lower] = jid_lower; } } } /** Function: getContact * * Returns contact entry for given jid * * Parameter: (String) jid - jid to return */ this.getContact = function(jid) { if (this.roster[jid.toLowerCase()]) { return this.roster[jid.toLowerCase()]['contact']; } } /** Function: getPresence * * Returns best presence for given jid as Array(resource, priority, show, * status) * * Parameter: (String) fulljid - jid to return best presence for */ this.getPresence = function(fulljid) { var jid = Strophe.getBareJidFromJid(fulljid); var current = null; if (this.roster[jid.toLowerCase()] && this.roster[jid.toLowerCase()]['presence']) { for (var resource in this.roster[jid.toLowerCase()]['presence']) { if ( this.roster[jid.toLowerCase()]['presence'][ resource ].constructor == Function ) continue; var presence = this.roster[jid.toLowerCase()]['presence'][resource]; if (current == null) { current = presence } else { if(presence['priority'] > current['priority'] && ((presence['show'] == "chat" || presence['show'] == "available") || (current['show'] != "chat" || current['show'] != "available"))) { current = presence } } } } return current; } /** Function: groupHasChanges * * Returns true if current group has members in this.changes * * Parameters: * (String) group - name of group to check */ this.groupHasChanges = function(group) { for (var c = 0; c < this.changes.length; c++) { if (this.groups[group][this.changes[c]]) { return true; } } return false; } /** Function removeContact * * Parameters * (String) jid */ this.removeContact = function(jid) { if( this.roster[ jid ] ) { var groups = this.roster[ jid ].contact.groups; if( groups ) { for ( var i = 0; i < groups.length; i++ ) { delete this.groups[ groups[ i ] ][ jid ]; } for ( var i = 0; i < groups.length; i++ ) { var contacts = 0; for ( var contact in this.groups[ groups[ i ] ] ) { if ( this.groups[ groups[ i ] ][ contact ].constructor == Function ) continue; contacts++; } if ( ! contacts ) delete this.groups[ groups[ i ] ]; } } // Delete Object roster if( this.roster[jid] ) delete this.roster[jid]; } } /** Function: setPresence * * Sets presence * * Parameters: * (String) fulljid: full jid with presence * (Integer) priority: priority attribute from presence * (String) show: show attribute from presence * (String) status: status attribute from presence */ this.setPresence = function(fulljid, priority, show, status) { var barejid = Strophe.getBareJidFromJid(fulljid); var resource = Strophe.getResourceFromJid(fulljid); var jid_lower = barejid.toLowerCase(); if( show != 'unavailable' || show != 'error' ) { if (!this.roster[jid_lower]) { this.addContact( barejid, 'not-in-roster' ); } var presence = { resource : resource, priority : priority, show : show, status : status } if (!this.roster[jid_lower]['presence']) { this.roster[jid_lower]['presence'] = {}; } this.roster[jid_lower]['presence'][resource] = presence; } } /** Fuction: save * * Saves roster data to JSON store */ this.save = function() { if (TrophyIM.JSONStore.store_working) { TrophyIM.JSONStore.setData({roster:this.roster, groups:this.groups, active_chat:TrophyIM.activeChats['current'], chat_history:TrophyIM.chatHistory}); } } } /** Class: TrophyIMJSONStore * * * This object is the mechanism by which TrophyIM stores and retrieves its * variables from the url provided by TROPHYIM_JSON_STORE * */ function TrophyIMJSONStore() { this.store_working = false; /** Function _newXHR * * Set up new cross-browser xmlhttprequest object * * Parameters: * (function) handler = what to set onreadystatechange to */ this._newXHR = function (handler) { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); if (xhr.overrideMimeType) { xhr.overrideMimeType("text/xml"); } } else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } return xhr; } /** Function getData * Gets data from JSONStore * * Parameters: * (Array) vars = Variables to get from JSON store * * Returns: * Object with variables indexed by names given in parameter 'vars' */ this.getData = function(vars) { if (typeof(TROPHYIM_JSON_STORE) != undefined) { Strophe.debug("Retrieving JSONStore data"); var xhr = this._newXHR(); var getdata = "get=" + vars.join(","); try { xhr.open("POST", TROPHYIM_JSON_STORE, false); } catch (e) { Strophe.error("JSONStore open failed."); return false; } xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader('Content-length', getdata.length); xhr.send(getdata); if (xhr.readyState == 4 && xhr.status == 200) { try { var dataObj = JSON.parse(xhr.responseText); return this.emptyFix(dataObj); } catch(e) { Strophe.error("Could not parse JSONStore response" + xhr.responseText); return false; } } else { Strophe.error("JSONStore open failed. Status: " + xhr.status); return false; } } } /** Function emptyFix * Fix for bugs in external JSON implementations such as * http://bugs.php.net/bug.php?id=41504. * A.K.A. Don't use PHP, people. */ this.emptyFix = function(obj) { if (typeof(obj) == "object") { for (var i in obj) { if ( obj[i].constructor == Function ) continue; if (i == '_empty_') { obj[""] = this.emptyFix(obj['_empty_']); delete obj['_empty_']; } else { obj[i] = this.emptyFix(obj[i]); } } } return obj } /** Function delData * Deletes data from JSONStore * * Parameters: * (Array) vars = Variables to delete from JSON store * * Returns: * Status of delete attempt. */ this.delData = function(vars) { if (typeof(TROPHYIM_JSON_STORE) != undefined) { Strophe.debug("Retrieving JSONStore data"); var xhr = this._newXHR(); var deldata = "del=" + vars.join(","); try { xhr.open("POST", TROPHYIM_JSON_STORE, false); } catch (e) { Strophe.error("JSONStore open failed."); return false; } xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader('Content-length', deldata.length); xhr.send(deldata); if (xhr.readyState == 4 && xhr.status == 200) { try { var dataObj = JSON.parse(xhr.responseText); return dataObj; } catch(e) { Strophe.error("Could not parse JSONStore response"); return false; } } else { Strophe.error("JSONStore open failed. Status: " + xhr.status); return false; } } } /** Function setData * Stores data in JSONStore, overwriting values if they exist * * Parameters: * (Object) vars : Object containing named vars to store ({name: value, * othername: othervalue}) * * Returns: * Status of storage attempt */ this.setData = function(vars) { if ( typeof(TROPHYIM_JSON_STORE) != undefined ) { var senddata = "set=" + JSON.stringify(vars); var xhr = this._newXHR(); try { xhr.open("POST", TROPHYIM_JSON_STORE, false); } catch (e) { Strophe.error("JSONStore open failed."); return false; } xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader('Content-length', senddata.length); xhr.send(senddata); if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText == "OK") { return true; } else { Strophe.error("JSONStore open failed. Status: " + xhr.status); return false; } } } var testData = true; if (this.setData({testData:testData})) { var testResult = this.getData(['testData']); if (testResult && testResult['testData'] == true) { this.store_working = true; } } } /** Constants: Node types * * Implementations of constants that IE doesn't have, but we need. */ if (document.ELEMENT_NODE == null) { document.ELEMENT_NODE = 1; document.ATTRIBUTE_NODE = 2; document.TEXT_NODE = 3; document.CDATA_SECTION_NODE = 4; document.ENTITY_REFERENCE_NODE = 5; document.ENTITY_NODE = 6; document.PROCESSING_INSTRUCTION_NODE = 7; document.COMMENT_NODE = 8; document.DOCUMENT_NODE = 9; document.DOCUMENT_TYPE_NODE = 10; document.DOCUMENT_FRAGMENT_NODE = 11; document.NOTATION_NODE = 12; } /** Function: importNode * * document.importNode implementation for IE, which doesn't have importNode * * Parameters: * (Object) node - dom object * (Boolean) allChildren - import node's children too */ if (!document.importNode) { document.importNode = function(node, allChildren) { switch (node.nodeType) { case document.ELEMENT_NODE: var newNode = document.createElement(node.nodeName); if (node.attributes && node.attributes.length > 0) { for(var i = 0; i < node.attributes.length; i++) { newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i].nodeName)); } } if (allChildren && node.childNodes && node.childNodes.length > 0) { for (var i = 0; i < node.childNodes.length; i++) { newNode.appendChild(document.importNode( node.childNodes[i], allChildren)); } } return newNode; break; case document.TEXT_NODE: case document.CDATA_SECTION_NODE: case document.COMMENT_NODE: return document.createTextNode(node.nodeValue); break; } }; } /** * * Bootstrap self into window.onload and window.onunload */ var oldonunload = window.onunload; window.onunload = function() { if( oldonunload ) { oldonunload(); } TrophyIM.setPresence('unavailable'); }