aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2019-09-28 21:40:43 +0200
committerfiaxh <git@lightrise.org>2019-09-29 01:53:59 +0200
commit74c29d4df19f97b9b67bbc3c1a963a8729be69fd (patch)
treeaf3624c4b34a21274758b830c3df404244113829 /xmpp-vala
parent1287135ebbe8420de44ab73ce6a553b17067dfdb (diff)
downloaddino-74c29d4df19f97b9b67bbc3c1a963a8729be69fd.tar.gz
dino-74c29d4df19f97b9b67bbc3c1a963a8729be69fd.zip
Add Bookmarks2 implementation, introduce bookmarks interfaces
Diffstat (limited to 'xmpp-vala')
-rw-r--r--xmpp-vala/CMakeLists.txt7
-rw-r--r--xmpp-vala/src/module/bookmarks_provider.vala17
-rw-r--r--xmpp-vala/src/module/conference.vala19
-rw-r--r--xmpp-vala/src/module/xep/0048_bookmarks.vala80
-rw-r--r--xmpp-vala/src/module/xep/0048_bookmarks/conference.vala92
-rw-r--r--xmpp-vala/src/module/xep/0048_bookmarks/module.vala89
-rw-r--r--xmpp-vala/src/module/xep/0048_conference.vala92
-rw-r--r--xmpp-vala/src/module/xep/0060_pubsub.vala88
-rw-r--r--xmpp-vala/src/module/xep/0084_user_avatars.vala4
-rw-r--r--xmpp-vala/src/module/xep/0402_bookmarks2.vala116
10 files changed, 407 insertions, 197 deletions
diff --git a/xmpp-vala/CMakeLists.txt b/xmpp-vala/CMakeLists.txt
index b945f9d0..5836f96f 100644
--- a/xmpp-vala/CMakeLists.txt
+++ b/xmpp-vala/CMakeLists.txt
@@ -19,6 +19,8 @@ SOURCES
"src/core/xmpp_stream.vala"
"src/module/bind.vala"
+ "src/module/bookmarks_provider.vala"
+ "src/module/conference.vala"
"src/module/iq/module.vala"
"src/module/iq/stanza.vala"
"src/module/jid.vala"
@@ -39,6 +41,9 @@ SOURCES
"src/module/tls.vala"
"src/module/util.vala"
+ "src/module/xep/0048_bookmarks.vala"
+ "src/module/xep/0048_conference.vala"
+ "src/module/xep/0402_bookmarks2.vala"
"src/module/xep/0004_data_forms.vala"
"src/module/xep/0030_service_discovery/flag.vala"
"src/module/xep/0030_service_discovery/identity.vala"
@@ -50,8 +55,6 @@ SOURCES
"src/module/xep/0045_muc/module.vala"
"src/module/xep/0045_muc/status_code.vala"
"src/module/xep/0047_in_band_bytestreams.vala"
- "src/module/xep/0048_bookmarks/conference.vala"
- "src/module/xep/0048_bookmarks/module.vala"
"src/module/xep/0049_private_xml_storage.vala"
"src/module/xep/0054_vcard/module.vala"
"src/module/xep/0060_pubsub.vala"
diff --git a/xmpp-vala/src/module/bookmarks_provider.vala b/xmpp-vala/src/module/bookmarks_provider.vala
new file mode 100644
index 00000000..69d2efa2
--- /dev/null
+++ b/xmpp-vala/src/module/bookmarks_provider.vala
@@ -0,0 +1,17 @@
+using Gee;
+
+namespace Xmpp {
+
+public interface BookmarksProvider : Object {
+ public signal void conference_added(XmppStream stream, Conference conferences);
+ public signal void conference_removed(XmppStream stream, Jid jid);
+ public signal void conference_changed(XmppStream stream, Conference conferences);
+ public signal void received_conferences(XmppStream stream, Set<Conference> conferences);
+
+ public async abstract async Set<Conference>? get_conferences(XmppStream stream);
+ public async abstract void add_conference(XmppStream stream, Conference conference);
+ public async abstract void remove_conference(XmppStream stream, Conference conference);
+ public async abstract void replace_conference(XmppStream stream, Conference orig_conference, Conference modified_conference);
+}
+
+}
diff --git a/xmpp-vala/src/module/conference.vala b/xmpp-vala/src/module/conference.vala
new file mode 100644
index 00000000..ee1be6b6
--- /dev/null
+++ b/xmpp-vala/src/module/conference.vala
@@ -0,0 +1,19 @@
+namespace Xmpp {
+
+public class Conference : Object {
+ public virtual Jid jid { get; set; }
+ public virtual bool autojoin { get; set; }
+ public virtual string? nick { get; set; }
+ public virtual string? name { get; set; }
+ public virtual string? password { get; set; }
+
+ public static bool equal_func(Conference a, Conference b) {
+ return a.jid.equals(b.jid);
+ }
+
+ public static uint hash_func(Conference a) {
+ return Jid.hash_func(a.jid);
+ }
+}
+
+}
diff --git a/xmpp-vala/src/module/xep/0048_bookmarks.vala b/xmpp-vala/src/module/xep/0048_bookmarks.vala
new file mode 100644
index 00000000..8454d711
--- /dev/null
+++ b/xmpp-vala/src/module/xep/0048_bookmarks.vala
@@ -0,0 +1,80 @@
+using Gee;
+
+namespace Xmpp.Xep.Bookmarks {
+private const string NS_URI = "storage:bookmarks";
+
+public class Module : BookmarksProvider, XmppStreamModule {
+ public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0048_bookmarks_module");
+
+ public async Set<Conference>? get_conferences(XmppStream stream) {
+ Set<Conference> ret = new HashSet<Conference>(Conference.hash_func, Conference.equal_func);
+
+ StanzaNode get_node = new StanzaNode.build("storage", NS_URI).add_self_xmlns();
+ stream.get_module(PrivateXmlStorage.Module.IDENTITY).retrieve(stream, get_node, (stream, node) => {
+ if (node != null) {
+ Gee.List<StanzaNode> conferences_node = node.get_subnode("storage", NS_URI).get_subnodes("conference", NS_URI);
+ foreach (StanzaNode conference_node in conferences_node) {
+ Conference? conference = Bookmarks1Conference.create_from_stanza_node(conference_node);
+ ret.add(conference);
+ }
+ }
+ Idle.add(get_conferences.callback);
+ });
+ yield;
+
+ return ret;
+ }
+
+ private void set_conferences(XmppStream stream, Set<Conference> conferences) {
+ StanzaNode storage_node = (new StanzaNode.build("storage", NS_URI)).add_self_xmlns();
+ foreach (Conference conference in conferences) {
+ Bookmarks1Conference? bookmarks1conference = conference as Bookmarks1Conference;
+ if (bookmarks1conference != null) {
+ storage_node.put_node(bookmarks1conference.stanza_node);
+ } else {
+ StanzaNode conference_node = new StanzaNode.build("conference", NS_URI)
+ .put_attribute("jid", conference.jid.to_string())
+ .put_attribute("autojoin", conference.autojoin ? "true" : "false");
+ if (conference.name != null) {
+ conference_node.put_attribute("name", conference.name);
+ }
+ if (conference.nick != null) {
+ conference_node.put_node(new StanzaNode.build("nick", NS_URI)
+ .put_node(new StanzaNode.text(conference.nick)));
+ }
+ storage_node.put_node(conference_node);
+ }
+ }
+ stream.get_module(PrivateXmlStorage.Module.IDENTITY).store(stream, storage_node, (stream) => {
+ stream.get_module(Module.IDENTITY).received_conferences(stream, conferences);
+ });
+ }
+
+ public async void add_conference(XmppStream stream, Conference conference) {
+ Set<Conference>? conferences = yield get_conferences(stream);
+ conferences.add(conference);
+ stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
+ }
+
+ public async void replace_conference(XmppStream stream, Conference orig_conference, Conference modified_conference) {
+ Set<Conference>? conferences = yield get_conferences(stream);
+ conferences.remove(orig_conference);
+ conferences.add(modified_conference);
+ stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
+ }
+
+ public async void remove_conference(XmppStream stream, Conference conference_remove) {
+ Set<Conference>? conferences = yield get_conferences(stream);
+ conferences.remove(conference_remove);
+ stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
+ }
+
+ public override void attach(XmppStream stream) { }
+
+ public override void detach(XmppStream stream) { }
+
+ public override string get_ns() { return NS_URI; }
+ public override string get_id() { return IDENTITY.id; }
+}
+
+}
diff --git a/xmpp-vala/src/module/xep/0048_bookmarks/conference.vala b/xmpp-vala/src/module/xep/0048_bookmarks/conference.vala
deleted file mode 100644
index 7f80490b..00000000
--- a/xmpp-vala/src/module/xep/0048_bookmarks/conference.vala
+++ /dev/null
@@ -1,92 +0,0 @@
-namespace Xmpp.Xep.Bookmarks {
-
-public class Conference : Object {
-
- public const string ATTRIBUTE_AUTOJOIN = "autojoin";
- public const string ATTRIBUTE_JID = "jid";
- public const string ATTRIBUTE_NAME = "name";
-
- public const string NODE_NICK = "nick";
- public const string NODE_PASSWORD = "password";
-
- public StanzaNode stanza_node;
-
- public bool autojoin {
- get {
- string? attr = stanza_node.get_attribute(ATTRIBUTE_AUTOJOIN);
- return attr == "true" || attr == "1";
- }
- set { stanza_node.set_attribute(ATTRIBUTE_AUTOJOIN, value.to_string()); }
- }
-
- private Jid jid_;
- public Jid jid {
- get { return jid_ ?? (jid_ = Jid.parse(stanza_node.get_attribute(ATTRIBUTE_JID))); }
- set { stanza_node.set_attribute(ATTRIBUTE_JID, value.to_string()); }
- }
-
- public string? name {
- get { return stanza_node.get_attribute(ATTRIBUTE_NAME); }
- set {
- if (value == null) return; // TODO actually remove
- stanza_node.set_attribute(ATTRIBUTE_NAME, value);
- }
- }
-
- public string? nick {
- get {
- StanzaNode? nick_node = stanza_node.get_subnode(NODE_NICK);
- return nick_node == null ? null : nick_node.get_string_content();
- }
- set {
- StanzaNode? nick_node = stanza_node.get_subnode(NODE_NICK);
- if (value == null) {
- if (nick_node != null) stanza_node.sub_nodes.remove(nick_node);
- return;
- }
- if (nick_node == null) {
- nick_node = new StanzaNode.build(NODE_NICK, NS_URI);
- stanza_node.put_node(nick_node);
- }
- nick_node.sub_nodes.clear();
- nick_node.put_node(new StanzaNode.text(value));
- }
- }
-
- public string? password {
- get {
- StanzaNode? password_node = stanza_node.get_subnode(NODE_PASSWORD);
- return password_node == null ? null : password_node.get_string_content();
- }
- set {
- StanzaNode? password_node = stanza_node.get_subnode(NODE_PASSWORD);
- if (value == null) {
- if (password_node != null) stanza_node.sub_nodes.remove(password_node);
- return;
- }
- if (password_node == null) {
- password_node = new StanzaNode.build(NODE_PASSWORD);
- stanza_node.put_node(password_node);
- }
- password_node.put_node(new StanzaNode.text(value));
- }
- }
-
- public Conference(Jid jid) {
- this.stanza_node = new StanzaNode.build("conference", NS_URI);
- this.jid = jid;
- }
-
- public static Conference? create_from_stanza_node(StanzaNode stanza_node) {
- if (stanza_node.get_attribute(ATTRIBUTE_JID) != null) {
- return new Conference.from_stanza_node(stanza_node);
- }
- return null;
- }
-
- private Conference.from_stanza_node(StanzaNode stanza_node) {
- this.stanza_node = stanza_node;
- }
-}
-
-}
diff --git a/xmpp-vala/src/module/xep/0048_bookmarks/module.vala b/xmpp-vala/src/module/xep/0048_bookmarks/module.vala
deleted file mode 100644
index 2c16f5f0..00000000
--- a/xmpp-vala/src/module/xep/0048_bookmarks/module.vala
+++ /dev/null
@@ -1,89 +0,0 @@
-using Gee;
-
-namespace Xmpp.Xep.Bookmarks {
-private const string NS_URI = "storage:bookmarks";
-
-public class Module : XmppStreamModule {
- public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0048_bookmarks_module");
-
- public signal void received_conferences(XmppStream stream, Gee.List<Conference> conferences);
-
- public delegate void OnResult(XmppStream stream, Gee.List<Conference>? conferences);
- public void get_conferences(XmppStream stream, owned OnResult listener) {
- StanzaNode get_node = new StanzaNode.build("storage", NS_URI).add_self_xmlns();
- stream.get_module(PrivateXmlStorage.Module.IDENTITY).retrieve(stream, get_node, (stream, node) => {
- if (node == null) {
- listener(stream, null);
- } else {
- Gee.List<Conference> conferences = get_conferences_from_stanza(node);
- listener(stream, conferences);
- }
- });
- }
-
- public void set_conferences(XmppStream stream, Gee.List<Conference> conferences) {
- StanzaNode storage_node = (new StanzaNode.build("storage", NS_URI)).add_self_xmlns();
- foreach (Conference conference in conferences) {
- storage_node.put_node(conference.stanza_node);
- }
- stream.get_module(PrivateXmlStorage.Module.IDENTITY).store(stream, storage_node, (stream) => {
- stream.get_module(Module.IDENTITY).received_conferences(stream, conferences);
- });
- }
-
- public void add_conference(XmppStream stream, Conference conference) {
- get_conferences(stream, (stream, conferences) => {
- conferences.add(conference);
- stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
- });
- }
-
- public void replace_conference(XmppStream stream, Conference orig_conference, Conference modified_conference) {
- get_conferences(stream, (stream, conferences) => {
- foreach (Conference conference in conferences) {
- if (conference.autojoin == orig_conference.autojoin && conference.jid.equals(orig_conference.jid) &&
- conference.name == orig_conference.name && conference.nick == orig_conference.nick) {
- conference.autojoin = modified_conference.autojoin;
- conference.jid = modified_conference.jid;
- conference.name = modified_conference.name;
- conference.nick = modified_conference.nick;
- break;
- }
- }
- stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
- });
- }
-
- public void remove_conference(XmppStream stream, Conference conference_remove) {
- get_conferences(stream, (stream, conferences) => {
- Conference? rem = null;
- foreach (Conference conference in conferences) {
- if (conference.name == conference_remove.name && conference.jid.equals(conference_remove.jid) && conference.autojoin == conference_remove.autojoin) {
- rem = conference;
- break;
- }
- }
- if (rem != null) conferences.remove(rem);
- stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
- });
- }
-
- public override void attach(XmppStream stream) { }
-
- public override void detach(XmppStream stream) { }
-
- public override string get_ns() { return NS_URI; }
- public override string get_id() { return IDENTITY.id; }
-
- private static Gee.List<Conference> get_conferences_from_stanza(StanzaNode node) {
- Gee.List<Conference> conferences = new ArrayList<Conference>();
- Gee.List<StanzaNode> conferenceNodes = node.get_subnode("storage", NS_URI).get_subnodes("conference", NS_URI);
- foreach (StanzaNode conferenceNode in conferenceNodes) {
- Conference? conference = Conference.create_from_stanza_node(conferenceNode);
- conferences.add(conference);
- }
- return conferences;
- }
-}
-
-}
diff --git a/xmpp-vala/src/module/xep/0048_conference.vala b/xmpp-vala/src/module/xep/0048_conference.vala
new file mode 100644
index 00000000..d78a2685
--- /dev/null
+++ b/xmpp-vala/src/module/xep/0048_conference.vala
@@ -0,0 +1,92 @@
+namespace Xmpp.Xep.Bookmarks {
+
+public class Bookmarks1Conference : Conference {
+
+ public const string ATTRIBUTE_AUTOJOIN = "autojoin";
+ public const string ATTRIBUTE_JID = "jid";
+ public const string ATTRIBUTE_NAME = "name";
+
+ public const string NODE_NICK = "nick";
+ public const string NODE_PASSWORD = "password";
+
+ public StanzaNode stanza_node;
+
+ public override bool autojoin {
+ get {
+ string? attr = stanza_node.get_attribute(ATTRIBUTE_AUTOJOIN);
+ return attr == "true" || attr == "1";
+ }
+ set { stanza_node.set_attribute(ATTRIBUTE_AUTOJOIN, value.to_string()); }
+ }
+
+ private Jid jid_;
+ public override Jid jid {
+ get { return jid_ ?? (jid_ = Jid.parse(stanza_node.get_attribute(ATTRIBUTE_JID))); }
+ set { stanza_node.set_attribute(ATTRIBUTE_JID, value.to_string()); }
+ }
+
+ public override string? name {
+ get { return stanza_node.get_attribute(ATTRIBUTE_NAME); }
+ set {
+ if (value == null) return; // TODO actually remove
+ stanza_node.set_attribute(ATTRIBUTE_NAME, value);
+ }
+ }
+
+ public override string? nick {
+ get {
+ StanzaNode? nick_node = stanza_node.get_subnode(NODE_NICK);
+ return nick_node == null ? null : nick_node.get_string_content();
+ }
+ set {
+ StanzaNode? nick_node = stanza_node.get_subnode(NODE_NICK);
+ if (value == null) {
+ if (nick_node != null) stanza_node.sub_nodes.remove(nick_node);
+ return;
+ }
+ if (nick_node == null) {
+ nick_node = new StanzaNode.build(NODE_NICK, NS_URI);
+ stanza_node.put_node(nick_node);
+ }
+ nick_node.sub_nodes.clear();
+ nick_node.put_node(new StanzaNode.text(value));
+ }
+ }
+
+ public override string? password {
+ get {
+ StanzaNode? password_node = stanza_node.get_subnode(NODE_PASSWORD);
+ return password_node == null ? null : password_node.get_string_content();
+ }
+ set {
+ StanzaNode? password_node = stanza_node.get_subnode(NODE_PASSWORD);
+ if (value == null) {
+ if (password_node != null) stanza_node.sub_nodes.remove(password_node);
+ return;
+ }
+ if (password_node == null) {
+ password_node = new StanzaNode.build(NODE_PASSWORD);
+ stanza_node.put_node(password_node);
+ }
+ password_node.put_node(new StanzaNode.text(value));
+ }
+ }
+
+ public Bookmarks1Conference(Jid jid) {
+ this.stanza_node = new StanzaNode.build("conference", NS_URI);
+ this.jid = jid;
+ }
+
+ public static Conference? create_from_stanza_node(StanzaNode stanza_node) {
+ if (stanza_node.get_attribute(ATTRIBUTE_JID) != null) {
+ return new Bookmarks1Conference.from_stanza_node(stanza_node);
+ }
+ return null;
+ }
+
+ private Bookmarks1Conference.from_stanza_node(StanzaNode stanza_node) {
+ this.stanza_node = stanza_node;
+ }
+}
+
+}
diff --git a/xmpp-vala/src/module/xep/0060_pubsub.vala b/xmpp-vala/src/module/xep/0060_pubsub.vala
index 91f5525d..434e9a7e 100644
--- a/xmpp-vala/src/module/xep/0060_pubsub.vala
+++ b/xmpp-vala/src/module/xep/0060_pubsub.vala
@@ -21,6 +21,24 @@ namespace Xmpp.Xep.Pubsub {
event_listeners[node] = new EventListenerDelegate((owned)listener);
}
+ public async Gee.List<StanzaNode>? request_all(XmppStream stream, Jid jid, string node) { // TODO multiple nodes gehen auch
+ Iq.Stanza request_iq = new Iq.Stanza.get(new StanzaNode.build("pubsub", NS_URI).add_self_xmlns().put_node(new StanzaNode.build("items", NS_URI).put_attribute("node", node)));
+ request_iq.to = jid;
+
+ Gee.List<StanzaNode>? ret = null;
+ stream.get_module(Iq.Module.IDENTITY).send_iq(stream, request_iq, (stream, 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;
+ ret = items_node.get_subnodes("item", NS_URI);
+ Idle.add(request_all.callback);
+ });
+ yield;
+
+ return ret;
+ }
+
public delegate void OnResult(XmppStream stream, Jid jid, string? id, StanzaNode? node);
public void request(XmppStream stream, Jid jid, string node, owned OnResult listener) { // TODO multiple nodes gehen auch
Iq.Stanza request_iq = new Iq.Stanza.get(new StanzaNode.build("pubsub", NS_URI).add_self_xmlns().put_node(new StanzaNode.build("items", NS_URI).put_attribute("node", node)));
@@ -34,7 +52,7 @@ namespace Xmpp.Xep.Pubsub {
});
}
- public void publish(XmppStream stream, Jid? jid, string node_id, string? item_id, StanzaNode content, string? access_model=null) {
+ public async bool publish(XmppStream stream, Jid? jid, string node_id, string? item_id, StanzaNode content, string? access_model=null, int? max_items = null) {
StanzaNode pubsub_node = new StanzaNode.build("pubsub", NS_URI).add_self_xmlns();
StanzaNode publish_node = new StanzaNode.build("publish", NS_URI).put_attribute("node", node_id);
pubsub_node.put_node(publish_node);
@@ -43,7 +61,7 @@ namespace Xmpp.Xep.Pubsub {
items_node.put_node(content);
publish_node.put_node(items_node);
- if (access_model != null) {
+ if (access_model != null || max_items != null) {
StanzaNode publish_options_node = new StanzaNode.build("publish-options", NS_URI);
pubsub_node.put_node(publish_options_node);
@@ -51,14 +69,44 @@ namespace Xmpp.Xep.Pubsub {
DataForms.DataForm.HiddenField form_type_field = new DataForms.DataForm.HiddenField() { var="FORM_TYPE" };
form_type_field.set_value_string(NS_URI + "#publish-options");
data_form.add_field(form_type_field);
- DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="pubsub#access_model" };
- field.set_value_string(access_model);
- data_form.add_field(field);
+ if (access_model != null) {
+ DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="pubsub#access_model" };
+ field.set_value_string(access_model);
+ data_form.add_field(field);
+ }
+ if (max_items != null) {
+ DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="pubsub#max_items" };
+ field.set_value_string(max_items.to_string());
+ data_form.add_field(field);
+ }
publish_options_node.put_node(data_form.get_submit_node());
}
Iq.Stanza iq = new Iq.Stanza.set(pubsub_node);
- stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, null);
+ bool ok = true;
+ stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, result_iq) => {
+ ok = !result_iq.is_error();
+ Idle.add(publish.callback);
+ });
+ yield;
+
+ return ok;
+ }
+
+ public async bool retract_item(XmppStream stream, Jid? jid, string node_id, string item_id) {
+ StanzaNode pubsub_node = new StanzaNode.build("pubsub", NS_URI).add_self_xmlns()
+ .put_node(new StanzaNode.build("retract", NS_URI).put_attribute("node", node_id).put_attribute("notify", "true")
+ .put_node(new StanzaNode.build("item", NS_URI).put_attribute("id", item_id)));
+
+ Iq.Stanza iq = new Iq.Stanza.set(pubsub_node);
+ bool ok = true;
+ stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, result_iq) => {
+ ok = !result_iq.is_error();
+ Idle.add(retract_item.callback);
+ });
+ yield;
+
+ return ok;
}
public void delete_node(XmppStream stream, Jid? jid, string node_id) {
@@ -82,14 +130,30 @@ namespace Xmpp.Xep.Pubsub {
public override string get_id() { return IDENTITY.id; }
private void on_received_message(XmppStream stream, MessageStanza message) {
- StanzaNode event_node = message.stanza.get_subnode("event", NS_URI_EVENT); if (event_node == null) return;
- StanzaNode items_node = event_node.get_subnode("items", NS_URI_EVENT); if (items_node == null) return;
- StanzaNode item_node = items_node.get_subnode("item", NS_URI_EVENT); if (item_node == null) return;
+ StanzaNode event_node = message.stanza.get_subnode("event", NS_URI_EVENT);
+ if (event_node == null) return;
+ StanzaNode items_node = event_node.get_subnode("items", NS_URI_EVENT);
+ if (items_node == null) return;
string node = items_node.get_attribute("node", NS_URI_EVENT);
- string id = item_node.get_attribute("id", NS_URI_EVENT);
- if (event_listeners.has_key(node)) {
- event_listeners[node].on_result(stream, message.from, id, item_node.sub_nodes[0]);
+
+ StanzaNode? item_node = items_node.get_subnode("item", NS_URI_EVENT);
+ if (item_node != null) {
+ string id = item_node.get_attribute("id", NS_URI_EVENT);
+
+ if (event_listeners.has_key(node)) {
+ event_listeners[node].on_result(stream, message.from, id, item_node);
+ }
+ }
+
+ StanzaNode? retract_node = items_node.get_subnode("retract", NS_URI_EVENT);
+ if (retract_node != null) {
+ string id = retract_node.get_attribute("id", NS_URI_EVENT);
+
+ if (event_listeners.has_key(node)) {
+ event_listeners[node].on_result(stream, message.from, id, retract_node);
+ }
}
+
}
}
diff --git a/xmpp-vala/src/module/xep/0084_user_avatars.vala b/xmpp-vala/src/module/xep/0084_user_avatars.vala
index 51c2a563..229b2e12 100644
--- a/xmpp-vala/src/module/xep/0084_user_avatars.vala
+++ b/xmpp-vala/src/module/xep/0084_user_avatars.vala
@@ -18,7 +18,7 @@ namespace Xmpp.Xep.UserAvatars {
string sha1 = Checksum.compute_for_data(ChecksumType.SHA1, image);
StanzaNode data_node = new StanzaNode.build("data", NS_URI_DATA).add_self_xmlns()
.put_node(new StanzaNode.text(Base64.encode(image)));
- stream.get_module(Pubsub.Module.IDENTITY).publish(stream, null, NS_URI_DATA, sha1, data_node);
+ stream.get_module(Pubsub.Module.IDENTITY).publish.begin(stream, null, NS_URI_DATA, sha1, data_node);
StanzaNode metadata_node = new StanzaNode.build("metadata", NS_URI_METADATA).add_self_xmlns();
StanzaNode info_node = new StanzaNode.build("info", NS_URI_METADATA)
@@ -28,7 +28,7 @@ namespace Xmpp.Xep.UserAvatars {
.put_attribute("height", height.to_string())
.put_attribute("type", "image/png");
metadata_node.put_node(info_node);
- stream.get_module(Pubsub.Module.IDENTITY).publish(stream, null, NS_URI_METADATA, sha1, metadata_node);
+ stream.get_module(Pubsub.Module.IDENTITY).publish.begin(stream, null, NS_URI_METADATA, sha1, metadata_node);
}
public override void attach(XmppStream stream) {
diff --git a/xmpp-vala/src/module/xep/0402_bookmarks2.vala b/xmpp-vala/src/module/xep/0402_bookmarks2.vala
new file mode 100644
index 00000000..cbe6ea45
--- /dev/null
+++ b/xmpp-vala/src/module/xep/0402_bookmarks2.vala
@@ -0,0 +1,116 @@
+using Gee;
+
+namespace Xmpp.Xep.Bookmarks2 {
+
+private const string NS_URI = "urn:xmpp:bookmarks:0";
+
+public class Module : BookmarksProvider, XmppStreamModule {
+ public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0402_bookmarks2");
+
+ public async Set<Conference>? get_conferences(XmppStream stream) {
+ HashMap<Jid, Conference>? hm = null;
+
+ Flag? flag = stream.get_flag(Flag.IDENTITY);
+ if (flag != null) {
+ hm = flag.conferences;
+ } else {
+ Gee.List<StanzaNode>? items = yield stream.get_module(Pubsub.Module.IDENTITY).request_all(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI);
+
+ hm = new HashMap<Jid, Conference>(Jid.hash_func, Jid.equals_func);
+ foreach (StanzaNode item_node in items) {
+ Conference? conference = parse_item_node(item_node, item_node.get_attribute("id"));
+ if (conference == null) continue;
+ hm[conference.jid] = conference;
+ }
+ stream.add_flag(new Flag(hm));
+ }
+
+
+ var ret = new HashSet<Conference>();
+ foreach (var conference in hm.values) {
+ ret.add(conference);
+ }
+ return ret;
+ }
+
+ public async void add_conference(XmppStream stream, Conference conference) {
+ StanzaNode conference_node = new StanzaNode.build("conference", NS_URI).add_self_xmlns()
+ .put_attribute("autojoin", conference.autojoin ? "true" : "false");
+ if (conference.name != null) {
+ conference_node.put_attribute("name", conference.name);
+ }
+ if (conference.nick != null) {
+ conference_node.put_node((new StanzaNode.build("nick", NS_URI)).put_node(new StanzaNode.text(conference.nick)));
+ }
+ yield stream.get_module(Pubsub.Module.IDENTITY).publish(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI, conference.jid.to_string(), conference_node, Xmpp.Xep.Pubsub.ACCESS_MODEL_WHITELIST, 128);
+ }
+
+ public async void replace_conference(XmppStream stream, Conference orig_conference, Conference modified_conference) {
+ yield add_conference(stream, modified_conference);
+ }
+
+ public async void remove_conference(XmppStream stream, Conference conference) {
+ yield stream.get_module(Pubsub.Module.IDENTITY).retract_item(stream,
+ stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid,
+ NS_URI,
+ conference.jid.to_string());
+ }
+
+ private void on_pupsub_event(XmppStream stream, Jid jid, string id, StanzaNode? node) {
+ if (node.name == "item") {
+ Conference conference = parse_item_node(node, id);
+ Flag? flag = stream.get_flag(Flag.IDENTITY);
+ if (flag != null) {
+ flag.conferences[conference.jid] = conference;
+ }
+ conference_added(stream, conference);
+ } else if (node.name == "retract") {
+ string jid_str = node.get_attribute("id");
+ Jid jid_parsed = Jid.parse(jid_str);
+ Flag? flag = stream.get_flag(Flag.IDENTITY);
+ if (flag != null) {
+ flag.conferences.unset(jid_parsed);
+ }
+ conference_removed(stream, jid_parsed);
+ }
+ }
+
+ private Conference? parse_item_node(StanzaNode item_node, string id) {
+ Conference conference = new Conference();
+ Jid? jid_parsed = Jid.parse(id);
+ if (jid_parsed == null || jid_parsed.resourcepart != null) return null;
+ conference.jid = jid_parsed;
+
+ StanzaNode? conference_node = item_node.get_subnode("conference", NS_URI);
+ if (conference_node == null) return null;
+
+ conference.name = conference_node.get_attribute("name", NS_URI);
+ conference.autojoin = conference_node.get_attribute("autojoin", NS_URI) == "true";
+ conference.nick = conference_node.get_deep_string_content("nick");
+ return conference;
+ }
+
+ public override void attach(XmppStream stream) {
+ stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI, on_pupsub_event);
+ }
+
+ public override void detach(XmppStream stream) { }
+
+ public override string get_ns() { return NS_URI; }
+ public override string get_id() { return IDENTITY.id; }
+}
+
+public class Flag : XmppStreamFlag {
+ public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "bookmarks2");
+
+ public Flag(HashMap<Jid, Conference> conferences) {
+ this.conferences = conferences;
+ }
+
+ public HashMap<Jid, Conference> conferences = new HashMap<Jid, Conference>(Jid.hash_func, Jid.equals_func);
+
+ public override string get_ns() { return NS_URI; }
+ public override string get_id() { return IDENTITY.id; }
+}
+
+}