/* Jappix - An open social platform These are the IQ JS scripts for Jappix ------------------------------------------------- License: AGPL Author: Valérian Saliou */ // Bundle var IQ = (function () { /** * Alias of this * @private */ var self = {}; /** * Handles OOB request * @private * @param {string} iqType * @param {string} iqID * @param {object} iqNode * @return {undefined} */ self._handleOOBRequest = function(iqFrom, iqID, iqNode) { try { /* REF: http://xmpp.org/extensions/xep-0066.html */ OOB.handle(iqFrom, iqID, 'iq', iqNode); Console.log('Received IQ OOB request: ' + iqFrom); } catch(e) { Console.error('IQ._handleOOBRequest', e); } }; /** * Handles OOB reply * @private * @param {object} iqResponse * @param {string} iqFrom * @param {string} iqType * @param {string} iqID * @param {object} iqNode * @return {undefined} */ self._handleOOBReply = function(iqResponse, iqFrom, iqType, iqID, iqNode) { try { // Get the values var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID); var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID); var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID); if($(iqNode).find('error').size()) { // Error? if($(iqNode).find('error not-acceptable').size()) { // Rejected? Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id); } else { // Failed? Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id); } // Remove the file $.get(oob_url + '&action=remove'); } else if(iqType == 'result') { // Success? Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id); } } catch(e) { Console.error('IQ._handleOOBReply', e); } }; /** * Handles Software Version * @private * @param {object} iqResponse * @param {string} iqFrom * @return {undefined} */ self._handleSoftwareVersion = function(iqResponse, iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0092.html */ iqQuery = iqResponse.setQuery(NS_VERSION); iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, Caps.disco_infos.identity.name)); iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION)); iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS)); con.send(iqResponse); Console.log('Received software version query: ' + iqFrom); } catch(e) { Console.error('IQ._handleSoftwareVersion', e); } }; /** * Handles Last Activity * @private * @param {object} iqResponse * @param {string} iqFrom * @return {undefined} */ self._handleLastActivity = function(iqResponse, iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0012.html */ iqQuery = iqResponse.setQuery(NS_LAST); iqQuery.setAttribute('seconds', DateUtils.getLastActivity()); con.send(iqResponse); Console.log('Received last activity query: ' + iqFrom); } catch(e) { Console.error('IQ._handleLastActivity', e); } }; /** * Handles Privacy Lists * @private * @param {object} iqResponse * @param {string} iqFrom * @param {string} iqQuery * @return {undefined} */ self._handlePrivacyLists = function(iqResponse, iqFrom, iqQuery) { try { // REF : http://xmpp.org/extensions/xep-0016.html // Roster push con.send(iqResponse); // Get the lists $(iqQuery).find('list').each(function() { Privacy.get($(this).attr('name')); }); Console.log('Received privacy lists push: ' + iqFrom); } catch(e) { Console.error('IQ._handlePrivacyLists', e); } }; /** * Handles Roster Push * @private * @param {object} iqResponse * @param {string} iqFrom * @param {string} iqQuery * @return {undefined} */ self._handleRosterPush = function(iqResponse, iqFrom, iqQuery) { try { // REF : http://xmpp.org/extensions/xep-0092.html // Roster push con.send(iqResponse); // Get the values $(iqQuery).find('item').each(function() { Roster.parse($(this), 'presence'); }); Console.log('Received roster push: ' + iqFrom); } catch(e) { Console.error('IQ._handleRosterPush', e); } }; /** * Handles Roster Item Exchange * @private * @param {object} iqNode * @param {string} iqFrom * @return {undefined} */ self._handleRosterItemExchange = function(iqNode, iqFrom) { try { // Open a new notification Notification.create('rosterx', iqFrom, [iqNode], ''); Console.log('Roster Item Exchange from: ' + iqFrom); } catch(e) { Console.error('IQ._handleRosterItemExchange', e); } }; /** * Handles Disco Info * @private * @param {object} iqResponse * @param {string} iqFrom * @return {undefined} */ self._handleDiscoInfo = function(iqResponse, iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0030.html */ iqQuery = iqResponse.setQuery(NS_DISCO_INFO); // We set the name of the client iqQuery.appendChild(iqResponse.buildNode('identity', { 'category': Caps.disco_infos.identity.category, 'type': Caps.disco_infos.identity.type, 'name': Caps.disco_infos.identity.name, 'xmlns': NS_DISCO_INFO })); // We set all the supported features var disco_infos = Caps.myDiscoInfos(); $.each(disco_infos, function(i, disco_info) { iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO})); }); con.send(iqResponse); Console.log('Received disco#infos query: ' + iqFrom); } catch(e) { Console.error('IQ._handleDiscoInfo', e); } }; /** * Handles User Time * @private * @param {object} iqResponse * @param {string} iqFrom * @return {undefined} */ self._handleUserTime = function(iqResponse, iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0202.html */ var iqTime = iqResponse.appendNode('time', { 'xmlns': NS_URN_TIME }); iqTime.appendChild(iqResponse.buildNode('tzo', { 'xmlns': NS_URN_TIME }, DateUtils.getTZO())); iqTime.appendChild(iqResponse.buildNode('utc', { 'xmlns': NS_URN_TIME }, DateUtils.getXMPPTime('utc'))); con.send(iqResponse); Console.log('Received local time query: ' + iqFrom); } catch(e) { Console.error('IQ._handleUserTime', e); } }; /** * Handles Ping * @private * @param {object} iqResponse * @param {string} iqFrom * @return {undefined} */ self._handlePing = function(iqResponse, iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0199.html */ con.send(iqResponse); Console.log('Received a ping: ' + iqFrom); } catch(e) { Console.error('IQ._handlePing', e); } }; /** * Handles Jingle * @private * @param {string} iqFrom * @return {undefined} */ self._handleJingle = function(iqFrom) { try { /* REF: http://xmpp.org/extensions/xep-0166.html */ // Handled via JSJaCJingle.route() (see above) Console.log('Received a Jingle packet: ' + iqFrom); } catch(e) { Console.error('IQ._handleJingle', e); } }; /** * Raises a not implemented error * @private * @param {object} iqResponse * @param {object} iqNode * @param {string} iqFrom * @return {undefined} */ self._raiseNotImplemented = function(iqResponse, iqNode, iqFrom) { try { // Change IQ type iqResponse.setType('error'); // Append stanza content for(var c = 0; c < iqNode.childNodes.length; c++) { iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true)); } // Append error content var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'}); iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS})); iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed."))); con.send(iqResponse); Console.log('Received an unsupported IQ query from: ' + iqFrom); } catch(e) { Console.error('IQ._raiseNotImplemented', e); } }; /** * Handles an incoming IQ packet * @public * @param {object} iq * @return {undefined} */ self.handle = function(iq) { try { // Gets the IQ content var iqNode = iq.getNode(); var iqFrom = Common.fullXID(Common.getStanzaFrom(iq)); var iqID = iq.getID(); var iqQueryXMLNS = iq.getQueryXMLNS(); var iqQuery = iq.getQuery(); var iqType = iq.getType(); // Build the response var iqResponse = new JSJaCIQ(); iqResponse.setID(iqID); iqResponse.setTo(iqFrom); iqResponse.setType('result'); // OOB request if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) { self._handleOOBRequest(iqFrom, iqID, iqNode); } // OOB reply else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) { self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode); } // Software version query else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) { self._handleSoftwareVersion(iqResponse, iqFrom); } // Last activity query else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) { self._handleLastActivity(iqResponse, iqFrom); } // Privacy lists push else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) { self._handlePrivacyLists(iqResponse, iqFrom, iqQuery); } // Roster push else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) { self._handleRosterPush(iqResponse, iqFrom, iqQuery); } // Roster Item Exchange query else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) { self._handleRosterItemExchange(iqNode, iqFrom); } // Disco info query else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) { self._handleDiscoInfo(iqResponse, iqFrom); } // User time query else if($(iqNode).find('time').size() && (iqType == 'get')) { self._handleUserTime(iqResponse, iqFrom); } // Ping else if($(iqNode).find('ping').size() && (iqType == 'get')) { self._handlePing(iqResponse, iqFrom); } // Jingle else if($(iqNode).find('jingle').size()) { self._handleJingle(iqFrom); } // Not implemented else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) { self._raiseNotImplemented(iqResponse, iqNode, iqFrom); } } catch(e) { Console.error('IQ.handle', e); } }; /** * Return class scope */ return self; })();