aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2020-09-03 22:52:07 +0200
committerfiaxh <git@lightrise.org>2020-09-07 15:21:42 +0200
commit2d31d9d4706d6fea870f9081a1451448f032473d (patch)
tree53a1f75def66bcb38076bd47c45a48992f850cf9 /xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala
parent49bcbdaa517e5d6f8d4860db70ae0a9960e2c519 (diff)
downloaddino-2d31d9d4706d6fea870f9081a1451448f032473d.tar.gz
dino-2d31d9d4706d6fea870f9081a1451448f032473d.zip
Cleanup
Diffstat (limited to 'xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala')
-rw-r--r--xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala175
1 files changed, 0 insertions, 175 deletions
diff --git a/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala b/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala
deleted file mode 100644
index 8e15e0c2..00000000
--- a/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala
+++ /dev/null
@@ -1,175 +0,0 @@
-using Gee;
-
-namespace Xmpp.Xep.EntityCapabilities {
- private const string NS_URI = "http://jabber.org/protocol/caps";
-
- private Regex? sha1_base64_regex = null;
-
- private Regex get_sha1_base64_regex() {
- if (sha1_base64_regex == null) {
- sha1_base64_regex = /^[A-Za-z0-9+\/]{27}=$/;
- }
- return sha1_base64_regex;
- }
-
- public string? get_caps_hash(Presence.Stanza presence) {
- Regex sha1_base64_regex = get_sha1_base64_regex();
- StanzaNode? c_node = presence.stanza.get_subnode("c", NS_URI);
- if (c_node == null) return null;
- string? ver_attribute = c_node.get_attribute("ver", NS_URI);
- if (ver_attribute == null || !sha1_base64_regex.match(ver_attribute)) return null;
- return ver_attribute;
- }
-
- public string? get_server_caps_hash(XmppStream stream) {
- StanzaNode? node = stream.features.get_subnode("c", NS_URI);
- if (node == null) return null;
-
- string? ver_attribute = node.get_attribute("ver", NS_URI);
- if (ver_attribute == null) return null;
-
- return ver_attribute;
- }
-
- public class Module : XmppStreamModule {
- public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0115_entity_capabilities");
-
- private string own_ver_hash;
- private Storage storage;
-
- public Module(Storage storage) {
- this.storage = storage;
- }
-
- private string get_own_hash(XmppStream stream) {
- if (own_ver_hash == null) {
- own_ver_hash = compute_hash(stream.get_flag(ServiceDiscovery.Flag.IDENTITY).own_identities, stream.get_flag(ServiceDiscovery.Flag.IDENTITY).own_features, new ArrayList<DataForms.DataForm>());
- }
- return own_ver_hash;
- }
-
- public override void attach(XmppStream stream) {
- stream.get_module(Presence.Module.IDENTITY).pre_send_presence_stanza.connect(on_pre_send_presence_stanza);
- stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI);
- }
-
- public override void detach(XmppStream stream) {
- stream.get_module(Presence.Module.IDENTITY).pre_send_presence_stanza.disconnect(on_pre_send_presence_stanza);
- stream.get_module(ServiceDiscovery.Module.IDENTITY).remove_feature(stream, NS_URI);
- }
-
- public override string get_ns() { return NS_URI; }
- public override string get_id() { return IDENTITY.id; }
-
- private void on_pre_send_presence_stanza(XmppStream stream, Presence.Stanza presence) {
- if (presence.type_ == Presence.Stanza.TYPE_AVAILABLE) {
- presence.stanza.put_node(new StanzaNode.build("c", NS_URI).add_self_xmlns()
- .put_attribute("hash", "sha-1")
- .put_attribute("node", "https://dino.im")
- .put_attribute("ver", get_own_hash(stream)));
- }
- }
-
- public static string compute_hash_for_info_result(ServiceDiscovery.InfoResult info_result) {
- Gee.List<DataForms.DataForm> data_forms = new ArrayList<DataForms.DataForm>();
- foreach (StanzaNode node in info_result.iq.stanza.get_deep_subnodes(ServiceDiscovery.NS_URI_INFO + ":query", DataForms.NS_URI + ":x")) {
- data_forms.add(DataForms.DataForm.create_from_node(node));
- }
-
- return compute_hash(info_result.identities, info_result.features, data_forms);
- }
-
- public static string compute_hash(Gee.Set<ServiceDiscovery.Identity> identities_set, Gee.List<string> features, Gee.List<DataForms.DataForm> data_forms) {
- var identities = new ArrayList<ServiceDiscovery.Identity>();
- foreach (var identity in identities_set) identities.add(identity);
-
- identities.sort(compare_identities);
- features.sort();
-
- StringBuilder sb = new StringBuilder();
- foreach (ServiceDiscovery.Identity identity in identities) {
- sb.append(sanitize(identity.category))
- .append("/")
- .append(sanitize(identity.type_))
- .append("//");
- if (identity.name != null) {
- sb.append(sanitize(identity.name));
- }
- sb.append("<");
- }
- foreach (string feature in features) {
- sb.append(sanitize(feature))
- .append("<");
- }
-
- data_forms.sort(compare_data_forms);
- foreach (DataForms.DataForm data_form in data_forms) {
- if (data_form.form_type == null) {
- // If [..] the FORM_TYPE field is not of type "hidden" or the form does not include a FORM_TYPE field, ignore the form but continue processing. (XEP-0115 5.4)
- continue;
- }
- sb.append(sanitize(data_form.form_type))
- .append("<");
-
- data_form.fields.sort(compare_data_fields);
- foreach (DataForms.DataForm.Field field in data_form.fields) {
- sb.append(sanitize(field.var))
- .append("<");
- Gee.List<string> values = field.get_values();
- values.sort();
- foreach (string value in values) {
- sb.append(sanitize(value ?? ""))
- .append("<");
- }
- }
- }
-
- Checksum c = new Checksum(ChecksumType.SHA1);
- c.update(sb.str.data, -1);
- size_t size = 20;
- uint8[] buf = new uint8[size];
- c.get_digest(buf, ref size);
-
- return Base64.encode(buf);
- }
-
- /*
- * If the four characters '&', 'l', 't', ';' appear consecutively in any of the factors of the verification
- * string S [...] then that string of characters MUST be treated as literally '&lt;' and MUST NOT be converted to
- * the character '<', because completing such a conversion would open the protocol to trivial attacks. (XEP-0115 5.1)
- */
- private static string sanitize(string s) {
- return s.replace("<", "&lt;");
- }
-
- private static int compare_identities(ServiceDiscovery.Identity a, ServiceDiscovery.Identity b) {
- int category_comp = a.category.collate(b.category);
- if (category_comp != 0) return category_comp;
- int type_comp = a.type_.collate(b.type_);
- if (type_comp != 0) return type_comp;
- // TODO lang
- return 0;
- }
-
- private static int compare_data_forms(DataForms.DataForm a, DataForms.DataForm b) {
- if (a.form_type != null && b.form_type != null) {
- return a.form_type.collate(b.form_type);
- }
- return 0;
- }
-
- private static int compare_data_fields(DataForms.DataForm.Field a, DataForms.DataForm.Field b) {
- if (a.var != null && b.var != null) {
- return a.var.collate(b.var);
- }
- return 0;
- }
- }
-
- public interface Storage : Object {
- public abstract void store_identities(string entity, Gee.Set<ServiceDiscovery.Identity> identities);
- public abstract void store_features(string entity, Gee.List<string> capabilities);
- public abstract ServiceDiscovery.Identity? get_identities(string entity);
- public abstract Gee.List<string> get_features(string entity);
- }
-}