diff options
Diffstat (limited to 'plugins/http-files/src/file_sender.vala')
-rw-r--r-- | plugins/http-files/src/file_sender.vala | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/plugins/http-files/src/file_sender.vala b/plugins/http-files/src/file_sender.vala index 91b50944..02336b43 100644 --- a/plugins/http-files/src/file_sender.vala +++ b/plugins/http-files/src/file_sender.vala @@ -17,7 +17,7 @@ public class HttpFileSender : FileSender, Object { session.user_agent = @"Dino/$(Dino.get_short_version()) "; stream_interactor.stream_negotiated.connect(on_stream_negotiated); - stream_interactor.get_module(MessageProcessor.IDENTITY).build_message_stanza.connect(check_add_oob); + stream_interactor.get_module(MessageProcessor.IDENTITY).build_message_stanza.connect(check_add_sfs_element); } public async FileSendData? prepare_send_file(Conversation conversation, FileTransfer file_transfer, FileMeta file_meta) throws FileSendError { @@ -43,39 +43,55 @@ public class HttpFileSender : FileSender, Object { HttpFileSendData? send_data = file_send_data as HttpFileSendData; if (send_data == null) return; - yield upload(file_transfer, send_data, file_meta); + bool can_reference_element = !conversation.type_.is_muc_semantic() || stream_interactor.get_module(EntityInfo.IDENTITY).has_feature_cached(conversation.account, conversation.counterpart, Xep.UniqueStableStanzaIDs.NS_URI); + + // Share unencrypted files via SFS (only if we'll be able to reference messages) + if (conversation.encryption == Encryption.NONE && can_reference_element) { + // Announce the file share + Entities.Message file_share_message = stream_interactor.get_module(MessageProcessor.IDENTITY).create_out_message(null, conversation); + file_transfer.info = file_share_message.id.to_string(); + file_transfer.file_sharing_id = Xmpp.random_uuid(); + stream_interactor.get_module(MessageProcessor.IDENTITY).send_xmpp_message(file_share_message, conversation); + + // Upload file + yield upload(file_transfer, send_data, file_meta); + + // Wait until we know the server id of the file share message (in MUCs; we get that from the reflected message) + if (conversation.type_.is_muc_semantic()) { + if (file_share_message.server_id == null) { + ulong server_id_notify_id = file_share_message.notify["server-id"].connect(() => { + Idle.add(send_file.callback); + }); + yield; + file_share_message.disconnect(server_id_notify_id); + } + } + + file_transfer.sfs_sources.add(new Xep.StatelessFileSharing.HttpSource() { url=send_data.url_down } ); + + // Send source attachment + MessageStanza stanza = new MessageStanza() { to = conversation.counterpart, type_ = conversation.type_ == GROUPCHAT ? MessageStanza.TYPE_GROUPCHAT : MessageStanza.TYPE_CHAT }; + stanza.body = send_data.url_down; + Xep.OutOfBandData.add_url_to_message(stanza, send_data.url_down); + var sources = new ArrayList<Xep.StatelessFileSharing.Source>(); + sources.add(new Xep.StatelessFileSharing.HttpSource() { url = send_data.url_down }); + string attach_to_id = MessageStorage.get_reference_id(file_share_message); + Xep.StatelessFileSharing.set_sfs_attachment(stanza, attach_to_id, file_transfer.file_sharing_id, sources); + + var stream = stream_interactor.get_stream(conversation.account); + if (stream == null) throw new FileSendError.UPLOAD_FAILED("No stream"); + + stream.get_module(MessageModule.IDENTITY).send_message.begin(stream, stanza); + } + // Share encrypted files without SFS + else { + yield upload(file_transfer, send_data, file_meta); - if (send_data.encrypt_message && conversation.encryption != Encryption.NONE) { Entities.Message message = stream_interactor.get_module(MessageProcessor.IDENTITY).create_out_message(send_data.url_down, conversation); file_transfer.info = message.id.to_string(); - message.encryption = conversation.encryption; + message.encryption = send_data.encrypt_message ? conversation.encryption : Encryption.NONE; stream_interactor.get_module(MessageProcessor.IDENTITY).send_xmpp_message(message, conversation); - } else { - // Use stateless file sharing for unencrypted file sharing - Xep.StatelessFileSharing.HttpSource source = new Xep.StatelessFileSharing.HttpSource(); - source.url = send_data.url_down; - file_transfer.sfs_sources.append(new FileTransfer.SerializedSfsSource.from_sfs_source(source) as Object); - this.db.sfs_sources.insert() - .value(db.sfs_sources.id, file_transfer.id) - .value(db.sfs_sources.type, source.type()) - .value(db.sfs_sources.data, source.serialize()) - .perform(); - XmppStream stream = stream_interactor.get_stream(conversation.account); - Xep.StatelessFileSharing.Module sfs_module = stream.get_module(Xep.StatelessFileSharing.Module.IDENTITY); - string message_type; - if (conversation.type_ == Conversation.Type.GROUPCHAT) { - message_type = MessageStanza.TYPE_GROUPCHAT; - } else { - message_type = MessageStanza.TYPE_CHAT; - } - MessageStanza sfs_message = new MessageStanza() { to=conversation.counterpart, type_=message_type }; - // TODO: is this the correct way of adding out-of-band-data? - sfs_message.body = source.url; - Xep.OutOfBandData.add_url_to_message(sfs_message, source.url); - // TODO: message hint correct? - Xep.MessageProcessingHints.set_message_hint(sfs_message, Xep.MessageProcessingHints.HINT_STORE); - sfs_module.send_stateless_file_transfer(stream, sfs_message, yield file_transfer.to_sfs_element()); } } @@ -159,10 +175,15 @@ public class HttpFileSender : FileSender, Object { }); } - private void check_add_oob(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) { - if (message.encryption == Encryption.NONE && message.body.has_prefix("http") && message_is_file(db, message)) { - Xep.OutOfBandData.add_url_to_message(message_stanza, message_stanza.body); - } + private void check_add_sfs_element(Entities.Message message, Xmpp.MessageStanza message_stanza, Conversation conversation) { + if (message.encryption != Encryption.NONE) return; + + FileTransfer? file_transfer = stream_interactor.get_module(FileTransferStorage.IDENTITY).get_file_by_message_id(message.id, conversation); + if (file_transfer == null) return; + + Xep.StatelessFileSharing.set_sfs_element(message_stanza, file_transfer.file_sharing_id, file_transfer.file_metadata, file_transfer.sfs_sources); + + Xep.MessageProcessingHints.set_message_hint(message_stanza, Xep.MessageProcessingHints.HINT_STORE); } public int get_id() { return 0; } |