Move Jid class to xmpp-vala, partially refactor namespace

This commit is contained in:
Marvin W 2018-01-12 21:03:09 +01:00 committed by fiaxh
parent d46d071e57
commit 782ae4c049
116 changed files with 925 additions and 961 deletions

View file

@ -17,7 +17,6 @@ SOURCES
src/entity/conversation.vala
src/entity/encryption.vala
src/entity/file_transfer.vala
src/entity/jid.vala
src/entity/message.vala
src/entity/settings.vala

View file

@ -1,4 +1,5 @@
using Gee;
using Xmpp;
namespace Dino.Entities {

View file

@ -1,3 +1,5 @@
using Xmpp;
namespace Dino.Entities {
public class Conversation : Object {
@ -11,6 +13,7 @@ public class Conversation : Object {
}
public int id { get; set; }
public Type type_ { get; set; }
public Account account { get; private set; }
public Jid counterpart { get; private set; }
public bool active { get; set; default = false; }
@ -25,7 +28,6 @@ public class Conversation : Object {
}
}
public Encryption encryption { get; set; default = Encryption.NONE; }
public Type type_ { get; set; }
public Message? read_up_to { get; set; }
public enum NotifySetting { DEFAULT, ON, OFF, HIGHLIGHT }
@ -48,14 +50,14 @@ public class Conversation : Object {
this.db = db;
id = row[db.conversation.id];
type_ = (Conversation.Type) row[db.conversation.type_];
account = db.get_account_by_id(row[db.conversation.account_id]);
string? resource = row[db.conversation.resource];
string jid = db.get_jid_by_id(row[db.conversation.jid_id]);
counterpart = resource != null ? new Jid.with_resource(jid, resource) : new Jid(jid);
counterpart = Jid.parse(db.get_jid_by_id(row[db.conversation.jid_id]));
if (type_ == Conversation.Type.GROUPCHAT_PM) counterpart = counterpart.with_resource(resource);
active = row[db.conversation.active];
int64? last_active = row[db.conversation.last_active];
if (last_active != null) this.last_active = new DateTime.from_unix_utc(last_active);
type_ = (Conversation.Type) row[db.conversation.type_];
encryption = (Encryption) row[db.conversation.encryption];
int? read_up_to = row[db.conversation.read_up_to];
if (read_up_to != null) this.read_up_to = db.get_message_by_id(read_up_to);
@ -95,10 +97,10 @@ public class Conversation : Object {
}
public NotifySetting get_notification_default_setting(StreamInteractor stream_interactor) {
Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(account);
Xmpp.XmppStream? stream = stream_interactor.get_stream(account);
if (!Application.get_default().settings.notifications) return NotifySetting.OFF;
if (type_ == Type.GROUPCHAT) {
bool members_only = stream.get_flag(Xmpp.Xep.Muc.Flag.IDENTITY).has_room_feature(counterpart.bare_jid.to_string(), Xmpp.Xep.Muc.Feature.MEMBERS_ONLY);
bool members_only = stream.get_flag(Xmpp.Xep.Muc.Flag.IDENTITY).has_room_feature(counterpart.bare_jid, Xmpp.Xep.Muc.Feature.MEMBERS_ONLY);
return members_only ? NotifySetting.ON : NotifySetting.HIGHLIGHT;
}
return NotifySetting.ON;

View file

@ -1,3 +1,5 @@
using Xmpp;
namespace Dino.Entities {
public class FileTransfer : Object {
@ -48,11 +50,12 @@ public class FileTransfer : Object {
string counterpart_jid = db.get_jid_by_id(row[db.file_transfer.counterpart_id]);
string counterpart_resource = row[db.file_transfer.counterpart_resource];
counterpart = counterpart_resource != null ? new Jid.with_resource(counterpart_jid, counterpart_resource) : new Jid(counterpart_jid);
counterpart = Jid.parse(counterpart_jid);
if (counterpart_resource != null) counterpart = counterpart.with_resource(counterpart_resource);
string our_resource = row[db.file_transfer.our_resource];
if (our_resource != null) {
ourpart = new Jid.with_resource(account.bare_jid.to_string(), our_resource);
ourpart = account.bare_jid.with_resource(our_resource);
} else {
ourpart = account.bare_jid;
}

View file

@ -1,4 +1,5 @@
using Gee;
using Xmpp;
namespace Dino.Entities {
@ -51,7 +52,7 @@ public class Message : Object {
marked_ = value;
}
}
public Xmpp.Message.Stanza stanza { get; set; }
public Xmpp.MessageStanza stanza { get; set; }
private Database? db;
@ -67,15 +68,15 @@ public class Message : Object {
stanza_id = row[db.message.stanza_id];
type_ = (Message.Type) row[db.message.type_];
string counterpart_jid = db.get_jid_by_id(row[db.message.counterpart_id]);
counterpart = Jid.parse(db.get_jid_by_id(row[db.message.counterpart_id]));
string counterpart_resource = row[db.message.counterpart_resource];
counterpart = counterpart_resource != null ? new Jid.with_resource(counterpart_jid, counterpart_resource) : new Jid(counterpart_jid);
if (counterpart_resource != null) counterpart = counterpart.with_resource(counterpart_resource);
string our_resource = row[db.message.our_resource];
if (type_ == Type.GROUPCHAT && our_resource != null) {
ourpart = new Jid.with_resource(counterpart_jid, our_resource);
ourpart = counterpart.with_resource(our_resource);
} else if (our_resource != null) {
ourpart = new Jid.with_resource(account.bare_jid.to_string(), our_resource);
ourpart = account.bare_jid.with_resource(our_resource);
} else {
ourpart = account.bare_jid;
}
@ -121,9 +122,9 @@ public class Message : Object {
public void set_type_string(string type) {
switch (type) {
case Xmpp.Message.Stanza.TYPE_CHAT:
case Xmpp.MessageStanza.TYPE_CHAT:
type_ = Type.CHAT; break;
case Xmpp.Message.Stanza.TYPE_GROUPCHAT:
case Xmpp.MessageStanza.TYPE_GROUPCHAT:
type_ = Type.GROUPCHAT; break;
}
}
@ -131,11 +132,11 @@ public class Message : Object {
public new string get_type_string() {
switch (type_) {
case Type.CHAT:
return Xmpp.Message.Stanza.TYPE_CHAT;
return Xmpp.MessageStanza.TYPE_CHAT;
case Type.GROUPCHAT:
return Xmpp.Message.Stanza.TYPE_GROUPCHAT;
return Xmpp.MessageStanza.TYPE_GROUPCHAT;
default:
return Xmpp.Message.Stanza.TYPE_NORMAL;
return Xmpp.MessageStanza.TYPE_NORMAL;
}
}

View file

@ -1,4 +1,5 @@
using Dino.Entities;
using Xmpp;
namespace Dino.Plugins {

View file

@ -41,22 +41,18 @@ public class AvatarManager : StreamInteractionModule, Object {
stream_interactor.module_manager.initialize_account_modules.connect(initialize_avatar_modules);
}
private void initialize_avatar_modules(Account account, ArrayList<Core.XmppStreamModule> modules) {
private void initialize_avatar_modules(Account account, ArrayList<XmppStreamModule> modules) {
modules.add(new Xep.UserAvatars.Module(avatar_storage));
modules.add(new Xep.VCard.Module(avatar_storage));
}
private Pixbuf? get_avatar_by_hash(string hash) {
lock (cached_pixbuf) {
if (cached_pixbuf.has_key(hash)) {
return cached_pixbuf[hash];
}
if (cached_pixbuf.has_key(hash)) {
return cached_pixbuf[hash];
}
Pixbuf? image = avatar_storage.get_image(hash);
if (image != null) {
lock (cached_pixbuf) {
cached_pixbuf[hash] = image;
}
cached_pixbuf[hash] = image;
}
return image;
}
@ -66,17 +62,13 @@ public class AvatarManager : StreamInteractionModule, Object {
if (!stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
jid_ = jid.bare_jid;
}
lock(user_avatars) {
string? user_avatars_id = user_avatars[jid_];
if (user_avatars_id != null) {
return get_avatar_by_hash(user_avatars_id);
}
string? user_avatars_id = user_avatars[jid_];
if (user_avatars_id != null) {
return get_avatar_by_hash(user_avatars_id);
}
lock(vcard_avatars) {
string? vcard_avatars_id = vcard_avatars[jid_];
if (vcard_avatars_id != null) {
return get_avatar_by_hash(vcard_avatars_id);
}
string? vcard_avatars_id = vcard_avatars[jid_];
if (vcard_avatars_id != null) {
return get_avatar_by_hash(vcard_avatars_id);
}
return null;
}
@ -93,7 +85,7 @@ public class AvatarManager : StreamInteractionModule, Object {
}
uint8[] buffer;
pixbuf.save_to_buffer(out buffer, "png");
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.UserAvatars.Module.IDENTITY).publish_png(stream, buffer, pixbuf.width, pixbuf.height);
on_user_avatar_received(account, account.bare_jid, Base64.encode(buffer));
@ -105,32 +97,26 @@ public class AvatarManager : StreamInteractionModule, Object {
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
on_user_avatar_received(account, new Jid(jid), id)
on_user_avatar_received(account, jid, id)
);
stream_interactor.module_manager.get_module(account, Xep.VCard.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
on_vcard_avatar_received(account, new Jid(jid), id)
on_vcard_avatar_received(account, jid, id)
);
lock (user_avatars) {
user_avatars = db.get_avatar_hashes(Source.USER_AVATARS);
foreach (Jid jid in user_avatars.keys) {
on_user_avatar_received(account, jid, user_avatars[jid]);
}
user_avatars = db.get_avatar_hashes(Source.USER_AVATARS);
foreach (Jid jid in user_avatars.keys) {
on_user_avatar_received(account, jid, user_avatars[jid]);
}
lock (vcard_avatars) {
vcard_avatars = db.get_avatar_hashes(Source.VCARD);
foreach (Jid jid in vcard_avatars.keys) {
on_vcard_avatar_received(account, jid, vcard_avatars[jid]);
}
vcard_avatars = db.get_avatar_hashes(Source.VCARD);
foreach (Jid jid in vcard_avatars.keys) {
on_vcard_avatar_received(account, jid, vcard_avatars[jid]);
}
}
private void on_user_avatar_received(Account account, Jid jid, string id) {
lock (user_avatars) {
if (!user_avatars.has_key(jid) || user_avatars[jid] != id) {
user_avatars[jid] = id;
db.set_avatar_hash(jid, id, Source.USER_AVATARS);
}
if (!user_avatars.has_key(jid) || user_avatars[jid] != id) {
user_avatars[jid] = id;
db.set_avatar_hash(jid, id, Source.USER_AVATARS);
}
Pixbuf? avatar = avatar_storage.get_image(id);
if (avatar != null) {
@ -139,12 +125,10 @@ public class AvatarManager : StreamInteractionModule, Object {
}
private void on_vcard_avatar_received(Account account, Jid jid, string id) {
lock (vcard_avatars) {
if (!vcard_avatars.has_key(jid) || vcard_avatars[jid] != id) {
vcard_avatars[jid] = id;
if (!jid.is_full()) { // don't save muc avatars
db.set_avatar_hash(jid, id, Source.VCARD);
}
if (!vcard_avatars.has_key(jid) || vcard_avatars[jid] != id) {
vcard_avatars[jid] = id;
if (!jid.is_full()) { // don't save muc avatars
db.set_avatar_hash(jid, id, Source.VCARD);
}
}
Pixbuf? avatar = avatar_storage.get_image(id);

View file

@ -21,22 +21,22 @@ public class BlockingManager : StreamInteractionModule, Object {
}
public bool is_blocked(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
return stream != null && stream.get_module(Xmpp.Xep.BlockingCommand.Module.IDENTITY).is_blocked(stream, jid.to_string());
}
public void block(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
stream.get_module(Xmpp.Xep.BlockingCommand.Module.IDENTITY).block(stream, new ArrayList<string>.wrap(new string[] {jid.to_string()}));
}
public void unblock(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
stream.get_module(Xmpp.Xep.BlockingCommand.Module.IDENTITY).unblock(stream, new ArrayList<string>.wrap(new string[] {jid.to_string()}));
}
public bool is_supported(Account account) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
return stream != null && stream.get_module(Xmpp.Xep.BlockingCommand.Module.IDENTITY).is_supported(stream);
}
}

View file

@ -138,7 +138,7 @@ public class ChatInteraction : StreamInteractionModule, Object {
}
private void send_chat_marker(Conversation conversation, Entities.Message message, string marker) {
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
XmppStream stream = stream_interactor.get_stream(conversation.account);
if (stream != null &&
(marker == Xep.ChatMarkers.MARKER_RECEIVED || conversation.get_send_marker_setting() == Conversation.Setting.ON) &&
Xep.ChatMarkers.Module.requests_marking(message.stanza)) {
@ -147,17 +147,17 @@ public class ChatInteraction : StreamInteractionModule, Object {
}
private void send_delivery_receipt(Conversation conversation, Entities.Message message) {
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
XmppStream stream = stream_interactor.get_stream(conversation.account);
if (stream != null && Xep.MessageDeliveryReceipts.Module.requests_receipt(message.stanza)) {
stream.get_module(Xep.MessageDeliveryReceipts.Module.IDENTITY).send_received(stream, message.from.to_string(), message.stanza_id);
stream.get_module(Xep.MessageDeliveryReceipts.Module.IDENTITY).send_received(stream, message.from, message.stanza_id);
}
}
private void send_chat_state_notification(Conversation conversation, string state) {
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
XmppStream stream = stream_interactor.get_stream(conversation.account);
if (stream != null && conversation.get_send_typing_setting() == Conversation.Setting.ON &&
conversation.type_ != Conversation.Type.GROUPCHAT) {
stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart.to_string(), state);
stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart, state);
}
}
}

View file

@ -7,7 +7,7 @@ namespace Dino {
public class ConnectionManager {
public signal void stream_opened(Account account, Core.XmppStream stream);
public signal void stream_opened(Account account, XmppStream stream);
public signal void connection_state_changed(Account account, ConnectionState state);
public signal void connection_error(Account account, ConnectionError error);
@ -53,11 +53,11 @@ public class ConnectionManager {
}
private class Connection {
public Core.XmppStream stream { get; set; }
public XmppStream stream { get; set; }
public ConnectionState connection_state { get; set; default = ConnectionState.DISCONNECTED; }
public DateTime established { get; set; }
public DateTime last_activity { get; set; }
public class Connection(Core.XmppStream stream, DateTime established) {
public class Connection(XmppStream stream, DateTime established) {
this.stream = stream;
this.established = established;
}
@ -85,7 +85,7 @@ public class ConnectionManager {
});
}
public Core.XmppStream? get_stream(Account account) {
public XmppStream? get_stream(Account account) {
if (get_state(account) == ConnectionState.CONNECTED) {
return connections[account].stream;
}
@ -110,7 +110,7 @@ public class ConnectionManager {
return connection_todo;
}
public Core.XmppStream? connect(Account account) {
public XmppStream? connect(Account account) {
if (!connection_todo.contains(account)) connection_todo.add(account);
if (!connections.has_key(account)) {
return connect_(account);
@ -144,16 +144,16 @@ public class ConnectionManager {
}
}
private Core.XmppStream? connect_(Account account, string? resource = null) {
private XmppStream? connect_(Account account, string? resource = null) {
if (connections.has_key(account)) connections[account].stream.detach_modules();
connection_errors.unset(account);
if (resource == null) resource = account.resourcepart;
Core.XmppStream stream = new Core.XmppStream();
foreach (Core.XmppStreamModule module in module_manager.get_modules(account, resource)) {
XmppStream stream = new XmppStream();
foreach (XmppStreamModule module in module_manager.get_modules(account, resource)) {
stream.add_module(module);
}
stream.log = new Core.XmppLog(account.bare_jid.to_string(), log_options);
stream.log = new XmppLog(account.bare_jid.to_string(), log_options);
Connection connection = new Connection(stream, new DateTime.now_utc());
connections[account] = connection;
@ -174,7 +174,7 @@ public class ConnectionManager {
return stream;
}
private async void connect_async(Account account, Core.XmppStream stream) {
private async void connect_async(Account account, XmppStream stream) {
try {
yield stream.connect(account.domainpart);
} catch (Error e) {
@ -184,7 +184,7 @@ public class ConnectionManager {
connections.unset(account);
return;
}
if (e is Core.IOStreamError.TLS) {
if (e is IOStreamError.TLS) {
set_connection_error(account, new ConnectionError(ConnectionError.Source.TLS, e.message) { reconnect_recomendation=ConnectionError.Reconnect.NEVER});
return;
}
@ -236,8 +236,8 @@ public class ConnectionManager {
private void check_reconnect(Account account) {
bool acked = false;
Core.XmppStream stream = connections[account].stream;
stream.get_module(Xep.Ping.Module.IDENTITY).send_ping(stream, account.domainpart, (stream) => {
XmppStream stream = connections[account].stream;
stream.get_module(Xep.Ping.Module.IDENTITY).send_ping(stream, account.bare_jid.domain_jid, (stream) => {
acked = true;
change_connection_state(account, ConnectionState.CONNECTED);
});

View file

@ -33,9 +33,10 @@ public class ConversationManager : StreamInteractionModule, Object {
public Conversation create_conversation(Jid jid, Account account, Conversation.Type? type = null) {
assert(conversations.has_key(account));
if (conversations[account].has_key(jid)) {
conversations[account][jid].type_ = type;
return conversations[account][jid];
Jid store_jid = type == Conversation.Type.GROUPCHAT ? jid.bare_jid : jid;
if (conversations[account].has_key(store_jid)) {
conversations[account][store_jid].type_ = type;
return conversations[account][store_jid];
} else {
Conversation conversation = new Conversation(jid, account, type);
add_conversation(conversation);
@ -84,10 +85,11 @@ public class ConversationManager : StreamInteractionModule, Object {
return null;
}
public Gee.List<Conversation> get_active_conversations() {
public Gee.List<Conversation> get_active_conversations(Account? account = null) {
Gee.List<Conversation> ret = new ArrayList<Conversation>(Conversation.equals_func);
foreach (Account account in conversations.keys) {
foreach (Conversation conversation in conversations[account].values) {
foreach (Account account_ in conversations.keys) {
if (account != null && !account_.equals(account)) continue;
foreach (Conversation conversation in conversations[account_].values) {
if(conversation.active) ret.add(conversation);
}
}

View file

@ -37,13 +37,13 @@ public class CounterpartInteractionManager : StreamInteractionModule, Object {
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Xep.ChatMarkers.Module.IDENTITY).marker_received.connect( (stream, jid, marker, id) => {
on_chat_marker_received(account, new Jid(jid), marker, id);
on_chat_marker_received(account, jid, marker, id);
});
stream_interactor.module_manager.get_module(account, Xep.MessageDeliveryReceipts.Module.IDENTITY).receipt_received.connect((stream, jid, id) => {
on_receipt_received(account, new Jid(jid), id);
on_receipt_received(account, jid, id);
});
stream_interactor.module_manager.get_module(account, Xep.ChatStateNotifications.Module.IDENTITY).chat_state_received.connect((stream, jid, state) => {
on_chat_state_received(account, new Jid(jid), state);
on_chat_state_received(account, jid, state);
});
}

View file

@ -232,7 +232,7 @@ public class Database : Qlite.Database {
}
}
public Gee.List<Message> get_messages(Jid jid, Account account, Message.Type? type, int count, DateTime? before) {
public Gee.List<Message> get_messages(Xmpp.Jid jid, Account account, Message.Type? type, int count, DateTime? before) {
QueryBuilder select = message.select()
.with(message.counterpart_id, "=", get_jid_id(jid))
.with(message.account_id, "=", account.id)
@ -255,7 +255,7 @@ public class Database : Qlite.Database {
return ret;
}
public Gee.List<Message> get_unsend_messages(Account account, Jid? jid = null) {
public Gee.List<Message> get_unsend_messages(Account account, Xmpp.Jid? jid = null) {
Gee.List<Message> ret = new ArrayList<Message>();
var select = message.select()
.with(message.account_id, "=", account.id)
@ -308,7 +308,7 @@ public class Database : Qlite.Database {
return ret;
}
public void set_avatar_hash(Jid jid, string hash, int type) {
public void set_avatar_hash(Xmpp.Jid jid, string hash, int type) {
avatar.insert().or("REPLACE")
.value(avatar.jid, jid.to_string())
.value(avatar.hash, hash)
@ -316,10 +316,10 @@ public class Database : Qlite.Database {
.perform();
}
public HashMap<Jid, string> get_avatar_hashes(int type) {
HashMap<Jid, string> ret = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
public HashMap<Xmpp.Jid, string> get_avatar_hashes(int type) {
HashMap<Xmpp.Jid, string> ret = new HashMap<Xmpp.Jid, string>(Xmpp.Jid.hash_func, Xmpp.Jid.equals_func);
foreach (Row row in avatar.select({avatar.jid, avatar.hash}).with(avatar.type_, "=", type)) {
ret[new Jid(row[avatar.jid])] = row[avatar.hash];
ret[Xmpp.Jid.parse(row[avatar.jid])] = row[avatar.hash];
}
return ret;
}
@ -342,7 +342,7 @@ public class Database : Qlite.Database {
}
public int get_jid_id(Jid jid_obj) {
public int get_jid_id(Xmpp.Jid jid_obj) {
string bare_jid = jid_obj.bare_jid.to_string();
if (jid_table_reverse.has_key(bare_jid)) {
return jid_table_reverse[bare_jid];
@ -372,7 +372,7 @@ public class Database : Qlite.Database {
}
}
private int add_jid(Jid jid_obj) {
private int add_jid(Xmpp.Jid jid_obj) {
string bare_jid = jid_obj.bare_jid.to_string();
int id = (int) jid.insert().value(jid.bare_jid, bare_jid).perform();
jid_table_cache[id] = bare_jid;

View file

@ -9,10 +9,10 @@ public class MessageProcessor : StreamInteractionModule, Object {
public static ModuleIdentity<MessageProcessor> IDENTITY = new ModuleIdentity<MessageProcessor>("message_processor");
public string id { get { return IDENTITY.id; } }
public signal void pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation);
public signal void pre_message_received(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation);
public signal void message_received(Entities.Message message, Conversation conversation);
public signal void build_message_stanza(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation);
public signal void pre_message_send(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation);
public signal void build_message_stanza(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation);
public signal void pre_message_send(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation);
public signal void message_sent(Entities.Message message, Conversation conversation);
private StreamInteractor stream_interactor;
@ -51,7 +51,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Xmpp.Message.Module.IDENTITY).received_message.connect( (stream, message) => {
stream_interactor.module_manager.get_module(account, Xmpp.MessageModule.IDENTITY).received_message.connect( (stream, message) => {
on_message_received(account, message);
});
stream_interactor.module_manager.get_module(account, Xmpp.Xep.MessageArchiveManagement.Module.IDENTITY).feature_available.connect( (stream) => {
@ -60,7 +60,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
});
}
private void on_message_received(Account account, Xmpp.Message.Stanza message) {
private void on_message_received(Account account, Xmpp.MessageStanza message) {
if (message.body == null) return;
Entities.Message new_message = create_in_message(account, message);
@ -68,19 +68,18 @@ public class MessageProcessor : StreamInteractionModule, Object {
determine_message_type(account, message, new_message);
}
private Entities.Message create_in_message(Account account, Xmpp.Message.Stanza message) {
private Entities.Message? create_in_message(Account account, Xmpp.MessageStanza message) {
Entities.Message new_message = new Entities.Message(message.body);
new_message.account = account;
new_message.stanza_id = message.id;
Jid from_jid = new Jid(message.from);
if (!account.bare_jid.equals_bare(from_jid) ||
from_jid.equals(stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(from_jid.bare_jid, account))) {
if (!account.bare_jid.equals_bare(message.from) ||
message.from.equals(stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(message.from.bare_jid, account))) {
new_message.direction = Entities.Message.DIRECTION_RECEIVED;
} else {
new_message.direction = Entities.Message.DIRECTION_SENT;
}
new_message.counterpart = new_message.direction == Entities.Message.DIRECTION_SENT ? new Jid(message.to) : new Jid(message.from);
new_message.ourpart = new_message.direction == Entities.Message.DIRECTION_SENT ? new Jid(message.from) : new Jid(message.to);
new_message.counterpart = new_message.direction == Entities.Message.DIRECTION_SENT ? message.to : message.from;
new_message.ourpart = new_message.direction == Entities.Message.DIRECTION_SENT ? message.from : message.to;
new_message.stanza = message;
Xep.MessageArchiveManagement.MessageFlag? mam_message_flag = Xep.MessageArchiveManagement.MessageFlag.get_flag(message);
@ -94,7 +93,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
return new_message;
}
private void process_message(Entities.Message new_message, Xmpp.Message.Stanza stanza) {
private void process_message(Entities.Message new_message, Xmpp.MessageStanza stanza) {
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(new_message);
if (conversation != null) {
pre_message_received(new_message, stanza, conversation);
@ -111,7 +110,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
bool is_mam_message = Xep.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null;
Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
XmppStream? stream = stream_interactor.get_stream(conversation.account);
Xep.MessageArchiveManagement.Flag? mam_flag = stream != null ? stream.get_flag(Xep.MessageArchiveManagement.Flag.IDENTITY) : null;
if (is_mam_message || (mam_flag != null && mam_flag.cought_up == true)) {
conversation.account.mam_earliest_synced = new_message.local_time;
@ -120,11 +119,11 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
}
private void determine_message_type(Account account, Xmpp.Message.Stanza message_stanza, Entities.Message message) {
if (message_stanza.type_ == Xmpp.Message.Stanza.TYPE_GROUPCHAT) {
private void determine_message_type(Account account, Xmpp.MessageStanza message_stanza, Entities.Message message) {
if (message_stanza.type_ == Xmpp.MessageStanza.TYPE_GROUPCHAT) {
message.type_ = Entities.Message.Type.GROUPCHAT;
process_message(message, message_stanza);
} else if (message_stanza.type_ == Xmpp.Message.Stanza.TYPE_CHAT) {
} else if (message_stanza.type_ == Xmpp.MessageStanza.TYPE_CHAT) {
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(message.counterpart.bare_jid, account);
if (conversation != null) {
if (conversation.type_ == Conversation.Type.CHAT) {
@ -134,8 +133,8 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
process_message(message, message_stanza);
} else {
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.ServiceDiscovery.Module.IDENTITY).get_entity_categories(stream, message.counterpart.bare_jid.to_string(), (stream, identities) => {
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.ServiceDiscovery.Module.IDENTITY).get_entity_categories(stream, message.counterpart.bare_jid, (stream, identities) => {
if (identities == null) {
message.type_ = Entities.Message.Type.CHAT;
process_message(message, message_stanza);
@ -168,7 +167,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
message.ourpart = stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(conversation.counterpart, conversation.account) ?? conversation.account.bare_jid;
message.real_jid = conversation.account.bare_jid;
} else {
message.ourpart = new Jid.with_resource(conversation.account.bare_jid.to_string(), conversation.account.resourcepart);
message.ourpart = conversation.account.bare_jid.with_resource(conversation.account.resourcepart);
}
message.marked = Entities.Message.Marked.UNSENT;
message.encryption = conversation.encryption;
@ -177,16 +176,16 @@ public class MessageProcessor : StreamInteractionModule, Object {
public void send_xmpp_message(Entities.Message message, Conversation conversation, bool delayed = false) {
lock (lock_send_unsent) {
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
XmppStream stream = stream_interactor.get_stream(conversation.account);
message.marked = Entities.Message.Marked.NONE;
if (stream != null) {
Xmpp.Message.Stanza new_message = new Xmpp.Message.Stanza(message.stanza_id);
new_message.to = message.counterpart.to_string();
Xmpp.MessageStanza new_message = new Xmpp.MessageStanza(message.stanza_id);
new_message.to = message.counterpart;
new_message.body = message.body;
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
new_message.type_ = Xmpp.Message.Stanza.TYPE_GROUPCHAT;
new_message.type_ = Xmpp.MessageStanza.TYPE_GROUPCHAT;
} else {
new_message.type_ = Xmpp.Message.Stanza.TYPE_CHAT;
new_message.type_ = Xmpp.MessageStanza.TYPE_CHAT;
}
build_message_stanza(message, new_message, conversation);
pre_message_send(message, new_message, conversation);
@ -194,7 +193,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
if (delayed) {
Xmpp.Xep.DelayedDelivery.Module.set_message_delay(new_message, message.time);
}
stream.get_module(Xmpp.Message.Module.IDENTITY).send_message(stream, new_message);
stream.get_module(Xmpp.MessageModule.IDENTITY).send_message(stream, new_message);
message.stanza_id = new_message.id;
message.stanza = new_message;
} else {

View file

@ -6,17 +6,17 @@ using Xmpp;
namespace Dino {
public class ModuleManager {
private HashMap<Account, ArrayList<Core.XmppStreamModule>> module_map = new HashMap<Account, ArrayList<Core.XmppStreamModule>>();
private HashMap<Account, ArrayList<XmppStreamModule>> module_map = new HashMap<Account, ArrayList<XmppStreamModule>>();
private EntityCapabilitiesStorage entity_capabilities_storage;
public signal void initialize_account_modules(Account account, ArrayList<Core.XmppStreamModule> modules);
public signal void initialize_account_modules(Account account, ArrayList<XmppStreamModule> modules);
public ModuleManager(Database db) {
entity_capabilities_storage = new EntityCapabilitiesStorage(db);
}
public T? get_module<T>(Account account, Core.ModuleIdentity<T> identity) {
public T? get_module<T>(Account account, Xmpp.ModuleIdentity<T> identity) {
if (identity == null) return null;
lock (module_map) {
if (!module_map.has_key(account)) {
@ -30,15 +30,15 @@ public class ModuleManager {
return null;
}
public ArrayList<Core.XmppStreamModule> get_modules(Account account, string? resource = null) {
ArrayList<Core.XmppStreamModule> modules = new ArrayList<Core.XmppStreamModule>();
public ArrayList<XmppStreamModule> get_modules(Account account, string? resource = null) {
ArrayList<XmppStreamModule> modules = new ArrayList<XmppStreamModule>();
lock (module_map) {
if (!module_map.has_key(account)) initialize(account);
foreach (Core.XmppStreamModule module in module_map[account]) modules.add(module);
foreach (XmppStreamModule module in module_map[account]) modules.add(module);
}
foreach (Core.XmppStreamModule module in module_map[account]) {
foreach (XmppStreamModule module in module_map[account]) {
if (module.get_id() == Bind.Module.IDENTITY.id) {
(module as Bind.Module).requested_resource == null ? account.resourcepart : resource;
} else if (module.get_id() == PlainSasl.Module.IDENTITY.id) {
@ -50,7 +50,7 @@ public class ModuleManager {
public void initialize(Account account) {
lock(module_map) {
module_map[account] = new ArrayList<Core.XmppStreamModule>();
module_map[account] = new ArrayList<XmppStreamModule>();
module_map[account].add(new Iq.Module());
module_map[account].add(new Tls.Module());
module_map[account].add(new Xep.SrvRecordsTls.Module());
@ -63,7 +63,7 @@ public class ModuleManager {
module_map[account].add(new Xep.PrivateXmlStorage.Module());
module_map[account].add(new Xep.Bookmarks.Module());
module_map[account].add(new Presence.Module());
module_map[account].add(new Xmpp.Message.Module());
module_map[account].add(new Xmpp.MessageModule());
module_map[account].add(new Xep.MessageArchiveManagement.Module());
module_map[account].add(new Xep.MessageCarbons.Module());
module_map[account].add(new Xep.Muc.Module());

View file

@ -30,7 +30,7 @@ public class MucManager : StreamInteractionModule, Object {
}
public void join(Account account, Jid jid, string? nick, string? password) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream == null) return;
string nick_ = nick ?? account.bare_jid.localpart ?? account.bare_jid.domainpart;
@ -41,14 +41,14 @@ public class MucManager : StreamInteractionModule, Object {
if (last_message != null) history_since = last_message.time;
}
stream.get_module(Xep.Muc.Module.IDENTITY).enter(stream, jid.bare_jid.to_string(), nick_, password, history_since);
stream.get_module(Xep.Muc.Module.IDENTITY).enter(stream, jid.bare_jid, nick_, password, history_since);
}
public void part(Account account, Jid jid) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream == null) return;
unset_autojoin(stream, jid);
stream.get_module(Xep.Muc.Module.IDENTITY).exit(stream, jid.bare_jid.to_string());
stream.get_module(Xep.Muc.Module.IDENTITY).exit(stream, jid.bare_jid);
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
if (conversation != null) stream_interactor.get_module(ConversationManager.IDENTITY).close_conversation(conversation);
@ -56,53 +56,53 @@ public class MucManager : StreamInteractionModule, Object {
public delegate void OnResult(Jid jid, Xep.DataForms.DataForm data_form);
public void get_config_form(Account account, Jid jid, owned OnResult listener) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream == null) return;
stream.get_module(Xep.Muc.Module.IDENTITY).get_config_form(stream, jid.to_string(), (stream, jid, data_form) => {
listener(new Jid(jid), data_form);
stream.get_module(Xep.Muc.Module.IDENTITY).get_config_form(stream, jid, (stream, jid, data_form) => {
listener(jid, data_form);
});
}
public void change_subject(Account account, Jid jid, string subject) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_subject(stream, jid.bare_jid.to_string(), subject);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_subject(stream, jid.bare_jid, subject);
}
public void change_nick(Account account, Jid jid, string new_nick) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_nick(stream, jid.bare_jid.to_string(), new_nick);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_nick(stream, jid.bare_jid, new_nick);
}
public void invite(Account account, Jid muc, Jid invitee) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).invite(stream, muc.bare_jid.to_string(), invitee.bare_jid.to_string());
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).invite(stream, muc.bare_jid, invitee.bare_jid);
}
public void kick(Account account, Jid jid, string nick) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).kick(stream, jid.bare_jid.to_string(), nick);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).kick(stream, jid.bare_jid, nick);
}
public void change_affiliation(Account account, Jid jid, string nick, string role) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_affiliation(stream, jid.bare_jid.to_string(), nick, role);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_affiliation(stream, jid.bare_jid, nick, role);
}
public bool kick_possible(Account account, Jid occupant) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_module(Xep.Muc.Module.IDENTITY).kick_possible(stream, occupant.to_string());
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_module(Xep.Muc.Module.IDENTITY).kick_possible(stream, occupant);
return false;
}
public ArrayList<Jid>? get_occupants(Jid jid, Account account) {
public Gee.List<Jid>? get_occupants(Jid jid, Account account) {
if (is_groupchat(jid, account)) {
return stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
}
return null;
}
public ArrayList<Jid>? get_other_occupants(Jid jid, Account account) {
ArrayList<Jid>? occupants = get_occupants(jid, account);
public Gee.List<Jid>? get_other_occupants(Jid jid, Account account) {
Gee.List<Jid>? occupants = get_occupants(jid, account);
Jid? own_jid = get_own_jid(jid, account);
if (occupants != null && own_jid != null) {
occupants.remove(own_jid);
@ -120,87 +120,79 @@ public class MucManager : StreamInteractionModule, Object {
}
public void get_bookmarks(Account account, owned Xep.Bookmarks.Module.OnResult listener) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, (owned)listener);
}
public void add_bookmark(Account account, Xep.Bookmarks.Conference conference) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).add_conference(stream, conference);
}
}
public void replace_bookmark(Account account, Xep.Bookmarks.Conference was, Xep.Bookmarks.Conference replace) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).replace_conference(stream, was, replace);
}
}
public void remove_bookmark(Account account, Xep.Bookmarks.Conference conference) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).remove_conference(stream, conference);
}
}
public string? get_room_name(Account account, Jid jid) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
return stream != null ? stream.get_flag(Xep.Muc.Flag.IDENTITY).get_room_name(jid.to_string()) : null;
XmppStream? stream = stream_interactor.get_stream(account);
return stream != null ? stream.get_flag(Xep.Muc.Flag.IDENTITY).get_room_name(jid) : null;
}
public string? get_groupchat_subject(Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_subject(jid.bare_jid.to_string());
return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_subject(jid.bare_jid);
}
return null;
}
public Jid? get_real_jid(Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
string? real_jid = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(jid.to_string());
if (real_jid != null) {
return new Jid(real_jid);
}
return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(jid);
}
return null;
}
public Xep.Muc.Role? get_role(Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_occupant_role(jid.to_string());
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_occupant_role(jid);
return null;
}
public Xep.Muc.Affiliation? get_affiliation(Jid muc_jid, Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_affiliation(muc_jid.to_string(), jid.to_string());
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_affiliation(muc_jid, jid);
return null;
}
public Gee.List<Jid>? get_offline_members(Jid jid, Account account) {
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
Gee.List<string>? members = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_offline_members(jid.to_string());
if (members == null) return null;
foreach (string member in members) {
ret.add(new Jid(member));
}
return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_offline_members(jid);
}
return ret;
return null;
}
public Jid? get_own_jid(Jid muc_jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
Xep.Muc.Flag? flag = stream.get_flag(Xep.Muc.Flag.IDENTITY);
if (flag == null) return null;
string? nick = flag.get_muc_nick(muc_jid.bare_jid.to_string());
if (nick != null) return new Jid.with_resource(muc_jid.bare_jid.to_string(), nick);
string? nick = flag.get_muc_nick(muc_jid);
if (nick != null) return muc_jid.with_resource(nick);
}
return null;
}
@ -210,23 +202,21 @@ public class MucManager : StreamInteractionModule, Object {
}
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_entered.connect( (stream, jid_string, nick) => {
Jid jid = new Jid(jid_string);
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_entered.connect( (stream, jid, nick) => {
enter_errors.unset(jid);
set_autojoin(stream, jid, nick, null); // TODO password
joined(account, jid, nick);
stream_interactor.get_module(MessageProcessor.IDENTITY).send_unsent_messages(account, jid);
});
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_enter_error.connect( (stream, jid_str, error) => {
Jid jid = new Jid(jid_str);
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_enter_error.connect( (stream, jid, error) => {
enter_errors[jid] = error;
enter_error(account, jid, error);
});
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).self_removed_from_room.connect( (stream, jid, code) => {
left(account, new Jid(jid));
left(account, jid);
});
stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).subject_set.connect( (stream, subject, jid) => {
subject_set(account, new Jid(jid), subject);
subject_set(account, jid, subject);
});
stream_interactor.module_manager.get_module(account, Xep.Bookmarks.Module.IDENTITY).received_conferences.connect( (stream, conferences) => {
sync_autojoin_active(account, conferences);
@ -234,29 +224,28 @@ public class MucManager : StreamInteractionModule, Object {
});
}
private void on_stream_negotiated(Account account, Core.XmppStream stream) {
private void on_stream_negotiated(Account account, XmppStream stream) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, (stream, conferences) => {
foreach (Xep.Bookmarks.Conference bookmark in conferences) {
Jid jid = new Jid(bookmark.jid);
if (bookmark.autojoin) {
join(account, jid, bookmark.nick, bookmark.password);
join(account, bookmark.jid, bookmark.nick, bookmark.password);
}
}
});
}
private void on_pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void on_pre_message_received(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
if (conversation.type_ != Conversation.Type.GROUPCHAT) return;
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
XmppStream stream = stream_interactor.get_stream(conversation.account);
if (stream == null) return;
if (Xep.DelayedDelivery.MessageFlag.get_flag(message.stanza) == null) {
string? real_jid = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(message.counterpart.to_string());
if (real_jid != null && real_jid != message.counterpart.to_string()) {
message.real_jid = new Jid(real_jid).bare_jid;
Jid? real_jid = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(message.counterpart);
if (real_jid != null && !real_jid.equals(message.counterpart)) {
message.real_jid = real_jid.bare_jid;
}
}
string? muc_nick = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_nick(conversation.counterpart.bare_jid.to_string());
if (muc_nick != null && message.from.equals(new Jid(@"$(message.from.bare_jid)/$muc_nick"))) { // TODO better from own
string? muc_nick = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_nick(conversation.counterpart.bare_jid);
if (muc_nick != null && message.from.equals(message.from.with_resource(muc_nick))) { // TODO better from own
Gee.List<Entities.Message> messages = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages(conversation);
foreach (Entities.Message m in messages) { // TODO not here
if (m.equals(message)) {
@ -267,7 +256,7 @@ public class MucManager : StreamInteractionModule, Object {
}
private void sync_autojoin_active(Account account, Gee.List<Xep.Bookmarks.Conference> conferences) {
Gee.List<Conversation> conversations = stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations();
Gee.List<Conversation> conversations = stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations(account);
leave_non_autojoin(account, conferences, conversations);
join_autojoin(account, conferences, conversations);
}
@ -277,7 +266,7 @@ public class MucManager : StreamInteractionModule, Object {
if (conversation.type_ != Conversation.Type.GROUPCHAT || !conversation.account.equals(account)) continue;
bool is_autojoin = false;
foreach (Xep.Bookmarks.Conference conference in conferences) {
if (conference.jid == conversation.counterpart.to_string()) {
if (conference.jid.equals(conversation.counterpart)) {
if (conference.autojoin) is_autojoin = true;
}
}
@ -292,19 +281,20 @@ public class MucManager : StreamInteractionModule, Object {
if (!conference.autojoin) continue;
bool is_active = false;
foreach (Conversation conversation in conversations) {
if (conference.jid == conversation.counterpart.to_string()) is_active = true;
if (conference.jid.equals(conversation.counterpart)) is_active = true;
}
if (!is_active) {
join(account, new Jid(conference.jid), conference.nick, conference.password);
join(account, conference.jid, conference.nick, conference.password);
}
}
}
private void set_autojoin(Core.XmppStream stream, Jid jid, string? nick, string? password) {
private void set_autojoin(XmppStream stream, Jid jid, string? nick, string? password) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, (stream, conferences) => {
Xep.Bookmarks.Conference changed = new Xep.Bookmarks.Conference(jid.to_string()) { nick=nick, password=password, autojoin=true };
if (conferences == null) return;
Xep.Bookmarks.Conference changed = new Xep.Bookmarks.Conference(jid) { nick=nick, password=password, autojoin=true };
foreach (Xep.Bookmarks.Conference conference in conferences) {
if (conference.jid == jid.bare_jid.to_string() && conference.nick == nick && conference.password == password) {
if (conference.jid.equals_bare(jid) && conference.nick == nick && conference.password == password) {
if (!conference.autojoin) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).replace_conference(stream, conference, changed);
}
@ -315,10 +305,11 @@ public class MucManager : StreamInteractionModule, Object {
});
}
private void unset_autojoin(Core.XmppStream stream, Jid jid) {
private void unset_autojoin(XmppStream stream, Jid jid) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, (stream, conferences) => {
if (conferences == null) return;
foreach (Xep.Bookmarks.Conference conference in conferences) {
if (conference.jid == jid.bare_jid.to_string()) {
if (conference.jid.equals_bare(jid)) {
if (conference.autojoin) {
Xep.Bookmarks.Conference change = new Xep.Bookmarks.Conference(conference.jid) { nick=conference.nick, password=conference.password, autojoin=false };
stream.get_module(Xep.Bookmarks.Module.IDENTITY).replace_conference(stream, conference, change);

View file

@ -27,9 +27,9 @@ public class PresenceManager : StreamInteractionModule, Object {
}
public Show get_last_show(Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
Xmpp.Presence.Stanza? presence = stream.get_flag(Presence.Flag.IDENTITY).get_presence(jid.to_string());
Xmpp.Presence.Stanza? presence = stream.get_flag(Presence.Flag.IDENTITY).get_presence(jid);
if (presence != null) {
return new Show(jid, presence.show, new DateTime.now_utc());
}
@ -41,20 +41,12 @@ public class PresenceManager : StreamInteractionModule, Object {
return shows[jid];
}
public ArrayList<Jid>? get_full_jids(Jid jid, Account account) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
public Gee.List<Jid>? get_full_jids(Jid jid, Account account) {
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
Xmpp.Presence.Flag flag = stream.get_flag(Presence.Flag.IDENTITY);
if (flag == null) return null;
Gee.List<string>? resources = flag.get_resources(jid.bare_jid.to_string());
if (resources == null) {
return null;
}
ArrayList<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
foreach (string resource in resources) {
ret.add(new Jid(resource));
}
return ret;
return flag.get_resources(jid.bare_jid);
}
return null;
}
@ -64,40 +56,39 @@ public class PresenceManager : StreamInteractionModule, Object {
}
public void request_subscription(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Presence.Module.IDENTITY).request_subscription(stream, jid.bare_jid.to_string());
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Presence.Module.IDENTITY).request_subscription(stream, jid.bare_jid);
}
public void approve_subscription(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xmpp.Presence.Module.IDENTITY).approve_subscription(stream, jid.bare_jid.to_string());
stream.get_module(Xmpp.Presence.Module.IDENTITY).approve_subscription(stream, jid.bare_jid);
subscription_requests.remove(jid);
}
}
public void deny_subscription(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xmpp.Presence.Module.IDENTITY).deny_subscription(stream, jid.bare_jid.to_string());
stream.get_module(Xmpp.Presence.Module.IDENTITY).deny_subscription(stream, jid.bare_jid);
subscription_requests.remove(jid);
}
}
public void cancel_subscription(Account account, Jid jid) {
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Presence.Module.IDENTITY).cancel_subscription(stream, jid.bare_jid.to_string());
XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Presence.Module.IDENTITY).cancel_subscription(stream, jid.bare_jid);
}
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Presence.Module.IDENTITY).received_available_show.connect((stream, jid, show) =>
on_received_available_show(account, new Jid(jid), show)
on_received_available_show(account, jid, show)
);
stream_interactor.module_manager.get_module(account, Presence.Module.IDENTITY).received_unavailable.connect((stream, presence) =>
on_received_unavailable(account, new Jid(presence.from))
on_received_unavailable(account, presence.from)
);
stream_interactor.module_manager.get_module(account, Presence.Module.IDENTITY).received_subscription_request.connect((stream, jid_str) => {
Jid jid = new Jid(jid_str);
stream_interactor.module_manager.get_module(account, Presence.Module.IDENTITY).received_subscription_request.connect((stream, jid) => {
if (!subscription_requests.contains(jid)) {
subscription_requests.add(jid);
}

View file

@ -40,18 +40,18 @@ public class RosterManager : StreamInteractionModule, Object {
}
public void remove_jid(Account account, Jid jid) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).remove_jid(stream, jid.bare_jid.to_string());
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).remove_jid(stream, jid.bare_jid);
}
public void add_jid(Account account, Jid jid, string? handle) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).add_jid(stream, jid.bare_jid.to_string(), handle);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).add_jid(stream, jid.bare_jid, handle);
}
public void set_jid_handle(Account account, Jid jid, string? handle) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).set_jid_handle(stream, jid.bare_jid.to_string(), handle);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).set_jid_handle(stream, jid.bare_jid, handle);
}
private void on_account_added(Account account) {
@ -61,7 +61,7 @@ public class RosterManager : StreamInteractionModule, Object {
}
});
stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_removed.connect( (stream, roster_item) => {
removed_roster_item(account, new Jid(roster_item.jid), roster_item);
removed_roster_item(account, roster_item.jid, roster_item);
});
stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_updated.connect( (stream, roster_item) => {
on_roster_item_updated(account, roster_item);
@ -69,7 +69,7 @@ public class RosterManager : StreamInteractionModule, Object {
}
private void on_roster_item_updated(Account account, Roster.Item roster_item) {
updated_roster_item(account, new Jid(roster_item.jid), roster_item);
updated_roster_item(account, roster_item.jid, roster_item);
}
}
@ -77,7 +77,7 @@ public class RosterStoreImpl : Roster.Storage, Object {
private Account account;
private Database db;
private HashMap<string, Roster.Item> items = new HashMap<string, Roster.Item>();
private HashMap<Jid, Roster.Item> items = new HashMap<Jid, Roster.Item>(Jid.hash_bare_func, Jid.equals_bare_func);
public class RosterStoreImpl(Account account, Database db) {
this.account = account;
@ -85,7 +85,7 @@ public class RosterStoreImpl : Roster.Storage, Object {
foreach (Qlite.Row row in db.roster.select().with(db.roster.account_id, "=", account.id)) {
Roster.Item item = new Roster.Item();
item.jid = row[db.roster.jid];
item.jid = Jid.parse(row[db.roster.jid]);
item.name = row[db.roster.handle];
item.subscription = row[db.roster.subscription];
items[item.jid] = item;
@ -101,7 +101,7 @@ public class RosterStoreImpl : Roster.Storage, Object {
}
public Roster.Item? get_item(Jid jid) {
return items.has_key(jid.bare_jid.to_string()) ? items[jid.bare_jid.to_string()] : null;
return items.has_key(jid) ? items[jid] : null;
}
public void set_roster_version(string version) {
@ -119,7 +119,7 @@ public class RosterStoreImpl : Roster.Storage, Object {
items[item.jid] = item;
db.roster.insert().or("REPLACE")
.value(db.roster.account_id, account.id)
.value(db.roster.jid, item.jid)
.value(db.roster.jid, item.jid.to_string())
.value(db.roster.handle, item.name)
.value(db.roster.subscription, item.subscription)
.perform();
@ -129,7 +129,7 @@ public class RosterStoreImpl : Roster.Storage, Object {
items.unset(item.jid);
db.roster.delete()
.with(db.roster.account_id, "=", account.id)
.with(db.roster.jid, "=", item.jid).perform();
.with(db.roster.jid, "=", item.jid.to_string()).perform();
}
}

View file

@ -9,8 +9,8 @@ public class StreamInteractor {
public signal void account_added(Account account);
public signal void account_removed(Account account);
public signal void stream_negotiated(Account account, Core.XmppStream stream);
public signal void attached_modules(Account account, Core.XmppStream stream);
public signal void stream_negotiated(Account account, XmppStream stream);
public signal void attached_modules(Account account, XmppStream stream);
public ModuleManager module_manager;
public ConnectionManager connection_manager;
@ -42,7 +42,7 @@ public class StreamInteractor {
return ret;
}
public Core.XmppStream? get_stream(Account account) {
public XmppStream? get_stream(Account account) {
return connection_manager.get_stream(account);
}
@ -58,7 +58,7 @@ public class StreamInteractor {
return null;
}
private void on_stream_opened(Account account, Core.XmppStream stream) {
private void on_stream_opened(Account account, XmppStream stream) {
stream.stream_negotiated.connect( (stream) => {
stream_negotiated(account, stream);
});

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {
@ -122,7 +123,7 @@ public class AddConferenceDialog : Gtk.Dialog {
ConferenceListRow? conference_row = conference_list.get_selected_row() as ConferenceListRow;
if (conference_row != null) {
details_fragment.account = conference_row.account;
details_fragment.jid = conference_row.bookmark.jid;
details_fragment.jid = conference_row.bookmark.jid.to_string();
details_fragment.nick = conference_row.bookmark.nick;
if (conference_row.bookmark.password != null) details_fragment.password = conference_row.bookmark.password;
ok_button.grab_focus();

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {
@ -43,7 +44,7 @@ protected class AddGroupchatDialog : Gtk.Dialog {
accounts_stack.set_visible_child_name("label");
account_label.label = account.bare_jid.to_string();
account_combobox.selected = account;
jid_entry.text = conference.jid;
jid_entry.text = conference.jid.to_string();
nick_entry.text = conference.nick ?? "";
alias_entry.text = conference.name;
}
@ -64,7 +65,7 @@ protected class AddGroupchatDialog : Gtk.Dialog {
}
private void on_ok_button_clicked() {
Xmpp.Xep.Bookmarks.Conference conference = new Xmpp.Xep.Bookmarks.Conference(jid_entry.text);
Xmpp.Xep.Bookmarks.Conference conference = new Xmpp.Xep.Bookmarks.Conference(Jid.parse(jid_entry.text));
conference.nick = nick_entry.text != "" ? nick_entry.text : null;
conference.name = alias_entry.text;
if (edit_conference == null) {

View file

@ -2,6 +2,7 @@ using Gdk;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {

View file

@ -39,8 +39,12 @@ protected class ConferenceList : FilterableList {
}
}
private void on_conference_bookmarks_received(Core.XmppStream stream, Account account, Gee.List<Xep.Bookmarks.Conference> conferences) {
lists[account] = conferences;
private void on_conference_bookmarks_received(XmppStream stream, Account account, Gee.List<Xep.Bookmarks.Conference>? conferences) {
if (conferences == null) {
lists.unset(account);
} else {
lists[account] = conferences;
}
refresh_conferences();
}
@ -77,15 +81,15 @@ internal class ConferenceListRow : ListRow {
public Xep.Bookmarks.Conference bookmark;
public ConferenceListRow(StreamInteractor stream_interactor, Xep.Bookmarks.Conference bookmark, Account account) {
this.jid = new Jid(bookmark.jid);
this.jid = bookmark.jid;
this.account = account;
this.bookmark = bookmark;
name_label.label = bookmark.name ?? bookmark.jid;
name_label.label = bookmark.name ?? bookmark.jid.to_string();
if (stream_interactor.get_accounts().size > 1) {
via_label.label = "via " + account.bare_jid.to_string();
} else if (bookmark.name != null && bookmark.name != bookmark.jid) {
via_label.label = bookmark.jid;
} else if (bookmark.name != null && bookmark.name != bookmark.jid.to_string()) {
via_label.label = bookmark.jid.to_string();
} else {
via_label.visible = false;
}

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {

View file

@ -49,7 +49,7 @@ protected class RosterList : FilterableList {
private void on_updated_roster_item(Account account, Jid jid, Roster.Item roster_item) {
on_removed_roster_item(account, jid, roster_item);
ListRow row = new ListRow.from_jid(stream_interactor, new Jid(roster_item.jid), account, accounts.size > 1);
ListRow row = new ListRow.from_jid(stream_interactor, roster_item.jid, account, accounts.size > 1);
rows[account][jid] = row;
add(row);
invalidate_sort();
@ -59,7 +59,7 @@ protected class RosterList : FilterableList {
private void fetch_roster_items(Account account) {
rows[account] = new HashMap<Jid, ListRow>(Jid.hash_func, Jid.equals_func);
foreach (Roster.Item roster_item in stream_interactor.get_module(RosterManager.IDENTITY).get_roster(account)) {
on_updated_roster_item(account, new Jid(roster_item.jid), roster_item);
on_updated_roster_item(account, roster_item.jid, roster_item);
}
}

View file

@ -3,6 +3,7 @@ using Gdk;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {

View file

@ -2,6 +2,7 @@ using Gtk;
using Dino.Entities;
using Dino.Ui;
using Xmpp;
public class Dino.Ui.Application : Gtk.Application, Dino.Application {
private Notifications notifications;

View file

@ -4,6 +4,7 @@ using Gdk;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui {
@ -109,7 +110,7 @@ public class AvatarGenerator {
}
private Pixbuf draw_groupchat_tile(Jid jid, Account account, int width, int height) {
ArrayList<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(jid, account);
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(jid, account);
if (stateless || occupants == null || occupants.size == 0) {
return draw_chat_tile(jid, account, width, height);
}

View file

@ -10,6 +10,7 @@ public class EncryptionButton : MenuButton {
private Conversation? conversation;
private RadioButton? button_unencrypted;
private Map<RadioButton, Plugins.EncryptionListEntry> encryption_radios = new HashMap<RadioButton, Plugins.EncryptionListEntry>();
private string? current_icon;
public EncryptionButton() {
relief = ReliefStyle.NONE;
@ -56,14 +57,17 @@ public class EncryptionButton : MenuButton {
}
}
private void update_encryption_menu_icon() {
if (conversation.encryption == Encryption.NONE) {
set_image(new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON));
} else {
set_image(new Image.from_icon_name("changes-prevent-symbolic", IconSize.BUTTON));
private void set_icon(string icon) {
if (icon != current_icon) {
image = new Image.from_icon_name(icon, IconSize.BUTTON);
current_icon = icon;
}
}
private void update_encryption_menu_icon() {
set_icon(conversation.encryption == Encryption.NONE ? "changes-allow-symbolic" : "changes-prevent-symbolic");
}
public new void set_conversation(Conversation conversation) {
this.conversation = conversation;
update_encryption_menu_state();

View file

@ -3,6 +3,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ChatInput {

View file

@ -84,8 +84,8 @@ public class View : Box {
stream_interactor.get_module(MucManager.IDENTITY).change_nick(conversation.account, conversation.counterpart, token[1]);
return;
case "/ping":
Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
stream.get_module(Xmpp.Xep.Ping.Module.IDENTITY).send_ping(stream, conversation.counterpart.to_string() + "/" + token[1], null);
Xmpp.XmppStream? stream = stream_interactor.get_stream(conversation.account);
stream.get_module(Xmpp.Xep.Ping.Module.IDENTITY).send_ping(stream, conversation.counterpart.with_resource(token[1]), null);
return;
case "/topic":
stream_interactor.get_module(MucManager.IDENTITY).change_subject(conversation.account, conversation.counterpart, token[1]);

View file

@ -17,7 +17,7 @@ public class MucConfigFormProvider : Plugins.ContactDetailsProvider, Object {
public void populate(Conversation conversation, Plugins.ContactDetails contact_details, Plugins.WidgetType type) {
if (type != Plugins.WidgetType.GTK) return;
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
Xmpp.XmppStream? stream = stream_interactor.get_stream(conversation.account);
if (stream == null) return;
stream_interactor.get_module(MucManager.IDENTITY).get_config_form(conversation.account, conversation.counterpart, (jid, data_form) => {
contact_details.save.connect(() => { data_form.submit(); });

View file

@ -3,6 +3,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSelector {
@ -18,7 +19,6 @@ public class ChatRow : ConversationRow {
stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect((account, jid, roster_item) => {
if (conversation.account.equals(account) && conversation.counterpart.equals(jid)) {
update_name_label();
update_avatar();
}
});
}
@ -41,7 +41,7 @@ public class ChatRow : ConversationRow {
jid_label.label = conversation.counterpart.to_string();
ArrayList<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
if (full_jids != null) {
for (int i = 0; i < full_jids.size; i++) {
inner_box.add(get_fulljid_box(full_jids[i]));

View file

@ -4,6 +4,7 @@ using Gtk;
using Pango;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSelector {

View file

@ -15,7 +15,6 @@ public class GroupchatPmRow : ConversationRow {
tooltip.set_custom(generate_tooltip());
return true;
});
update_avatar();
}
protected override void update_message_label() {

View file

@ -8,12 +8,10 @@ public class GroupchatRow : ConversationRow {
base(stream_interactor, conversation);
has_tooltip = true;
set_tooltip_text(conversation.counterpart.bare_jid.to_string());
update_avatar();
closed.connect(() => {
stream_interactor.get_module(MucManager.IDENTITY).part(conversation.account, conversation.counterpart);
});
stream_interactor.get_module(MucManager.IDENTITY).left.connect(update_avatar);
}
protected override void update_message_label() {

View file

@ -26,18 +26,6 @@ public class List : ListBox {
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_deactivated.connect(remove_conversation);
stream_interactor.get_module(MessageProcessor.IDENTITY).message_received.connect(on_message_received);
stream_interactor.get_module(MessageProcessor.IDENTITY).message_sent.connect(on_message_received);
stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect((show, jid, account) => {
foreach (Conversation conversation in stream_interactor.get_module(ConversationManager.IDENTITY).get_conversations_for_presence(show, account)) {
if (rows.has_key(conversation)) rows[conversation].on_show_received(show);
}
});
stream_interactor.get_module(AvatarManager.IDENTITY).received_avatar.connect((avatar, jid, account) => {
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
if (conversation != null && rows.has_key(conversation)) {
ChatRow row = rows[conversation] as ChatRow;
if (row != null) row.update_avatar();
}
});
Timeout.add_seconds(60, () => {
foreach (ConversationRow row in rows.values) row.update();
return true;
@ -99,7 +87,7 @@ public class List : ListBox {
row.closed.connect(() => { select_next_conversation(conversation); });
row.main_revealer.set_reveal_child(true);
}
invalidate_sort();
//invalidate_sort();
}
private void select_next_conversation(Conversation conversation) {

View file

@ -2,6 +2,7 @@ using Gdk;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSummary {
@ -26,7 +27,7 @@ public class DefaultFileDisplay : Plugins.MetaConversationItem {
this.stream_interactor = stream_interactor;
this.file_transfer = file_transfer;
this.jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? new Jid.with_resource(file_transfer.account.bare_jid.to_string(), file_transfer.account.resourcepart) : file_transfer.counterpart;
this.jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? file_transfer.account.bare_jid.with_resource(file_transfer.account.resourcepart) : file_transfer.counterpart;
this.sort_time = file_transfer.time;
this.seccondary_sort_indicator = file_transfer.id + 0.2903;
this.display_time = file_transfer.time;

View file

@ -1,4 +1,5 @@
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSummary {

View file

@ -1,6 +1,7 @@
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSummary {
@ -25,7 +26,7 @@ public class ImageDisplay : Plugins.MetaConversationItem {
this.stream_interactor = stream_interactor;
this.file_transfer = file_transfer;
this.jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? new Jid.with_resource(file_transfer.account.bare_jid.to_string(), file_transfer.account.resourcepart) : file_transfer.counterpart;
this.jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? file_transfer.account.bare_jid.with_resource(file_transfer.account.resourcepart) : file_transfer.counterpart;
this.sort_time = file_transfer.time;
this.seccondary_sort_indicator = file_transfer.id + 0.2903;
this.display_time = file_transfer.time;

View file

@ -1,6 +1,7 @@
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ConversationSummary {

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ManageAccounts {

View file

@ -4,6 +4,7 @@ using Gtk;
using Markup;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ManageAccounts {

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.OccupantMenu{
@ -39,6 +40,7 @@ public class List : Box {
add_occupant(occupant);
}
}
list_box.invalidate_filter();
}
private void refilter() {
@ -57,8 +59,6 @@ public class List : Box {
public void add_occupant(Jid jid) {
rows[jid] = new ListRow(stream_interactor, conversation.account, jid);
list_box.add(rows[jid]);
list_box.invalidate_filter();
list_box.invalidate_sort();
}
public void remove_occupant(Jid jid) {
@ -77,6 +77,7 @@ public class List : Box {
} else if (show.as != Show.OFFLINE && !rows.has_key(jid)) {
add_occupant(jid);
}
list_box.invalidate_filter();
}
}

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.OccupantMenu {
public class View : Popover {

View file

@ -65,7 +65,7 @@ public static string get_display_name(StreamInteractor stream_interactor, Jid ji
}
return jid.resourcepart;
} else {
if (jid.bare_jid.equals(account.bare_jid.bare_jid)) {
if (jid.equals_bare(account.bare_jid)) {
if (account.alias == null || account.alias == "") {
return account.bare_jid.to_string();
} else {
@ -84,9 +84,24 @@ public static string get_message_display_name(StreamInteractor stream_interactor
return get_display_name(stream_interactor, message.from, account);
}
public static void image_set_from_scaled_pixbuf(Image image, Gdk.Pixbuf pixbuf, int scale = 0) {
public static void image_set_from_scaled_pixbuf(Image image, Gdk.Pixbuf pixbuf, int scale = 0, int width = 0, int height = 0) {
if (scale == 0) scale = image.scale_factor;
image.set_from_surface(Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, image.get_window()));
Cairo.Surface surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, image.get_window());
if (height == 0 && width != 0) {
height = (int) ((double) width / pixbuf.width * pixbuf.height);
} else if (height != 0 && width == 0) {
width = (int) ((double) height / pixbuf.height * pixbuf.width);
}
if (width != 0) {
Cairo.Surface surface_new = new Cairo.Surface.similar_image(surface, Cairo.Format.ARGB32, width, height);
Cairo.Context context = new Cairo.Context(surface_new);
context.scale((double) width * scale / pixbuf.width, (double) height * scale / pixbuf.height);
context.set_source_surface(surface, 0, 0);
context.get_source().set_filter(Cairo.Filter.BEST);
context.paint();
surface = surface_new;
}
image.set_from_surface(surface);
}
private const string force_background_css = "%s { background-color: %s; }";

View file

@ -2,6 +2,7 @@ using Gee;
using Gtk;
using Dino.Entities;
using Xmpp;
namespace Dino.Plugins.HttpFiles {

View file

@ -30,7 +30,7 @@ public class Manager : StreamInteractionModule, FileSender, Object {
}
public void send_file(Conversation conversation, FileTransfer file_transfer) {
Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(file_transfer.account);
Xmpp.XmppStream? stream = stream_interactor.get_stream(file_transfer.account);
if (stream != null) {
stream_interactor.module_manager.get_module(file_transfer.account, UploadStreamModule.IDENTITY).upload(stream, file_transfer.input_stream, file_transfer.server_file_name, file_transfer.size, file_transfer.mime_type,
(stream, url_down) => {
@ -60,7 +60,7 @@ public class Manager : StreamInteractionModule, FileSender, Object {
}
}
private void on_stream_negotiated(Account account, Core.XmppStream stream) {
private void on_stream_negotiated(Account account, XmppStream stream) {
stream_interactor.module_manager.get_module(account, UploadStreamModule.IDENTITY).feature_available.connect((stream, max_file_size) => {
lock (max_file_sizes) {
max_file_sizes[account] = max_file_size;
@ -69,7 +69,7 @@ public class Manager : StreamInteractionModule, FileSender, Object {
});
}
private void check_add_oob(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void check_add_oob(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
if (message_is_file(db, message)) {
Xep.OutOfBandData.add_url_to_message(message_stanza, message_stanza.body);
}

View file

@ -1,5 +1,5 @@
using Xmpp;
using Xmpp.Core;
using Xmpp;
using Xmpp.Xep;
namespace Dino.Plugins.HttpFiles {
@ -8,7 +8,7 @@ private const string NS_URI = "urn:xmpp:http:upload";
private const string NS_URI_0 = "urn:xmpp:http:upload:0";
public class UploadStreamModule : XmppStreamModule {
public static Core.ModuleIdentity<UploadStreamModule> IDENTITY = new Core.ModuleIdentity<UploadStreamModule>(NS_URI, "0363_http_file_upload");
public static Xmpp.ModuleIdentity<UploadStreamModule> IDENTITY = new Xmpp.ModuleIdentity<UploadStreamModule>(NS_URI, "0363_http_file_upload");
public signal void feature_available(XmppStream stream, long max_file_size);
@ -116,7 +116,7 @@ public class UploadStreamModule : XmppStreamModule {
});
}
private bool check_ns_in_info(XmppStream stream, string jid, Xep.ServiceDiscovery.InfoResult info_result) {
private bool check_ns_in_info(XmppStream stream, Jid jid, Xep.ServiceDiscovery.InfoResult info_result) {
bool ver_available = false;
bool ver_0_available = false;
foreach (string feature in info_result.features) {
@ -162,11 +162,11 @@ public class UploadStreamModule : XmppStreamModule {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "service_discovery");
public string file_store_jid;
public Jid file_store_jid;
public string ns_ver;
public int? max_file_size;
public Flag(string file_store_jid, string ns_ver) {
public Flag(Jid file_store_jid, string ns_ver) {
this.file_store_jid = file_store_jid;
this.ns_ver = ns_ver;
}

View file

@ -1,6 +1,6 @@
using Gee;
using Signal;
using Xmpp.Core;
using Xmpp;
namespace Dino.Plugins.Omemo {

View file

@ -69,16 +69,16 @@ public class Manager : StreamInteractionModule, Object {
stream_interactor.get_module(MessageProcessor.IDENTITY).pre_message_send.connect(on_pre_message_send);
}
private void on_pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void on_pre_message_received(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
MessageFlag? flag = MessageFlag.get_flag(message_stanza);
if (flag != null && ((!)flag).decrypted) {
message.encryption = Encryption.OMEMO;
}
}
private void on_pre_message_send(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void on_pre_message_send(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
if (message.encryption == Encryption.OMEMO) {
Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
XmppStream? stream = stream_interactor.get_stream(conversation.account);
if (stream == null) {
message.marked = Entities.Message.Marked.UNSENT;
return;
@ -89,7 +89,7 @@ public class Manager : StreamInteractionModule, Object {
return;
}
StreamModule module = (!)module_;
EncryptState enc_state = module.encrypt(message_stanza, conversation.account.bare_jid.to_string());
EncryptState enc_state = module.encrypt(message_stanza, conversation.account.bare_jid);
MessageState state;
lock (message_states) {
if (message_states.has_key(message)) {
@ -111,13 +111,13 @@ public class Manager : StreamInteractionModule, Object {
if (Plugin.DEBUG) print(@"OMEMO: message will be delayed: $state\n");
if (state.waiting_own_sessions > 0) {
module.start_sessions_with((!)stream, conversation.account.bare_jid.to_string());
module.start_sessions_with((!)stream, conversation.account.bare_jid);
}
if (state.waiting_other_sessions > 0 && message.counterpart != null) {
module.start_sessions_with((!)stream, ((!)message.counterpart).bare_jid.to_string());
module.start_sessions_with((!)stream, ((!)message.counterpart).bare_jid);
}
if (state.waiting_other_devicelist && message.counterpart != null) {
module.request_user_devicelist((!)stream, ((!)message.counterpart).bare_jid.to_string());
module.request_user_devicelist((!)stream, ((!)message.counterpart).bare_jid);
}
}
}
@ -132,20 +132,20 @@ public class Manager : StreamInteractionModule, Object {
stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).session_start_failed.connect((jid, device_id) => on_session_started(account, jid, true));
}
private void on_stream_negotiated(Account account, Core.XmppStream stream) {
stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist(stream, account.bare_jid.to_string());
private void on_stream_negotiated(Account account, XmppStream stream) {
stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist(stream, account.bare_jid);
}
private void on_session_started(Account account, string jid, bool failed) {
private void on_session_started(Account account, Jid jid, bool failed) {
if (Plugin.DEBUG) print(@"OMEMO: session start between $(account.bare_jid) and $jid $(failed ? "failed" : "successful")\n");
HashSet<Entities.Message> send_now = new HashSet<Entities.Message>();
lock (message_states) {
foreach (Entities.Message msg in message_states.keys) {
if (!msg.account.equals(account)) continue;
MessageState state = message_states[msg];
if (account.bare_jid.to_string() == jid) {
if (account.bare_jid.equals(jid)) {
state.waiting_own_sessions--;
} else if (msg.counterpart != null && ((!)msg.counterpart).bare_jid.to_string() == jid) {
} else if (msg.counterpart != null && msg.counterpart.equals_bare(jid)) {
state.waiting_other_sessions--;
}
if (state.should_retry_now()) {
@ -162,16 +162,16 @@ public class Manager : StreamInteractionModule, Object {
}
}
private void on_device_list_loaded(Account account, string jid) {
private void on_device_list_loaded(Account account, Jid jid) {
if (Plugin.DEBUG) print(@"OMEMO: received device list for $(account.bare_jid) from $jid\n");
HashSet<Entities.Message> send_now = new HashSet<Entities.Message>();
lock (message_states) {
foreach (Entities.Message msg in message_states.keys) {
if (!msg.account.equals(account)) continue;
MessageState state = message_states[msg];
if (account.bare_jid.to_string() == jid) {
if (account.bare_jid.equals(jid)) {
state.waiting_own_devicelist = false;
} else if (msg.counterpart != null && ((!)msg.counterpart).bare_jid.to_string() == jid) {
} else if (msg.counterpart != null && msg.counterpart.equals_bare(jid)) {
state.waiting_other_devicelist = false;
}
if (state.should_retry_now()) {
@ -188,7 +188,7 @@ public class Manager : StreamInteractionModule, Object {
}
// Update meta database
Core.XmppStream? stream = stream_interactor.get_stream(account);
XmppStream? stream = stream_interactor.get_stream(account);
if (stream == null) {
return;
}
@ -197,10 +197,10 @@ public class Manager : StreamInteractionModule, Object {
return;
}
ArrayList<int32> device_list = module.get_device_list(jid);
db.identity_meta.insert_device_list(jid, device_list);
db.identity_meta.insert_device_list(jid.bare_jid.to_string(), device_list);
int inc = 0;
foreach (Row row in db.identity_meta.with_address(jid).with_null(db.identity_meta.identity_key_public_base64)) {
module.fetch_bundle(stream, row[db.identity_meta.address_name], row[db.identity_meta.device_id]);
foreach (Row row in db.identity_meta.with_address(jid.bare_jid.to_string()).with_null(db.identity_meta.identity_key_public_base64)) {
module.fetch_bundle(stream, Jid.parse(row[db.identity_meta.address_name]), row[db.identity_meta.device_id]);
inc++;
}
if (inc > 0) {
@ -208,8 +208,8 @@ public class Manager : StreamInteractionModule, Object {
}
}
public void on_bundle_fetched(Account account, string jid, int32 device_id, Bundle bundle) {
db.identity_meta.insert_device_bundle(jid, device_id, bundle);
public void on_bundle_fetched(Account account, Jid jid, int32 device_id, Bundle bundle) {
db.identity_meta.insert_device_bundle(jid.bare_jid.to_string(), device_id, bundle);
}
private void on_store_created(Account account, Store store) {
@ -252,11 +252,11 @@ public class Manager : StreamInteractionModule, Object {
public bool can_encrypt(Entities.Conversation conversation) {
Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
XmppStream? stream = stream_interactor.get_stream(conversation.account);
if (stream == null) return false;
StreamModule? module = ((!)stream).get_module(StreamModule.IDENTITY);
if (module == null) return false;
return ((!)module).is_known_address(conversation.counterpart.bare_jid.to_string());
return ((!)module).is_known_address(conversation.counterpart.bare_jid);
}
public static void start(StreamInteractor stream_interactor, Database db) {

View file

@ -2,12 +2,12 @@ using Xmpp;
namespace Dino.Plugins.Omemo {
public class MessageFlag : Message.MessageFlag {
public class MessageFlag : Xmpp.MessageFlag {
public const string id = "omemo";
public bool decrypted = false;
public static MessageFlag? get_flag(Message.Stanza message) {
public static MessageFlag? get_flag(MessageStanza message) {
return (MessageFlag) message.get_flag(NS_URI, id);
}

View file

@ -1,6 +1,6 @@
using Gee;
using Xmpp;
using Xmpp.Core;
using Xmpp;
using Xmpp.Xep;
using Signal;
@ -14,33 +14,32 @@ private const string NODE_VERIFICATION = NS_URI + ".verification";
private const int NUM_KEYS_TO_PUBLISH = 100;
public class StreamModule : XmppStreamModule {
public static Core.ModuleIdentity<StreamModule> IDENTITY = new Core.ModuleIdentity<StreamModule>(NS_URI, "omemo_module");
public static Xmpp.ModuleIdentity<StreamModule> IDENTITY = new Xmpp.ModuleIdentity<StreamModule>(NS_URI, "omemo_module");
private Store store;
private ConcurrentSet<string> active_bundle_requests = new ConcurrentSet<string>();
private ConcurrentSet<string> active_devicelist_requests = new ConcurrentSet<string>();
private Map<string, ArrayList<int32>> device_lists = new HashMap<string, ArrayList<int32>>();
private Map<string, ArrayList<int32>> ignored_devices = new HashMap<string, ArrayList<int32>>();
private ConcurrentSet<Jid> active_devicelist_requests = new ConcurrentSet<Jid>();
private Map<Jid, ArrayList<int32>> device_lists = new HashMap<Jid, ArrayList<int32>>(Jid.hash_bare_func, Jid.equals_bare_func);
private Map<Jid, ArrayList<int32>> ignored_devices = new HashMap<Jid, ArrayList<int32>>(Jid.hash_bare_func, Jid.equals_bare_func);
private ReceivedPipelineListener received_pipeline_listener;
public signal void store_created(Store store);
public signal void device_list_loaded(string jid);
public signal void bundle_fetched(string jid, int device_id, Bundle bundle);
public signal void session_started(string jid, int device_id);
public signal void session_start_failed(string jid, int device_id);
public signal void device_list_loaded(Jid jid);
public signal void bundle_fetched(Jid jid, int device_id, Bundle bundle);
public signal void session_started(Jid jid, int device_id);
public signal void session_start_failed(Jid jid, int device_id);
public EncryptState encrypt(Message.Stanza message, string self_bare_jid) {
public EncryptState encrypt(MessageStanza message, Jid self_jid) {
EncryptState status = new EncryptState();
if (!Plugin.ensure_context()) return status;
if (message.to == null) return status;
try {
string name = get_bare_jid((!)message.to);
if (!device_lists.has_key(self_bare_jid)) return status;
if (!device_lists.has_key(self_jid)) return status;
status.own_list = true;
status.own_devices = device_lists.get(self_bare_jid).size;
if (!device_lists.has_key(name)) return status;
status.own_devices = device_lists.get(self_jid).size;
if (!device_lists.has_key(message.to)) return status;
status.other_list = true;
status.other_devices = device_lists.get(name).size;
status.other_devices = device_lists.get(message.to).size;
if (status.own_devices == 0 || status.other_devices == 0) return status;
uint8[] key = new uint8[16];
@ -59,9 +58,9 @@ public class StreamModule : XmppStreamModule {
.put_node(new StanzaNode.build("payload", NS_URI)
.put_node(new StanzaNode.text(Base64.encode(ciphertext))));
Address address = new Address(name, 0);
foreach(int32 device_id in device_lists[name]) {
if (is_ignored_device(name, device_id)) {
Address address = new Address(message.to.bare_jid.to_string(), 0);
foreach(int32 device_id in device_lists[message.to]) {
if (is_ignored_device(message.to, device_id)) {
status.other_lost++;
continue;
}
@ -75,9 +74,9 @@ public class StreamModule : XmppStreamModule {
else status.other_failure++;
}
}
address.name = self_bare_jid;
foreach(int32 device_id in device_lists[self_bare_jid]) {
if (is_ignored_device(self_bare_jid, device_id)) {
address.name = self_jid.bare_jid.to_string();
foreach(int32 device_id in device_lists[self_jid]) {
if (is_ignored_device(self_jid, device_id)) {
status.own_lost++;
continue;
}
@ -119,26 +118,26 @@ public class StreamModule : XmppStreamModule {
this.store = Plugin.get_context().create_store();
store_created(store);
received_pipeline_listener = new ReceivedPipelineListener(store);
stream.get_module(Message.Module.IDENTITY).received_pipeline.connect(received_pipeline_listener);
stream.get_module(MessageModule.IDENTITY).received_pipeline.connect(received_pipeline_listener);
stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NODE_DEVICELIST, (stream, jid, id, node) => on_devicelist(stream, jid, id, node));
}
public override void detach(XmppStream stream) {
stream.get_module(Message.Module.IDENTITY).received_pipeline.disconnect(received_pipeline_listener);
stream.get_module(MessageModule.IDENTITY).received_pipeline.disconnect(received_pipeline_listener);
}
public void request_user_devicelist(XmppStream stream, string jid) {
public void request_user_devicelist(XmppStream stream, Jid jid) {
if (active_devicelist_requests.add(jid)) {
if (Plugin.DEBUG) print(@"OMEMO: requesting device list for $jid\n");
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid, NODE_DEVICELIST, (stream, jid, id, node) => on_devicelist(stream, jid, id, node));
}
}
public void on_devicelist(XmppStream stream, string jid, string? id, StanzaNode? node_) {
public void on_devicelist(XmppStream stream, Jid jid, string? id, StanzaNode? node_) {
StanzaNode node = node_ ?? new StanzaNode.build("list", NS_URI).add_self_xmlns();
string? my_jid = stream.get_flag(Bind.Flag.IDENTITY).my_jid;
Jid? my_jid = stream.get_flag(Bind.Flag.IDENTITY).my_jid;
if (my_jid == null) return;
if (jid == get_bare_jid((!)my_jid) && store.local_registration_id != 0) {
if (jid.equals_bare(my_jid) && store.local_registration_id != 0) {
bool am_on_devicelist = false;
foreach (StanzaNode device_node in node.get_subnodes("device")) {
int device_id = device_node.get_attribute_int("id");
@ -164,17 +163,17 @@ public class StreamModule : XmppStreamModule {
device_list_loaded(jid);
}
public void start_sessions_with(XmppStream stream, string bare_jid) {
if (!device_lists.has_key(bare_jid)) {
public void start_sessions_with(XmppStream stream, Jid jid) {
if (!device_lists.has_key(jid)) {
return;
}
Address address = new Address(bare_jid, 0);
foreach(int32 device_id in device_lists[bare_jid]) {
if (!is_ignored_device(bare_jid, device_id)) {
Address address = new Address(jid.bare_jid.to_string(), 0);
foreach(int32 device_id in device_lists[jid]) {
if (!is_ignored_device(jid, device_id)) {
address.device_id = device_id;
try {
if (!store.contains_session(address)) {
start_session_with(stream, bare_jid, device_id);
start_session_with(stream, jid, device_id);
}
} catch (Error e) {
// Ignore
@ -184,25 +183,25 @@ public class StreamModule : XmppStreamModule {
address.device_id = 0;
}
public void start_session_with(XmppStream stream, string bare_jid, int device_id) {
if (active_bundle_requests.add(bare_jid + @":$device_id")) {
if (Plugin.DEBUG) print(@"OMEMO: Asking for bundle from $bare_jid:$device_id\n");
stream.get_module(Pubsub.Module.IDENTITY).request(stream, bare_jid, @"$NODE_BUNDLES:$device_id", (stream, jid, id, node) => {
public void start_session_with(XmppStream stream, Jid jid, int device_id) {
if (active_bundle_requests.add(jid.bare_jid.to_string() + @":$device_id")) {
if (Plugin.DEBUG) print(@"OMEMO: Asking for bundle from $(jid.bare_jid.to_string()):$device_id\n");
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid.bare_jid, @"$NODE_BUNDLES:$device_id", (stream, jid, id, node) => {
on_other_bundle_result(stream, jid, device_id, id, node);
});
}
}
public void fetch_bundle(XmppStream stream, string bare_jid, int device_id) {
if (active_bundle_requests.add(bare_jid + @":$device_id")) {
if (Plugin.DEBUG) print(@"OMEMO: Asking for bundle from $bare_jid:$device_id\n");
stream.get_module(Pubsub.Module.IDENTITY).request(stream, bare_jid, @"$NODE_BUNDLES:$device_id", (stream, jid, id, node) => {
public void fetch_bundle(XmppStream stream, Jid jid, int device_id) {
if (active_bundle_requests.add(jid.bare_jid.to_string() + @":$device_id")) {
if (Plugin.DEBUG) print(@"OMEMO: Asking for bundle from $(jid.bare_jid.to_string()):$device_id\n");
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid.bare_jid, @"$NODE_BUNDLES:$device_id", (stream, jid, id, node) => {
bundle_fetched(jid, device_id, new Bundle(node));
});
}
}
public ArrayList<int32> get_device_list(string jid) {
public ArrayList<int32> get_device_list(Jid jid) {
if (is_known_address(jid)) {
return device_lists[jid];
} else {
@ -210,11 +209,11 @@ public class StreamModule : XmppStreamModule {
}
}
public bool is_known_address(string name) {
return device_lists.has_key(name);
public bool is_known_address(Jid jid) {
return device_lists.has_key(jid);
}
public void ignore_device(string jid, int32 device_id) {
public void ignore_device(Jid jid, int32 device_id) {
if (device_id <= 0) return;
lock (ignored_devices) {
if (!ignored_devices.has_key(jid)) {
@ -225,14 +224,14 @@ public class StreamModule : XmppStreamModule {
session_start_failed(jid, device_id);
}
public bool is_ignored_device(string jid, int32 device_id) {
public bool is_ignored_device(Jid jid, int32 device_id) {
if (device_id <= 0) return true;
lock (ignored_devices) {
return ignored_devices.has_key(jid) && ignored_devices[jid].contains(device_id);
}
}
private void on_other_bundle_result(XmppStream stream, string jid, int device_id, string? id, StanzaNode? node) {
private void on_other_bundle_result(XmppStream stream, Jid jid, int device_id, string? id, StanzaNode? node) {
bool fail = false;
if (node == null) {
// Device not registered, shouldn't exist
@ -255,7 +254,7 @@ public class StreamModule : XmppStreamModule {
if (pre_key_id < 0 || pre_key == null) {
fail = true;
} else {
Address address = new Address(jid, device_id);
Address address = new Address(jid.bare_jid.to_string(), device_id);
try {
if (store.contains_session(address)) {
return;
@ -273,16 +272,16 @@ public class StreamModule : XmppStreamModule {
if (fail) {
stream.get_module(IDENTITY).ignore_device(jid, device_id);
}
stream.get_module(IDENTITY).active_bundle_requests.remove(jid + @":$device_id");
stream.get_module(IDENTITY).active_bundle_requests.remove(jid.bare_jid.to_string() + @":$device_id");
}
public void publish_bundles_if_needed(XmppStream stream, string jid) {
if (active_bundle_requests.add(jid + @":$(store.local_registration_id)")) {
public void publish_bundles_if_needed(XmppStream stream, Jid jid) {
if (active_bundle_requests.add(jid.bare_jid.to_string() + @":$(store.local_registration_id)")) {
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid, @"$NODE_BUNDLES:$(store.local_registration_id)", on_self_bundle_result);
}
}
private void on_self_bundle_result(XmppStream stream, string jid, string? id, StanzaNode? node) {
private void on_self_bundle_result(XmppStream stream, Jid jid, string? id, StanzaNode? node) {
if (!Plugin.ensure_context()) return;
Map<int, ECPublicKey> keys = new HashMap<int, ECPublicKey>();
ECPublicKey? identity_key = null;
@ -350,7 +349,7 @@ public class StreamModule : XmppStreamModule {
} catch (Error e) {
if (Plugin.DEBUG) print(@"Unexpected error while publishing bundle: $(e.message)\n");
}
stream.get_module(IDENTITY).active_bundle_requests.remove(jid + @":$(store.local_registration_id)");
stream.get_module(IDENTITY).active_bundle_requests.remove(jid.bare_jid.to_string() + @":$(store.local_registration_id)");
}
public static void publish_bundles(XmppStream stream, SignedPreKeyRecord signed_pre_key_record, IdentityKeyPair identity_key_pair, Set<PreKeyRecord> pre_key_records, int32 device_id) throws Error {
@ -385,7 +384,7 @@ public class StreamModule : XmppStreamModule {
}
public class ReceivedPipelineListener : StanzaListener<Message.Stanza> {
public class ReceivedPipelineListener : StanzaListener<MessageStanza> {
private const string[] after_actions_const = {"EXTRACT_MESSAGE_2"};
@ -398,7 +397,7 @@ public class ReceivedPipelineListener : StanzaListener<Message.Stanza> {
this.store = store;
}
public override async void run(Core.XmppStream stream, Message.Stanza message) {
public override async void run(XmppStream stream, MessageStanza message) {
StanzaNode? _encrypted = message.stanza.get_subnode("encrypted", NS_URI);
if (_encrypted == null || MessageFlag.get_flag(message) != null || message.from == null) return;
StanzaNode encrypted = (!)_encrypted;
@ -419,7 +418,7 @@ public class ReceivedPipelineListener : StanzaListener<Message.Stanza> {
uint8[] key;
uint8[] ciphertext = Base64.decode((!)payload);
uint8[] iv = Base64.decode((!)iv_node);
Address address = new Address(get_bare_jid((!)message.from), header.get_attribute_int("sid"));
Address address = new Address(message.from.bare_jid.to_string(), header.get_attribute_int("sid"));
if (key_node.get_attribute_bool("prekey")) {
PreKeySignalMessage msg = Plugin.get_context().deserialize_pre_key_signal_message(Base64.decode((!)key_node_content));
SessionCipher cipher = store.create_session_cipher(address);

View file

@ -1,6 +1,7 @@
using Qlite;
using Dino.Entities;
using Xmpp;
namespace Dino.Plugins.OpenPgp {

View file

@ -1,6 +1,7 @@
using Gee;
using Dino.Entities;
using Xmpp;
namespace Dino.Plugins.OpenPgp {

View file

@ -63,17 +63,17 @@ public class Manager : StreamInteractionModule, Object {
return gpgkeys;
}
private void on_pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void on_pre_message_received(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
if (MessageFlag.get_flag(message_stanza) != null && MessageFlag.get_flag(message_stanza).decrypted) {
message.encryption = Encryption.PGP;
}
}
private void check_encypt(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
private void check_encypt(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) {
try {
if (message.encryption == Encryption.PGP) {
GPG.Key[] keys = get_key_fprs(conversation);
Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
XmppStream? stream = stream_interactor.get_stream(conversation.account);
if (stream != null) {
bool encrypted = stream.get_module(Module.IDENTITY).encrypt(message_stanza, keys);
if (!encrypted) message.marked = Entities.Message.Marked.WONTSEND;
@ -91,7 +91,7 @@ public class Manager : StreamInteractionModule, Object {
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Module.IDENTITY).received_jid_key_id.connect((stream, jid, key_id) => {
on_jid_key_received(account, new Jid(jid), key_id);
on_jid_key_received(account, jid, key_id);
});
}

View file

@ -37,7 +37,7 @@ public class Plugin : Plugins.RootInterface, Object {
public void shutdown() { }
private void on_initialize_account_modules(Account account, ArrayList<Xmpp.Core.XmppStreamModule> modules) {
private void on_initialize_account_modules(Account account, ArrayList<Xmpp.XmppStreamModule> modules) {
Module module = new Module(db.get_account_key(account));
this.modules[account] = module;
modules.add(module);

View file

@ -1,18 +1,18 @@
using Gee;
using Xmpp;
using Xmpp.Core;
using Xmpp;
namespace Dino.Plugins.OpenPgp {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "pgp");
public HashMap<string, string> key_ids = new HashMap<string, string>();
public HashMap<Jid, string> key_ids = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func);
public string? get_key_id(string jid) { return key_ids[get_bare_jid(jid)]; }
public string? get_key_id(Jid jid) { return key_ids[jid]; }
public void set_key_id(string jid, string key) { key_ids[get_bare_jid(jid)] = key; }
public void set_key_id(Jid jid, string key) { key_ids[jid] = key; }
public override string get_ns() { return NS_URI; }

View file

@ -1,7 +1,6 @@
using GPG;
using Xmpp;
using Xmpp.Core;
namespace Dino.Plugins.OpenPgp {
private const string NS_URI = "jabber:x";
@ -9,9 +8,9 @@ namespace Dino.Plugins.OpenPgp {
private const string NS_URI_SIGNED = NS_URI + ":signed";
public class Module : XmppStreamModule {
public static Core.ModuleIdentity<Module> IDENTITY = new Core.ModuleIdentity<Module>(NS_URI, "0027_current_pgp_usage");
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0027_current_pgp_usage");
public signal void received_jid_key_id(XmppStream stream, string jid, string key_id);
public signal void received_jid_key_id(XmppStream stream, Jid jid, string key_id);
private string? signed_status = null;
private Key? own_key = null;
@ -33,7 +32,7 @@ namespace Dino.Plugins.OpenPgp {
}
}
public bool encrypt(Message.Stanza message, GPG.Key[] keys) {
public bool encrypt(MessageStanza message, GPG.Key[] keys) {
string? enc_body = gpg_encrypt(message.body, keys);
if (enc_body != null) {
message.stanza.put_node(new StanzaNode.build("x", NS_URI_ENCRYPTED).add_self_xmlns().put_node(new StanzaNode.text(enc_body)));
@ -46,14 +45,14 @@ namespace Dino.Plugins.OpenPgp {
public override void attach(XmppStream stream) {
stream.get_module(Presence.Module.IDENTITY).received_presence.connect(on_received_presence);
stream.get_module(Presence.Module.IDENTITY).pre_send_presence_stanza.connect(on_pre_send_presence_stanza);
stream.get_module(Message.Module.IDENTITY).received_pipeline.connect(received_pipeline_decrypt_listener);
stream.get_module(MessageModule.IDENTITY).received_pipeline.connect(received_pipeline_decrypt_listener);
stream.add_flag(new Flag());
}
public override void detach(XmppStream stream) {
stream.get_module(Presence.Module.IDENTITY).received_presence.disconnect(on_received_presence);
stream.get_module(Presence.Module.IDENTITY).pre_send_presence_stanza.disconnect(on_pre_send_presence_stanza);
stream.get_module(Message.Module.IDENTITY).received_pipeline.disconnect(received_pipeline_decrypt_listener);
stream.get_module(MessageModule.IDENTITY).received_pipeline.disconnect(received_pipeline_decrypt_listener);
}
public static void require(XmppStream stream) {
@ -121,12 +120,12 @@ namespace Dino.Plugins.OpenPgp {
}
}
public class MessageFlag : Message.MessageFlag {
public class MessageFlag : Xmpp.MessageFlag {
public const string id = "pgp";
public bool decrypted = false;
public static MessageFlag? get_flag(Message.Stanza message) {
public static MessageFlag? get_flag(MessageStanza message) {
return (MessageFlag) message.get_flag(NS_URI, id);
}
@ -134,14 +133,14 @@ namespace Dino.Plugins.OpenPgp {
public override string get_id() { return id; }
}
public class ReceivedPipelineDecryptListener : StanzaListener<Message.Stanza> {
public class ReceivedPipelineDecryptListener : StanzaListener<MessageStanza> {
private const string[] after_actions_const = {"MODIFY_BODY"};
public override string action_group { get { return "ENCRYPT_BODY"; } }
public override string[] after_actions { get { return after_actions_const; } }
public override async void run(Core.XmppStream stream, Message.Stanza message) {
public override async void run(XmppStream stream, MessageStanza message) {
string? encrypted = get_cyphertext(message);
if (encrypted != null) {
MessageFlag flag = new MessageFlag();
@ -171,7 +170,7 @@ public class ReceivedPipelineDecryptListener : StanzaListener<Message.Stanza> {
return res;
}
private string? get_cyphertext(Message.Stanza message) {
private string? get_cyphertext(MessageStanza message) {
StanzaNode? x_node = message.stanza.get_subnode("x", NS_URI_ENCRYPTED);
return x_node == null ? null : x_node.get_string_content();
}

View file

@ -21,6 +21,7 @@ SOURCES
"src/module/bind.vala"
"src/module/iq/module.vala"
"src/module/iq/stanza.vala"
"src/module/jid.vala"
"src/module/message/module.vala"
"src/module/message/stanza.vala"
"src/module/presence/flag.vala"

View file

@ -1,6 +1,6 @@
using Gee;
namespace Xmpp.Core {
namespace Xmpp {
public class NamespaceState {
private HashMap<string, string> uri_to_name = new HashMap<string, string> ();

View file

@ -1,4 +1,4 @@
namespace Xmpp.Core {
namespace Xmpp {
public class StanzaAttribute : StanzaEntry {

View file

@ -1,6 +1,6 @@
using Gee;
namespace Xmpp.Core {
namespace Xmpp {
public abstract class StanzaEntry {
protected const string ANSI_COLOR_END = "\x1b[0m";

View file

@ -1,6 +1,6 @@
using Gee;
namespace Xmpp.Core {
namespace Xmpp {
public const string XMLNS_URI = "http://www.w3.org/2000/xmlns/";
public const string XML_URI = "http://www.w3.org/XML/1998/namespace";

View file

@ -1,4 +1,5 @@
namespace Xmpp.Core {
namespace Xmpp {
public class StanzaWriter {
private OutputStream output;

View file

@ -1,6 +1,6 @@
using Gee;
namespace Xmpp.Core {
namespace Xmpp {
public class XmppLog {
protected const string ANSI_COLOR_END = "\x1b[0m";

View file

@ -1,6 +1,6 @@
using Gee;
namespace Xmpp.Core {
namespace Xmpp {
public errordomain IOStreamError {
READ,
@ -13,7 +13,7 @@ public errordomain IOStreamError {
public class XmppStream {
public const string NS_URI = "http://etherx.jabber.org/streams";
public string remote_name;
public Jid remote_name;
public XmppLog log = new XmppLog();
public StanzaNode? features { get; private set; default = new StanzaNode.build("features", NS_URI); }
@ -43,13 +43,13 @@ public class XmppStream {
}
public async void connect(string? remote_name = null) throws IOStreamError {
if (remote_name != null) this.remote_name = (!)remote_name;
if (remote_name != null) this.remote_name = Jid.parse(remote_name);
attach_negotation_modules();
try {
int min_priority = -1;
ConnectionProvider? best_provider = null;
foreach (ConnectionProvider connection_provider in connection_providers) {
int? priority = yield connection_provider.get_priority(remote_name);
int? priority = yield connection_provider.get_priority(this.remote_name);
if (priority != null && (priority < min_priority || min_priority == -1)) {
min_priority = priority;
best_provider = connection_provider;
@ -60,7 +60,7 @@ public class XmppStream {
stream = yield best_provider.connect(this);
}
if (stream == null) {
stream = yield (new SocketClient()).connect_async(new NetworkService("xmpp-client", "tcp", this.remote_name));
stream = yield (new SocketClient()).connect_async(new NetworkService("xmpp-client", "tcp", this.remote_name.to_string()));
}
if (stream == null) {
throw new IOStreamError.CONNECT("client.connect() returned null");
@ -187,7 +187,7 @@ public class XmppStream {
private async void setup() throws IOStreamError {
StanzaNode outs = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
.put_attribute("to", remote_name)
.put_attribute("to", remote_name.to_string())
.put_attribute("version", "1.0")
.put_attribute("xmlns", "jabber:client")
.put_attribute("stream", "http://etherx.jabber.org/streams", XMLNS_URI);
@ -349,7 +349,7 @@ public abstract class XmppStreamNegotiationModule : XmppStreamModule {
}
public abstract class ConnectionProvider {
public async abstract int? get_priority(string remote_name);
public async abstract int? get_priority(Jid remote_name);
public async abstract IOStream? connect(XmppStream stream);
public abstract string get_id();
}
@ -357,11 +357,11 @@ public abstract class ConnectionProvider {
public class StartTlsConnectionProvider : ConnectionProvider {
private SrvTarget? srv_target;
public async override int? get_priority(string remote_name) {
public async override int? get_priority(Jid remote_name) {
GLib.List<SrvTarget>? xmpp_target = null;
try {
GLibFixes.Resolver resolver = GLibFixes.Resolver.get_default();
xmpp_target = yield resolver.lookup_service_async("xmpp-client", "tcp", remote_name, null);
xmpp_target = yield resolver.lookup_service_async("xmpp-client", "tcp", remote_name.to_string(), null);
} catch (Error e) {
return null;
}

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.Bind {
private const string NS_URI = "urn:ietf:params:xml:ns:xmpp-bind";
@ -9,7 +7,7 @@ namespace Xmpp.Bind {
public string requested_resource { get; set; }
public signal void bound_to_resource(XmppStream stream, string my_jid);
public signal void bound_to_resource(XmppStream stream, Jid my_jid);
public Module(string requested_resource) {
this.requested_resource = requested_resource;
@ -20,7 +18,7 @@ namespace Xmpp.Bind {
if (flag == null || flag.finished) return;
if (iq.type_ == Iq.Stanza.TYPE_RESULT) {
flag.my_jid = iq.stanza.get_subnode("jid", NS_URI, true).get_string_content();
flag.my_jid = Jid.parse(iq.stanza.get_subnode("jid", NS_URI, true).get_string_content());
flag.finished = true;
bound_to_resource(stream, flag.my_jid);
}
@ -62,7 +60,7 @@ namespace Xmpp.Bind {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "bind");
public string? my_jid;
public Jid? my_jid;
public bool finished = false;
public override string get_ns() { return NS_URI; }

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Iq {
private const string NS_URI = "jabber:client";

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Iq {
public class Stanza : Xmpp.Stanza {
@ -44,7 +42,7 @@ public class Stanza : Xmpp.Stanza {
stanza.put_node(associated_child);
}
}
public Stanza.from_stanza(StanzaNode stanza_node, string? my_jid) {
public Stanza.from_stanza(StanzaNode stanza_node, Jid? my_jid) {
base.incoming(stanza_node, my_jid);
}
}

View file

@ -1,28 +1,36 @@
public class Dino.Entities.Jid : Object {
public string? localpart { get; set; }
public string domainpart { get; set; }
public string? resourcepart { get; set; }
namespace Xmpp {
public class Jid {
public string? localpart;
public string domainpart;
public string? resourcepart;
public Jid bare_jid {
owned get { return localpart != null ? new Jid(@"$localpart@$domainpart") : new Jid(domainpart); }
owned get { return is_bare() ? this : new Jid.components(localpart, domainpart, null); }
}
private string jid { get; private set; }
public Jid domain_jid {
owned get { return is_domain() ? this : new Jid.components(null, domainpart, null); }
}
private string jid;
public Jid(string jid) {
Jid? parsed = Jid.parse(jid);
string? localpart = parsed != null ? parsed.localpart : null;
string domainpart = parsed != null ? parsed.domainpart : jid;
string? resourcepart = parsed != null ? parsed.resourcepart : null;
this.components(localpart, domainpart, resourcepart);
string? localpart = parsed != null ? (owned) parsed.localpart : null;
string domainpart = parsed != null ? (owned) parsed.domainpart : jid;
string? resourcepart = parsed != null ? (owned) parsed.resourcepart : null;
this.intern(jid, (owned) localpart, (owned) domainpart, (owned) resourcepart);
}
public Jid.with_resource(string bare_jid, string resource) {
Jid? parsed = Jid.parse(bare_jid);
this.components(parsed.localpart, parsed.domainpart, resource);
private Jid.intern(owned string jid, owned string? localpart, owned string domainpart, owned string? resourcepart) {
this.jid = (owned) jid;
this.localpart = (owned) localpart;
this.domainpart = (owned) domainpart;
this.resourcepart = (owned) resourcepart;
}
public Jid.components(string? localpart, string domainpart, string? resourcepart) {
public Jid.components(owned string? localpart, owned string domainpart, owned string? resourcepart) {
string jid = domainpart;
if (localpart != null) {
jid = @"$localpart@$jid";
@ -31,9 +39,9 @@ public class Dino.Entities.Jid : Object {
jid = @"$jid/$resourcepart";
}
this.jid = jid;
this.localpart = localpart;
this.domainpart = domainpart;
this.resourcepart = resourcepart;
this.localpart = (owned) localpart;
this.domainpart = (owned) domainpart;
this.resourcepart = (owned) resourcepart;
}
public static Jid? parse(string jid) {
@ -48,9 +56,17 @@ public class Dino.Entities.Jid : Object {
if (slash_index != -1 && resourcepart == "") return null;
if (at_index != -1 && localpart == "") return null;
return new Jid.intern(jid, (owned) localpart, (owned) domainpart, (owned) resourcepart);
}
public Jid with_resource(string? resourcepart) {
return new Jid.components(localpart, domainpart, resourcepart);
}
public bool is_domain() {
return localpart == null && resourcepart == null;
}
public bool is_bare() {
return localpart != null && resourcepart == null;
}
@ -87,3 +103,5 @@ public class Dino.Entities.Jid : Object {
return jid.to_string().hash();
}
}
}

View file

@ -1,27 +1,27 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Message {
namespace Xmpp {
private const string NS_URI = "jabber:client";
public class Module : XmppStreamModule {
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "message_module");
public class MessageModule : XmppStreamModule {
public static ModuleIdentity<MessageModule> IDENTITY = new ModuleIdentity<MessageModule>(NS_URI, "message_module");
public StanzaListenerHolder<Message.Stanza> received_pipeline = new StanzaListenerHolder<Message.Stanza>();
public StanzaListenerHolder<Message.Stanza> send_pipeline = new StanzaListenerHolder<Message.Stanza>();
public StanzaListenerHolder<MessageStanza> received_pipeline = new StanzaListenerHolder<MessageStanza>();
public StanzaListenerHolder<MessageStanza> send_pipeline = new StanzaListenerHolder<MessageStanza>();
public signal void pre_received_message(XmppStream stream, Message.Stanza message);
public signal void received_message(XmppStream stream, Message.Stanza message);
public signal void pre_received_message(XmppStream stream, MessageStanza message);
public signal void received_message(XmppStream stream, MessageStanza message);
public void send_message(XmppStream stream, Message.Stanza message) {
public void send_message(XmppStream stream, MessageStanza message) {
send_pipeline.run.begin(stream, message, (obj, res) => {
stream.write(message.stanza);
});
}
public async void received_message_stanza_async(XmppStream stream, StanzaNode node) {
Message.Stanza message = new Message.Stanza.from_stanza(node, stream.get_flag(Bind.Flag.IDENTITY).my_jid);
MessageStanza message = new MessageStanza.from_stanza(node, stream.get_flag(Bind.Flag.IDENTITY).my_jid);
yield received_pipeline.run(stream, message);
received_message(stream, message);
}

View file

@ -1,10 +1,8 @@
using Gee;
using Xmpp.Core;
namespace Xmpp {
namespace Xmpp.Message {
public class Stanza : Xmpp.Stanza {
public class MessageStanza : Xmpp.Stanza {
public const string NODE_BODY = "body";
public const string NODE_SUBJECT = "subject";
public const string NODE_THREAD = "thread";
@ -40,12 +38,12 @@ public class Stanza : Xmpp.Stanza {
set { base.type_ = value; }
}
public Stanza(string? id = null) {
public MessageStanza(string? id = null) {
base.outgoing(new StanzaNode.build("message"));
stanza.set_attribute(ATTRIBUTE_ID, id ?? random_uuid());
}
public Stanza.from_stanza(StanzaNode stanza_node, string my_jid) {
public MessageStanza.from_stanza(StanzaNode stanza_node, Jid my_jid) {
base.incoming(stanza_node, my_jid);
}

View file

@ -1,60 +1,60 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Presence {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "presence");
private HashMap<string, ConcurrentList<string>> resources = new HashMap<string, ConcurrentList<string>>();
private HashMap<string, Presence.Stanza> presences = new HashMap<string, Presence.Stanza>();
private HashMap<Jid, Gee.List<Jid>> resources = new HashMap<Jid, Gee.List<Jid>>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, Presence.Stanza> presences = new HashMap<Jid, Presence.Stanza>(Jid.hash_func, Jid.equals_func);
public Set<string> get_available_jids() {
public Set<Jid> get_available_jids() {
return resources.keys;
}
public Gee.List<string>? get_resources(string bare_jid) {
return resources[bare_jid];
public Gee.List<Jid>? get_resources(Jid jid) {
return resources[jid];
}
public Presence.Stanza? get_presence(string full_jid) {
public Presence.Stanza? get_presence(Jid full_jid) {
return presences[full_jid];
}
public void add_presence(Presence.Stanza presence) {
string bare_jid = get_bare_jid(presence.from);
if (!resources.has_key(bare_jid)) {
resources[bare_jid] = new ConcurrentList<string>();
if (!resources.has_key(presence.from)) {
resources[presence.from] = new ArrayList<Jid>(Jid.equals_func);
}
if (resources[bare_jid].contains(presence.from)) {
resources[bare_jid].remove(presence.from);
if (resources[presence.from].contains(presence.from)) {
resources[presence.from].remove(presence.from);
}
resources[bare_jid].add(presence.from);
resources[presence.from].add(presence.from);
presences[presence.from] = presence;
}
public void remove_presence(string jid) {
string bare_jid = get_bare_jid(jid);
if (resources.has_key(bare_jid)) {
if (is_bare_jid(jid)) {
foreach (string full_jid in resources[jid]) {
public void remove_presence(Jid jid) {
if (resources.has_key(jid)) {
if (jid.is_bare()) {
foreach (Jid full_jid in resources[jid]) {
presences.unset(full_jid);
}
resources.unset(jid);
} else {
resources[bare_jid].remove(jid);
if (resources[bare_jid].size == 0) {
resources.unset(bare_jid);
resources[jid].remove(jid);
if (resources[jid].size == 0) {
resources.unset(jid);
}
presences.unset(jid);
}
}
}
public override string get_ns() { return NS_URI; }
public override string get_ns() {
return NS_URI;
}
public override string get_id() { return IDENTITY.id; }
public override string get_id() {
return IDENTITY.id;
}
}
}

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.Presence {
private const string NS_URI = "jabber:client";
@ -10,39 +8,39 @@ namespace Xmpp.Presence {
public signal void pre_send_presence_stanza(XmppStream stream, Presence.Stanza presence);
public signal void initial_presence_sent(XmppStream stream, Presence.Stanza presence);
public signal void received_available(XmppStream stream, Presence.Stanza presence);
public signal void received_available_show(XmppStream stream, string jid, string show);
public signal void received_available_show(XmppStream stream, Jid jid, string show);
public signal void received_unavailable(XmppStream stream, Presence.Stanza presence);
public signal void received_subscription_request(XmppStream stream, string jid);
public signal void received_unsubscription(XmppStream stream, string jid);
public signal void received_subscription_request(XmppStream stream, Jid jid);
public signal void received_unsubscription(XmppStream stream, Jid jid);
public bool available_resource = true;
public void request_subscription(XmppStream stream, string bare_jid) {
public void request_subscription(XmppStream stream, Jid bare_jid) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid;
presence.type_ = Presence.Stanza.TYPE_SUBSCRIBE;
send_presence(stream, presence);
}
public void approve_subscription(XmppStream stream, string bare_jid) {
public void approve_subscription(XmppStream stream, Jid bare_jid) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid;
presence.type_ = Presence.Stanza.TYPE_SUBSCRIBED;
send_presence(stream, presence);
}
public void deny_subscription(XmppStream stream, string bare_jid) {
public void deny_subscription(XmppStream stream, Jid bare_jid) {
cancel_subscription(stream, bare_jid);
}
public void cancel_subscription(XmppStream stream, string bare_jid) {
public void cancel_subscription(XmppStream stream, Jid bare_jid) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid;
presence.type_ = Presence.Stanza.TYPE_UNSUBSCRIBED;
send_presence(stream, presence);
}
public void unsubscribe(XmppStream stream, string bare_jid) {
public void unsubscribe(XmppStream stream, Jid bare_jid) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid;
presence.type_ = Presence.Stanza.TYPE_UNSUBSCRIBE;

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.Presence {
public class Stanza : Xmpp.Stanza {
@ -85,7 +83,7 @@ public class Stanza : Xmpp.Stanza {
this.id = id ?? random_uuid();
}
public Stanza.from_stanza(StanzaNode stanza_node, string my_jid) {
public Stanza.from_stanza(StanzaNode stanza_node, Jid my_jid) {
base.incoming(stanza_node, my_jid);
}
}

View file

@ -1,14 +1,12 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Roster {
public class Flag : XmppStreamFlag {
public const string ID = "roster";
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, ID);
public HashMap<string, Item> roster_items = new HashMap<string, Item>();
public HashMap<Jid, Item> roster_items = new HashMap<Jid, Item>();
public string? iq_id;
@ -16,7 +14,7 @@ public class Flag : XmppStreamFlag {
return roster_items.values;
}
public Item? get_item(string jid) {
public Item? get_item(Jid jid) {
return roster_items[jid];
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Roster {
public class Item {
@ -18,9 +16,10 @@ public class Item {
public StanzaNode stanza_node;
public string jid {
get { return stanza_node.get_attribute(NODE_JID); }
set { stanza_node.set_attribute(NODE_JID, value); }
private Jid jid_;
public Jid jid {
get { return jid_ ?? (jid_ = Jid.parse(stanza_node.get_attribute(NODE_JID))); }
set { stanza_node.set_attribute(NODE_JID, value.to_string()); }
}
public string? name {

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Roster {
private const string NS_URI = "jabber:iq:roster";
@ -16,7 +14,7 @@ public class Module : XmppStreamModule, Iq.Handler {
public bool interested_resource = true;
public void add_jid(XmppStream stream, string jid, string? handle = null) {
public void add_jid(XmppStream stream, Jid jid, string? handle = null) {
Item roster_item = new Item();
roster_item.jid = jid;
if (handle != null) {
@ -25,7 +23,7 @@ public class Module : XmppStreamModule, Iq.Handler {
roster_set(stream, roster_item);
}
public void remove_jid(XmppStream stream, string jid) {
public void remove_jid(XmppStream stream, Jid jid) {
Item roster_item = new Item();
roster_item.jid = jid;
roster_item.subscription = Item.SUBSCRIPTION_REMOVE;
@ -37,7 +35,7 @@ public class Module : XmppStreamModule, Iq.Handler {
* Set a handle for a jid
* @param handle Handle to be set. If null, any handle will be removed.
*/
public void set_jid_handle(XmppStream stream, string jid, string? handle) {
public void set_jid_handle(XmppStream stream, Jid jid, string? handle) {
Flag flag = stream.get_flag(Flag.IDENTITY);
Item item = flag.get_item(jid) ?? new Item() { jid=jid };
item.name = handle != null ? handle : "";

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Roster {
public class VersioningModule : XmppStreamModule {

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.PlainSasl {
private const string NS_URI = "urn:ietf:params:xml:ns:xmpp-sasl";
@ -56,16 +54,16 @@ namespace Xmpp.PlainSasl {
}
}
if (!supportsPlain) {
stderr.printf("Server at %s does not support %s auth, use full-features Sasl implementation!\n", stream.remote_name, MECHANISM);
stderr.printf("Server at %s does not support %s auth, use full-features Sasl implementation!\n", stream.remote_name.to_string(), MECHANISM);
return;
}
if (!name.contains("@")) {
name = "%s@%s".printf(name, stream.remote_name);
name = "%s@%s".printf(name, stream.remote_name.to_string());
}
if (!use_full_name && name.contains("@")) {
var split = name.split("@");
if (split[1] == stream.remote_name) {
if (split[1] == stream.remote_name.to_string()) {
name = split[0];
} else {
use_full_name = true;
@ -74,7 +72,7 @@ namespace Xmpp.PlainSasl {
var name = this.name;
if (!use_full_name && name.contains("@")) {
var split = name.split("@");
if (split[1] == stream.remote_name) {
if (split[1] == stream.remote_name.to_string()) {
name = split[0];
}
}

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
/* Legacy. RFC 3921 3*/
namespace Xmpp.Session {
private const string NS_URI = "urn:ietf:params:xml:ns:xmpp-session";
@ -24,7 +22,7 @@ public class Module : XmppStreamNegotiationModule {
public override string get_ns() { return NS_URI; }
public override string get_id() { return IDENTITY.id; }
private void on_bound_resource(XmppStream stream, string my_jid) {
private void on_bound_resource(XmppStream stream, Jid my_jid) {
StanzaNode? session_node = stream.features.get_subnode("session", NS_URI);
if (session_node != null && session_node.get_subnode("optional", NS_URI) == null) {
stream.add_flag(new Flag());

View file

@ -1,70 +1,70 @@
using Xmpp.Core;
namespace Xmpp {
public class Stanza : Object {
public class Stanza : Object {
public const string ATTRIBUTE_FROM = "from";
public const string ATTRIBUTE_ID = "id";
public const string ATTRIBUTE_TO = "to";
public const string ATTRIBUTE_TYPE = "type";
public const string ATTRIBUTE_FROM = "from";
public const string ATTRIBUTE_ID = "id";
public const string ATTRIBUTE_TO = "to";
public const string ATTRIBUTE_TYPE = "type";
public const string TYPE_ERROR = "error";
public const string TYPE_ERROR = "error";
private string? my_jid;
private Jid? my_jid;
private Jid? from_;
private Jid? to_;
public virtual string? from {
owned get {
string? from_attribute = stanza.get_attribute(ATTRIBUTE_FROM);
// "when a client receives a stanza that does not include a 'from' attribute, it MUST assume that the stanza
// is from the user's account on the server." (RFC6120 8.1.2.1)
if (from_attribute != null) return from_attribute;
if (my_jid != null) {
string my_bare_jid = get_bare_jid(my_jid); // has to be left-side value
return my_bare_jid;
}
return null;
public virtual Jid? from {
owned get {
string? from_attribute = stanza.get_attribute(ATTRIBUTE_FROM);
// "when a client receives a stanza that does not include a 'from' attribute, it MUST assume that the stanza
// is from the user's account on the server." (RFC6120 8.1.2.1)
if (from_attribute != null) return from_ = Jid.parse(from_attribute);
if (my_jid != null) {
return my_jid.bare_jid;
}
set { stanza.set_attribute(ATTRIBUTE_FROM, value); }
return null;
}
set { stanza.set_attribute(ATTRIBUTE_FROM, value.to_string()); }
}
public virtual string? id {
get { return stanza.get_attribute(ATTRIBUTE_ID); }
set { stanza.set_attribute(ATTRIBUTE_ID, value); }
public virtual string? id {
get { return stanza.get_attribute(ATTRIBUTE_ID); }
set { stanza.set_attribute(ATTRIBUTE_ID, value); }
}
public virtual Jid? to {
owned get {
string? to_attribute = stanza.get_attribute(ATTRIBUTE_TO);
// "if the stanza does not include a 'to' address then the client MUST treat it as if the 'to' address were
// included with a value of the client's full JID." (RFC6120 8.1.1.1)
return to_attribute == null ? my_jid : to_ = Jid.parse(to_attribute);
}
set { stanza.set_attribute(ATTRIBUTE_TO, value.to_string()); }
}
public virtual string? to {
owned get {
string? to_attribute = stanza.get_attribute(ATTRIBUTE_TO);
// "if the stanza does not include a 'to' address then the client MUST treat it as if the 'to' address were
// included with a value of the client's full JID." (RFC6120 8.1.1.1)
return to_attribute == null ? my_jid : to_attribute;
}
set { stanza.set_attribute(ATTRIBUTE_TO, value); }
}
public virtual string? type_ {
get { return stanza.get_attribute(ATTRIBUTE_TYPE); }
set { stanza.set_attribute(ATTRIBUTE_TYPE, value); }
}
public virtual string? type_ {
get { return stanza.get_attribute(ATTRIBUTE_TYPE); }
set { stanza.set_attribute(ATTRIBUTE_TYPE, value); }
}
public StanzaNode stanza;
public StanzaNode stanza;
public Stanza.incoming(StanzaNode stanza, Jid? my_jid) {
this.stanza = stanza;
this.my_jid = my_jid;
}
public Stanza.incoming(StanzaNode stanza, string? my_jid) {
this.stanza = stanza;
this.my_jid = my_jid;
}
public Stanza.outgoing(StanzaNode stanza) {
this.stanza = stanza;
}
public Stanza.outgoing(StanzaNode stanza) {
this.stanza = stanza;
}
public bool is_error() {
return type_ == TYPE_ERROR;
}
public bool is_error() {
return type_ == TYPE_ERROR;
}
public ErrorStanza? get_error() {
return new ErrorStanza.from_stanza(this.stanza);
}
public ErrorStanza? get_error() {
return new ErrorStanza.from_stanza(this.stanza);
}
}
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp {
public class ErrorStanza {

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.StreamError {
private const string NS_URI = "jabber:client";
private const string NS_ERROR = "urn:ietf:params:xml:ns:xmpp-streams";

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.Tls {
private const string NS_URI = "urn:ietf:params:xml:ns:xmpp-tls";
@ -52,7 +50,7 @@ namespace Xmpp.Tls {
stream.write(new StanzaNode.build("starttls", NS_URI).add_self_xmlns());
}
if (identity == null) {
identity = new NetworkService("xmpp-client", "tcp", stream.remote_name);
identity = new NetworkService("xmpp-client", "tcp", stream.remote_name.to_string());
}
stream.add_flag(new Flag());
}

View file

@ -1,32 +1,22 @@
using Gee;
namespace Xmpp {
public string get_bare_jid(string jid) {
return jid.split("/")[0];
}
public bool is_bare_jid(string jid) {
return !jid.contains("/");
}
public string? get_resource_part(string jid) {
return jid.split("/")[1];
}
public string random_uuid() {
uint32 b1 = Random.next_int();
uint16 b2 = (uint16)Random.next_int();
uint16 b3 = (uint16)(Random.next_int() | 0x4000u) & ~0xb000u;
uint16 b4 = (uint16)(Random.next_int() | 0x8000u) & ~0x4000u;
uint16 b5_1 = (uint16)Random.next_int();
uint32 b5_2 = Random.next_int();
return "%08x-%04x-%04x-%04x-%04x%08x".printf(b1, b2, b3, b4, b5_1, b5_2);
}
public string random_uuid() {
uint32 b1 = Random.next_int();
uint16 b2 = (uint16)Random.next_int();
uint16 b3 = (uint16)(Random.next_int() | 0x4000u) & ~0xb000u;
uint16 b4 = (uint16)(Random.next_int() | 0x8000u) & ~0x4000u;
uint16 b5_1 = (uint16)Random.next_int();
uint32 b5_2 = Random.next_int();
return "%08x-%04x-%04x-%04x-%04x%08x".printf(b1, b2, b3, b4, b5_1, b5_2);
}
public abstract class StanzaListener<T> : Object {
public abstract string action_group { get; }
public abstract string[] after_actions { get; }
public abstract async void run(Core.XmppStream stream, T stanza);
public abstract async void run(XmppStream stream, T stanza);
}
public class StanzaListenerHolder<T> : Object {
@ -42,14 +32,14 @@ public class StanzaListenerHolder<T> : Object {
resort_list();
}
public async void run(Core.XmppStream stream, T stanza) {
public async void run(XmppStream stream, T stanza) {
foreach (StanzaListener<T> l in listeners) {
yield l.run(stream, stanza);
}
}
private bool set_contains_action(Gee.List<StanzaListener<T>> s, string[] actions) {
foreach(StanzaListener<T> l in s) {
foreach (StanzaListener<T> l in s) {
if (l.action_group in actions) {
return true;
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.DataForms {
public const string NS_URI = "jabber:x:data";

View file

@ -1,22 +1,20 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.ServiceDiscovery {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "service_discovery");
private HashMap<string, Gee.List<string>?> entity_features = new HashMap<string, Gee.List<string>?>();
private HashMap<string, Gee.List<Identity>?> entity_identities = new HashMap<string, Gee.List<Identity>?>();
private HashMap<string, Gee.List<Item>?> entity_items = new HashMap<string, Gee.List<Item>?>();
private HashMap<Jid, Gee.List<string>?> entity_features = new HashMap<Jid, Gee.List<string>?>(Jid.hash_func, Jid.equals_func);
private HashMap<Jid, Gee.List<Identity>?> entity_identities = new HashMap<Jid, Gee.List<Identity>?>(Jid.hash_func, Jid.equals_func);
private HashMap<Jid, Gee.List<Item>?> entity_items = new HashMap<Jid, Gee.List<Item>?>(Jid.hash_func, Jid.equals_func);
public Gee.List<string> features = new ArrayList<string>();
public Gee.List<Identity>? get_entity_categories(string jid) {
public Gee.List<Identity>? get_entity_categories(Jid jid) {
return entity_identities.has_key(jid) ? entity_identities[jid] : null; // TODO isnt this default for hashmap
}
public bool? has_entity_identity(string jid, string category, string type) {
public bool? has_entity_identity(Jid jid, string category, string type) {
if (!entity_identities.has_key(jid)) return null;
if (entity_identities[jid] == null) return false;
foreach (Identity identity in entity_identities[jid]) {
@ -25,21 +23,21 @@ public class Flag : XmppStreamFlag {
return false;
}
public bool? has_entity_feature(string jid, string feature) {
public bool? has_entity_feature(Jid jid, string feature) {
if (!entity_features.has_key(jid)) return null;
if (entity_features[jid] == null) return false;
return entity_features[jid].contains(feature);
}
public void set_entity_identities(string jid, Gee.List<Identity>? identities) {
public void set_entity_identities(Jid jid, Gee.List<Identity>? identities) {
entity_identities[jid] = identities;
}
public void set_entity_features(string jid, Gee.List<string>? features) {
public void set_entity_features(Jid jid, Gee.List<string>? features) {
entity_features[jid] = features;
}
public void set_entity_items(string jid, Gee.List<Item>? features) {
public void set_entity_items(Jid jid, Gee.List<Item>? features) {
entity_items[jid] = features;
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.ServiceDiscovery {
public class InfoResult {

View file

@ -1,11 +1,11 @@
namespace Xmpp.Xep.ServiceDiscovery {
public class Item {
public string jid;
public Jid jid;
public string? name;
public string? node;
public Item(string jid, string? name = null, string? node = null) {
public Item(Jid jid, string? name = null, string? node = null) {
this.jid = jid;
this.name = name;
this.node = node;

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.ServiceDiscovery {
public class ItemsResult {
@ -11,7 +9,7 @@ public class ItemsResult {
owned get {
ArrayList<Item> ret = new ArrayList<Item>();
foreach (StanzaNode feature_node in iq.stanza.get_subnode("query", NS_URI_ITEMS).get_subnodes("item", NS_URI_ITEMS)) {
ret.add(new Item(feature_node.get_attribute("jid", NS_URI_ITEMS),
ret.add(new Item(Jid.parse(feature_node.get_attribute("jid", NS_URI_ITEMS)),
feature_node.get_attribute("name", NS_URI_ITEMS),
feature_node.get_attribute("node", NS_URI_ITEMS)));
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.ServiceDiscovery {
private const string NS_URI = "http://jabber.org/protocol/disco";
@ -30,7 +28,7 @@ public class Module : XmppStreamModule, Iq.Handler {
}
public delegate void HasEntryCategoryRes(XmppStream stream, Gee.List<Identity>? identities);
public void get_entity_categories(XmppStream stream, string jid, owned HasEntryCategoryRes listener) {
public void get_entity_categories(XmppStream stream, Jid jid, owned HasEntryCategoryRes listener) {
Gee.List<Identity>? res = stream.get_flag(Flag.IDENTITY).get_entity_categories(jid);
if (res != null) listener(stream, res);
request_info(stream, jid, (stream, query_result) => {
@ -39,7 +37,7 @@ public class Module : XmppStreamModule, Iq.Handler {
}
public delegate void OnInfoResult(XmppStream stream, InfoResult? query_result);
public void request_info(XmppStream stream, string jid, owned OnInfoResult listener) {
public void request_info(XmppStream stream, Jid jid, owned OnInfoResult listener) {
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
iq.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq) => {
@ -51,7 +49,7 @@ public class Module : XmppStreamModule, Iq.Handler {
}
public delegate void OnItemsResult(XmppStream stream, ItemsResult query_result);
public void request_items(XmppStream stream, string jid, owned OnItemsResult listener) {
public void request_items(XmppStream stream, Jid jid, owned OnItemsResult listener) {
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns());
iq.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq) => {

View file

@ -1,128 +1,123 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.Muc {
public class Flag : XmppStreamFlag {
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "muc");
private HashMap<string, Gee.List<Feature>> room_features = new HashMap<string, Gee.List<Feature>>();
private HashMap<string, string> room_names = new HashMap<string, string>();
private HashMap<Jid, Gee.List<Feature>> room_features = new HashMap<Jid, Gee.List<Feature>>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, string> room_names = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<string, string> enter_ids = new HashMap<string, string>();
private HashMap<string, string> own_nicks = new HashMap<string, string>();
private HashMap<string, string> subjects = new HashMap<string, string>();
private HashMap<string, string> subjects_by = new HashMap<string, string>();
private HashMap<Jid, string> enter_ids = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, string> own_nicks = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, string> subjects = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, Jid> subjects_by = new HashMap<Jid, Jid>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<string, string> occupant_real_jids = new HashMap<string, string>();
private HashMap<string, HashMap<string, Affiliation>> affiliations = new HashMap<string, HashMap<string, Affiliation>>();
private HashMap<string, Role> occupant_role = new HashMap<string, Role>();
private HashMap<Jid, Jid> occupant_real_jids = new HashMap<Jid, Jid>(Jid.hash_func, Jid.equals_bare_func);
private HashMap<Jid, HashMap<Jid, Affiliation>> affiliations = new HashMap<Jid, HashMap<Jid, Affiliation>>(Jid.hash_bare_func, Jid.equals_bare_func);
private HashMap<Jid, Role> occupant_role = new HashMap<Jid, Role>(Jid.hash_func, Jid.equals_func);
public string? get_room_name(string jid) { return room_names.has_key(jid) ? room_names[jid] : null; }
public string? get_room_name(Jid muc_jid) { return room_names.has_key(muc_jid.bare_jid) ? room_names[muc_jid.bare_jid] : null; }
public bool has_room_feature(string jid, Feature feature) {
return room_features.has_key(jid) && room_features[jid].contains(feature);
public bool has_room_feature(Jid muc_jid, Feature feature) {
return room_features.has_key(muc_jid.bare_jid) && room_features[muc_jid.bare_jid].contains(feature);
}
public string? get_real_jid(string full_jid) { return occupant_real_jids[full_jid]; }
public Jid? get_real_jid(Jid full_jid) { return occupant_real_jids[full_jid]; }
public Gee.List<string> get_offline_members(string muc_jid) {
Gee.List<string> ret = new ArrayList<string>();
HashMap<string, Affiliation>? muc_affiliations = affiliations[muc_jid];
public Gee.List<Jid> get_offline_members(Jid muc_jid) {
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
HashMap<Jid, Affiliation>? muc_affiliations = affiliations[muc_jid.bare_jid];
if (muc_affiliations != null) {
foreach (string jid in muc_affiliations.keys) {
if (!jid.has_prefix(muc_jid)) ret.add(jid);
foreach (Jid jid in muc_affiliations.keys) {
if (!jid.equals_bare(muc_jid)) ret.add(jid);
}
}
return ret;
}
public Affiliation get_affiliation(string muc_jid, string full_jid) {
HashMap<string, Affiliation>? muc_affiliations = affiliations[muc_jid];
public Affiliation get_affiliation(Jid muc_jid, Jid full_jid) {
HashMap<Jid, Affiliation>? muc_affiliations = affiliations[muc_jid.bare_jid];
if (muc_affiliations != null) return muc_affiliations[full_jid];
return Affiliation.NONE;
}
public Role? get_occupant_role(string full_jid) {
public Role? get_occupant_role(Jid full_jid) {
if (occupant_role.has_key(full_jid)) return occupant_role[full_jid];
return Role.NONE;
}
public string? get_muc_nick(string bare_jid) { return own_nicks[bare_jid]; }
public string? get_muc_nick(Jid muc_jid) { return own_nicks[muc_jid.bare_jid]; }
public string? get_enter_id(string bare_jid) { return enter_ids[bare_jid]; }
public string? get_enter_id(Jid muc_jid) { return enter_ids[muc_jid.bare_jid]; }
public bool is_muc(string jid) { return own_nicks[jid] != null; }
public bool is_muc(Jid jid) { return own_nicks[jid] != null; }
public bool is_occupant(string jid) {
string bare_jid = get_bare_jid(jid);
return own_nicks.has_key(bare_jid) || enter_ids.has_key(bare_jid);
public bool is_occupant(Jid jid) {
return own_nicks.has_key(jid.bare_jid) || enter_ids.has_key(jid.bare_jid);
}
public bool is_muc_enter_outstanding() { return enter_ids.size != 0; }
public string? get_muc_subject(string bare_jid) { return subjects[bare_jid]; }
public string? get_muc_subject(Jid muc_jid) { return subjects[muc_jid.bare_jid]; }
internal void set_room_name(string jid, string name) {
room_names[jid] = name;
internal void set_room_name(Jid muc_jid, string name) {
room_names[muc_jid.bare_jid] = name;
}
internal void set_room_features(string jid, Gee.List<Feature> features) {
room_features[jid] = features;
internal void set_room_features(Jid muc_jid, Gee.List<Feature> features) {
room_features[muc_jid.bare_jid] = features;
}
internal void set_real_jid(string full_jid, string real_jid) { occupant_real_jids[full_jid] = real_jid; }
internal void set_real_jid(Jid full_jid, Jid real_jid) { occupant_real_jids[full_jid] = real_jid; }
internal void set_offline_member(string muc_jid, string real_jid, Affiliation affiliation) {
set_affiliation(muc_jid, real_jid, affiliation);
internal void set_offline_member(Jid muc_jid, Jid real_jid, Affiliation affiliation) {
set_affiliation(muc_jid.bare_jid, real_jid, affiliation);
}
internal void set_affiliation(string muc_jid, string full_jid, Affiliation affiliation) {
if (!affiliations.has_key(muc_jid)) affiliations[muc_jid] = new HashMap<string, Affiliation>();
internal void set_affiliation(Jid muc_jid, Jid full_jid, Affiliation affiliation) {
if (!affiliations.has_key(muc_jid.bare_jid)) affiliations[muc_jid.bare_jid] = new HashMap<Jid, Affiliation>(Jid.hash_func, Jid.equals_func);
if (affiliation == Affiliation.NONE) {
affiliations[muc_jid].unset(full_jid);
affiliations[muc_jid.bare_jid].unset(full_jid);
} else {
affiliations[muc_jid][full_jid] = affiliation;
affiliations[muc_jid.bare_jid][full_jid] = affiliation;
}
}
internal void set_occupant_role(string full_jid, Role role) {
internal void set_occupant_role(Jid full_jid, Role role) {
occupant_role[full_jid] = role;
}
internal void set_muc_subject(string full_jid, string? subject) {
string bare_jid = get_bare_jid(full_jid);
subjects[bare_jid] = subject;
subjects_by[bare_jid] = full_jid;
internal void set_muc_subject(Jid full_jid, string? subject) {
subjects[full_jid.bare_jid] = subject;
subjects_by[full_jid.bare_jid] = full_jid;
}
internal void start_muc_enter(string bare_jid, string presence_id) {
enter_ids[bare_jid] = presence_id;
internal void start_muc_enter(Jid jid, string presence_id) {
enter_ids[jid.bare_jid] = presence_id;
}
internal void finish_muc_enter(string bare_jid, string? nick = null) {
if (nick != null) own_nicks[bare_jid] = nick;
enter_ids.unset(bare_jid);
internal void finish_muc_enter(Jid jid, string? nick = null) {
if (nick != null) own_nicks[jid.bare_jid] = nick;
enter_ids.unset(jid.bare_jid);
}
internal void left_muc(XmppStream stream, string muc) {
own_nicks.unset(muc);
subjects.unset(muc);
subjects_by.unset(muc);
Gee.List<string>? occupants = stream.get_flag(Presence.Flag.IDENTITY).get_resources(muc);
internal void left_muc(XmppStream stream, Jid muc_jid) {
own_nicks.unset(muc_jid);
subjects.unset(muc_jid);
subjects_by.unset(muc_jid);
Gee.List<Jid>? occupants = stream.get_flag(Presence.Flag.IDENTITY).get_resources(muc_jid);
if (occupants != null) {
foreach (string occupant in occupants) {
foreach (Jid occupant in occupants) {
remove_occupant_info(occupant);
}
}
}
internal void remove_occupant_info(string full_jid) {
occupant_real_jids.unset(full_jid);
string bare_jid = get_bare_jid(full_jid);
if (affiliations.has_key(full_jid)) affiliations[bare_jid].unset(full_jid);
occupant_role.unset(full_jid);
internal void remove_occupant_info(Jid jid) {
occupant_real_jids.unset(jid);
if (affiliations.has_key(jid)) affiliations[jid].unset(jid);
occupant_role.unset(jid);
}
internal override string get_ns() { return NS_URI; }

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.Muc {
private const string NS_URI = "http://jabber.org/protocol/muc";
@ -58,20 +56,20 @@ public enum Feature {
public class Module : XmppStreamModule {
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0045_muc_module");
public signal void received_occupant_affiliation(XmppStream stream, string jid, Affiliation? affiliation);
public signal void received_occupant_jid(XmppStream stream, string jid, string? real_jid);
public signal void received_occupant_role(XmppStream stream, string jid, Role? role);
public signal void subject_set(XmppStream stream, string subject, string jid);
public signal void room_configuration_changed(XmppStream stream, string jid, StatusCode code);
public signal void received_occupant_affiliation(XmppStream stream, Jid jid, Affiliation? affiliation);
public signal void received_occupant_jid(XmppStream stream, Jid jid, Jid? real_jid);
public signal void received_occupant_role(XmppStream stream, Jid jid, Role? role);
public signal void subject_set(XmppStream stream, string? subject, Jid jid);
public signal void room_configuration_changed(XmppStream stream, Jid jid, StatusCode code);
public signal void room_entered(XmppStream stream, string jid, string nick);
public signal void room_enter_error(XmppStream stream, string jid, MucEnterError? error); // TODO "?" shoudln't be necessary (vala bug), remove someday
public signal void self_removed_from_room(XmppStream stream, string jid, StatusCode code);
public signal void removed_from_room(XmppStream stream, string jid, StatusCode? code);
public signal void room_entered(XmppStream stream, Jid jid, string nick);
public signal void room_enter_error(XmppStream stream, Jid jid, MucEnterError? error); // TODO "?" shoudln't be necessary (vala bug), remove someday
public signal void self_removed_from_room(XmppStream stream, Jid jid, StatusCode code);
public signal void removed_from_room(XmppStream stream, Jid jid, StatusCode? code);
public void enter(XmppStream stream, string bare_jid, string nick, string? password, DateTime? history_since) {
public void enter(XmppStream stream, Jid bare_jid, string nick, string? password, DateTime? history_since) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid + "/" + nick;
presence.to = bare_jid.with_resource(nick);
StanzaNode x_node = new StanzaNode.build("x", NS_URI).add_self_xmlns();
if (password != null) {
x_node.put_node(new StanzaNode.build("password", NS_URI).put_node(new StanzaNode.text(password)));
@ -89,47 +87,47 @@ public class Module : XmppStreamModule {
stream.get_module(Presence.Module.IDENTITY).send_presence(stream, presence);
}
public void exit(XmppStream stream, string jid) {
public void exit(XmppStream stream, Jid jid) {
string nick = stream.get_flag(Flag.IDENTITY).get_muc_nick(jid);
Presence.Stanza presence = new Presence.Stanza();
presence.to = jid + "/" + nick;
presence.to = jid.with_resource(nick);
presence.type_ = Presence.Stanza.TYPE_UNAVAILABLE;
stream.get_module(Presence.Module.IDENTITY).send_presence(stream, presence);
}
public void change_subject(XmppStream stream, string jid, string subject) {
Message.Stanza message = new Message.Stanza();
public void change_subject(XmppStream stream, Jid jid, string subject) {
MessageStanza message = new MessageStanza();
message.to = jid;
message.type_ = Message.Stanza.TYPE_GROUPCHAT;
message.type_ = MessageStanza.TYPE_GROUPCHAT;
message.stanza.put_node((new StanzaNode.build("subject")).put_node(new StanzaNode.text(subject)));
stream.get_module(Message.Module.IDENTITY).send_message(stream, message);
stream.get_module(MessageModule.IDENTITY).send_message(stream, message);
}
public void change_nick(XmppStream stream, string jid, string new_nick) {
public void change_nick(XmppStream stream, Jid jid, string new_nick) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = jid + "/" + new_nick;
presence.to = jid.with_resource(new_nick);
stream.get_module(Presence.Module.IDENTITY).send_presence(stream, presence);
}
public void invite(XmppStream stream, string to_muc, string jid) {
Message.Stanza message = new Message.Stanza();
public void invite(XmppStream stream, Jid to_muc, Jid jid) {
MessageStanza message = new MessageStanza();
message.to = to_muc;
StanzaNode invite_node = new StanzaNode.build("x", NS_URI_USER).add_self_xmlns()
.put_node(new StanzaNode.build("invite", NS_URI_USER).put_attribute("to", jid));
.put_node(new StanzaNode.build("invite", NS_URI_USER).put_attribute("to", jid.to_string()));
message.stanza.put_node(invite_node);
stream.get_module(Message.Module.IDENTITY).send_message(stream, message);
stream.get_module(MessageModule.IDENTITY).send_message(stream, message);
}
public void kick(XmppStream stream, string jid, string nick) {
public void kick(XmppStream stream, Jid jid, string nick) {
change_role(stream, jid, nick, "none");
}
/* XEP 0046: "A user cannot be kicked by a moderator with a lower affiliation." (XEP 0045 8.2) */
public bool kick_possible(XmppStream stream, string occupant) {
string muc_jid = get_bare_jid(occupant);
public bool kick_possible(XmppStream stream, Jid occupant) {
Jid muc_jid = occupant.bare_jid;
Flag flag = stream.get_flag(Flag.IDENTITY);
string own_nick = flag.get_muc_nick(muc_jid);
Affiliation my_affiliation = flag.get_affiliation(muc_jid, muc_jid + "/" + own_nick);
Affiliation my_affiliation = flag.get_affiliation(muc_jid, muc_jid.with_resource(own_nick));
Affiliation other_affiliation = flag.get_affiliation(muc_jid, occupant);
switch (my_affiliation) {
case Affiliation.MEMBER:
@ -142,22 +140,22 @@ public class Module : XmppStreamModule {
return true;
}
public void change_role(XmppStream stream, string jid, string nick, string new_role) {
public void change_role(XmppStream stream, Jid jid, string nick, string new_role) {
StanzaNode query = new StanzaNode.build("query", NS_URI_ADMIN).add_self_xmlns();
query.put_node(new StanzaNode.build("item", NS_URI_ADMIN).put_attribute("nick", nick, NS_URI_ADMIN).put_attribute("role", new_role, NS_URI_ADMIN));
Iq.Stanza iq = new Iq.Stanza.set(query) { to=jid };
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
}
public void change_affiliation(XmppStream stream, string jid, string nick, string new_affiliation) {
public void change_affiliation(XmppStream stream, Jid jid, string nick, string new_affiliation) {
StanzaNode query = new StanzaNode.build("query", NS_URI_ADMIN).add_self_xmlns();
query.put_node(new StanzaNode.build("item", NS_URI_ADMIN).put_attribute("nick", nick, NS_URI_ADMIN).put_attribute("affiliation", new_affiliation, NS_URI_ADMIN));
Iq.Stanza iq = new Iq.Stanza.set(query) { to=jid };
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
}
public delegate void OnConfigFormResult(XmppStream stream, string jid, DataForms.DataForm data_form);
public void get_config_form(XmppStream stream, string jid, owned OnConfigFormResult listener) {
public delegate void OnConfigFormResult(XmppStream stream, Jid jid, DataForms.DataForm data_form);
public void get_config_form(XmppStream stream, Jid jid, owned OnConfigFormResult listener) {
Iq.Stanza get_iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_OWNER).add_self_xmlns()) { to=jid };
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, get_iq, (stream, form_iq) => {
StanzaNode? x_node = form_iq.stanza.get_deep_subnode(NS_URI_OWNER + ":query", DataForms.NS_URI + ":x");
@ -176,7 +174,7 @@ public class Module : XmppStreamModule {
public override void attach(XmppStream stream) {
stream.add_flag(new Muc.Flag());
stream.get_module(Message.Module.IDENTITY).received_message.connect(on_received_message);
stream.get_module(MessageModule.IDENTITY).received_message.connect(on_received_message);
stream.get_module(Presence.Module.IDENTITY).received_presence.connect(check_for_enter_error);
stream.get_module(Presence.Module.IDENTITY).received_available.connect(on_received_available);
stream.get_module(Presence.Module.IDENTITY).received_unavailable.connect(on_received_unavailable);
@ -192,7 +190,7 @@ public class Module : XmppStreamModule {
}
public override void detach(XmppStream stream) {
stream.get_module(Message.Module.IDENTITY).received_message.disconnect(on_received_message);
stream.get_module(MessageModule.IDENTITY).received_message.disconnect(on_received_message);
stream.get_module(Presence.Module.IDENTITY).received_presence.disconnect(check_for_enter_error);
stream.get_module(Presence.Module.IDENTITY).received_available.disconnect(on_received_available);
stream.get_module(Presence.Module.IDENTITY).received_unavailable.disconnect(on_received_unavailable);
@ -201,8 +199,8 @@ public class Module : XmppStreamModule {
public override string get_ns() { return NS_URI; }
public override string get_id() { return IDENTITY.id; }
private void on_received_message(XmppStream stream, Message.Stanza message) {
if (message.type_ == Message.Stanza.TYPE_GROUPCHAT) {
private void on_received_message(XmppStream stream, MessageStanza message) {
if (message.type_ == MessageStanza.TYPE_GROUPCHAT) {
StanzaNode? subject_node = message.stanza.get_subnode("subject");
if (subject_node != null) {
string subject = subject_node.get_string_content();
@ -215,7 +213,7 @@ public class Module : XmppStreamModule {
private void check_for_enter_error(XmppStream stream, Presence.Stanza presence) {
Flag flag = stream.get_flag(Flag.IDENTITY);
if (presence.is_error() && flag.is_muc_enter_outstanding() && flag.is_occupant(presence.from)) {
string bare_jid = get_bare_jid(presence.from);
Jid bare_jid = presence.from.bare_jid;
ErrorStanza? error_stanza = presence.get_error();
if (flag.get_enter_id(bare_jid) == presence.id) {
MucEnterError error = MucEnterError.NONE;
@ -258,20 +256,21 @@ public class Module : XmppStreamModule {
if (x_node != null) {
ArrayList<int> status_codes = get_status_codes(x_node);
if (status_codes.contains(StatusCode.SELF_PRESENCE)) {
string bare_jid = get_bare_jid(presence.from);
Jid bare_jid = presence.from.bare_jid;
if (flag.get_enter_id(bare_jid) != null) {
room_entered(stream, bare_jid, get_resource_part(presence.from));
flag.finish_muc_enter(bare_jid, get_resource_part(presence.from));
room_entered(stream, bare_jid, presence.from.resourcepart);
flag.finish_muc_enter(bare_jid, presence.from.resourcepart);
}
}
string? affiliation_str = x_node.get_deep_attribute("item", "affiliation");
if (affiliation_str != null) {
Affiliation affiliation = parse_affiliation(affiliation_str);
flag.set_affiliation(get_bare_jid(presence.from), presence.from, affiliation);
flag.set_affiliation(presence.from.bare_jid, presence.from, affiliation);
received_occupant_affiliation(stream, presence.from, affiliation);
}
string? jid = x_node.get_deep_attribute("item", "jid");
if (jid != null) {
string? jid_ = x_node.get_deep_attribute("item", "jid");
if (jid_ != null) {
Jid? jid = Jid.parse(jid_);
flag.set_real_jid(presence.from, jid);
received_occupant_jid(stream, presence.from, jid);
}
@ -301,10 +300,10 @@ public class Module : XmppStreamModule {
foreach (StatusCode code in USER_REMOVED_CODES) {
if (code in status_codes) {
if (StatusCode.SELF_PRESENCE in status_codes) {
flag.left_muc(stream, get_bare_jid(presence.from));
flag.left_muc(stream, presence.from.bare_jid);
self_removed_from_room(stream, presence.from, code);
Presence.Flag presence_flag = stream.get_flag(Presence.Flag.IDENTITY);
presence_flag.remove_presence(get_bare_jid(presence.from));
presence_flag.remove_presence(presence.from.bare_jid);
} else {
removed_from_room(stream, presence.from, code);
}
@ -312,7 +311,7 @@ public class Module : XmppStreamModule {
}
}
private void query_room_info(XmppStream stream, string jid) {
private void query_room_info(XmppStream stream, Jid jid) {
stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, jid, (stream, query_result) => {
Gee.List<Feature> features = new ArrayList<Feature>();
@ -351,8 +350,8 @@ public class Module : XmppStreamModule {
});
}
public delegate void OnAffiliationResult(XmppStream stream, Gee.List<string> jids);
private void query_affiliation(XmppStream stream, string jid, string affiliation, owned OnAffiliationResult? listener) {
public delegate void OnAffiliationResult(XmppStream stream, Gee.List<Jid> jids);
private void query_affiliation(XmppStream stream, Jid jid, string affiliation, owned OnAffiliationResult? listener) {
Iq.Stanza iq = new Iq.Stanza.get(
new StanzaNode.build("query", NS_URI_ADMIN)
.add_self_xmlns()
@ -364,9 +363,9 @@ public class Module : XmppStreamModule {
StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI_ADMIN);
if (query_node == null) return;
Gee.List<StanzaNode> item_nodes = query_node.get_subnodes("item", NS_URI_ADMIN);
Gee.List<string> ret_jids = new ArrayList<string>();
Gee.List<Jid> ret_jids = new ArrayList<Jid>(Jid.equals_func);
foreach (StanzaNode item in item_nodes) {
string? jid_ = item.get_attribute("jid");
Jid? jid_ = Jid.parse(item.get_attribute("jid"));
string? affiliation_ = item.get_attribute("affiliation");
if (jid_ != null && affiliation_ != null) {
stream.get_flag(Muc.Flag.IDENTITY).set_offline_member(iq.from, jid_, parse_affiliation(affiliation_));

View file

@ -1,5 +1,3 @@
using Xmpp.Core;
namespace Xmpp.Xep.Bookmarks {
public class Conference : Object {
@ -21,9 +19,10 @@ public class Conference : Object {
set { stanza_node.set_attribute(ATTRIBUTE_AUTOJOIN, value.to_string()); }
}
public string jid {
get { return stanza_node.get_attribute(ATTRIBUTE_JID); }
set { stanza_node.set_attribute(ATTRIBUTE_JID, value); }
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 {
@ -73,7 +72,7 @@ public class Conference : Object {
}
}
public Conference(string jid) {
public Conference(Jid jid) {
this.stanza_node = new StanzaNode.build("conference", NS_URI);
this.jid = jid;
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.Bookmarks {
private const string NS_URI = "storage:bookmarks";
@ -10,12 +8,16 @@ public class Module : XmppStreamModule {
public signal void received_conferences(XmppStream stream, Gee.List<Conference> conferences);
public delegate void OnResult(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) => {
Gee.List<Conference> conferences = get_conferences_from_stanza(node);
listener(stream, conferences);
if (node == null) {
listener(stream, null);
} else {
Gee.List<Conference> conferences = get_conferences_from_stanza(node);
listener(stream, conferences);
}
});
}
@ -39,7 +41,7 @@ public class Module : XmppStreamModule {
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 == orig_conference.jid &&
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;
@ -56,7 +58,7 @@ public class Module : XmppStreamModule {
get_conferences(stream, (stream, conferences) => {
Conference? rem = null;
foreach (Conference conference in conferences) {
if (conference.name == conference_remove.name && conference.jid == conference_remove.jid && conference.autojoin == conference_remove.autojoin) {
if (conference.name == conference_remove.name && conference.jid.equals(conference_remove.jid) && conference.autojoin == conference_remove.autojoin) {
rem = conference;
break;
}

View file

@ -1,7 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.PrivateXmlStorage {
private const string NS_URI = "jabber:iq:private";
@ -17,7 +15,7 @@ namespace Xmpp.Xep.PrivateXmlStorage {
});
}
public delegate void OnResponse(XmppStream stream, StanzaNode node);
public delegate void OnResponse(XmppStream stream, StanzaNode? node);
public void retrieve(XmppStream stream, StanzaNode node, owned OnResponse listener) {
StanzaNode queryNode = new StanzaNode.build("query", NS_URI).add_self_xmlns().put_node(node);
Iq.Stanza iq = new Iq.Stanza.get(queryNode);

Some files were not shown because too many files have changed in this diff Show more