From 2fe8489d368a371aefbfbe66e74621a8df14cdc2 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Fri, 10 Mar 2017 17:01:45 +0100 Subject: Rename vala-xmpp library to xmpp-vala --- xmpp-vala/src/core/stanza_node.vala | 297 ++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 xmpp-vala/src/core/stanza_node.vala (limited to 'xmpp-vala/src/core/stanza_node.vala') diff --git a/xmpp-vala/src/core/stanza_node.vala b/xmpp-vala/src/core/stanza_node.vala new file mode 100644 index 00000000..1dfacfdd --- /dev/null +++ b/xmpp-vala/src/core/stanza_node.vala @@ -0,0 +1,297 @@ +using Gee; + +namespace Xmpp.Core { + +public abstract class StanzaEntry { + public string? ns_uri; + public string name; + public string? val; + + public string encoded_val { + owned get { + return val.replace("&", "&").replace("\"", """).replace("'", "'").replace("<", "<").replace(">", ">"); + } + set { + string tmp = value.replace(">", ">").replace("<", "<").replace("'","'").replace(""","\""); + while (tmp.contains("&#")) { + int start = tmp.index_of("&#"); + int end = tmp.index_of(";", start); + if (end < start) break; + unichar num = -1; + if (tmp[start+2]=='x') { + tmp.substring(start+3, start-end-3).scanf("%x", &num); + } else { + num = int.parse(tmp.substring(start+2, start-end-2)); + } + tmp = tmp.splice(start, end, num.to_string()); + } + val = tmp.replace("&", "&"); + } + } + + public virtual unowned string? get_string_content() { + return val; + } +} + +public class NoStanza : StanzaEntry { + public NoStanza(string? name) { + this.name = name; + } +} + +public class StanzaNode : StanzaEntry { + public ArrayList sub_nodes = new ArrayList(); + public ArrayList attributes = new ArrayList(); + public bool has_nodes = false; + public bool pseudo = false; + + public StanzaNode () {} + + public StanzaNode.build(string name, string ns_uri = "jabber:client", ArrayList? nodes = null, ArrayList? attrs = null) { + this.ns_uri = ns_uri; + this.name = name; + if (nodes != null) this.sub_nodes.add_all(nodes); + if (attrs != null) this.attributes.add_all(attrs); + } + + public StanzaNode.text(string text) { + this.name = "#text"; + this.val = text; + } + + public StanzaNode.encoded_text(string text) { + this.name = "#text"; + this.encoded_val = text; + } + + public StanzaNode add_self_xmlns() { + return put_attribute("xmlns", ns_uri); + } + + public unowned string? get_attribute(string name, string? ns_uri = null) { + 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 attr in attributes) { + if (attr.ns_uri == _ns_uri && attr.name == _name) return attr.val; + } + return null; + } + + public StanzaAttribute get_attribute_raw(string name, string? ns_uri = null) { + 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 attr in attributes) { + if (attr.ns_uri == _ns_uri && attr.name == _name) return attr; + } + return null; + } + + public ArrayList get_attributes_by_ns_uri(string ns_uri) { + ArrayList ret = new ArrayList (); + foreach(var attr in attributes) { + if (attr.ns_uri == ns_uri) ret.add(attr); + } + return ret; + } + + public StanzaEntry get(...) { + va_list l = va_list(); + StanzaEntry? res = get_deep_attribute_(va_list.copy(l)); + if (res != null) return res; + res = get_deep_subnode_(va_list.copy(l)); + if (res != null) return res; + return new NoStanza("-"); + } + + public unowned string? get_deep_attribute(...) { + va_list l = va_list(); + var res = get_deep_attribute_(va_list.copy(l)); + if (res == null) return null; + return res.val; + } + + public StanzaAttribute? get_deep_attribute_(va_list l) { + StanzaNode? node = this; + string? attribute_name = l.arg(); + if (attribute_name == null) return null; + while(true) { + string? s = l.arg(); + if (s == null) break; + node = get_subnode(attribute_name); + if (node == null) return null; + attribute_name = s; + } + return node.get_attribute_raw(attribute_name); + } + + public StanzaNode? get_subnode(string name, string? ns_uri = null, bool recurse = false) { + 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) return node; + if (recurse) { + var x = node.get_subnode(_name, _ns_uri, recurse); + if (x != null) return x; + } + } + return null; + } + + 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; + foreach(var node in sub_nodes) { + if (node.ns_uri == ns_uri && node.name == name) ret.add(node); + if (recurse) { + ret.add_all(node.get_subnodes(name, ns_uri, recurse)); + } + } + return ret; + } + + public StanzaNode? get_deep_subnode(...) { + va_list l = va_list(); + return get_deep_subnode_(va_list.copy(l)); + } + + public StanzaNode? get_deep_subnode_(va_list l) { + StanzaNode? node = this; + while(true) { + string? s = l.arg(); + if (s == null) break; + node = get_subnode(s); + } + return node; + } + + public ArrayList get_all_subnodes() { + return sub_nodes; + } + + public void add_attribute(StanzaAttribute attr) { + attributes.add(attr); + } + + public override unowned string? get_string_content() { + if (val != null) return val; + if (sub_nodes.size == 1) return sub_nodes[0].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; + attributes.add(new StanzaAttribute.build(ns_uri, name, val)); + return this; + } + + /** + * Set only occurence + **/ + public void set_attribute(string name, string val, string? ns_uri = null) { + if (ns_uri == null) ns_uri = this.ns_uri; + foreach(var attr in attributes) { + if (attr.ns_uri == ns_uri && attr.name == name) { + attr.val = val; + return; + } + } + put_attribute(name, val, ns_uri); + } + + public StanzaNode put_node(StanzaNode node) { + sub_nodes.add(node); + return this; + } + + public string to_string(int i = 0) { + string indent = string.nfill (i * 2, ' '); + if (name == "#text") { + return @"$indent$val\n"; + } + var sb = new StringBuilder(); + sb.append(@"$indent<{$ns_uri}:$name"); + foreach (StanzaAttribute attr in attributes) { + sb.append_printf(" %s", attr.to_string()); + } + if (!has_nodes && sub_nodes.size == 0) { + sb.append(" />\n"); + } else { + sb.append(">\n"); + if (sub_nodes.size != 0) { + foreach (StanzaNode subnode in sub_nodes) { + sb.append(subnode.to_string(i+1)); + } + sb.append(@"$indent\n"); + } + } + return sb.str; + } + + public string to_xml (NamespaceState? state = null) throws XmlError { + NamespaceState my_state = state ?? new NamespaceState.for_stanza(); + if (name == "#text") return @"$encoded_val"; + foreach(var xmlns in get_attributes_by_ns_uri (XMLNS_URI)) { + if (xmlns.name == "xmlns") { + my_state = new NamespaceState.with_current(my_state, xmlns.val); + } else { + my_state = new NamespaceState.with_assoc(my_state, xmlns.val, xmlns.name); + } + } + var sb = new StringBuilder(); + if (ns_uri == my_state.current_ns_uri) { + sb.append(@"<$name"); + } else { + sb.append_printf("<%s:%s", my_state.find_name (ns_uri), name); + } + var attr_ns_state = new NamespaceState.with_current(my_state, ns_uri); + foreach (StanzaAttribute attr in attributes) { + sb.append_printf(" %s", attr.to_xml(attr_ns_state)); + } + if (!has_nodes && sub_nodes.size == 0) { + sb.append("/>"); + } else { + sb.append(">"); + if (sub_nodes.size != 0) { + foreach (StanzaNode subnode in sub_nodes) { + sb.append(subnode.to_xml(my_state)); + } + if (ns_uri == my_state.current_ns_uri) { + sb.append(@""); + } else { + sb.append_printf("", my_state.find_name (ns_uri), name); + } + } + } + return sb.str; + } +} +} -- cgit v1.2.3-54-g00ecf