Skip to content

Commit

Permalink
See RN4.1.0 (20240514)
Browse files Browse the repository at this point in the history
- Add Jingle Content Thumbnails (XEP-0264) support in Jingle File Transfer (XEP-0234) protocol.
  * Thumbnails is disabled for OMEMO Jet; no defined protocol to support.
  * Add ThumbnailProvider class for Thumbnail element parsing in JingleFileTransferProvider.
  * Include Thumbnail element handling in JingleFile and JingleFileTransferChild classes.
  * OutgoingFileOfferJingleImpl: Implement bobInfoInit handler for thumbnail support.
  * IncomingFileOfferJingleImpl: implement getThumbnail() with callback.
- Optimize and cleanup OperationSetFileTransferJabberImpl for XEP-0264: Jingle Content Thumbnails support:
  * OperationSetFileTransferJabberImpl#fileTransferRequest: let thumbnail request to be handled by FileReceiveConversation.
  * OutgoingFileTransferJabberIml handles bobInfoInit at constructor, and remove StanzaListener to insert Thumbnail element.
  * IncomingFileTransferRequestJabberImpl: add getThumbnail() with callback.
- Block and alert user if attempt to send encrypted file via XEP-0096: SI File Transfer.
- Update smack library classes to fully support Jingle Content Thumbnails (XEP-0264) in legacy Si and Jingle File Transfer.
  * Rename ThumbnailStreamInitiationProvider to StreamInitiationProvider, and replace smack class file.
  * Cleanup and update StreamInitiation.File to support Thumbnail element, and remove thumbnail.ThumbnailFile class file.
  * FileTransferRequest: add getThumbnail() method.
  * OutgoingFileTransfer: Add new thumbnail parameter in sendFile() etc for use in FileTransferNegotiator.negotiateOutgoingTransfer().
  * FileTransferNegotiator: Add thumbnail element in XEP-0096: SI File Transfer stanza sending.
  * JingleFileTransferProvider: Support Thumbnail parsing.
- Dropped changing thumbnail default size to 128x96 in file transfer.
  * Current BobData response time is ~16s (jpeg=14784) and 39s (png=31326) with thumbnail size = 128 x 96.
  * Thumbnail size 64x64 => jpeg 5303 and takes ~7s; use this as default
- Scale thumbnail x2 for display in file transfer request UI.
- OutgoingFileOfferJingleImpl needs to perform process cleanup upon ProgressListener#onFinished().
- Must init JetManager when user is authenticated, ready for advertise JET feature in DiscoveryManager;
  else JetManager security file transfer support is not working.
  • Loading branch information
cmeng-git committed May 14, 2024
1 parent 38eb17f commit c689bd1
Show file tree
Hide file tree
Showing 52 changed files with 2,178 additions and 642 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ It supports the following XEP's, standards for XMPP clients.
* [XEP-0260: Jingle SOCKS5 Bytestreams Transport Method 1.0.3](https://xmpp.org/extensions/xep-0260.html)
* [XEP-0261: Jingle In-Band Bytestreams Transport Method 1.0](https://xmpp.org/extensions/xep-0261.html)
* [XEP-0262: Use of ZRTP in Jingle RTP Sessions 1.0](https://xmpp.org/extensions/xep-0262.html)
* [XEP-0264: File Transfer Thumbnails 0.4](https://xmpp.org/extensions/xep-0264.html)
* [XEP-0264: Jingle Content Thumbnails 0.4.1](https://xmpp.org/extensions/xep-0264.html)
* [XEP-0278: Jingle Relay Nodes 0.4.1](https://xmpp.org/extensions/xep-0278.html)
* [XEP-0280: Message Carbons 1.0.1](https://xmpp.org/extensions/xep-0280.html)
* [XEP-0293: Jingle RTP Feedback Negotiation 1.0.2](https://xmpp.org/extensions/xep-0293.html)
Expand All @@ -143,6 +143,7 @@ It supports the following XEP's, standards for XMPP clients.
* [XEP-0371: Jingle ICE Transport Method 0.3.1](https://xmpp.org/extensions/xep-0371.html)
* [XEP-0384: OMEMO Encryption 0.8.3](https://xmpp.org/extensions/xep-0384.html)
* [XEP-0391: Jingle Encrypted Transports 0.1.2](https://xmpp.org/extensions/xep-0391.html)
* [XEP-0396: Jingle Encrypted Transports - OMEMO 0.2.0](https://xmpp.org/extensions/xep-0396.html)
* [XEP-0441: Message Archive Management Preferences 0.2.0](https://xmpp.org/extensions/xep-0441.html)
* [XEP-0453: DOAP usage in XMPP 0.1.2](https://xmpp.org/extensions/xep-0453.html)
* [XEP-0454: OMEMO Media sharing 0.1.0](https://xmpp.org/extensions/xep-0454.html)
Expand Down
32 changes: 31 additions & 1 deletion aTalk/ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
Project aTalk-Android Release Notes
=========================================================================
Version: 4.1.0 (401000)
Release Date: 05/14/2024
Author: cmeng
- Add Jingle Content Thumbnails (XEP-0264) support in Jingle File Transfer (XEP-0234) protocol.
* Thumbnails is disabled for OMEMO Jet; no defined protocol to support.
* Add ThumbnailProvider class for Thumbnail element parsing in JingleFileTransferProvider.
* Include Thumbnail element handling in JingleFile and JingleFileTransferChild classes.
* OutgoingFileOfferJingleImpl: Implement bobInfoInit handler for thumbnail support.
* IncomingFileOfferJingleImpl: implement getThumbnail() with callback.
- Optimize and cleanup OperationSetFileTransferJabberImpl for XEP-0264: Jingle Content Thumbnails support:
* OperationSetFileTransferJabberImpl#fileTransferRequest: let thumbnail request to be handled by FileReceiveConversation.
* OutgoingFileTransferJabberIml handles bobInfoInit at constructor, and remove StanzaListener to insert Thumbnail element.
* IncomingFileTransferRequestJabberImpl: add getThumbnail() with callback.
- Block and alert user if attempt to send encrypted file via XEP-0096: SI File Transfer.
- Update smack library classes to fully support Jingle Content Thumbnails (XEP-0264) in legacy Si and Jingle File Transfer.
* Rename ThumbnailStreamInitiationProvider to StreamInitiationProvider, and replace smack class file.
* Cleanup and update StreamInitiation.File to support Thumbnail element, and remove thumbnail.ThumbnailFile class file.
* FileTransferRequest: add getThumbnail() method.
* OutgoingFileTransfer: Add new thumbnail parameter in sendFile() etc for use in FileTransferNegotiator.negotiateOutgoingTransfer().
* FileTransferNegotiator: Add thumbnail element in XEP-0096: SI File Transfer stanza sending.
* JingleFileTransferProvider: Support Thumbnail parsing.
- Dropped changing thumbnail default size to 128x96 in file transfer.
* Current BobData response time is ~16s (jpeg=14784) and 39s (png=31326) with thumbnail size = 128 x 96.
* Thumbnail size 64x64 => jpeg 5303 and takes ~7s; use this as default
- Scale thumbnail x2 for display in file transfer request UI.
- OutgoingFileOfferJingleImpl needs to perform process cleanup upon ProgressListener#onFinished().
- Must init JetManager when user is authenticated, ready for advertise JET feature in DiscoveryManager;
else JetManager security file transfer support is not working.

=========================================================================
Version: 4.0.2 (400020)
Release Date: 05/01/2024
Expand Down Expand Up @@ -2465,7 +2495,7 @@ Author: cmeng
- Check to ensure dialog is showing before dismissed": PhoneWindow$DecorView-not attached to window manager
- Remove inactive account status icon in preference setting screens
- Use smack BobManager to handle Bob thumbnail request in OperationSetFileTransferJabberImpl and OutgoingFileTransferJabberImpl
- Remove ThumbNailIQ and ThumbNailProvider; use BobManager instead
- Remove ThumbNailIQ and ThumbNail(IQ)Provider; use BobManager instead
- Change aTalk Bob to BobExt and update to use smack BoBHash and BoBData format
- Omit Set Type=chat for Omemo message before sending - implemented in OmemoMessage - 4.4.0-alpha2
- Fixed BaseContactListAdapter#contactListFragment.getLayoutInflater() exception when it is not attached to FragmentManager
Expand Down
11 changes: 9 additions & 2 deletions aTalk/aTalk.doap
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0264.html"/>
<xmpp:version>0.4</xmpp:version>
<xmpp:note xml:lang='en'>XEP-0264: File Transfer Thumbnails</xmpp:note>
<xmpp:version>0.4.1</xmpp:version>
<xmpp:note xml:lang='en'>XEP-0264: Jingle Content Thumbnails</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
Expand Down Expand Up @@ -485,6 +485,13 @@
<xmpp:note xml:lang='en'>XEP-0391: Jingle Encrypted Transports</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0396.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:note xml:lang='en'>XEP-0396: Jingle Encrypted Transports - OMEMO</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0441.html"/>
Expand Down
21 changes: 16 additions & 5 deletions aTalk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ android {
namespace 'org.atalk.android'
applicationId "org.atalk.android"

versionCode 400020
versionName "4.0.2"
versionCode 401000
versionName "4.1.0"

minSdkVersion rootProject.minSdk
targetSdkVersion rootProject.compileSdk
Expand Down Expand Up @@ -216,12 +216,12 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

// 1.12.0 is only compatible with API-34
implementation 'androidx.core:core-ktx:1.13.0'
implementation 'androidx.core:core-ktx:1.13.1'

implementation 'androidx.activity:activity-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
implementation 'androidx.fragment:fragment-ktx:1.7.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Expand All @@ -248,7 +248,7 @@ dependencies {

implementation 'com.github.yalantis:ucrop:2.2.8'
// Do not update to 1.7.x or higher; has problem and reported need to use gradle 7 which is not compatible with aTalk.
implementation 'com.google.android.material:material:1.11.0'
implementation 'com.google.android.material:material:1.12.0'

implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.29'
implementation 'com.jakewharton.threetenabp:threetenabp:1.4.2'
Expand Down Expand Up @@ -430,6 +430,9 @@ dependencies {

// Fix AbstractMethodError: source in aTalk local directory and with in file QNAME defined
classDelete 'org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChild**'

// Support Thumbnail parsing.
classDelete 'org.jivesoftware.smackx.jingle_filetransfer.provider.JingleFileTransferProvider**'
}

// smack-extensions
Expand All @@ -446,6 +449,14 @@ dependencies {
// Stop duplicate <presence/> sending if Configuration.isSendPresence() is false
classDelete 'org.jivesoftware.smackx.disco.ServiceDiscoveryManager**'

// Support XEP-0264: Jingle Content Thumbnails in XEP-0096: SI File Transfer
classDelete 'org.jivesoftware.smackx.filetransfer.FileTransferNegotiator**'
classDelete 'org.jivesoftware.smackx.filetransfer.FileTransferRequest**'
classDelete 'org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer**'
// Custom smack classes that handle the XEP-0264 <File/> element
classDelete 'org.jivesoftware.smackx.si.packet.StreamInitiation**'
classDelete 'org.jivesoftware.smackx.si.provider.StreamInitiationProvider**'

classDelete 'org.jivesoftware.smackx.jingle.JingleManager**'
classDelete 'org.jivesoftware.smackx.jingle.JingleUtil**'

Expand Down
6 changes: 3 additions & 3 deletions aTalk/release/version.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Date: Wed May 01 10:45:34 SGT 2024
Date: Tue May 14 07:08:31 SGT 2024

last_version=4.0.2
last_version_code=400020
last_version=4.1.0
last_version_code=401000
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import net.java.sip.communicator.service.protocol.ChatRoom;
import net.java.sip.communicator.service.protocol.Contact;
import net.java.sip.communicator.service.protocol.FileTransfer;
Expand All @@ -26,24 +33,24 @@
import net.java.sip.communicator.service.protocol.OperationSetPersistentPresence;
import net.java.sip.communicator.service.protocol.event.FileTransferCreatedEvent;
import net.java.sip.communicator.service.protocol.event.FileTransferRequestEvent;
import net.java.sip.communicator.util.ConfigurationUtils;

import org.atalk.android.R;
import org.atalk.android.aTalkApp;
import org.atalk.android.gui.chat.filetransfer.FileReceiveConversation;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bob.BoBManager;
import org.jivesoftware.smackx.bob.ContentId;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.jet.component.JetSecurityImpl;
import org.jivesoftware.smackx.jingle.component.JingleContentImpl;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFile;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
import org.jxmpp.jid.BareJid;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import org.jivesoftware.smackx.thumbnail.element.Thumbnail;
import org.jxmpp.jid.Jid;

import timber.log.Timber;

Expand All @@ -53,18 +60,26 @@
* @author Eng Chong Meng
*/
public class IncomingFileOfferJingleImpl implements IncomingFileTransferRequest {
private final OperationSetFileTransferJabberImpl fileTransferOpSet;
/**
* Thread to fetch thumbnails in the background, one at a time
*/
private static final ExecutorService thumbnailCollector = Executors.newSingleThreadExecutor();

private final OperationSetFileTransferJabberImpl fileTransferOpSet;
private final IncomingFileOfferController mOffer;
private final JingleFile mJingleFile;
private IncomingFileTransferJingleImpl mFileTransfer = null;
private File mFile;
private IncomingFileTransferJingleImpl mFileTransfer;

private final XMPPConnection mConnection;

private final Jid remoteJid;
private Contact mSender;
private final String mId;

private final JingleFile mJingleFile;
private File mFile;
private final Thumbnail thumbnailElement;
private byte[] thumbnail = null;
FileReceiveConversation mCallback = null;

/*
* Transfer file encryption type based on incoming encryption detection.
*/
Expand All @@ -76,18 +91,13 @@ public class IncomingFileOfferJingleImpl implements IncomingFileTransferRequest
*
* @param pps the protocol provider
* @param fileTransferOpSet file transfer operation set
* @param fileTransferRequest the request coming from the Jabber protocol
* @param offer the IncomingFileOfferController coming from the Jabber protocol
*/
public IncomingFileOfferJingleImpl(ProtocolProviderServiceJabberImpl pps,
OperationSetFileTransferJabberImpl fileTransferOpSet, IncomingFileOfferController offer) {
this.fileTransferOpSet = fileTransferOpSet;
mConnection = pps.getConnection();

this.fileTransferOpSet = fileTransferOpSet;
mOffer = offer;
mJingleFile = mOffer.getMetadata();
HashElement hashElement = mJingleFile.getHash();
mId = (hashElement != null) ? hashElement.getHashB64()
: String.valueOf(System.currentTimeMillis()) + hashCode();

// Determine the incoming content encryption type.
mEncryption = IMessage.ENCRYPTION_NONE;
Expand All @@ -96,20 +106,27 @@ public IncomingFileOfferJingleImpl(ProtocolProviderServiceJabberImpl pps,
if (jingleContent.getSecurity() instanceof JetSecurityImpl) {
mEncryption = IMessage.ENCRYPTION_OMEMO;
break;
};
}
}

BareJid remoteJid = mOffer.getJingleSession().getRemote().asBareJid();
mJingleFile = mOffer.getMetadata();
HashElement hashElement = mJingleFile.getHash();
mId = (hashElement != null) ? hashElement.getHashB64()
: String.valueOf(System.currentTimeMillis()) + hashCode();
thumbnailElement = mJingleFile.getThumbnail();

remoteJid = mOffer.getJingleSession().getRemote();
OperationSetPersistentPresenceJabberImpl opSetPersPresence
= (OperationSetPersistentPresenceJabberImpl) pps.getOperationSet(OperationSetPersistentPresence.class);

mSender = opSetPersPresence.findContactByJid(remoteJid);
if (mSender == null) {
ChatRoom privateContactRoom = null;
OperationSetMultiUserChatJabberImpl mucOpSet
= (OperationSetMultiUserChatJabberImpl) pps.getOperationSet(OperationSetMultiUserChat.class);

if (mucOpSet != null)
privateContactRoom = mucOpSet.getChatRoom(remoteJid);
privateContactRoom = mucOpSet.getChatRoom(remoteJid.asBareJid());

if (privateContactRoom != null) {
mSender = opSetPersPresence.createVolatileContact(remoteJid, true);
Expand Down Expand Up @@ -200,18 +217,27 @@ public int getEncryptionType() {
}

/**
* Returns the thumbnail contained in this request. Jingle file transfer does not support thumbnail.
* Returns the thumbnail contained in this request.
* Proceed to request for the available thumbnail if auto accept file not permitted
*
* @param callback the caller requesting the thumbnail
*
* @return the thumbnail contained in this request
*/
@Override
public byte[] getThumbnail() {
return null;
public byte[] getThumbnail(FileReceiveConversation callback) {
if (thumbnail == null && thumbnailElement != null) {
mCallback = callback;
boolean isAutoAccept = ConfigurationUtils.isAutoAcceptFile(mJingleFile.getSize());
if (!isAutoAccept && ConfigurationUtils.isSendThumbnail()) {
fetchThumbnailAndNotify(thumbnailElement.getCid());
}
}
return thumbnail;
}

/**
* Accepts the file and starts the transfer.
*
* Note: If user cancels while in protocol negotiation; the accept() will return an error:
* XMPPError: item-not-found - cancel
*/
Expand All @@ -237,11 +263,40 @@ public void declineFile()
try {
mOffer.cancel(mConnection);
mFileTransfer.removeIfoListener();
} catch (NotConnectedException | InterruptedException | XMPPException.XMPPErrorException | SmackException.NoResponseException e) {
} catch (NotConnectedException | InterruptedException | XMPPException.XMPPErrorException |
SmackException.NoResponseException e) {
throw new OperationFailedException("Could not decline the file offer", OperationFailedException.GENERAL_ERROR, e);
}

fileTransferOpSet.fireFileTransferRequestRejected(
new FileTransferRequestEvent(fileTransferOpSet, this, new Date()));
}

/**
* Request the thumbnail from the peer, allow extended smack timeout on thumbnail request.
* Then fire the incoming transfer request event to start the actual incoming file transfer.
*
* @param cid the thumbnail content-Id
*/
private void fetchThumbnailAndNotify(final ContentId cid) {
final BoBManager bobManager = BoBManager.getInstanceFor(mConnection);
thumbnailCollector.submit(() -> {
try {
// Current BobData response time is ~16s (jpeg=14784) and 39s (png=31326) with thumbnail size = 128 x 96.
// Thumbnail size 64x64 => jpeg 5303 and takes ~7s; use this as default
// mConnection.setReplyTimeout(ProtocolProviderServiceJabberImpl.SMACK_REPLY_EXTENDED_TIMEOUT_20);
thumbnail = bobManager.requestBoB(remoteJid, cid).getContent();
} catch (SmackException.NotLoggedInException
| SmackException.NoResponseException
| XMPPException.XMPPErrorException
| NotConnectedException
| InterruptedException e) {
Timber.e("Error in requesting for thumbnail: %s", e.getMessage());
} finally {
// mConnection.setReplyTimeout(ProtocolProviderServiceJabberImpl.SMACK_DEFAULT_REPLY_TIMEOUT);
if (mCallback != null)
mCallback.showThumbnail(thumbnail);
}
});
}
}
Loading

0 comments on commit c689bd1

Please sign in to comment.