From a0a956ee0878d24bd06be7f5d75dc4ccd4e7901d Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sun, 22 Dec 2019 04:10:53 +0100 Subject: Properly check Jids everywhere --- libdino/src/application.vala | 8 ++++- libdino/src/entity/account.vala | 30 +++++++++++----- libdino/src/entity/conversation.vala | 2 +- libdino/src/entity/file_transfer.vala | 2 +- libdino/src/entity/message.vala | 2 +- libdino/src/service/content_item_store.vala | 24 +++++++++---- libdino/src/service/database.vala | 54 ++++++++++++++++++++++------- libdino/src/service/file_manager.vala | 10 ++++-- libdino/src/service/message_processor.vala | 2 +- libdino/src/service/muc_manager.vala | 12 ++++--- libdino/src/service/roster_manager.vala | 14 +++++--- libdino/src/service/search_processor.vala | 44 +++++++++++++++++------ 12 files changed, 148 insertions(+), 56 deletions(-) (limited to 'libdino/src') diff --git a/libdino/src/application.vala b/libdino/src/application.vala index 86283823..82d392f6 100644 --- a/libdino/src/application.vala +++ b/libdino/src/application.vala @@ -78,6 +78,12 @@ public interface Application : GLib.Application { while (jid[0] == '/') { jid = jid.substring(1); } + jid = Uri.unescape_string(jid); + try { + jid = new Xmpp.Jid(jid).to_string(); + } catch (Xmpp.InvalidJidError e) { + warning("Received invalid jid in xmpp:-URI: %s", e.message); + } string query = "message"; Gee.Map options = new Gee.HashMap(); if (m.length == 2) { @@ -85,7 +91,7 @@ public interface Application : GLib.Application { query = cmds[0]; for (int i = 1; i < cmds.length; ++i) { string[] opt = cmds[i].split("=", 2); - options[opt[0]] = opt.length == 2 ? opt[1] : ""; + options[Uri.unescape_string(opt[0])] = opt.length == 2 ? Uri.unescape_string(opt[1]) : ""; } } activate(); diff --git a/libdino/src/entity/account.vala b/libdino/src/entity/account.vala index f7257b5a..3eb75505 100644 --- a/libdino/src/entity/account.vala +++ b/libdino/src/entity/account.vala @@ -6,10 +6,11 @@ namespace Dino.Entities { public class Account : Object { public int id { get; set; } - public string localpart { get { return bare_jid.localpart; } } - public string domainpart { get { return bare_jid.domainpart; } } - public string resourcepart { get; set; } - public Jid bare_jid { get; private set; } + public string localpart { get { return full_jid.localpart; } } + public string domainpart { get { return full_jid.domainpart; } } + public string resourcepart { get { return full_jid.resourcepart;} } + public Jid bare_jid { owned get { return full_jid.bare_jid; } } + public Jid full_jid { get; private set; } public string? password { get; set; } public string display_name { owned get { return alias ?? bare_jid.to_string(); } @@ -23,17 +24,28 @@ public class Account : Object { public Account(Jid bare_jid, string? resourcepart, string? password, string? alias) { this.id = -1; - this.resourcepart = resourcepart ?? "dino." + Random.next_int().to_string("%x"); - this.bare_jid = bare_jid; + if (resourcepart != null) { + try { + this.full_jid = bare_jid.with_resource(resourcepart); + } catch (InvalidJidError e) { + warning("Tried to create account with invalid resource (%s), defaulting to auto generated", e.message); + } + } + if (this.full_jid == null) { + try { + this.full_jid = bare_jid.with_resource("dino." + Random.next_int().to_string("%x")); + } catch (InvalidJidError e) { + error("Auto-generated resource was invalid (%s)", e.message); + } + } this.password = password; this.alias = alias; } - public Account.from_row(Database db, Qlite.Row row) { + public Account.from_row(Database db, Qlite.Row row) throws InvalidJidError { this.db = db; id = row[db.account.id]; - resourcepart = row[db.account.resourcepart]; - bare_jid = new Jid(row[db.account.bare_jid]); + full_jid = new Jid(row[db.account.bare_jid]).with_resource(row[db.account.resourcepart]); password = row[db.account.password]; alias = row[db.account.alias]; enabled = row[db.account.enabled]; diff --git a/libdino/src/entity/conversation.vala b/libdino/src/entity/conversation.vala index 53c59bd2..d0ba4920 100644 --- a/libdino/src/entity/conversation.vala +++ b/libdino/src/entity/conversation.vala @@ -47,7 +47,7 @@ public class Conversation : Object { this.type_ = type; } - public Conversation.from_row(Database db, Qlite.Row row) { + public Conversation.from_row(Database db, Qlite.Row row) throws InvalidJidError { this.db = db; id = row[db.conversation.id]; diff --git a/libdino/src/entity/file_transfer.vala b/libdino/src/entity/file_transfer.vala index 9c0099d0..a8e386bf 100644 --- a/libdino/src/entity/file_transfer.vala +++ b/libdino/src/entity/file_transfer.vala @@ -63,7 +63,7 @@ public class FileTransfer : Object { private Database? db; private string storage_dir; - public FileTransfer.from_row(Database db, Qlite.Row row, string storage_dir) { + public FileTransfer.from_row(Database db, Qlite.Row row, string storage_dir) throws InvalidJidError { this.db = db; this.storage_dir = storage_dir; diff --git a/libdino/src/entity/message.vala b/libdino/src/entity/message.vala index 4b16d12c..d5697c72 100644 --- a/libdino/src/entity/message.vala +++ b/libdino/src/entity/message.vala @@ -60,7 +60,7 @@ public class Message : Object { this.body = body; } - public Message.from_row(Database db, Qlite.Row row) { + public Message.from_row(Database db, Qlite.Row row) throws InvalidJidError { this.db = db; id = row[db.message.id]; diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala index 7baba1fd..03278b4b 100644 --- a/libdino/src/service/content_item_store.vala +++ b/libdino/src/service/content_item_store.vala @@ -49,19 +49,29 @@ public class ContentItemStore : StreamInteractionModule, Object { case 1: RowOption row_option = db.message.select().with(db.message.id, "=", foreign_id).row(); if (row_option.is_present()) { - Message message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(foreign_id, conversation); + Message? message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(foreign_id, conversation); if (message == null) { - message = new Message.from_row(db, row_option.inner); + try { + message = new Message.from_row(db, row_option.inner); + } catch (InvalidJidError e) { + warning("Ignoring message with invalid Jid: %s", e.message); + } + } + if (message != null) { + items.add(new MessageItem(message, conversation, row[db.content_item.id])); } - items.add(new MessageItem(message, conversation, row[db.content_item.id])); } break; case 2: RowOption row_option = db.file_transfer.select().with(db.file_transfer.id, "=", foreign_id).row(); if (row_option.is_present()) { - string storage_dir = FileManager.get_storage_dir(); - FileTransfer file_transfer = new FileTransfer.from_row(db, row_option.inner, storage_dir); - items.add(new FileItem(file_transfer, row[db.content_item.id])); + try { + string storage_dir = FileManager.get_storage_dir(); + FileTransfer file_transfer = new FileTransfer.from_row(db, row_option.inner, storage_dir); + items.add(new FileItem(file_transfer, row[db.content_item.id])); + } catch (InvalidJidError e) { + warning("Ignoring file transfer with invalid Jid: %s", e.message); + } } break; } @@ -256,7 +266,7 @@ public class FileItem : ContentItem { public Conversation conversation; public FileItem(FileTransfer file_transfer, int id) { - Jid jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? file_transfer.account.bare_jid.with_resource(file_transfer.account.resourcepart) : file_transfer.counterpart; + Jid jid = file_transfer.direction == FileTransfer.DIRECTION_SENT ? file_transfer.account.full_jid : file_transfer.counterpart; Entities.Message.Marked mark = Entities.Message.Marked.NONE; if (file_transfer.direction == FileTransfer.DIRECTION_SENT) { mark = file_to_message_state(file_transfer.state); diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala index e230c3af..792b4b5f 100644 --- a/libdino/src/service/database.vala +++ b/libdino/src/service/database.vala @@ -311,9 +311,13 @@ public class Database : Qlite.Database { public ArrayList get_accounts() { ArrayList ret = new ArrayList(Account.equals_func); foreach(Row row in account.select()) { - Account account = new Account.from_row(this, row); - ret.add(account); - account_table_cache[account.id] = account; + try { + Account account = new Account.from_row(this, row); + ret.add(account); + account_table_cache[account.id] = account; + } catch (InvalidJidError e) { + warning("Ignoring account with invalid Jid: %s", e.message); + } } return ret; } @@ -324,9 +328,13 @@ public class Database : Qlite.Database { } else { Row? row = account.row_with(account.id, id).inner; if (row != null) { - Account a = new Account.from_row(this, row); - account_table_cache[a.id] = a; - return a; + try { + Account a = new Account.from_row(this, row); + account_table_cache[a.id] = a; + return a; + } catch (InvalidJidError e) { + warning("Ignoring account with invalid Jid: %s", e.message); + } } return null; } @@ -380,7 +388,11 @@ public class Database : Qlite.Database { LinkedList ret = new LinkedList(); foreach (Row row in select) { - ret.insert(0, new Message.from_row(this, row)); + try { + ret.insert(0, new Message.from_row(this, row)); + } catch (InvalidJidError e) { + warning("Ignoring message with invalid Jid: %s", e.message); + } } return ret; } @@ -394,7 +406,11 @@ public class Database : Qlite.Database { select.with(message.counterpart_id, "=", get_jid_id(jid)); } foreach (Row row in select) { - ret.add(new Message.from_row(this, row)); + try { + ret.add(new Message.from_row(this, row)); + } catch (InvalidJidError e) { + warning("Ignoring message with invalid Jid: %s", e.message); + } } return ret; } @@ -402,7 +418,11 @@ public class Database : Qlite.Database { public Message? get_message_by_id(int id) { Row? row = message.row_with(message.id, id).inner; if (row != null) { - return new Message.from_row(this, row); + try { + return new Message.from_row(this, row); + } catch (InvalidJidError e) { + warning("Ignoring message with invalid Jid: %s", e.message); + } } return null; } @@ -410,7 +430,11 @@ public class Database : Qlite.Database { public ArrayList get_conversations(Account account) { ArrayList ret = new ArrayList(); foreach (Row row in conversation.select().with(conversation.account_id, "=", account.id)) { - ret.add(new Conversation.from_row(this, row)); + try { + ret.add(new Conversation.from_row(this, row)); + } catch (InvalidJidError e) { + warning("Ignoring conversation with invalid Jid: %s", e.message); + } } return ret; } @@ -426,7 +450,11 @@ public class Database : Qlite.Database { public HashMap get_avatar_hashes(int type) { HashMap ret = new HashMap(Jid.hash_func, Jid.equals_func); foreach (Row row in avatar.select({avatar.jid, avatar.hash}).with(avatar.type_, "=", type)) { - ret[Jid.parse(row[avatar.jid])] = row[avatar.hash]; + try { + ret[new Jid(row[avatar.jid])] = row[avatar.hash]; + } catch (InvalidJidError e) { + warning("Ignoring avatar of invalid Jid: %s", e.message); + } } return ret; } @@ -466,13 +494,13 @@ public class Database : Qlite.Database { } } - public Jid? get_jid_by_id(int id) { + public Jid? get_jid_by_id(int id) throws InvalidJidError { if (jid_table_cache.has_key(id)) { return jid_table_cache[id]; } else { string? bare_jid = jid.select({jid.bare_jid}).with(jid.id, "=", id)[jid.bare_jid]; if (bare_jid != null) { - Jid jid_parsed = Jid.parse(bare_jid); + Jid jid_parsed = new Jid(bare_jid); jid_table_cache[id] = jid_parsed; jid_table_reverse[jid_parsed] = id; return jid_parsed; diff --git a/libdino/src/service/file_manager.vala b/libdino/src/service/file_manager.vala index a7d7b94a..5f3db040 100644 --- a/libdino/src/service/file_manager.vala +++ b/libdino/src/service/file_manager.vala @@ -169,8 +169,12 @@ public class FileManager : StreamInteractionModule, Object { private Gee.List get_transfers_from_qry(Qlite.QueryBuilder select) { Gee.List ret = new ArrayList(); foreach (Qlite.Row row in select) { - FileTransfer file_transfer = new FileTransfer.from_row(db, row, get_storage_dir()); - ret.insert(0, file_transfer); + try { + FileTransfer file_transfer = new FileTransfer.from_row(db, row, get_storage_dir()); + ret.insert(0, file_transfer); + } catch (InvalidJidError e) { + warning("Ignoring file transfer with invalid Jid: %s", e.message); + } } return ret; } @@ -287,7 +291,7 @@ public class FileManager : StreamInteractionModule, Object { if (conversation.type_ in new Conversation.Type[]{Conversation.Type.GROUPCHAT, Conversation.Type.GROUPCHAT_PM}) { file_transfer.ourpart = stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(conversation.counterpart, conversation.account) ?? conversation.account.bare_jid; } else { - file_transfer.ourpart = conversation.account.bare_jid.with_resource(conversation.account.resourcepart); + file_transfer.ourpart = conversation.account.full_jid; } file_transfer.time = time; file_transfer.local_time = local_time; diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala index a7d186ef..a0000936 100644 --- a/libdino/src/service/message_processor.vala +++ b/libdino/src/service/message_processor.vala @@ -534,7 +534,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 = conversation.account.bare_jid.with_resource(conversation.account.resourcepart); + message.ourpart = conversation.account.full_jid; } message.marked = Entities.Message.Marked.UNSENT; message.encryption = conversation.encryption; diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala index 01185731..018f78b3 100644 --- a/libdino/src/service/muc_manager.vala +++ b/libdino/src/service/muc_manager.vala @@ -239,10 +239,14 @@ public class MucManager : StreamInteractionModule, Object { } public Jid? get_own_jid(Jid muc_jid, Account account) { - Xep.Muc.Flag? flag = get_muc_flag(account); - if (flag != null) { - string? nick = flag.get_muc_nick(muc_jid); - if (nick != null) return muc_jid.with_resource(nick); + try { + Xep.Muc.Flag? flag = get_muc_flag(account); + if (flag != null) { + string? nick = flag.get_muc_nick(muc_jid); + if (nick != null) return muc_jid.with_resource(nick); + } + } catch (InvalidJidError e) { + warning("Joined MUC with invalid Jid: %s", e.message); } return null; } diff --git a/libdino/src/service/roster_manager.vala b/libdino/src/service/roster_manager.vala index 6f004c01..62428882 100644 --- a/libdino/src/service/roster_manager.vala +++ b/libdino/src/service/roster_manager.vala @@ -91,11 +91,15 @@ public class RosterStoreImpl : Roster.Storage, Object { this.db = db; foreach (Qlite.Row row in db.roster.select().with(db.roster.account_id, "=", account.id)) { - Roster.Item item = new Roster.Item(); - item.jid = Jid.parse(row[db.roster.jid]); - item.name = row[db.roster.handle]; - item.subscription = row[db.roster.subscription]; - items[item.jid] = item; + try { + Roster.Item item = new Roster.Item(); + item.jid = new Jid(row[db.roster.jid]); + item.name = row[db.roster.handle]; + item.subscription = row[db.roster.subscription]; + items[item.jid] = item; + } catch (InvalidJidError e) { + warning("Ignoring roster entry with invalid Jid: %s", e.message); + } } } diff --git a/libdino/src/service/search_processor.vala b/libdino/src/service/search_processor.vala index 37f524ac..9a41ad98 100644 --- a/libdino/src/service/search_processor.vala +++ b/libdino/src/service/search_processor.vala @@ -132,10 +132,14 @@ public class SearchProcessor : StreamInteractionModule, Object { .with(db.conversation.type_, "=", Conversation.Type.CHAT) .order_by(db.conversation.last_active, "DESC"); foreach(Row chat in chats) { - if (suggestions.size == 0) { - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "from:"+chat[db.jid.bare_jid], after_prev_space, next_space)); + try { + if (suggestions.size == 0) { + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "from:"+chat[db.jid.bare_jid], after_prev_space, next_space)); + } + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.account.bare_jid]), "from:"+chat[db.account.bare_jid], after_prev_space, next_space)); + } catch (InvalidJidError e) { + warning("Ignoring search suggestion with invalid Jid: %s", e.message); } - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.account.bare_jid]), "from:"+chat[db.account.bare_jid], after_prev_space, next_space)); } return suggestions; } @@ -155,7 +159,11 @@ public class SearchProcessor : StreamInteractionModule, Object { .order_by_name(@"MAX($(db.message.time))", "DESC") .limit(5); foreach(Row msg in msgs) { - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, msg), new Jid(current_in).with_resource(msg[db.message.counterpart_resource]), "from:"+msg[db.message.counterpart_resource], after_prev_space, next_space)); + try { + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, msg), new Jid(current_in).with_resource(msg[db.message.counterpart_resource]), "from:"+msg[db.message.counterpart_resource], after_prev_space, next_space)); + } catch (InvalidJidError e) { + warning("Ignoring search suggestion with invalid Jid: %s", e.message); + } } } // TODO: auto complete from @@ -181,7 +189,11 @@ public class SearchProcessor : StreamInteractionModule, Object { .order_by(db.conversation.last_active, "DESC") .limit(limit); foreach(Row chat in chats) { - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "with:"+chat[db.jid.bare_jid], after_prev_space, next_space) { order = chat[db.conversation.last_active]}); + try { + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "with:"+chat[db.jid.bare_jid], after_prev_space, next_space) { order = chat[db.conversation.last_active]}); + } catch (InvalidJidError e) { + warning("Ignoring search suggestion with invalid Jid: %s", e.message); + } } // Groupchat PM @@ -195,7 +207,11 @@ public class SearchProcessor : StreamInteractionModule, Object { .order_by(db.conversation.last_active, "DESC") .limit(limit - suggestions.size); foreach(Row chat in chats) { - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]).with_resource(chat[db.conversation.resource]), "with:"+chat[db.jid.bare_jid]+"/"+chat[db.conversation.resource], after_prev_space, next_space) { order = chat[db.conversation.last_active]}); + try { + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]).with_resource(chat[db.conversation.resource]), "with:"+chat[db.jid.bare_jid]+"/"+chat[db.conversation.resource], after_prev_space, next_space) { order = chat[db.conversation.last_active]}); + } catch (InvalidJidError e) { + warning("Ignoring search suggestion with invalid Jid: %s", e.message); + } } suggestions.sort((a, b) => (int)(b.order - a.order)); } @@ -218,7 +234,11 @@ public class SearchProcessor : StreamInteractionModule, Object { .order_by(db.conversation.last_active, "DESC") .limit(limit); foreach(Row chat in groupchats) { - suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "in:"+chat[db.jid.bare_jid], after_prev_space, next_space)); + try { + suggestions.add(new SearchSuggestion(new Conversation.from_row(db, chat), new Jid(chat[db.jid.bare_jid]), "in:"+chat[db.jid.bare_jid], after_prev_space, next_space)); + } catch (InvalidJidError e) { + warning("Ignoring search suggestion with invalid Jid: %s", e.message); + } } } else { // Other auto complete? @@ -233,9 +253,13 @@ public class SearchProcessor : StreamInteractionModule, Object { rows.offset(offset); } foreach (Row row in rows) { - Message message = new Message.from_row(db, row); - Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message); - ret.add(new MessageItem(message, conversation, row[db.content_item.id])); + try { + Message message = new Message.from_row(db, row); + Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message); + ret.add(new MessageItem(message, conversation, row[db.content_item.id])); + } catch (InvalidJidError e) { + warning("Ignoring search result with invalid Jid: %s", e.message); + } } return ret; } -- cgit v1.2.3-54-g00ecf