From a257b163376174e4f5efcbc82c9fdd56463c3191 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Wed, 30 Aug 2017 00:03:37 +0200 Subject: Download & inline display images --- libdino/src/service/database.vala | 35 ++++++++++++-- libdino/src/service/file_manager.vala | 74 ++++++++++++++++++++++++++++++ libdino/src/service/message_processor.vala | 2 +- 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 libdino/src/service/file_manager.vala (limited to 'libdino/src/service') diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala index 51d16e59..1678c077 100644 --- a/libdino/src/service/database.vala +++ b/libdino/src/service/database.vala @@ -6,7 +6,7 @@ using Dino.Entities; namespace Dino { public class Database : Qlite.Database { - private const int VERSION = 5; + private const int VERSION = 6; public class AccountTable : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; @@ -53,6 +53,7 @@ public class Database : Qlite.Database { base(db, "message"); init({id, stanza_id, account_id, counterpart_id, our_resource, counterpart_resource, direction, type_, time, local_time, body, encryption, marked}); + index("message_localtime_counterpart_idx", {local_time, counterpart_id}); } } @@ -77,6 +78,32 @@ public class Database : Qlite.Database { } } + public class FileTransferTable : Table { + public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; + public Column account_id = new Column.Integer("account_id") { not_null = true }; + public Column counterpart_id = new Column.Integer("counterpart_id") { not_null = true }; + public Column counterpart_resource = new Column.Text("counterpart_resource"); + public Column our_resource = new Column.Text("our_resource"); + public Column direction = new Column.BoolInt("direction") { not_null = true }; + public Column time = new Column.Long("time"); + public Column local_time = new Column.Long("local_time"); + public Column encryption = new Column.Integer("encryption"); + public Column file_name = new Column.Text("file_name"); + public Column path = new Column.Text("path"); + public Column mime_type = new Column.Text("mime_type"); + public Column size = new Column.Integer("size"); + public Column state = new Column.Integer("state"); + public Column provider = new Column.Integer("provider"); + public Column info = new Column.Text("info"); + + internal FileTransferTable(Database db) { + base(db, "file_transfer"); + init({id, account_id, counterpart_id, counterpart_resource, our_resource, direction, time, local_time, + encryption, file_name, path, mime_type, size, state, provider, info}); + index("filetransfer_localtime_counterpart_idx", {local_time, counterpart_id}); + } + } + public class ConversationTable : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; public Column account_id = new Column.Integer("account_id") { not_null = true }; @@ -148,6 +175,7 @@ public class Database : Qlite.Database { public JidTable jid { get; private set; } public MessageTable message { get; private set; } public RealJidTable real_jid { get; private set; } + public FileTransferTable file_transfer { get; private set; } public ConversationTable conversation { get; private set; } public AvatarTable avatar { get; private set; } public EntityFeatureTable entity_feature { get; private set; } @@ -164,12 +192,13 @@ public class Database : Qlite.Database { jid = new JidTable(this); message = new MessageTable(this); real_jid = new RealJidTable(this); + file_transfer = new FileTransferTable(this); conversation = new ConversationTable(this); avatar = new AvatarTable(this); entity_feature = new EntityFeatureTable(this); roster = new RosterTable(this); settings = new SettingsTable(this); - init({ account, jid, message, real_jid, conversation, avatar, entity_feature, roster, settings }); + init({ account, jid, message, real_jid, file_transfer, conversation, avatar, entity_feature, roster, settings }); exec("PRAGMA synchronous=0"); } @@ -214,7 +243,7 @@ public class Database : Qlite.Database { select.with(message.type_, "=", (int) type); } if (before != null) { - select.with(message.time, "<", (long) before.to_unix()); + select.with(message.local_time, "<", (long) before.to_unix()); } LinkedList ret = new LinkedList(); diff --git a/libdino/src/service/file_manager.vala b/libdino/src/service/file_manager.vala new file mode 100644 index 00000000..b165039f --- /dev/null +++ b/libdino/src/service/file_manager.vala @@ -0,0 +1,74 @@ +using Gdk; +using Gee; + +using Xmpp; +using Dino.Entities; + +namespace Dino { + +public class FileManager : StreamInteractionModule, Object { + public static ModuleIdentity IDENTITY = new ModuleIdentity("file"); + public string id { get { return IDENTITY.id; } } + + public signal void received_file(FileTransfer file_transfer); + + private StreamInteractor stream_interactor; + private Database db; + private Gee.List file_transfers = new ArrayList(); + + public static void start(StreamInteractor stream_interactor, Database db) { + FileManager m = new FileManager(stream_interactor, db); + stream_interactor.add_module(m); + } + + public static string get_storage_dir() { + return Path.build_filename(Dino.get_storage_dir(), "files"); + } + + private FileManager(StreamInteractor stream_interactor, Database db) { + this.stream_interactor = stream_interactor; + this.db = db; + DirUtils.create_with_parents(get_storage_dir(), 0700); + } + + public void add_provider(Plugins.FileProvider file_provider) { + file_provider.file_incoming.connect((file_transfer) => { + file_transfers.add(file_transfer); + string filename = Random.next_int().to_string("%x") + "_" + file_transfer.file_name; + file_transfer.file_name = filename; + File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename)); + try { + OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION); + os.splice(file_transfer.input_stream, 0); + os.close(); + file_transfer.state = FileTransfer.State.COMPLETE; + } catch (Error e) { + file_transfer.state = FileTransfer.State.FAILED; + } + file_transfer.persist(db); + file_transfer.input_stream = file.read(); + received_file(file_transfer); + }); + } + + public Gee.List get_file_transfers(Account account, Jid counterpart, DateTime after, DateTime before) { + Qlite.QueryBuilder select = db.file_transfer.select() + .with(db.file_transfer.counterpart_id, "=", db.get_jid_id(counterpart)) + .with(db.file_transfer.account_id, "=", account.id) + .with(db.file_transfer.local_time, ">", (long)after.to_unix()) + .with(db.file_transfer.local_time, "<", (long)before.to_unix()) + .order_by(db.file_transfer.id, "DESC"); + + Gee.List ret = new ArrayList(); + foreach (Qlite.Row row in select) { + FileTransfer file_transfer = new FileTransfer.from_row(db, row); + File file = File.new_for_path(Path.build_filename(get_storage_dir(), file_transfer.file_name)); + file_transfer.input_stream = file.read(); + ret.insert(0, file_transfer); + } + return ret; + } + +} + +} diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala index 2bf3d615..4bb30ce6 100644 --- a/libdino/src/service/message_processor.vala +++ b/libdino/src/service/message_processor.vala @@ -6,7 +6,7 @@ using Dino.Entities; namespace Dino { public class MessageProcessor : StreamInteractionModule, Object { - public static ModuleIdentity IDENTITY = new ModuleIdentity("message_manager"); + public static ModuleIdentity IDENTITY = new ModuleIdentity("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); -- cgit v1.2.3-70-g09d2