get rid of OTR

Daniel Gultsch created

Change summary

build.gradle                                                             |   1 
src/main/AndroidManifest.xml                                             |   4 
src/main/java/eu/siacs/conversations/crypto/OtrService.java              | 310 
src/main/java/eu/siacs/conversations/entities/Account.java               |  37 
src/main/java/eu/siacs/conversations/entities/Conversation.java          | 133 
src/main/java/eu/siacs/conversations/entities/Transferable.java          |   2 
src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java    |   3 
src/main/java/eu/siacs/conversations/generator/MessageGenerator.java     |  40 
src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java    |   4 
src/main/java/eu/siacs/conversations/parser/MessageParser.java           | 118 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 139 
src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java      |  28 
src/main/java/eu/siacs/conversations/ui/ConversationActivity.java        |  57 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java        |  48 
src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java         |  27 
src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java           |   3 
src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java           | 443 
src/main/java/eu/siacs/conversations/ui/XmppActivity.java                |  14 
src/main/java/eu/siacs/conversations/utils/UIHelper.java                 |   2 
src/main/java/eu/siacs/conversations/utils/XmppUri.java                  |   8 
src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java                   |  10 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java   |  31 
src/main/res/layout/activity_edit_account.xml                            |  46 
src/main/res/menu/conversations.xml                                      |   3 
24 files changed, 15 insertions(+), 1,496 deletions(-)

Detailed changes

build.gradle πŸ”—

@@ -45,7 +45,6 @@ dependencies {
     implementation "com.android.support:design:$supportLibVersion"
     freeImplementation "com.android.support:support-emoji-bundled:$supportLibVersion"
     implementation 'org.bouncycastle:bcmail-jdk15on:1.58'
-    implementation 'org.jitsi:org.otr4j:0.22'
     implementation 'org.gnu.inet:libidn:1.15'
     implementation 'com.google.zxing:core:3.3.0'
     implementation 'de.measite.minidns:minidns-hla:0.2.4'

src/main/AndroidManifest.xml πŸ”—

@@ -141,10 +141,6 @@
             android:name=".ui.PublishProfilePictureActivity"
             android:label="@string/mgmt_account_publish_avatar"
             android:windowSoftInputMode="stateHidden" />
-        <activity
-            android:name=".ui.VerifyOTRActivity"
-            android:label="@string/verify_otr"
-            android:windowSoftInputMode="stateHidden" />
         <activity
             android:name=".ui.ShareWithActivity"
             android:label="@string/app_name"

src/main/java/eu/siacs/conversations/crypto/OtrService.java πŸ”—

@@ -1,310 +0,0 @@
-package eu.siacs.conversations.crypto;
-
-import android.util.Log;
-
-import net.java.otr4j.OtrEngineHost;
-import net.java.otr4j.OtrException;
-import net.java.otr4j.OtrPolicy;
-import net.java.otr4j.OtrPolicyImpl;
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.crypto.OtrCryptoException;
-import net.java.otr4j.session.FragmenterInstructions;
-import net.java.otr4j.session.InstanceTag;
-import net.java.otr4j.session.SessionID;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.generator.MessageGenerator;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.xmpp.chatstate.ChatState;
-import eu.siacs.conversations.xmpp.jid.InvalidJidException;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
-
-public class OtrService extends OtrCryptoEngineImpl implements OtrEngineHost {
-
-	private Account account;
-	private OtrPolicy otrPolicy;
-	private KeyPair keyPair;
-	private XmppConnectionService mXmppConnectionService;
-
-	public OtrService(XmppConnectionService service, Account account) {
-		this.account = account;
-		this.otrPolicy = new OtrPolicyImpl();
-		this.otrPolicy.setAllowV1(false);
-		this.otrPolicy.setAllowV2(true);
-		this.otrPolicy.setAllowV3(true);
-		this.keyPair = loadKey(account.getKeys());
-		this.mXmppConnectionService = service;
-	}
-
-	private KeyPair loadKey(final JSONObject keys) {
-		if (keys == null) {
-			return null;
-		}
-		synchronized (keys) {
-			try {
-				BigInteger x = new BigInteger(keys.getString("otr_x"), 16);
-				BigInteger y = new BigInteger(keys.getString("otr_y"), 16);
-				BigInteger p = new BigInteger(keys.getString("otr_p"), 16);
-				BigInteger q = new BigInteger(keys.getString("otr_q"), 16);
-				BigInteger g = new BigInteger(keys.getString("otr_g"), 16);
-				KeyFactory keyFactory = KeyFactory.getInstance("DSA");
-				DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, p, q, g);
-				DSAPrivateKeySpec privateKeySpec = new DSAPrivateKeySpec(x, p, q, g);
-				PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
-				PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
-				return new KeyPair(publicKey, privateKey);
-			} catch (JSONException e) {
-				return null;
-			} catch (NoSuchAlgorithmException e) {
-				return null;
-			} catch (InvalidKeySpecException e) {
-				return null;
-			}
-		}
-	}
-
-	private void saveKey() {
-		PublicKey publicKey = keyPair.getPublic();
-		PrivateKey privateKey = keyPair.getPrivate();
-		KeyFactory keyFactory;
-		try {
-			keyFactory = KeyFactory.getInstance("DSA");
-			DSAPrivateKeySpec privateKeySpec = keyFactory.getKeySpec(
-					privateKey, DSAPrivateKeySpec.class);
-			DSAPublicKeySpec publicKeySpec = keyFactory.getKeySpec(publicKey,
-					DSAPublicKeySpec.class);
-			this.account.setKey("otr_x", privateKeySpec.getX().toString(16));
-			this.account.setKey("otr_g", privateKeySpec.getG().toString(16));
-			this.account.setKey("otr_p", privateKeySpec.getP().toString(16));
-			this.account.setKey("otr_q", privateKeySpec.getQ().toString(16));
-			this.account.setKey("otr_y", publicKeySpec.getY().toString(16));
-		} catch (final NoSuchAlgorithmException | InvalidKeySpecException e) {
-			e.printStackTrace();
-		}
-
-    }
-
-	@Override
-	public void askForSecret(SessionID id, InstanceTag instanceTag, String question) {
-		try {
-			final Jid jid = Jid.fromSessionID(id);
-			Conversation conversation = this.mXmppConnectionService.find(this.account,jid);
-			if (conversation!=null) {
-				conversation.smp().hint = question;
-				conversation.smp().status = Conversation.Smp.STATUS_CONTACT_REQUESTED;
-				mXmppConnectionService.updateConversationUi();
-			}
-		} catch (InvalidJidException e) {
-			Log.d(Config.LOGTAG,account.getJid().toBareJid()+": smp in invalid session "+id.toString());
-		}
-	}
-
-	@Override
-	public void finishedSessionMessage(SessionID arg0, String arg1)
-			throws OtrException {
-
-	}
-
-	@Override
-	public String getFallbackMessage(SessionID arg0) {
-		return MessageGenerator.OTR_FALLBACK_MESSAGE;
-	}
-
-	@Override
-	public byte[] getLocalFingerprintRaw(SessionID arg0) {
-		try {
-			return getFingerprintRaw(getPublicKey());
-		} catch (OtrCryptoException e) {
-			return null;
-		}
-	}
-
-	public PublicKey getPublicKey() {
-		if (this.keyPair == null) {
-			return null;
-		}
-		return this.keyPair.getPublic();
-	}
-
-	@Override
-	public KeyPair getLocalKeyPair(SessionID arg0) throws OtrException {
-		if (this.keyPair == null) {
-			KeyPairGenerator kg;
-			try {
-				kg = KeyPairGenerator.getInstance("DSA");
-				this.keyPair = kg.genKeyPair();
-				this.saveKey();
-				mXmppConnectionService.databaseBackend.updateAccount(account);
-			} catch (NoSuchAlgorithmException e) {
-				Log.d(Config.LOGTAG,
-						"error generating key pair " + e.getMessage());
-			}
-		}
-		return this.keyPair;
-	}
-
-	@Override
-	public String getReplyForUnreadableMessage(SessionID arg0) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public OtrPolicy getSessionPolicy(SessionID arg0) {
-		return otrPolicy;
-	}
-
-	@Override
-	public void injectMessage(SessionID session, String body)
-			throws OtrException {
-		MessagePacket packet = new MessagePacket();
-		packet.setFrom(account.getJid());
-		if (session.getUserID().isEmpty()) {
-			packet.setAttribute("to", session.getAccountID());
-		} else {
-			packet.setAttribute("to", session.getAccountID() + "/" + session.getUserID());
-		}
-		packet.setBody(body);
-		MessageGenerator.addMessageHints(packet);
-		try {
-			Jid jid = Jid.fromSessionID(session);
-			Conversation conversation = mXmppConnectionService.find(account,jid);
-			if (conversation != null && conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) {
-				if (mXmppConnectionService.sendChatStates()) {
-					packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
-				}
-			}
-		} catch (final InvalidJidException ignored) {
-
-		}
-		packet.setType(MessagePacket.TYPE_CHAT);
-		packet.addChild("encryption","urn:xmpp:eme:0")
-				.setAttribute("namespace","urn:xmpp:otr:0");
-		account.getXmppConnection().sendMessagePacket(packet);
-	}
-
-	@Override
-	public void messageFromAnotherInstanceReceived(SessionID session) {
-		sendOtrErrorMessage(session, "Message from another OTR-instance received");
-	}
-
-	@Override
-	public void multipleInstancesDetected(SessionID arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public void requireEncryptedMessage(SessionID arg0, String arg1)
-			throws OtrException {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public void showError(SessionID arg0, String arg1) throws OtrException {
-		Log.d(Config.LOGTAG,"show error");
-	}
-
-	@Override
-	public void smpAborted(SessionID id) throws OtrException {
-		setSmpStatus(id, Conversation.Smp.STATUS_NONE);
-	}
-
-	private void setSmpStatus(SessionID id, int status) {
-		try {
-			final Jid jid = Jid.fromSessionID(id);
-			Conversation conversation = this.mXmppConnectionService.find(this.account,jid);
-			if (conversation!=null) {
-				conversation.smp().status = status;
-				mXmppConnectionService.updateConversationUi();
-			}
-		} catch (final InvalidJidException ignored) {
-
-		}
-	}
-
-	@Override
-	public void smpError(SessionID id, int arg1, boolean arg2)
-			throws OtrException {
-		setSmpStatus(id, Conversation.Smp.STATUS_NONE);
-	}
-
-	@Override
-	public void unencryptedMessageReceived(SessionID arg0, String arg1)
-			throws OtrException {
-		throw new OtrException(new Exception("unencrypted message received"));
-	}
-
-	@Override
-	public void unreadableMessageReceived(SessionID session) throws OtrException {
-		Log.d(Config.LOGTAG,"unreadable message received");
-		sendOtrErrorMessage(session, "You sent me an unreadable OTR-encrypted message");
-	}
-
-	public void sendOtrErrorMessage(SessionID session, String errorText) {
-		try {
-			Jid jid = Jid.fromSessionID(session);
-			Conversation conversation = mXmppConnectionService.find(account, jid);
-			String id = conversation == null ? null : conversation.getLastReceivedOtrMessageId();
-			if (id != null) {
-				MessagePacket packet = mXmppConnectionService.getMessageGenerator()
-						.generateOtrError(jid, id, errorText);
-				packet.setFrom(account.getJid());
-				mXmppConnectionService.sendMessagePacket(account,packet);
-				Log.d(Config.LOGTAG,packet.toString());
-				Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()
-						+": unreadable OTR message in "+conversation.getName());
-			}
-		} catch (InvalidJidException e) {
-			return;
-		}
-	}
-
-	@Override
-	public void unverify(SessionID id, String arg1) {
-		setSmpStatus(id, Conversation.Smp.STATUS_FAILED);
-	}
-
-	@Override
-	public void verify(SessionID id, String fingerprint, boolean approved) {
-		Log.d(Config.LOGTAG,"OtrService.verify("+id.toString()+","+fingerprint+","+String.valueOf(approved)+")");
-		try {
-			final Jid jid = Jid.fromSessionID(id);
-			Conversation conversation = this.mXmppConnectionService.find(this.account,jid);
-			if (conversation!=null) {
-				if (approved) {
-					conversation.getContact().addOtrFingerprint(fingerprint);
-				}
-				conversation.smp().hint = null;
-				conversation.smp().status = Conversation.Smp.STATUS_VERIFIED;
-				mXmppConnectionService.updateConversationUi();
-				mXmppConnectionService.syncRosterToDisk(conversation.getAccount());
-			}
-		} catch (final InvalidJidException ignored) {
-		}
-	}
-
-	@Override
-	public FragmenterInstructions getFragmenterInstructions(SessionID sessionID) {
-		return null;
-	}
-
-}

src/main/java/eu/siacs/conversations/entities/Account.java πŸ”—

@@ -7,24 +7,17 @@ import android.util.Pair;
 
 import eu.siacs.conversations.crypto.PgpDecryptionService;
 
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.crypto.OtrCryptoException;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import java.security.PublicKey;
-import java.security.interfaces.DSAPublicKey;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 
 import eu.siacs.conversations.R;
-import eu.siacs.conversations.crypto.OtrService;
 import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
 import eu.siacs.conversations.services.XmppConnectionService;
@@ -241,7 +234,6 @@ public class Account extends AbstractEntity {
 	protected String hostname = null;
 	protected int port = 5222;
 	protected boolean online = false;
-	private OtrService mOtrService = null;
 	private AxolotlService axolotlService = null;
 	private PgpDecryptionService pgpDecryptionService = null;
 	private XmppConnection xmppConnection = null;
@@ -499,7 +491,6 @@ public class Account extends AbstractEntity {
 	}
 
 	public void initAccountServices(final XmppConnectionService context) {
-		this.mOtrService = new OtrService(context, this);
 		this.axolotlService = new AxolotlService(this, context);
 		this.pgpDecryptionService = new PgpDecryptionService(context);
 		if (xmppConnection != null) {
@@ -507,10 +498,6 @@ public class Account extends AbstractEntity {
 		}
 	}
 
-	public OtrService getOtrService() {
-		return this.mOtrService;
-	}
-
 	public PgpDecryptionService getPgpDecryptionService() {
 		return this.pgpDecryptionService;
 	}
@@ -523,26 +510,6 @@ public class Account extends AbstractEntity {
 		this.xmppConnection = connection;
 	}
 
-	public String getOtrFingerprint() {
-		if (this.otrFingerprint == null) {
-			try {
-				if (this.mOtrService == null) {
-					return null;
-				}
-				final PublicKey publicKey = this.mOtrService.getPublicKey();
-				if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
-					return null;
-				}
-				this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey).toLowerCase(Locale.US);
-				return this.otrFingerprint;
-			} catch (final OtrCryptoException ignored) {
-				return null;
-			}
-		} else {
-			return this.otrFingerprint;
-		}
-	}
-
 	public String getRosterVersion() {
 		if (this.rosterVersion == null) {
 			return "";
@@ -674,10 +641,6 @@ public class Account extends AbstractEntity {
 
 	private List<XmppUri.Fingerprint> getFingerprints() {
 		ArrayList<XmppUri.Fingerprint> fingerprints = new ArrayList<>();
-		final String otr = this.getOtrFingerprint();
-		if (otr != null) {
-			fingerprints.add(new XmppUri.Fingerprint(XmppUri.FingerprintType.OTR,otr));
-		}
 		if (axolotlService == null) {
 			return fingerprints;
 		}

src/main/java/eu/siacs/conversations/entities/Conversation.java πŸ”—

@@ -4,17 +4,10 @@ import android.content.ContentValues;
 import android.database.Cursor;
 import android.support.annotation.NonNull;
 
-import net.java.otr4j.OtrException;
-import net.java.otr4j.crypto.OtrCryptoException;
-import net.java.otr4j.session.SessionID;
-import net.java.otr4j.session.SessionImpl;
-import net.java.otr4j.session.SessionStatus;
-
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import java.security.interfaces.DSAPublicKey;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -77,11 +70,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	protected final ArrayList<Message> messages = new ArrayList<>();
 	protected Account account = null;
 
-	private transient SessionImpl otrSession;
-
-	private transient String otrFingerprint = null;
-	private Smp mSmp = new Smp();
-
 	private transient MucOptions mucOptions = null;
 
 	private byte[] symmetricKey;
@@ -89,7 +77,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	private boolean messagesLeftOnServer = true;
 	private ChatState mOutgoingChatState = Config.DEFAULT_CHATSTATE;
 	private ChatState mIncomingChatState = Config.DEFAULT_CHATSTATE;
-	private String mLastReceivedOtrMessageId = null;
 	private String mFirstMamReference = null;
 	private Message correctingMessage;
 	public AtomicBoolean messagesLoaded = new AtomicBoolean(true);
@@ -335,14 +322,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		return getContact().getBlockedJid();
 	}
 
-	public String getLastReceivedOtrMessageId() {
-		return this.mLastReceivedOtrMessageId;
-	}
-
-	public void setLastReceivedOtrMessageId(String id) {
-		this.mLastReceivedOtrMessageId = id;
-	}
-
 	public int countMessages() {
 		synchronized (this.messages) {
 			return this.messages.size();
@@ -587,110 +566,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		this.mode = mode;
 	}
 
-	public SessionImpl startOtrSession(String presence, boolean sendStart) {
-		if (this.otrSession != null) {
-			return this.otrSession;
-		} else {
-			final SessionID sessionId = new SessionID(this.getJid().toBareJid().toString(),
-					presence,
-					"xmpp");
-			this.otrSession = new SessionImpl(sessionId, getAccount().getOtrService());
-			try {
-				if (sendStart) {
-					this.otrSession.startSession();
-					return this.otrSession;
-				}
-				return this.otrSession;
-			} catch (OtrException e) {
-				return null;
-			}
-		}
-
-	}
-
-	public SessionImpl getOtrSession() {
-		return this.otrSession;
-	}
-
-	public void resetOtrSession() {
-		this.otrFingerprint = null;
-		this.otrSession = null;
-		this.mSmp.hint = null;
-		this.mSmp.secret = null;
-		this.mSmp.status = Smp.STATUS_NONE;
-	}
-
-	public Smp smp() {
-		return mSmp;
-	}
-
-	public boolean startOtrIfNeeded() {
-		if (this.otrSession != null && this.otrSession.getSessionStatus() != SessionStatus.ENCRYPTED) {
-			try {
-				this.otrSession.startSession();
-				return true;
-			} catch (OtrException e) {
-				this.resetOtrSession();
-				return false;
-			}
-		} else {
-			return true;
-		}
-	}
-
-	public boolean endOtrIfNeeded() {
-		if (this.otrSession != null) {
-			if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) {
-				try {
-					this.otrSession.endSession();
-					this.resetOtrSession();
-					return true;
-				} catch (OtrException e) {
-					this.resetOtrSession();
-					return false;
-				}
-			} else {
-				this.resetOtrSession();
-				return false;
-			}
-		} else {
-			return false;
-		}
-	}
-
-	public boolean hasValidOtrSession() {
-		return this.otrSession != null;
-	}
-
-	public synchronized String getOtrFingerprint() {
-		if (this.otrFingerprint == null) {
-			try {
-				if (getOtrSession() == null || getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
-					return null;
-				}
-				DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession().getRemotePublicKey();
-				this.otrFingerprint = getAccount().getOtrService().getFingerprint(remotePubKey).toLowerCase(Locale.US);
-			} catch (final OtrCryptoException | UnsupportedOperationException ignored) {
-				return null;
-			}
-		}
-		return this.otrFingerprint;
-	}
-
-	public boolean verifyOtrFingerprint() {
-		final String fingerprint = getOtrFingerprint();
-		if (fingerprint != null) {
-			getContact().addOtrFingerprint(fingerprint);
-			return true;
-		} else {
-			return false;
-		}
-	}
-
-	public boolean isOtrFingerprintVerified() {
-		return getContact().getOtrFingerprints().contains(getOtrFingerprint());
-	}
-
 	/**
 	 * short for is Private and Non-anonymous
 	 */
@@ -735,8 +610,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 				return Config.supportUnencrypted() ? selectedEncryption : getDefaultEncryption();
 			case Message.ENCRYPTION_AXOLOTL:
 				return Config.supportOmemo() ? selectedEncryption : getDefaultEncryption();
-			case Message.ENCRYPTION_OTR:
-				return Config.supportOtr() ? selectedEncryption : getDefaultEncryption();
 			case Message.ENCRYPTION_PGP:
 			case Message.ENCRYPTION_DECRYPTED:
 			case Message.ENCRYPTION_DECRYPTION_FAILED:
@@ -753,8 +626,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		} else if (Config.supportOmemo()
 				&& (axolotlService != null && axolotlService.isConversationAxolotlCapable(this) || !Config.multipleEncryptionChoices())) {
 			return Message.ENCRYPTION_AXOLOTL;
-		} else if (Config.supportOtr() && mode == MODE_SINGLE) {
-			return Message.ENCRYPTION_OTR;
 		} else if (Config.supportOpenPgp()) {
 			return Message.ENCRYPTION_PGP;
 		} else {
@@ -771,10 +642,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		return nextMessage == null ? "" : nextMessage;
 	}
 
-	public boolean smpRequested() {
-		return smp().status == Smp.STATUS_CONTACT_REQUESTED;
-	}
-
 	public boolean setNextMessage(String message) {
 		boolean changed = !getNextMessage().equals(message);
 		this.setAttribute(ATTRIBUTE_NEXT_MESSAGE, message);

src/main/java/eu/siacs/conversations/entities/Transferable.java πŸ”—

@@ -6,7 +6,7 @@ import java.util.List;
 public interface Transferable {
 
 	List<String> VALID_IMAGE_EXTENSIONS = Arrays.asList("webp", "jpeg", "jpg", "png", "jpe");
-	List<String> VALID_CRYPTO_EXTENSIONS = Arrays.asList("pgp", "gpg", "otr");
+	List<String> VALID_CRYPTO_EXTENSIONS = Arrays.asList("pgp", "gpg");
 	List<String> WELL_KNOWN_EXTENSIONS = Arrays.asList("pdf","m4a","mp4","3gp","aac","amr","mp3");
 
 	int STATUS_UNKNOWN = 0x200;

src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java πŸ”—

@@ -118,9 +118,6 @@ public abstract class AbstractGenerator {
 		if (!mXmppConnectionService.useTorToConnect()) {
 			features.addAll(Arrays.asList(PRIVACY_SENSITIVE));
 		}
-		if (Config.supportOtr()) {
-			features.addAll(Arrays.asList(OTR));
-		}
 		if (mXmppConnectionService.broadcastLastActivity()) {
 			features.add(Namespace.IDLE);
 		}

src/main/java/eu/siacs/conversations/generator/MessageGenerator.java πŸ”—

@@ -1,8 +1,5 @@
 package eu.siacs.conversations.generator;
 
-import net.java.otr4j.OtrException;
-import net.java.otr4j.session.Session;
-
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -24,7 +21,6 @@ import eu.siacs.conversations.xmpp.jid.Jid;
 import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 
 public class MessageGenerator extends AbstractGenerator {
-	public static final String OTR_FALLBACK_MESSAGE = "I would like to start a private (OTR encrypted) conversation but your client doesn’t seem to support that";
 	private static final String OMEMO_FALLBACK_MESSAGE = "I sent you an OMEMO encrypted message but your client doesn’t seem to support that. Find more information on https://conversations.im/omemo";
 	private static final String PGP_FALLBACK_MESSAGE = "I sent you a PGP encrypted message but your client doesn’t seem to support that.";
 
@@ -112,29 +108,6 @@ public class MessageGenerator extends AbstractGenerator {
 		packet.addChild("no-permanent-storage", "urn:xmpp:hints"); //do not copy this. this is wrong. it is *store*
 	}
 
-	public MessagePacket generateOtrChat(Message message) {
-		Session otrSession = message.getConversation().getOtrSession();
-		if (otrSession == null) {
-			return null;
-		}
-		MessagePacket packet = preparePacket(message);
-		addMessageHints(packet);
-		try {
-			String content;
-			if (message.hasFileOnRemoteHost()) {
-				content = message.getFileParams().url.toString();
-			} else {
-				content = message.getBody();
-			}
-			packet.setBody(otrSession.transformSending(content)[0]);
-			packet.addChild("encryption","urn:xmpp:eme:0")
-					.setAttribute("namespace","urn:xmpp:otr:0");
-			return packet;
-		} catch (OtrException e) {
-			return null;
-		}
-	}
-
 	public MessagePacket generateChat(Message message) {
 		MessagePacket packet = preparePacket(message);
 		String content;
@@ -254,17 +227,4 @@ public class MessageGenerator extends AbstractGenerator {
 		packet.addChild("store", "urn:xmpp:hints");
 		return packet;
 	}
-
-	public MessagePacket generateOtrError(Jid to, String id, String errorText) {
-		MessagePacket packet = new MessagePacket();
-		packet.setType(MessagePacket.TYPE_ERROR);
-		packet.setAttribute("id",id);
-		packet.setTo(to);
-		Element error = packet.addChild("error");
-		error.setAttribute("code","406");
-		error.setAttribute("type","modify");
-		error.addChild("not-acceptable","urn:ietf:params:xml:ns:xmpp-stanzas");
-		error.addChild("text").setContent("?OTR Error:" + errorText);
-		return packet;
-	}
 }

src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java πŸ”—

@@ -96,9 +96,7 @@ public class HttpDownloadConnection implements Transferable {
 				this.file.setKeyAndIv(CryptoHelper.hexToBytes(reference));
 			}
 
-			if ((this.message.getEncryption() == Message.ENCRYPTION_OTR
-					|| this.message.getEncryption() == Message.ENCRYPTION_AXOLOTL)
-					&& this.file.getKey() == null) {
+			if (this.message.getEncryption() == Message.ENCRYPTION_AXOLOTL && this.file.getKey() == null) {
 				this.message.setEncryption(Message.ENCRYPTION_NONE);
 			}
 			checkFileSize(interactive);

src/main/java/eu/siacs/conversations/parser/MessageParser.java πŸ”—

@@ -1,13 +1,8 @@
 package eu.siacs.conversations.parser;
 
-import android.os.Build;
-import android.text.Html;
 import android.util.Log;
 import android.util.Pair;
 
-import net.java.otr4j.session.Session;
-import net.java.otr4j.session.SessionStatus;
-
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -19,7 +14,6 @@ import java.util.UUID;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
-import eu.siacs.conversations.crypto.OtrService;
 import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
 import eu.siacs.conversations.entities.Account;
@@ -28,10 +22,8 @@ import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
 import eu.siacs.conversations.entities.MucOptions;
-import eu.siacs.conversations.entities.Presence;
 import eu.siacs.conversations.entities.ReadByMarker;
 import eu.siacs.conversations.entities.ReceiptRequest;
-import eu.siacs.conversations.entities.ServiceDiscoveryResult;
 import eu.siacs.conversations.http.HttpConnectionManager;
 import eu.siacs.conversations.services.MessageArchiveService;
 import eu.siacs.conversations.services.XmppConnectionService;
@@ -46,8 +38,6 @@ import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 
 public class MessageParser extends AbstractParser implements OnMessagePacketReceived {
 
-	private static final List<String> CLIENTS_SENDING_HTML_IN_OTR = Arrays.asList("Pidgin", "Adium", "Trillian");
-
 	public MessageParser(XmppConnectionService service) {
 		super(service);
 	}
@@ -80,90 +70,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 		return false;
 	}
 
-	private Message parseOtrChat(String body, Jid from, String id, Conversation conversation) {
-		String presence;
-		if (from.isBareJid()) {
-			presence = "";
-		} else {
-			presence = from.getResourcepart();
-		}
-		if (body.matches("^\\?OTRv\\d{1,2}\\?.*")) {
-			conversation.endOtrIfNeeded();
-		}
-		if (!conversation.hasValidOtrSession()) {
-			conversation.startOtrSession(presence, false);
-		} else {
-			String foreignPresence = conversation.getOtrSession().getSessionID().getUserID();
-			if (!foreignPresence.equals(presence)) {
-				conversation.endOtrIfNeeded();
-				conversation.startOtrSession(presence, false);
-			}
-		}
-		try {
-			conversation.setLastReceivedOtrMessageId(id);
-			Session otrSession = conversation.getOtrSession();
-			body = otrSession.transformReceiving(body);
-			SessionStatus status = otrSession.getSessionStatus();
-			if (body == null && status == SessionStatus.ENCRYPTED) {
-				mXmppConnectionService.onOtrSessionEstablished(conversation);
-				return null;
-			} else if (body == null && status == SessionStatus.FINISHED) {
-				conversation.resetOtrSession();
-				mXmppConnectionService.updateConversationUi();
-				return null;
-			} else if (body == null || (body.isEmpty())) {
-				return null;
-			}
-			if (body.startsWith(CryptoHelper.FILETRANSFER)) {
-				String key = body.substring(CryptoHelper.FILETRANSFER.length());
-				conversation.setSymmetricKey(CryptoHelper.hexToBytes(key));
-				return null;
-			}
-			if (clientMightSendHtml(conversation.getAccount(), from)) {
-				Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": received OTR message from bad behaving client. escaping HTML…");
-				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-					body = Html.fromHtml(body, Html.FROM_HTML_MODE_LEGACY).toString();
-				} else {
-					body = Html.fromHtml(body).toString();
-				}
-			}
-
-			final OtrService otrService = conversation.getAccount().getOtrService();
-			Message finishedMessage = new Message(conversation, body, Message.ENCRYPTION_OTR, Message.STATUS_RECEIVED);
-			finishedMessage.setFingerprint(otrService.getFingerprint(otrSession.getRemotePublicKey()));
-			conversation.setLastReceivedOtrMessageId(null);
-
-			return finishedMessage;
-		} catch (Exception e) {
-			conversation.resetOtrSession();
-			return null;
-		}
-	}
-
-	private static boolean clientMightSendHtml(Account account, Jid from) {
-		String resource = from.getResourcepart();
-		if (resource == null) {
-			return false;
-		}
-		Presence presence = account.getRoster().getContact(from).getPresences().getPresences().get(resource);
-		ServiceDiscoveryResult disco = presence == null ? null : presence.getServiceDiscoveryResult();
-		if (disco == null) {
-			return false;
-		}
-		return hasIdentityKnowForSendingHtml(disco.getIdentities());
-	}
-
-	private static boolean hasIdentityKnowForSendingHtml(List<ServiceDiscoveryResult.Identity> identities) {
-		for (ServiceDiscoveryResult.Identity identity : identities) {
-			if (identity.getName() != null) {
-				if (CLIENTS_SENDING_HTML_IN_OTR.contains(identity.getName())) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
 	private Message parseAxolotlChat(Element axolotlMessage, Jid from, Conversation conversation, int status, boolean postpone) {
 		final AxolotlService service = conversation.getAccount().getAxolotlService();
 		final XmppAxolotlMessage xmppAxolotlMessage;
@@ -316,11 +222,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 						packet.getId(),
 						Message.STATUS_SEND_FAILED,
 						extractErrorMessage(packet));
-				if (message != null) {
-					if (message.getEncryption() == Message.ENCRYPTION_OTR) {
-						message.getConversation().endOtrIfNeeded();
-					}
-				}
 			}
 			return true;
 		}
@@ -467,17 +368,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 				}
 			}
 			final Message message;
-			if (body != null && body.startsWith("?OTR") && Config.supportOtr()) {
-				if (!isForwarded && !isTypeGroupChat && isProperlyAddressed && !conversationMultiMode) {
-					message = parseOtrChat(body, from, remoteMsgId, conversation);
-					if (message == null) {
-						return;
-					}
-				} else {
-					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ignoring OTR message from " + from + " isForwarded=" + Boolean.toString(isForwarded) + ", isProperlyAddressed=" + Boolean.valueOf(isProperlyAddressed));
-					message = new Message(conversation, body, Message.ENCRYPTION_NONE, status);
-				}
-			} else if (pgpEncrypted != null && Config.supportOpenPgp()) {
+			if (pgpEncrypted != null && Config.supportOpenPgp()) {
 				message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status);
 			} else if (axolotlEncrypted != null && Config.supportOmemo()) {
 				Jid origin;
@@ -669,13 +560,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 				processMessageReceipts(account, packet, query);
 			}
 
-			if (message.getStatus() == Message.STATUS_RECEIVED
-					&& conversation.getOtrSession() != null
-					&& !conversation.getOtrSession().getSessionID().getUserID()
-					.equals(message.getCounterpart().getResourcepart())) {
-				conversation.endOtrIfNeeded();
-			}
-
 			mXmppConnectionService.databaseBackend.createMessage(message);
 			final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager();
 			if (message.trusted() && message.treatAsDownloadable() && manager.getAutoAcceptFileSize() > 0) {

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java πŸ”—

@@ -34,12 +34,6 @@ import android.util.Log;
 import android.util.LruCache;
 import android.util.Pair;
 
-import net.java.otr4j.OtrException;
-import net.java.otr4j.session.Session;
-import net.java.otr4j.session.SessionID;
-import net.java.otr4j.session.SessionImpl;
-import net.java.otr4j.session.SessionStatus;
-
 import org.openintents.openpgp.IOpenPgpService2;
 import org.openintents.openpgp.util.OpenPgpApi;
 import org.openintents.openpgp.util.OpenPgpServiceConnection;
@@ -214,18 +208,9 @@ public class XmppConnectionService extends Service {
 			Conversation conversation = find(getConversations(), contact);
 			if (conversation != null) {
 				if (online) {
-					conversation.endOtrIfNeeded();
 					if (contact.getPresences().size() == 1) {
 						sendUnsentMessages(conversation);
 					}
-				} else {
-					//check if the resource we are haveing a conversation with is still online
-					if (conversation.hasValidOtrSession()) {
-						String otrResource = conversation.getOtrSession().getSessionID().getUserID();
-						if (!(Arrays.asList(contact.getPresences().toResourceArray()).contains(otrResource))) {
-							conversation.endOtrIfNeeded();
-						}
-					}
 				}
 			}
 		}
@@ -351,11 +336,7 @@ public class XmppConnectionService extends Service {
 				}
 				List<Conversation> conversations = getConversations();
 				for (Conversation conversation : conversations) {
-					if (conversation.getAccount() == account
-							&& !account.pendingConferenceJoins.contains(conversation)) {
-						if (!conversation.startOtrIfNeeded()) {
-							Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": couldn't start OTR with " + conversation.getContact().getJid() + " when needed");
-						}
+					if (conversation.getAccount() == account && !account.pendingConferenceJoins.contains(conversation)) {
 						sendUnsentMessages(conversation);
 					}
 				}
@@ -1209,17 +1190,6 @@ public class XmppConnectionService extends Service {
 		boolean saveInDb = addToConversation;
 		message.setStatus(Message.STATUS_WAITING);
 
-		if (!resend && message.getEncryption() != Message.ENCRYPTION_OTR) {
-			message.getConversation().endOtrIfNeeded();
-			message.getConversation().findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR,
-					new Conversation.OnMessageFound() {
-						@Override
-						public void onMessageFound(Message message) {
-							markMessage(message, Message.STATUS_SEND_FAILED);
-						}
-					});
-		}
-
 		if (account.isOnlineAndConnected()) {
 			switch (message.getEncryption()) {
 				case Message.ENCRYPTION_NONE:
@@ -1249,30 +1219,6 @@ public class XmppConnectionService extends Service {
 						packet = mMessageGenerator.generatePgpChat(message);
 					}
 					break;
-				case Message.ENCRYPTION_OTR:
-					SessionImpl otrSession = conversation.getOtrSession();
-					if (otrSession != null && otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) {
-						try {
-							message.setCounterpart(Jid.fromSessionID(otrSession.getSessionID()));
-						} catch (InvalidJidException e) {
-							break;
-						}
-						if (message.needsUploading()) {
-							mJingleConnectionManager.createNewConnection(message);
-						} else {
-							packet = mMessageGenerator.generateOtrChat(message);
-						}
-					} else if (otrSession == null) {
-						if (message.fixCounterpart()) {
-							conversation.startOtrSession(message.getCounterpart().getResourcepart(), true);
-						} else {
-							Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fix counterpart for OTR message to contact " + message.getCounterpart());
-							break;
-						}
-					} else {
-						Log.d(Config.LOGTAG, account.getJid().toBareJid() + " OTR session with " + message.getContact() + " is in wrong state: " + otrSession.getSessionStatus().toString());
-					}
-					break;
 				case Message.ENCRYPTION_AXOLOTL:
 					message.setFingerprint(account.getAxolotlService().getOwnFingerprint());
 					if (message.needsUploading()) {
@@ -1324,12 +1270,6 @@ public class XmppConnectionService extends Service {
 						}
 					}
 					break;
-				case Message.ENCRYPTION_OTR:
-					if (!conversation.hasValidOtrSession() && message.getCounterpart() != null) {
-						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": create otr session without starting for " + message.getContact().getJid());
-						conversation.startOtrSession(message.getCounterpart().getResourcepart(), false);
-					}
-					break;
 				case Message.ENCRYPTION_AXOLOTL:
 					message.setFingerprint(account.getAxolotlService().getOwnFingerprint());
 					break;
@@ -1804,7 +1744,6 @@ public class XmppConnectionService extends Service {
 				}
 				leaveMuc(conversation);
 			} else {
-				conversation.endOtrIfNeeded();
 				if (conversation.getContact().getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
 					Log.d(Config.LOGTAG, "Canceling presence request from " + conversation.getJid().toString());
 					sendPresencePacket(
@@ -1941,8 +1880,6 @@ public class XmppConnectionService extends Service {
 				if (conversation.getAccount() == account) {
 					if (conversation.getMode() == Conversation.MODE_MULTI) {
 						leaveMuc(conversation);
-					} else if (conversation.getMode() == Conversation.MODE_SINGLE) {
-						conversation.endOtrIfNeeded();
 					}
 					conversations.remove(conversation);
 				}
@@ -2750,12 +2687,6 @@ public class XmppConnectionService extends Service {
 					if (conversation.getAccount() == account) {
 						if (conversation.getMode() == Conversation.MODE_MULTI) {
 							leaveMuc(conversation, true);
-						} else {
-							if (conversation.endOtrIfNeeded()) {
-								Log.d(Config.LOGTAG, account.getJid().toBareJid()
-										+ ": ended otr session with "
-										+ conversation.getJid());
-							}
 						}
 					}
 				}
@@ -2800,65 +2731,6 @@ public class XmppConnectionService extends Service {
 		pushContactToServer(contact);
 	}
 
-	public void onOtrSessionEstablished(Conversation conversation) {
-		final Account account = conversation.getAccount();
-		final Session otrSession = conversation.getOtrSession();
-		Log.d(Config.LOGTAG,
-				account.getJid().toBareJid() + " otr session established with "
-						+ conversation.getJid() + "/"
-						+ otrSession.getSessionID().getUserID());
-		conversation.findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR, new Conversation.OnMessageFound() {
-
-			@Override
-			public void onMessageFound(Message message) {
-				SessionID id = otrSession.getSessionID();
-				try {
-					message.setCounterpart(Jid.fromString(id.getAccountID() + "/" + id.getUserID()));
-				} catch (InvalidJidException e) {
-					return;
-				}
-				if (message.needsUploading()) {
-					mJingleConnectionManager.createNewConnection(message);
-				} else {
-					MessagePacket outPacket = mMessageGenerator.generateOtrChat(message);
-					if (outPacket != null) {
-						mMessageGenerator.addDelay(outPacket, message.getTimeSent());
-						message.setStatus(Message.STATUS_SEND);
-						databaseBackend.updateMessage(message);
-						sendMessagePacket(account, outPacket);
-					}
-				}
-				updateConversationUi();
-			}
-		});
-	}
-
-	public boolean renewSymmetricKey(Conversation conversation) {
-		Account account = conversation.getAccount();
-		byte[] symmetricKey = new byte[32];
-		this.mRandom.nextBytes(symmetricKey);
-		Session otrSession = conversation.getOtrSession();
-		if (otrSession != null) {
-			MessagePacket packet = new MessagePacket();
-			packet.setType(MessagePacket.TYPE_CHAT);
-			packet.setFrom(account.getJid());
-			MessageGenerator.addMessageHints(packet);
-			packet.setAttribute("to", otrSession.getSessionID().getAccountID() + "/"
-					+ otrSession.getSessionID().getUserID());
-			try {
-				packet.setBody(otrSession
-						.transformSending(CryptoHelper.FILETRANSFER
-								+ CryptoHelper.bytesToHex(symmetricKey))[0]);
-				sendMessagePacket(account, packet);
-				conversation.setSymmetricKey(symmetricKey);
-				return true;
-			} catch (OtrException e) {
-				return false;
-			}
-		}
-		return false;
-	}
-
 	public void pushContactToServer(final Contact contact) {
 		contact.resetOption(Contact.Options.DIRTY_DELETE);
 		contact.setOption(Contact.Options.DIRTY_PUSH);
@@ -3959,14 +3831,10 @@ public class XmppConnectionService extends Service {
 	}
 
 	public boolean verifyFingerprints(Contact contact, List<XmppUri.Fingerprint> fingerprints) {
-		boolean needsRosterWrite = false;
 		boolean performedVerification = false;
 		final AxolotlService axolotlService = contact.getAccount().getAxolotlService();
 		for (XmppUri.Fingerprint fp : fingerprints) {
-			if (fp.type == XmppUri.FingerprintType.OTR) {
-				performedVerification |= contact.addOtrFingerprint(fp.fingerprint);
-				needsRosterWrite |= performedVerification;
-			} else if (fp.type == XmppUri.FingerprintType.OMEMO) {
+			if (fp.type == XmppUri.FingerprintType.OMEMO) {
 				String fingerprint = "05" + fp.fingerprint.replaceAll("\\s", "");
 				FingerprintStatus fingerprintStatus = axolotlService.getFingerprintTrust(fingerprint);
 				if (fingerprintStatus != null) {
@@ -3979,9 +3847,6 @@ public class XmppConnectionService extends Service {
 				}
 			}
 		}
-		if (needsRosterWrite) {
-			syncRosterToDisk(contact.getAccount());
-		}
 		return performedVerification;
 	}
 

src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java πŸ”—

@@ -409,33 +409,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
 
 		binding.detailsContactKeys.removeAllViews();
 		boolean hasKeys = false;
-		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-		if (Config.supportOtr()) {
-			for (final String otrFingerprint : contact.getOtrFingerprints()) {
-				hasKeys = true;
-				View view = inflater.inflate(R.layout.contact_key, binding.detailsContactKeys, false);
-				TextView key = (TextView) view.findViewById(R.id.key);
-				TextView keyType = (TextView) view.findViewById(R.id.key_type);
-				ImageButton removeButton = (ImageButton) view
-						.findViewById(R.id.button_remove);
-				removeButton.setVisibility(View.VISIBLE);
-				key.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
-				if (otrFingerprint != null && otrFingerprint.equalsIgnoreCase(messageFingerprint)) {
-					keyType.setText(R.string.otr_fingerprint_selected_message);
-					keyType.setTextColor(ContextCompat.getColor(this, R.color.accent));
-				} else {
-					keyType.setText(R.string.otr_fingerprint);
-				}
-				binding.detailsContactKeys.addView(view);
-				removeButton.setOnClickListener(new OnClickListener() {
-
-					@Override
-					public void onClick(View v) {
-						confirmToDeleteFingerprint(otrFingerprint);
-					}
-				});
-			}
-		}
+		final LayoutInflater inflater = getLayoutInflater();
 		final AxolotlService axolotlService = contact.getAccount().getAxolotlService();
 		if (Config.supportOmemo() && axolotlService != null) {
 			boolean skippedInactive = false;

src/main/java/eu/siacs/conversations/ui/ConversationActivity.java πŸ”—

@@ -32,12 +32,8 @@ import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.CheckBox;
-import android.widget.PopupMenu;
-import android.widget.PopupMenu.OnMenuItemClickListener;
 import android.widget.Toast;
 
-import net.java.otr4j.session.SessionStatus;
-
 import org.openintents.openpgp.util.OpenPgpApi;
 
 import java.util.ArrayList;
@@ -454,17 +450,12 @@ public class ConversationActivity extends XmppActivity
 	}
 
 	private static void configureEncryptionMenu(Conversation conversation, Menu menu) {
-		MenuItem otr = menu.findItem(R.id.encryption_choice_otr);
 		MenuItem none = menu.findItem(R.id.encryption_choice_none);
 		MenuItem pgp = menu.findItem(R.id.encryption_choice_pgp);
 		MenuItem axolotl = menu.findItem(R.id.encryption_choice_axolotl);
 		pgp.setVisible(Config.supportOpenPgp());
 		none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI);
-		otr.setVisible(Config.supportOtr());
 		axolotl.setVisible(Config.supportOmemo());
-		if (conversation.getMode() == Conversation.MODE_MULTI) {
-			otr.setVisible(false);
-		}
 		if (!conversation.getAccount().getAxolotlService().isConversationAxolotlCapable(conversation)) {
 			axolotl.setEnabled(false);
 		}
@@ -472,9 +463,6 @@ public class ConversationActivity extends XmppActivity
 			case Message.ENCRYPTION_NONE:
 				none.setChecked(true);
 				break;
-			case Message.ENCRYPTION_OTR:
-				otr.setChecked(true);
-				break;
 			case Message.ENCRYPTION_PGP:
 				pgp.setChecked(true);
 				break;
@@ -542,7 +530,7 @@ public class ConversationActivity extends XmppActivity
 				startActivity(getInstallApkIntent(fallbackPackageId));
 			}
 		};
-		if ((account.httpUploadAvailable() || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) && encryption != Message.ENCRYPTION_OTR) {
+		if (account.httpUploadAvailable() || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) {
 			conversation.setNextCounterpart(null);
 			callback.onPresenceSelected();
 		} else {
@@ -699,7 +687,6 @@ public class ConversationActivity extends XmppActivity
 		} else if (getSelectedConversation() != null) {
 			switch (item.getItemId()) {
 				case R.id.encryption_choice_axolotl:
-				case R.id.encryption_choice_otr:
 				case R.id.encryption_choice_pgp:
 				case R.id.encryption_choice_none:
 					handleEncryptionSelection(item);
@@ -808,41 +795,6 @@ public class ConversationActivity extends XmppActivity
 		builder.create().show();
 	}
 
-	public void verifyOtrSessionDialog(final Conversation conversation, View view) {
-		if (!conversation.hasValidOtrSession() || conversation.getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
-			Toast.makeText(this, R.string.otr_session_not_started, Toast.LENGTH_LONG).show();
-			return;
-		}
-		if (view == null) {
-			return;
-		}
-		PopupMenu popup = new PopupMenu(this, view);
-		popup.inflate(R.menu.verification_choices);
-		popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
-			@Override
-			public boolean onMenuItemClick(MenuItem menuItem) {
-				Intent intent = new Intent(ConversationActivity.this, VerifyOTRActivity.class);
-				intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
-				intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
-				intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString());
-				switch (menuItem.getItemId()) {
-					case R.id.scan_fingerprint:
-						intent.putExtra("mode", VerifyOTRActivity.MODE_SCAN_FINGERPRINT);
-						break;
-					case R.id.ask_question:
-						intent.putExtra("mode", VerifyOTRActivity.MODE_ASK_QUESTION);
-						break;
-					case R.id.manual_verification:
-						intent.putExtra("mode", VerifyOTRActivity.MODE_MANUAL_VERIFICATION);
-						break;
-				}
-				startActivity(intent);
-				return true;
-			}
-		});
-		popup.show();
-	}
-
 	private void handleEncryptionSelection(MenuItem item) {
 		Conversation conversation = getSelectedConversation();
 		if (conversation == null) {
@@ -854,10 +806,6 @@ public class ConversationActivity extends XmppActivity
 				conversation.setNextEncryption(Message.ENCRYPTION_NONE);
 				item.setChecked(true);
 				break;
-			case R.id.encryption_choice_otr:
-				conversation.setNextEncryption(Message.ENCRYPTION_OTR);
-				item.setChecked(true);
-				break;
 			case R.id.encryption_choice_pgp:
 				if (hasPgp()) {
 					if (conversation.getAccount().getPgpSignature() != null) {
@@ -1388,8 +1336,7 @@ public class ConversationActivity extends XmppActivity
 					}
 				};
 				if (c == null || c.getMode() == Conversation.MODE_MULTI
-						|| FileBackend.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c))
-						|| c.getNextEncryption() == Message.ENCRYPTION_OTR) {
+						|| FileBackend.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c))) {
 					callback.onPresenceSelected();
 				} else {
 					selectPresence(c, callback);

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java πŸ”—

@@ -42,8 +42,6 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 import android.widget.Toast;
 
-import net.java.otr4j.session.SessionStatus;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -221,13 +219,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 			}
 		}
 	};
-	protected OnClickListener clickToVerify = new OnClickListener() {
 
-		@Override
-		public void onClick(View v) {
-			activity.verifyOtrSessionDialog(conversation, v);
-		}
-	};
 	private EditMessage.OnCommitContentListener mEditorContentListener = new EditMessage.OnCommitContentListener() {
 		@Override
 		public boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] contentMimeTypes) {
@@ -316,17 +308,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 			}
 		}
 	};
-	private OnClickListener mAnswerSmpClickListener = new OnClickListener() {
-		@Override
-		public void onClick(View view) {
-			Intent intent = new Intent(activity, VerifyOTRActivity.class);
-			intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
-			intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
-			intent.putExtra(VerifyOTRActivity.EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString());
-			intent.putExtra("mode", VerifyOTRActivity.MODE_ANSWER_QUESTION);
-			startActivity(intent);
-		}
-	};
+
 	protected OnClickListener clickToDecryptListener = new OnClickListener() {
 
 		@Override
@@ -483,9 +465,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 			message.setUuid(UUID.randomUUID().toString());
 		}
 		switch (message.getConversation().getNextEncryption()) {
-			case Message.ENCRYPTION_OTR:
-				sendOtrMessage(message);
-				break;
 			case Message.ENCRYPTION_PGP:
 				sendPgpMessage(message);
 				break;
@@ -600,8 +579,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 				if (message.getEncryption() == Message.ENCRYPTION_PGP
 						|| message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
 					fingerprint = "pgp";
-				} else if (message.getEncryption() == Message.ENCRYPTION_OTR) {
-					fingerprint = "otr";
 				} else {
 					fingerprint = message.getFingerprint();
 				}
@@ -1114,14 +1091,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 			}
 		} else if (account.hasPendingPgpIntent(conversation)) {
 			showSnackbar(R.string.openpgp_messages_found, R.string.decrypt, clickToDecryptListener);
-		} else if (mode == Conversation.MODE_SINGLE
-				&& conversation.smpRequested()) {
-			showSnackbar(R.string.smp_requested, R.string.verify, this.mAnswerSmpClickListener);
-		} else if (mode == Conversation.MODE_SINGLE
-				&& conversation.hasValidOtrSession()
-				&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED)
-				&& (!conversation.isOtrFingerprintVerified())) {
-			showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify);
 		} else if (connection != null
 				&& connection.getFeatures().blocking()
 				&& conversation.countMessages() != 0
@@ -1612,21 +1581,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 		messageSent();
 	}
 
-	protected void sendOtrMessage(final Message message) {
-		final ConversationActivity activity = (ConversationActivity) getActivity();
-		final XmppConnectionService xmppService = activity.xmppConnectionService;
-		activity.selectPresence(message.getConversation(),
-				new OnPresenceSelected() {
-
-					@Override
-					public void onPresenceSelected() {
-						message.setCounterpart(conversation.getNextCounterpart());
-						xmppService.sendMessage(message);
-						messageSent();
-					}
-				});
-	}
-
 	public void appendText(String text) {
 		if (text == null) {
 			return;

src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java πŸ”—

@@ -96,17 +96,13 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
 	private TextView mServerInfoHttpUpload;
 	private TextView mServerInfoPush;
 	private TextView mSessionEst;
-	private TextView mOtrFingerprint;
 	private TextView mAxolotlFingerprint;
 	private TextView mPgpFingerprint;
 	private TextView mOwnFingerprintDesc;
-	private TextView mOtrFingerprintDesc;
 	private TextView getmPgpFingerprintDesc;
 	private ImageView mAvatar;
-	private RelativeLayout mOtrFingerprintBox;
 	private RelativeLayout mAxolotlFingerprintBox;
 	private RelativeLayout mPgpFingerprintBox;
-	private ImageButton mOtrFingerprintToClipboardButton;
 	private ImageButton mAxolotlFingerprintToClipboardButton;
 	private ImageButton mPgpDeleteFingerprintButton;
 	private LinearLayout keys;
@@ -567,10 +563,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
 		this.mPgpFingerprint = (TextView) findViewById(R.id.pgp_fingerprint);
 		this.getmPgpFingerprintDesc = (TextView) findViewById(R.id.pgp_fingerprint_desc);
 		this.mPgpDeleteFingerprintButton = (ImageButton) findViewById(R.id.action_delete_pgp);
-		this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint);
-		this.mOtrFingerprintDesc = (TextView) findViewById(R.id.otr_fingerprint_desc);
-		this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box);
-		this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard);
 		this.mAxolotlFingerprint = (TextView) findViewById(R.id.axolotl_fingerprint);
 		this.mAxolotlFingerprintBox = (RelativeLayout) findViewById(R.id.axolotl_fingerprint_box);
 		this.mAxolotlFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_axolotl_to_clipboard);
@@ -980,25 +972,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
 			} else {
 				this.mPgpFingerprintBox.setVisibility(View.GONE);
 			}
-			final String otrFingerprint = this.mAccount.getOtrFingerprint();
-			if (otrFingerprint != null && Config.supportOtr()) {
-				if ("otr".equals(messageFingerprint)) {
-					this.mOtrFingerprintDesc.setTextColor(ContextCompat.getColor(this, R.color.accent));
-				}
-				this.mOtrFingerprintBox.setVisibility(View.VISIBLE);
-				this.mOtrFingerprint.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
-				this.mOtrFingerprintToClipboardButton.setVisibility(View.VISIBLE);
-				this.mOtrFingerprintToClipboardButton.setOnClickListener(v -> {
-					if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(otrFingerprint), R.string.otr_fingerprint)) {
-						Toast.makeText(
-								EditAccountActivity.this,
-								R.string.toast_message_otr_fingerprint,
-								Toast.LENGTH_SHORT).show();
-					}
-				});
-			} else {
-				this.mOtrFingerprintBox.setVisibility(View.GONE);
-			}
 			final String ownAxolotlFingerprint = this.mAccount.getAxolotlService().getOwnFingerprint();
 			if (ownAxolotlFingerprint != null && Config.supportOmemo()) {
 				this.mAxolotlFingerprintBox.setVisibility(View.VISIBLE);

src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java πŸ”—

@@ -332,8 +332,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
 			if (account.httpUploadAvailable()
 					&& ((share.image && !neverCompressPictures())
 					|| conversation.getMode() == Conversation.MODE_MULTI
-					|| FileBackend.allFilesUnderSize(this, share.uris, max))
-					&& conversation.getNextEncryption() != Message.ENCRYPTION_OTR) {
+					|| FileBackend.allFilesUnderSize(this, share.uris, max))) {
 				callback.onPresenceSelected();
 			} else {
 				selectPresence(conversation, callback);

src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java πŸ”—

@@ -1,443 +0,0 @@
-package eu.siacs.conversations.ui;
-
-import android.support.v7.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.view.Menu;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import net.java.otr4j.OtrException;
-import net.java.otr4j.session.Session;
-
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Contact;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.utils.CryptoHelper;
-import eu.siacs.conversations.utils.XmppUri;
-import eu.siacs.conversations.utils.zxing.IntentIntegrator;
-import eu.siacs.conversations.utils.zxing.IntentResult;
-import eu.siacs.conversations.xmpp.jid.InvalidJidException;
-import eu.siacs.conversations.xmpp.jid.Jid;
-
-public class VerifyOTRActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
-
-	public static final String ACTION_VERIFY_CONTACT = "verify_contact";
-	public static final int MODE_SCAN_FINGERPRINT = - 0x0502;
-	public static final int MODE_ASK_QUESTION = 0x0503;
-	public static final int MODE_ANSWER_QUESTION = 0x0504;
-	public static final int MODE_MANUAL_VERIFICATION = 0x0505;
-
-	private LinearLayout mManualVerificationArea;
-	private LinearLayout mSmpVerificationArea;
-	private TextView mRemoteFingerprint;
-	private TextView mYourFingerprint;
-	private TextView mVerificationExplain;
-	private TextView mStatusMessage;
-	private TextView mSharedSecretHint;
-	private EditText mSharedSecretHintEditable;
-	private EditText mSharedSecretSecret;
-	private Button mLeftButton;
-	private Button mRightButton;
-	private Account mAccount;
-	private Conversation mConversation;
-	private int mode = MODE_MANUAL_VERIFICATION;
-	private XmppUri mPendingUri = null;
-
-	private DialogInterface.OnClickListener mVerifyFingerprintListener = new DialogInterface.OnClickListener() {
-
-		@Override
-		public void onClick(DialogInterface dialogInterface, int click) {
-			mConversation.verifyOtrFingerprint();
-			xmppConnectionService.syncRosterToDisk(mConversation.getAccount());
-			Toast.makeText(VerifyOTRActivity.this,R.string.verified,Toast.LENGTH_SHORT).show();
-			finish();
-		}
-	};
-
-	private View.OnClickListener mCreateSharedSecretListener = new View.OnClickListener() {
-		@Override
-		public void onClick(final View view) {
-			if (isAccountOnline()) {
-				final String question = mSharedSecretHintEditable.getText().toString();
-				final String secret = mSharedSecretSecret.getText().toString();
-				if (question.trim().isEmpty()) {
-					mSharedSecretHintEditable.requestFocus();
-					mSharedSecretHintEditable.setError(getString(R.string.shared_secret_hint_should_not_be_empty));
-				} else if (secret.trim().isEmpty()) {
-					mSharedSecretSecret.requestFocus();
-					mSharedSecretSecret.setError(getString(R.string.shared_secret_can_not_be_empty));
-				} else {
-					mSharedSecretSecret.setError(null);
-					mSharedSecretHintEditable.setError(null);
-					initSmp(question, secret);
-					updateView();
-				}
-			}
-		}
-	};
-	private View.OnClickListener mCancelSharedSecretListener = new View.OnClickListener() {
-		@Override
-		public void onClick(View view) {
-			if (isAccountOnline()) {
-				abortSmp();
-				updateView();
-			}
-		}
-	};
-	private View.OnClickListener mRespondSharedSecretListener = new View.OnClickListener() {
-
-		@Override
-		public void onClick(View view) {
-			if (isAccountOnline()) {
-				final String question = mSharedSecretHintEditable.getText().toString();
-				final String secret = mSharedSecretSecret.getText().toString();
-				respondSmp(question, secret);
-				updateView();
-			}
-		}
-	};
-	private View.OnClickListener mRetrySharedSecretListener = new View.OnClickListener() {
-		@Override
-		public void onClick(View view) {
-			mConversation.smp().status = Conversation.Smp.STATUS_NONE;
-			mConversation.smp().hint = null;
-			mConversation.smp().secret = null;
-			updateView();
-		}
-	};
-	private View.OnClickListener mFinishListener = new View.OnClickListener() {
-		@Override
-		public void onClick(View view) {
-			mConversation.smp().status = Conversation.Smp.STATUS_NONE;
-			finish();
-		}
-	};
-
-	protected boolean initSmp(final String question, final String secret) {
-		final Session session = mConversation.getOtrSession();
-		if (session!=null) {
-			try {
-				session.initSmp(question, secret);
-				mConversation.smp().status = Conversation.Smp.STATUS_WE_REQUESTED;
-				mConversation.smp().secret = secret;
-				mConversation.smp().hint = question;
-				return true;
-			} catch (OtrException e) {
-				return false;
-			}
-		} else {
-			return false;
-		}
-	}
-
-	protected boolean abortSmp() {
-		final Session session = mConversation.getOtrSession();
-		if (session!=null) {
-			try {
-				session.abortSmp();
-				mConversation.smp().status = Conversation.Smp.STATUS_NONE;
-				mConversation.smp().hint = null;
-				mConversation.smp().secret = null;
-				return true;
-			} catch (OtrException e) {
-				return false;
-			}
-		} else {
-			return false;
-		}
-	}
-
-	protected boolean respondSmp(final String question, final String secret) {
-		final Session session = mConversation.getOtrSession();
-		if (session!=null) {
-			try {
-				session.respondSmp(question,secret);
-				return true;
-			} catch (OtrException e) {
-				return false;
-			}
-		} else {
-			return false;
-		}
-	}
-
-	protected boolean verifyWithUri(XmppUri uri) {
-		Contact contact = mConversation.getContact();
-		if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.hasFingerprints()) {
-			xmppConnectionService.verifyFingerprints(contact,uri.getFingerprints());
-			Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show();
-			updateView();
-			return true;
-		} else {
-			Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show();
-			return false;
-		}
-	}
-
-	protected boolean isAccountOnline() {
-		if (this.mAccount.getStatus() != Account.State.ONLINE) {
-			Toast.makeText(this,R.string.not_connected_try_again,Toast.LENGTH_SHORT).show();
-			return false;
-		} else {
-			return true;
-		}
-	}
-
-	protected boolean handleIntent(Intent intent) {
-		if (intent != null && intent.getAction().equals(ACTION_VERIFY_CONTACT)) {
-			this.mAccount = extractAccount(intent);
-			if (this.mAccount == null) {
-				return false;
-			}
-			try {
-				this.mConversation = this.xmppConnectionService.find(this.mAccount,Jid.fromString(intent.getExtras().getString("contact")));
-				if (this.mConversation == null) {
-					return false;
-				}
-			} catch (final InvalidJidException ignored) {
-				return false;
-			}
-			this.mode = intent.getIntExtra("mode", MODE_MANUAL_VERIFICATION);
-			if (this.mode == MODE_SCAN_FINGERPRINT) {
-				new IntentIntegrator(this).initiateScan();
-				return false;
-			}
-			return true;
-		} else {
-			return false;
-		}
-	}
-
-	@Override
-	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
-		if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) {
-			IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
-			if (scanResult != null && scanResult.getFormatName() != null) {
-				String data = scanResult.getContents();
-				XmppUri uri = new XmppUri(data);
-				if (xmppConnectionServiceBound) {
-					verifyWithUri(uri);
-					finish();
-				} else {
-					this.mPendingUri = uri;
-				}
-			} else {
-				finish();
-			}
-		}
-		super.onActivityResult(requestCode, requestCode, intent);
-	}
-
-	@Override
-	protected void onBackendConnected() {
-		if (handleIntent(getIntent())) {
-			updateView();
-		} else if (mPendingUri!=null) {
-			verifyWithUri(mPendingUri);
-			finish();
-			mPendingUri = null;
-		}
-		setIntent(null);
-	}
-
-	protected void updateView() {
-		if (this.mConversation != null && this.mConversation.hasValidOtrSession()) {
-			final ActionBar actionBar = getSupportActionBar();
-			this.mVerificationExplain.setText(R.string.no_otr_session_found);
-			invalidateOptionsMenu();
-			switch(this.mode) {
-				case MODE_ASK_QUESTION:
-					if (actionBar != null ) {
-						actionBar.setTitle(R.string.ask_question);
-					}
-					this.updateViewAskQuestion();
-					break;
-				case MODE_ANSWER_QUESTION:
-					if (actionBar != null ) {
-						actionBar.setTitle(R.string.smp_requested);
-					}
-					this.updateViewAnswerQuestion();
-					break;
-				case MODE_MANUAL_VERIFICATION:
-				default:
-					if (actionBar != null ) {
-						actionBar.setTitle(R.string.manually_verify);
-					}
-					this.updateViewManualVerification();
-					break;
-			}
-		} else {
-			this.mManualVerificationArea.setVisibility(View.GONE);
-			this.mSmpVerificationArea.setVisibility(View.GONE);
-		}
-	}
-
-	protected void updateViewManualVerification() {
-		this.mVerificationExplain.setText(R.string.manual_verification_explanation);
-		this.mManualVerificationArea.setVisibility(View.VISIBLE);
-		this.mSmpVerificationArea.setVisibility(View.GONE);
-		this.mYourFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mAccount.getOtrFingerprint()));
-		this.mRemoteFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mConversation.getOtrFingerprint()));
-		if (this.mConversation.isOtrFingerprintVerified()) {
-			deactivateButton(this.mRightButton,R.string.verified);
-			activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
-		} else {
-			activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
-			activateButton(this.mRightButton,R.string.verify, new View.OnClickListener() {
-				@Override
-				public void onClick(View view) {
-					showManuallyVerifyDialog();
-				}
-			});
-		}
-	}
-
-	protected void updateViewAskQuestion() {
-		this.mManualVerificationArea.setVisibility(View.GONE);
-		this.mSmpVerificationArea.setVisibility(View.VISIBLE);
-		this.mVerificationExplain.setText(R.string.smp_explain_question);
-		final int smpStatus = this.mConversation.smp().status;
-		switch (smpStatus) {
-			case Conversation.Smp.STATUS_WE_REQUESTED:
-				this.mStatusMessage.setVisibility(View.GONE);
-				this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
-				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
-				this.mSharedSecretHintEditable.setText(this.mConversation.smp().hint);
-				this.mSharedSecretSecret.setText(this.mConversation.smp().secret);
-				this.activateButton(this.mLeftButton, R.string.cancel, this.mCancelSharedSecretListener);
-				this.deactivateButton(this.mRightButton, R.string.in_progress);
-				break;
-			case Conversation.Smp.STATUS_FAILED:
-				this.mStatusMessage.setVisibility(View.GONE);
-				this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
-				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
-				this.mSharedSecretSecret.requestFocus();
-				this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match));
-				this.deactivateButton(this.mLeftButton, R.string.cancel);
-				this.activateButton(this.mRightButton, R.string.try_again, this.mRetrySharedSecretListener);
-				break;
-			case Conversation.Smp.STATUS_VERIFIED:
-				this.mSharedSecretHintEditable.setText("");
-				this.mSharedSecretHintEditable.setVisibility(View.GONE);
-				this.mSharedSecretSecret.setText("");
-				this.mSharedSecretSecret.setVisibility(View.GONE);
-				this.mStatusMessage.setVisibility(View.VISIBLE);
-				this.deactivateButton(this.mLeftButton, R.string.cancel);
-				this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener);
-				break;
-			default:
-				this.mStatusMessage.setVisibility(View.GONE);
-				this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
-				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
-				this.activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
-				this.activateButton(this.mRightButton, R.string.ask_question, this.mCreateSharedSecretListener);
-				break;
-		}
-	}
-
-	protected void updateViewAnswerQuestion() {
-		this.mManualVerificationArea.setVisibility(View.GONE);
-		this.mSmpVerificationArea.setVisibility(View.VISIBLE);
-		this.mVerificationExplain.setText(R.string.smp_explain_answer);
-		this.mSharedSecretHintEditable.setVisibility(View.GONE);
-		this.mSharedSecretHint.setVisibility(View.VISIBLE);
-		this.deactivateButton(this.mLeftButton, R.string.cancel);
-		final int smpStatus = this.mConversation.smp().status;
-		switch (smpStatus) {
-			case Conversation.Smp.STATUS_CONTACT_REQUESTED:
-				this.mStatusMessage.setVisibility(View.GONE);
-				this.mSharedSecretHint.setText(this.mConversation.smp().hint);
-				this.activateButton(this.mRightButton,R.string.respond,this.mRespondSharedSecretListener);
-				break;
-			case Conversation.Smp.STATUS_VERIFIED:
-				this.mSharedSecretHintEditable.setText("");
-				this.mSharedSecretHintEditable.setVisibility(View.GONE);
-				this.mSharedSecretHint.setVisibility(View.GONE);
-				this.mSharedSecretSecret.setText("");
-				this.mSharedSecretSecret.setVisibility(View.GONE);
-				this.mStatusMessage.setVisibility(View.VISIBLE);
-				this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener);
-				break;
-			case Conversation.Smp.STATUS_FAILED:
-			default:
-				this.mSharedSecretSecret.requestFocus();
-				this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match));
-				this.activateButton(this.mRightButton,R.string.finish,this.mFinishListener);
-				break;
-		}
-	}
-
-	protected void activateButton(Button button, int text, View.OnClickListener listener) {
-		button.setEnabled(true);
-		button.setTextColor(getPrimaryTextColor());
-		button.setText(text);
-		button.setOnClickListener(listener);
-	}
-
-	protected void deactivateButton(Button button, int text) {
-		button.setEnabled(false);
-		button.setTextColor(getSecondaryTextColor());
-		button.setText(text);
-		button.setOnClickListener(null);
-	}
-
-	@Override
-	protected void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-		setContentView(R.layout.activity_verify_otr);
-		this.mRemoteFingerprint = (TextView) findViewById(R.id.remote_fingerprint);
-		this.mYourFingerprint = (TextView) findViewById(R.id.your_fingerprint);
-		this.mLeftButton = (Button) findViewById(R.id.left_button);
-		this.mRightButton = (Button) findViewById(R.id.right_button);
-		this.mVerificationExplain = (TextView) findViewById(R.id.verification_explanation);
-		this.mStatusMessage = (TextView) findViewById(R.id.status_message);
-		this.mSharedSecretSecret = (EditText) findViewById(R.id.shared_secret_secret);
-		this.mSharedSecretHintEditable = (EditText) findViewById(R.id.shared_secret_hint_editable);
-		this.mSharedSecretHint = (TextView) findViewById(R.id.shared_secret_hint);
-		this.mManualVerificationArea = (LinearLayout) findViewById(R.id.manual_verification_area);
-		this.mSmpVerificationArea = (LinearLayout) findViewById(R.id.smp_verification_area);
-	}
-
-	@Override
-	public boolean onCreateOptionsMenu(final Menu menu) {
-		super.onCreateOptionsMenu(menu);
-		getMenuInflater().inflate(R.menu.verify_otr, menu);
-		return true;
-	}
-
-	private void showManuallyVerifyDialog() {
-		AlertDialog.Builder builder = new AlertDialog.Builder(this);
-		builder.setTitle(R.string.manually_verify);
-		builder.setMessage(R.string.are_you_sure_verify_fingerprint);
-		builder.setNegativeButton(R.string.cancel, null);
-		builder.setPositiveButton(R.string.verify, mVerifyFingerprintListener);
-		builder.create().show();
-	}
-
-	@Override
-	protected String getShareableUri() {
-		if (mAccount!=null) {
-			return mAccount.getShareableUri();
-		} else {
-			return "";
-		}
-	}
-
-	public void onConversationUpdate() {
-		refreshUi();
-	}
-
-	@Override
-	protected void refreshUiReal() {
-		updateView();
-	}
-}

src/main/java/eu/siacs/conversations/ui/XmppActivity.java πŸ”—

@@ -48,8 +48,6 @@ import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.Toast;
 
-import net.java.otr4j.session.SessionID;
-
 import java.io.FileNotFoundException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -782,17 +780,7 @@ public abstract class XmppActivity extends AppCompatActivity {
 	public void selectPresence(final Conversation conversation,
 	                           final OnPresenceSelected listener) {
 		final Contact contact = conversation.getContact();
-		if (conversation.hasValidOtrSession()) {
-			SessionID id = conversation.getOtrSession().getSessionID();
-			Jid jid;
-			try {
-				jid = Jid.fromString(id.getAccountID() + "/" + id.getUserID());
-			} catch (InvalidJidException e) {
-				jid = null;
-			}
-			conversation.setNextCounterpart(jid);
-			listener.onPresenceSelected();
-		} else if (!contact.showInRoster()) {
+		if (!contact.showInRoster()) {
 			showAddToRosterDialog(conversation);
 		} else {
 			final Presences presences = contact.getPresences();

src/main/java/eu/siacs/conversations/utils/UIHelper.java πŸ”—

@@ -483,8 +483,6 @@ public class UIHelper {
 				} else {
 					return context.getString(R.string.send_message_to_x, conversation.getName());
 				}
-			case Message.ENCRYPTION_OTR:
-				return context.getString(R.string.send_otr_message);
 			case Message.ENCRYPTION_AXOLOTL:
 				AxolotlService axolotlService = conversation.getAccount().getAxolotlService();
 				if (axolotlService != null && axolotlService.trustedSessionVerified(conversation)) {

src/main/java/eu/siacs/conversations/utils/XmppUri.java πŸ”—

@@ -132,9 +132,6 @@ public class XmppUri {
 			if (parts.length == 2) {
 				String key = parts[0].toLowerCase(Locale.US);
 				String value = parts[1].toLowerCase(Locale.US);
-				if (OTR_URI_PARAM.equals(key)) {
-					fingerprints.add(new Fingerprint(FingerprintType.OTR,value));
-				}
 				if (key.startsWith(OMEMO_URI_PARAM)) {
 					try {
 						int id = Integer.parseInt(key.substring(OMEMO_URI_PARAM.length()));
@@ -213,8 +210,7 @@ public class XmppUri {
 		return fingerprints.size() > 0;
 	}
 	public enum FingerprintType {
-		OMEMO,
-		OTR
+		OMEMO
 	}
 
 	public static String getFingerprintUri(String base, List<XmppUri.Fingerprint> fingerprints, char seperator) {
@@ -225,8 +221,6 @@ public class XmppUri {
 			if (type == XmppUri.FingerprintType.OMEMO) {
 				builder.append(XmppUri.OMEMO_URI_PARAM);
 				builder.append(fingerprints.get(i).deviceId);
-			} else if (type == XmppUri.FingerprintType.OTR) {
-				builder.append(XmppUri.OTR_URI_PARAM);
 			}
 			builder.append('=');
 			builder.append(fingerprints.get(i).fingerprint);

src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java πŸ”—

@@ -2,8 +2,6 @@ package eu.siacs.conversations.xmpp.jid;
 
 import android.util.LruCache;
 
-import net.java.otr4j.session.SessionID;
-
 import java.net.IDN;
 
 import eu.siacs.conversations.Config;
@@ -51,14 +49,6 @@ public final class Jid {
 		return resourcepart;
 	}
 
-	public static Jid fromSessionID(final SessionID id) throws InvalidJidException{
-		if (id.getUserID().isEmpty()) {
-			return Jid.fromString(id.getAccountID());
-		} else {
-			return Jid.fromString(id.getAccountID()+"/"+id.getUserID());
-		}
-	}
-
 	public static Jid fromString(final String jid) throws InvalidJidException {
 		return Jid.fromString(jid, false);
 	}

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java πŸ”—

@@ -404,11 +404,7 @@ public class JingleConnection implements Transferable {
 						} else {
 							message.setType(Message.TYPE_FILE);
 						}
-						if (filename[filename.length - 1].equals("otr")) {
-							message.setEncryption(Message.ENCRYPTION_OTR);
-						} else {
-							message.setEncryption(Message.ENCRYPTION_PGP);
-						}
+						message.setEncryption(Message.ENCRYPTION_PGP);
 					}
 				} else {
 					message.setType(Message.TYPE_FILE);
@@ -418,9 +414,7 @@ public class JingleConnection implements Transferable {
 					if (!fileNameElement.getContent().isEmpty()) {
 						String parts[] = fileNameElement.getContent().split("/");
 						suffix = parts[parts.length - 1];
-						if (message.getEncryption() == Message.ENCRYPTION_OTR  && suffix.endsWith(".otr")) {
-							suffix = suffix.substring(0,suffix.length() - 4);
-						} else if (message.getEncryption() == Message.ENCRYPTION_PGP && (suffix.endsWith(".pgp") || suffix.endsWith(".gpg"))) {
+						if (message.getEncryption() == Message.ENCRYPTION_PGP && (suffix.endsWith(".pgp") || suffix.endsWith(".gpg"))) {
 							suffix = suffix.substring(0,suffix.length() - 4);
 						}
 					}
@@ -457,15 +451,6 @@ public class JingleConnection implements Transferable {
 					} else {
 						Log.d(Config.LOGTAG,"could not process KeyTransportMessage");
 					}
-				} else if (message.getEncryption() == Message.ENCRYPTION_OTR) {
-					byte[] key = conversation.getSymmetricKey();
-					if (key == null) {
-						this.sendCancel();
-						this.fail();
-						return;
-					} else {
-						this.file.setKeyAndIv(key);
-					}
 				}
 				this.file.setExpectedSize(size);
 				message.resetFileParams();
@@ -488,17 +473,7 @@ public class JingleConnection implements Transferable {
 			this.file = this.mXmppConnectionService.getFileBackend().getFile(message, false);
 			Pair<InputStream,Integer> pair;
 			try {
-				if (message.getEncryption() == Message.ENCRYPTION_OTR) {
-					Conversation conversation = this.message.getConversation();
-					if (!this.mXmppConnectionService.renewSymmetricKey(conversation)) {
-						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not set symmetric key");
-						cancel();
-					}
-					this.file.setKeyAndIv(conversation.getSymmetricKey());
-					pair = AbstractConnectionManager.createInputStream(this.file, false);
-					this.file.setExpectedSize(pair.second);
-					content.setFileOffer(this.file, true, this.ftVersion);
-				} else if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
+				if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
 					this.file.setKey(mXmppAxolotlMessage.getInnerKey());
 					this.file.setIv(mXmppAxolotlMessage.getIV());
 					pair = AbstractConnectionManager.createInputStream(this.file, true);

src/main/res/layout/activity_edit_account.xml πŸ”—

@@ -525,52 +525,6 @@
                                 android:visibility="visible"/>
                         </RelativeLayout>
 
-                        <RelativeLayout
-                            android:id="@+id/otr_fingerprint_box"
-                            android:layout_width="wrap_content"
-                            android:layout_height="match_parent"
-                            android:layout_marginTop="24dp">
-
-                            <LinearLayout
-                                android:layout_width="wrap_content"
-                                android:layout_height="wrap_content"
-                                android:layout_alignParentLeft="true"
-                                android:layout_centerVertical="true"
-                                android:layout_toLeftOf="@+id/action_copy_to_clipboard"
-                                android:orientation="vertical">
-
-                                <TextView
-                                    android:id="@+id/otr_fingerprint"
-                                    android:layout_width="wrap_content"
-                                    android:layout_height="wrap_content"
-                                    android:fontFamily="monospace"
-                                    android:textColor="?attr/color_text_primary"
-                                    android:textSize="?attr/TextSizeBody"
-                                    android:typeface="monospace"/>
-
-                                <TextView
-                                    android:id="@+id/otr_fingerprint_desc"
-                                    android:layout_width="wrap_content"
-                                    android:layout_height="wrap_content"
-                                    android:text="@string/otr_fingerprint"
-                                    android:textColor="?attr/color_text_secondary"
-                                    android:textSize="?attr/TextSizeInfo"/>
-                            </LinearLayout>
-
-                            <ImageButton
-                                android:id="@+id/action_copy_to_clipboard"
-                                android:layout_width="wrap_content"
-                                android:layout_height="wrap_content"
-                                android:layout_alignParentRight="true"
-                                android:layout_centerVertical="true"
-                                android:alpha="?attr/icon_alpha"
-                                android:background="?attr/selectableItemBackgroundBorderless"
-                                android:contentDescription="@string/copy_otr_clipboard_description"
-                                android:padding="@dimen/image_button_padding"
-                                android:src="?attr/icon_copy"
-                                android:visibility="visible"/>
-                        </RelativeLayout>
-
                         <RelativeLayout
                             android:id="@+id/axolotl_fingerprint_box"
                             android:layout_width="wrap_content"

src/main/res/menu/conversations.xml πŸ”—

@@ -21,9 +21,6 @@
                 <item
                     android:id="@+id/encryption_choice_axolotl"
                     android:title="@string/encryption_choice_omemo"/>
-                <item
-                    android:id="@+id/encryption_choice_otr"
-                    android:title="@string/encryption_choice_otr"/>
                 <item
                     android:id="@+id/encryption_choice_pgp"
                     android:title="@string/encryption_choice_pgp"/>