From e59b9d2fff347bf779dff1fa8c945bc2a3c59d8b Mon Sep 17 00:00:00 2001 From: Marvin W Date: Thu, 9 Mar 2017 21:47:50 +0100 Subject: [PATCH] Various fixes in vala-xmpp --- xmpp-vala/src/core/stanza_node.vala | 70 +++++++++++++++++-- xmpp-vala/src/module/iq/module.vala | 6 +- xmpp-vala/src/module/tls.vala | 4 +- xmpp-vala/src/module/xep/0060_pubsub.vala | 31 ++++---- .../src/module/xep/0084_user_avatars.vala | 24 +++---- 5 files changed, 102 insertions(+), 33 deletions(-) diff --git a/xmpp-vala/src/core/stanza_node.vala b/xmpp-vala/src/core/stanza_node.vala index 1dfacfdd..f615a240 100644 --- a/xmpp-vala/src/core/stanza_node.vala +++ b/xmpp-vala/src/core/stanza_node.vala @@ -9,7 +9,7 @@ public abstract class StanzaEntry { public string encoded_val { owned get { - return val.replace("&", "&").replace("\"", """).replace("'", "'").replace("<", "<").replace(">", ">"); + return val != null ? val.replace("&", "&").replace("\"", """).replace("'", "'").replace("<", "<").replace(">", ">") : null; } set { string tmp = value.replace(">", ">").replace("<", "<").replace("'","'").replace(""","\""); @@ -87,6 +87,18 @@ public class StanzaNode : StanzaEntry { return null; } + public int get_attribute_int(string name, int def = -1, string? ns_uri = null) { + string? res = get_attribute(name, ns_uri); + if (res == null) return def; + return int.parse(res); + } + + public bool get_attribute_bool(string name, bool def = false, string? ns_uri = null) { + string? res = get_attribute(name, ns_uri); + if (res == null) return def; + return res.down() == "true" || res == "1"; + } + public StanzaAttribute get_attribute_raw(string name, string? ns_uri = null) { string _name = name; string? _ns_uri = ns_uri; @@ -136,7 +148,7 @@ public class StanzaNode : StanzaEntry { while(true) { string? s = l.arg(); if (s == null) break; - node = get_subnode(attribute_name); + node = node.get_subnode(attribute_name); if (node == null) return null; attribute_name = s; } @@ -167,11 +179,21 @@ public class StanzaNode : StanzaEntry { public ArrayList get_subnodes(string name, string? ns_uri = null, bool recurse = false) { ArrayList ret = new ArrayList(); - if (ns_uri == null) ns_uri = this.ns_uri; + string _name = name; + string? _ns_uri = ns_uri; + if (ns_uri == null) { + if (_name.contains(":")) { + var lastIndex = _name.last_index_of_char(':'); + _ns_uri = _name.substring(0, lastIndex); + _name = _name.substring(lastIndex + 1); + } else { + _ns_uri = this.ns_uri; + } + } foreach(var node in sub_nodes) { - if (node.ns_uri == ns_uri && node.name == name) ret.add(node); + if (node.ns_uri == _ns_uri && node.name == _name) ret.add(node); if (recurse) { - ret.add_all(node.get_subnodes(name, ns_uri, recurse)); + ret.add_all(node.get_subnodes(_name, _ns_uri, recurse)); } } return ret; @@ -187,15 +209,44 @@ public class StanzaNode : StanzaEntry { while(true) { string? s = l.arg(); if (s == null) break; - node = get_subnode(s); + node = node.get_subnode(s); + if (node == null) return null; } return node; } + public ArrayList get_deep_subnodes(...) { + va_list l = va_list(); + var res = get_deep_subnodes_(va_list.copy(l)); + if (res != null) return res; + return new ArrayList(); + } + + public ArrayList get_deep_subnodes_(va_list l) { + StanzaNode? node = this; + string? subnode_name = l.arg(); + if (subnode_name == null) return null; + while(true) { + string? s = l.arg(); + if (s == null) break; + node = node.get_subnode(subnode_name); + if (node == null) return null; + subnode_name = s; + } + return node.get_subnodes(subnode_name); + } + public ArrayList get_all_subnodes() { return sub_nodes; } + public ArrayList get_deep_all_subnodes(...) { + va_list l = va_list(); + StanzaNode? node = get_deep_subnode_(va_list.copy(l)); + if (node != null) return node.get_all_subnodes(); + return new ArrayList(); + } + public void add_attribute(StanzaAttribute attr) { attributes.add(attr); } @@ -206,6 +257,13 @@ public class StanzaNode : StanzaEntry { return null; } + public unowned string? get_deep_string_content(...) { + va_list l = va_list(); + StanzaNode? node = get_deep_subnode_(va_list.copy(l)); + if (node != null) return node.get_string_content(); + return null; + } + public StanzaNode put_attribute(string name, string val, string? ns_uri = null) { if (name == "xmlns") ns_uri = XMLNS_URI; if (ns_uri == null) ns_uri = this.ns_uri; diff --git a/xmpp-vala/src/module/iq/module.vala b/xmpp-vala/src/module/iq/module.vala index b5c50bd7..2e9ffa5d 100644 --- a/xmpp-vala/src/module/iq/module.vala +++ b/xmpp-vala/src/module/iq/module.vala @@ -12,7 +12,11 @@ namespace Xmpp.Iq { private HashMap> namespaceRegistrants = new HashMap>(); public void send_iq(XmppStream stream, Iq.Stanza iq, ResponseListener? listener = null) { - stream.write(iq.stanza); + try { + stream.write(iq.stanza); + } catch (IOStreamError e) { + print(@"$(e.message)\n"); + } if (listener != null) { responseListeners.set(iq.id, listener); } diff --git a/xmpp-vala/src/module/tls.vala b/xmpp-vala/src/module/tls.vala index 1f8447ec..06535319 100644 --- a/xmpp-vala/src/module/tls.vala +++ b/xmpp-vala/src/module/tls.vala @@ -24,7 +24,9 @@ namespace Xmpp.Tls { private void received_nonza(XmppStream stream, StanzaNode node) { if (node.ns_uri == NS_URI && node.name == "proceed") { try { - var conn = TlsClientConnection.new(stream.get_stream(), identity); + var io_stream = stream.get_stream(); + if (io_stream == null) return; + var conn = TlsClientConnection.new(io_stream, identity); // TODO: Add certificate error handling, that is, allow the // program to handle certificate errors. The certificate // *is checked* by TlsClientConnection, and connection is diff --git a/xmpp-vala/src/module/xep/0060_pubsub.vala b/xmpp-vala/src/module/xep/0060_pubsub.vala index 3f96e7a1..600ddded 100644 --- a/xmpp-vala/src/module/xep/0060_pubsub.vala +++ b/xmpp-vala/src/module/xep/0060_pubsub.vala @@ -9,11 +9,11 @@ namespace Xmpp.Xep.Pubsub { public class Module : XmppStreamModule { public const string ID = "0060_pubsub_module"; - private HashMap event_listeners = new HashMap(); + private HashMap event_listeners = new HashMap(); - public void add_filtered_notification(XmppStream stream, string node, EventListener listener) { + public void add_filtered_notification(XmppStream stream, string node, EventListenerDelegate.ResultFunc on_result, Object? reference = null) { ServiceDiscovery.Module.get_module(stream).add_feature_notify(stream, node); - event_listeners[node] = listener; + event_listeners[node] = new EventListenerDelegate(on_result, reference); } public void request(XmppStream stream, string jid, string node, RequestResponseListener listener) { // TODO multiple nodes gehen auch @@ -26,12 +26,12 @@ namespace Xmpp.Xep.Pubsub { RequestResponseListener response_listener; public IqRequestResponseListener(RequestResponseListener response_listener) { this.response_listener = response_listener; } public void on_result(XmppStream stream, Iq.Stanza iq) { - StanzaNode event_node = iq.stanza.get_subnode("pubsub", NS_URI); if (event_node == null) return; - StanzaNode items_node = event_node.get_subnode("items", NS_URI); if (items_node == null) return; - StanzaNode item_node = items_node.get_subnode("item", NS_URI); if (item_node == null) return; - string node = items_node.get_attribute("node", NS_URI); - string id = item_node.get_attribute("id", NS_URI); - response_listener.on_result(stream, iq.from, id, item_node.sub_nodes[0]); + StanzaNode event_node = iq.stanza.get_subnode("pubsub", NS_URI); + StanzaNode items_node = event_node != null ? event_node.get_subnode("items", NS_URI) : null; + StanzaNode item_node = items_node != null ? items_node.get_subnode("item", NS_URI) : null; + string? node = items_node != null ? items_node.get_attribute("node", NS_URI) : null; + string? id = item_node != null ? item_node.get_attribute("id", NS_URI) : null; + response_listener.on_result(stream, iq.from, id, item_node != null ? item_node.sub_nodes[0] : null); } } @@ -93,11 +93,18 @@ namespace Xmpp.Xep.Pubsub { } public interface RequestResponseListener : Object { - public abstract void on_result(XmppStream stream, string jid, string id, StanzaNode node); + public abstract void on_result(XmppStream stream, string jid, string? id, StanzaNode? node); } - public interface EventListener : Object { - public abstract void on_result(XmppStream stream, string jid, string id, StanzaNode node); + public class EventListenerDelegate { + public delegate void ResultFunc(XmppStream stream, string jid, string id, StanzaNode node); + public ResultFunc on_result { get; private set; } + private Object reference; + + public EventListenerDelegate(ResultFunc on_result, Object? reference = null) { + this.on_result = on_result; + this.reference = reference; + } } public interface PublishResponseListener : Object { diff --git a/xmpp-vala/src/module/xep/0084_user_avatars.vala b/xmpp-vala/src/module/xep/0084_user_avatars.vala index 13d19674..575b5d78 100644 --- a/xmpp-vala/src/module/xep/0084_user_avatars.vala +++ b/xmpp-vala/src/module/xep/0084_user_avatars.vala @@ -46,29 +46,27 @@ namespace Xmpp.Xep.UserAvatars { public override void attach(XmppStream stream) { Pubsub.Module.require(stream); - Pubsub.Module.get_module(stream).add_filtered_notification(stream, NS_URI_METADATA, new PubsubEventListenerImpl(storage)); + Pubsub.Module.get_module(stream).add_filtered_notification(stream, NS_URI_METADATA, on_event_result, this); } public override void detach(XmppStream stream) { } - class PubsubEventListenerImpl : Pubsub.EventListener, Object { - PixbufStorage storage; - public PubsubEventListenerImpl(PixbufStorage storage) { this.storage = storage; } - public void on_result(XmppStream stream, string jid, string id, StanzaNode node) { - StanzaNode info_node = node.get_subnode("info", NS_URI_METADATA); - if (info_node.get_attribute("type") != "image/png") return; - if (storage.has_image(id)) { - Module.get_module(stream).received_avatar(stream, jid, id); - } else { - Pubsub.Module.get_module(stream).request(stream, jid, NS_URI_DATA, new PubsubRequestResponseListenerImpl(storage)); - } + + public void on_event_result(XmppStream stream, string jid, string id, StanzaNode node) { + StanzaNode info_node = node.get_subnode("info", NS_URI_METADATA); + if (info_node.get_attribute("type") != "image/png") return; + if (storage.has_image(id)) { + Module.get_module(stream).received_avatar(stream, jid, id); + } else { + Pubsub.Module.get_module(stream).request(stream, jid, NS_URI_DATA, new PubsubRequestResponseListenerImpl(storage)); } } class PubsubRequestResponseListenerImpl : Pubsub.RequestResponseListener, Object { PixbufStorage storage; public PubsubRequestResponseListenerImpl(PixbufStorage storage) { this.storage = storage; } - public void on_result(XmppStream stream, string jid, string id, StanzaNode node) { + public void on_result(XmppStream stream, string jid, string? id, StanzaNode? node) { + if (node == null) return; storage.store(id, Base64.decode(node.get_string_content())); Module.get_module(stream).received_avatar(stream, jid, id); }