Skip to content

Commit

Permalink
fix xmpp
Browse files Browse the repository at this point in the history
  • Loading branch information
nfsprodriver committed Jul 7, 2017
1 parent 3aa2523 commit e61fad8
Show file tree
Hide file tree
Showing 6 changed files with 1,920 additions and 1,583 deletions.
333 changes: 98 additions & 235 deletions src/scripts/strophe/plugins/caps.js
Original file line number Diff line number Diff line change
@@ -1,240 +1,103 @@
/**
* Entity Capabilities (XEP-0115)
*
* Depends on disco plugin.
*
* See: http://xmpp.org/extensions/xep-0115.html
*
* Authors:
* - Michael Weibel <[email protected]>
*
* Copyright:
* - Michael Weibel <[email protected]>
*/
/*
# This plugin is distributed under the terms of the MIT licence.
# Please see the LICENCE file for details.
#
# Copyright (c)
# Markus Kohlhase, 2011
# Adán Sánchez de Pedro Crespo, 2014
Strophe.addConnectionPlugin('caps', {
/** Constant: HASH
* Hash used
*
* Currently only sha-1 is supported.
*/
HASH: 'sha-1',
/** Variable: node
* Client which is being used.
*
* Can be overwritten as soon as Strophe has been initialized.
*/
node: 'http://strophe.im/strophejs/',
/** PrivateVariable: _ver
* Own generated version string
*/
_ver: '',
/** PrivateVariable: _connection
* Strophe connection
*/
_connection: null,
/** PrivateVariable: _knownCapabilities
* A hashtable containing version-strings and their capabilities, serialized
* as string.
*
* TODO: Maybe those caps shouldn't be serialized.
*/
_knownCapabilities: {},
/** PrivateVariable: _jidVerIndex
* A hashtable containing jids and their versions for better lookup of capabilities.
*/
_jidVerIndex: {},
# File: strophe.caps.js
# A Strophe plugin for ( http://xmpp.org/extensions/xep-0115.html )
/** Function: init
* Initialize plugin:
* - Add caps namespace
* - Add caps feature to disco plugin
* - Add handler for caps stanzas
*
* Parameters:
* (Strophe.Connection) conn - Strophe connection
*/
init: function(conn) {
this._connection = conn;
# NOTE: This plugin has following dependencies:
#
# - strophe.disco.js (by François de Metz)
# - sha1.js
*/

Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps');

if (!this._connection.disco) {
throw "Caps plugin requires the disco plugin to be installed.";
}
Strophe.addConnectionPlugin('caps',
{
_connection: null,

init: function (conn) {
this._conn = conn;
Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps');
if (this._conn.disco === void 0) throw new Error('disco plugin required!');
if (b64_sha1 === void 0) throw new Error('SHA-1 library required!');
this._conn.disco.addFeature(Strophe.NS.CAPS);
this._conn.disco.addFeature(Strophe.NS.DISCO_INFO);
this._conn.disco.addFeature(Strophe.NS.DISCO_ITEMS);
if (this._conn.disco._identities.length === 0) {
return this._conn.disco.addIdentity('client', Lungo.Core.environment().isMobile ? 'phone' : 'pc', 'http://loqui.im', '');
}
},

addFeature: function(feature) {
return this._conn.disco.addFeature(feature);
},

removeFeature: function(feature) {
return this._conn.disco.removeFeature(feature);
},

sendPres: function() {
return this._conn.send($pres().cnode(this.createCapsNode().tree()));
},

createCapsNode: function() {
var node;
if (this._conn.disco._identities.length > 0) {
node = this._conn.disco._identities[0].name || "";
} else {
node = dummyId.name;
}
return $build("c", {
xmlns: Strophe.NS.CAPS,
hash: "sha-1",
node: node,
ver: this.generateVerificationString()
});
},

propertySort: function(array, property) {
return array.sort(function(a, b) {
if (a[property] > b[property]) {
return -1;
} else {
return 1;
}
});
},

generateVerificationString: function() {
var S, features, i, id, ids, k, key, ns, _i, _j, _k, _len, _len2, _len3, _ref, _ref2;
ids = [];
_ref = this._conn.disco._identities;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
i = _ref[_i];
ids.push(i);
}
features = [];
_ref2 = this._conn.disco._features;
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
k = _ref2[_j];
features.push(k);
}
S = "";
this.propertySort(ids, "category");
this.propertySort(ids, "type");
this.propertySort(ids, "lang");
for (key in ids) {
id = ids[key];
S += "" + id.category + "/" + id.type + "/" + id.lang + "/" + id.name + "<";
}
features.sort();
for (_k = 0, _len3 = features.length; _k < _len3; _k++) {
ns = features[_k];
S += "" + ns + "<";
}
return "" + (b64_sha1(S)) + "=";
}

this._connection.disco.addFeature(Strophe.NS.CAPS);
this._connection.addHandler(this._delegateCapabilities.bind(this), Strophe.NS.CAPS);
},

/** Function: generateCapsAttrs
* Returns the attributes for generating the "c"-stanza containing the own version
*
* Returns:
* (Object) - attributes
*/
generateCapsAttrs: function() {
return {
'xmlns': Strophe.NS.CAPS,
'hash': this.HASH,
'node': this.node,
'ver': this.generateVer()
};
},

/** Function: generateVer
* Returns the base64 encoded version string (encoded itself with sha1)
*
* Returns:
* (String) - version
*/
generateVer: function() {
if (this._ver !== "") {
return this._ver;
}

var ver = "",
identities = this._connection.disco._identities.sort(this._sortIdentities),
identitiesLen = identities.length,
features = this._connection.disco._features.sort(),
featuresLen = features.length;
for(var i = 0; i < identitiesLen; i++) {
var curIdent = identities[i];
ver += curIdent.category + "/" + curIdent.type + "/" + curIdent.lang + "/" + curIdent.name + "<";
}
for(var i = 0; i < featuresLen; i++) {
ver += features[i] + '<';
}

this._ver = b64_sha1(ver);
return this._ver;
},

/** Function: getCapabilitiesByJid
* Returns serialized capabilities of a jid (if available).
* Otherwise null.
*
* Parameters:
* (String) jid - Jabber id
*
* Returns:
* (String|null) - capabilities, serialized; or null when not available.
*/
getCapabilitiesByJid: function(jid) {
if (this._jidVerIndex[jid]) {
return this._knownCapabilities[this._jidVerIndex[jid]];
}
return null;
},

/** PrivateFunction: _delegateCapabilities
* Checks if the version has already been saved.
* If yes: do nothing.
* If no: Request capabilities
*
* Parameters:
* (Strophe.Builder) stanza - Stanza
*
* Returns:
* (Boolean)
*/
_delegateCapabilities: function(stanza) {
var from = stanza.getAttribute('from'),
c = stanza.querySelector('c'),
ver = c.getAttribute('ver'),
node = c.getAttribute('node');
if (!this._knownCapabilities[ver]) {
return this._requestCapabilities(from, node, ver);
} else {
this._jidVerIndex[from] = ver;
}
if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) {
this._jidVerIndex[from] = ver;
}
return true;
},

/** PrivateFunction: _requestCapabilities
* Requests capabilities from the one which sent the caps-info stanza.
* This is done using disco info.
*
* Additionally, it registers a handler for handling the reply.
*
* Parameters:
* (String) to - Destination jid
* (String) node - Node attribute of the caps-stanza
* (String) ver - Version of the caps-stanza
*
* Returns:
* (Boolean) - true
*/
_requestCapabilities: function(to, node, ver) {
if (to !== this._connection.jid) {
var id = this._connection.disco.info(to, node + '#' + ver);
this._connection.addHandler(this._handleDiscoInfoReply.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'result', id, to);
}
return true;
},

/** PrivateFunction: _handleDiscoInfoReply
* Parses the disco info reply and adds the version & it's capabilities to the _knownCapabilities variable.
* Additionally, it adds the jid & the version to the _jidVerIndex variable for a better lookup.
*
* Parameters:
* (Strophe.Builder) stanza - Disco info stanza
*
* Returns:
* (Boolean) - false, to automatically remove the handler.
*/
_handleDiscoInfoReply: function(stanza) {
var query = stanza.querySelector('query'),
node = query.getAttribute('node').split('#'),
ver = node[1],
from = stanza.getAttribute('from');
if (!this._knownCapabilities[ver]) {
var childNodes = query.childNodes,
childNodesLen = childNodes.length;
this._knownCapabilities[ver] = [];
for(var i = 0; i < childNodesLen; i++) {
var node =childNodes[i];
this._knownCapabilities[ver].push({name: node.nodeName, attributes: node.attributes});
}
this._jidVerIndex[from] = ver;
} else if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) {
this._jidVerIndex[from] = ver;
}
return false;
},

/** PrivateFunction: _sortIdentities
* Sorts two identities according the sorting requirements in XEP-0115.
*
* Parameters:
* (Object) a - Identity a
* (Object) b - Identity b
*
* Returns:
* (Integer) - 1, 0 or -1; according to which one's greater.
*/
_sortIdentities: function(a, b) {
if (a.category > b.category) {
return 1;
}
if (a.category < b.category) {
return -1;
}
if (a.type > b.type) {
return 1;
}
if (a.type < b.type) {
return -1;
}
if (a.lang > b.lang) {
return 1;
}
if (a.lang < b.lang) {
return -1;
}
return 0;
}
});
});
Loading

0 comments on commit e61fad8

Please sign in to comment.