forked from mirror/monocles_chat_clean
remove OTR
This commit is contained in:
parent
74c11b6712
commit
2f812d5a7d
28 changed files with 17 additions and 1809 deletions
|
@ -50,7 +50,6 @@ dependencies {
|
|||
exclude group: 'com.android.support', module: 'exifinterface'
|
||||
}
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.64'
|
||||
implementation 'org.jitsi:org.otr4j:0.22'
|
||||
implementation 'org.gnu.inet:libidn:1.15'
|
||||
implementation 'com.google.zxing:core:3.3.3' // > 3.3.x not working below SDK 24
|
||||
implementation 'de.measite.minidns:minidns-hla:0.2.4'
|
||||
|
|
|
@ -243,10 +243,6 @@
|
|||
<activity
|
||||
android:name=".ui.PublishGroupChatProfilePictureActivity"
|
||||
android:label="@string/group_chat_avatar" />
|
||||
<activity
|
||||
android:name=".ui.VerifyOTRActivity"
|
||||
android:label="@string/verify_otr"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:name=".ui.ShareWithActivity"
|
||||
android:label="@string/app_name"
|
||||
|
|
|
@ -1,312 +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.Jid;
|
||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||
import eu.siacs.conversations.xmpp.jid.OtrJidHelper;
|
||||
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 e) {
|
||||
e.printStackTrace();
|
||||
} catch (final InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void askForSecret(SessionID id, InstanceTag instanceTag, String question) {
|
||||
try {
|
||||
final Jid jid = OtrJidHelper.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 (IllegalArgumentException e) {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": 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 = OtrJidHelper.fromSessionID(session);
|
||||
Conversation conversation = mXmppConnectionService.find(account, jid);
|
||||
if (conversation != null && conversation.setOutgoingChatState(Config.DEFAULT_CHAT_STATE)) {
|
||||
if (mXmppConnectionService.sendChatStates()) {
|
||||
packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
|
||||
}
|
||||
}
|
||||
} catch (final IllegalArgumentException 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 = OtrJidHelper.fromSessionID(id);
|
||||
Conversation conversation = this.mXmppConnectionService.find(this.account, jid);
|
||||
if (conversation != null) {
|
||||
conversation.smp().status = status;
|
||||
mXmppConnectionService.updateConversationUi();
|
||||
}
|
||||
} catch (final IllegalArgumentException 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 = OtrJidHelper.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().asBareJid().toString()
|
||||
+ ": unreadable OTR message in " + conversation.getName());
|
||||
}
|
||||
} catch (IllegalArgumentException 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 = OtrJidHelper.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 IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FragmenterInstructions getFragmenterInstructions(SessionID sessionID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,27 +6,20 @@ import android.os.SystemClock;
|
|||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
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.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.OtrService;
|
||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
|
@ -34,9 +27,9 @@ import eu.siacs.conversations.services.AvatarService;
|
|||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import eu.siacs.conversations.utils.XmppUri;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
public class Account extends AbstractEntity implements AvatarService.Avatarable {
|
||||
|
||||
|
@ -89,7 +82,6 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
|||
protected String hostname = null;
|
||||
protected int port = 5222;
|
||||
protected boolean online = false;
|
||||
private OtrService mOtrService = null;
|
||||
private String rosterVersion;
|
||||
private String displayName = null;
|
||||
private AxolotlService axolotlService = null;
|
||||
|
@ -404,7 +396,6 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -412,10 +403,6 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
|||
}
|
||||
}
|
||||
|
||||
public OtrService getOtrService() {
|
||||
return this.mOtrService;
|
||||
}
|
||||
|
||||
public PgpDecryptionService getPgpDecryptionService() {
|
||||
return this.pgpDecryptionService;
|
||||
}
|
||||
|
@ -428,26 +415,6 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
|||
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 "";
|
||||
|
@ -611,10 +578,6 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -9,23 +9,16 @@ import androidx.annotation.Nullable;
|
|||
import com.google.common.collect.ComparisonChain;
|
||||
|
||||
|
||||
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.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
|
@ -36,9 +29,9 @@ import eu.siacs.conversations.services.AvatarService;
|
|||
import eu.siacs.conversations.services.QuickConversationsService;
|
||||
import eu.siacs.conversations.utils.JidHelper;
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
import static eu.siacs.conversations.entities.Bookmark.printableValue;
|
||||
|
||||
|
@ -85,15 +78,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
private int mode;
|
||||
private JSONObject attributes;
|
||||
private Jid nextCounterpart;
|
||||
private transient SessionImpl otrSession;
|
||||
private transient String otrFingerprint = null;
|
||||
private Smp mSmp = new Smp();
|
||||
private transient MucOptions mucOptions = null;
|
||||
private byte[] symmetricKey;
|
||||
private boolean messagesLeftOnServer = true;
|
||||
private ChatState mOutgoingChatState = Config.DEFAULT_CHAT_STATE;
|
||||
private ChatState mIncomingChatState = Config.DEFAULT_CHAT_STATE;
|
||||
private String mLastReceivedOtrMessageId = null;
|
||||
private String mFirstMamReference = null;
|
||||
|
||||
public Conversation(final String name, final Account account, final Jid contactJid,
|
||||
|
@ -357,17 +345,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
}
|
||||
}
|
||||
|
||||
public void findUnsentMessagesWithEncryption(int encryptionType, OnMessageFound onMessageFound) {
|
||||
synchronized (this.messages) {
|
||||
for (Message message : this.messages) {
|
||||
if ((message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_WAITING)
|
||||
&& (message.getEncryption() == encryptionType)) {
|
||||
onMessageFound.onMessageFound(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void findUnsentTextMessages(OnMessageFound onMessageFound) {
|
||||
final ArrayList<Message> results = new ArrayList<>();
|
||||
synchronized (this.messages) {
|
||||
|
@ -489,14 +466,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();
|
||||
|
@ -693,112 +662,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().asBareJid().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 ignored) {
|
||||
return null;
|
||||
} catch (final 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
|
||||
*/
|
||||
|
@ -834,7 +697,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
}
|
||||
|
||||
public int getNextEncryption() {
|
||||
if (!Config.supportOmemo() && !Config.supportOpenPgp() && !Config.supportOtr()) {
|
||||
if (!Config.supportOmemo() && !Config.supportOpenPgp()) {
|
||||
return Message.ENCRYPTION_NONE;
|
||||
}
|
||||
if (OmemoSetting.isAlways()) {
|
||||
|
@ -850,10 +713,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
defaultEncryption = Message.ENCRYPTION_NONE;
|
||||
}
|
||||
int encryption = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, defaultEncryption);
|
||||
if (encryption < 0) {
|
||||
if (encryption == Message.ENCRYPTION_OTR || encryption < 0) {
|
||||
return defaultEncryption;
|
||||
} else if (encryption == Message.ENCRYPTION_OTR) {
|
||||
return encryption;
|
||||
} else {
|
||||
return encryption;
|
||||
}
|
||||
|
@ -868,10 +729,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
return nextMessage == null ? "" : nextMessage;
|
||||
}
|
||||
|
||||
public boolean smpRequested() {
|
||||
return smp().status == Smp.STATUS_CONTACT_REQUESTED;
|
||||
}
|
||||
|
||||
public @Nullable
|
||||
Draft getDraft() {
|
||||
long timestamp = getLongAttribute(ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP, 0);
|
||||
|
@ -894,14 +751,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
return changed;
|
||||
}
|
||||
|
||||
public void setSymmetricKey(byte[] key) {
|
||||
this.symmetricKey = key;
|
||||
}
|
||||
|
||||
public byte[] getSymmetricKey() {
|
||||
return this.symmetricKey;
|
||||
}
|
||||
|
||||
public Bookmark getBookmark() {
|
||||
return this.account.getBookmark(this.contactJid);
|
||||
}
|
||||
|
@ -1263,16 +1112,4 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
public class Smp {
|
||||
public static final int STATUS_NONE = 0;
|
||||
public static final int STATUS_CONTACT_REQUESTED = 1;
|
||||
public static final int STATUS_WE_REQUESTED = 2;
|
||||
public static final int STATUS_FAILED = 3;
|
||||
public static final int STATUS_VERIFIED = 4;
|
||||
|
||||
public String secret = null;
|
||||
public String hint = null;
|
||||
public int status = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package eu.siacs.conversations.generator;
|
||||
|
||||
import net.java.otr4j.OtrException;
|
||||
import net.java.otr4j.session.Session;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
@ -29,7 +26,6 @@ import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
|||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
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.";
|
||||
|
||||
|
@ -111,29 +107,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) {
|
||||
Conversation conversation = (Conversation) message.getConversation();
|
||||
Session otrSession = conversation.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;
|
||||
|
|
|
@ -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.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
@ -22,7 +17,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.BrokenSessionException;
|
||||
import eu.siacs.conversations.crypto.axolotl.NotEncryptedForThisDeviceException;
|
||||
|
@ -35,10 +29,8 @@ import eu.siacs.conversations.entities.Conversation;
|
|||
import eu.siacs.conversations.entities.Conversational;
|
||||
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.entities.RtpSessionStatus;
|
||||
import eu.siacs.conversations.http.HttpConnectionManager;
|
||||
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
|
||||
|
@ -49,20 +41,19 @@ import eu.siacs.conversations.utils.Namespace;
|
|||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.LocalizedContent;
|
||||
import eu.siacs.conversations.xmpp.InvalidJid;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
|
||||
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
|
||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
import static eu.siacs.conversations.entities.Message.DELETED_MESSAGE_BODY;
|
||||
import static eu.siacs.conversations.entities.Message.DELETED_MESSAGE_BODY_OLD;
|
||||
|
||||
public class MessageParser extends AbstractParser implements OnMessagePacketReceived {
|
||||
|
||||
private static final List<String> CLIENTS_SENDING_HTML_IN_OTR = Arrays.asList("Pidgin", "Adium", "Trillian");
|
||||
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);
|
||||
|
||||
private static final List<String> JINGLE_MESSAGE_ELEMENT_NAMES = Arrays.asList("accept", "propose", "proceed", "reject", "retract");
|
||||
|
@ -107,30 +98,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
return result != null ? result : fallback;
|
||||
}
|
||||
|
||||
private static boolean clientMightSendHtml(Account account, Jid from) {
|
||||
String resource = from.getResource();
|
||||
if (resource == null) {
|
||||
return false;
|
||||
}
|
||||
Presence presence = account.getRoster().getContact(from).getPresences().getPresencesMap().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 boolean extractChatState(Conversation c, final boolean isTypeGroupChat, final MessagePacket packet) {
|
||||
ChatState state = ChatState.parse(packet);
|
||||
if (state != null && c != null) {
|
||||
|
@ -159,66 +126,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.getResource();
|
||||
}
|
||||
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().asBareJid() + ": 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 Message parseAxolotlChat(Element axolotlMessage, Jid from, Conversation conversation, int status, final boolean checkedForDuplicates, boolean postpone) {
|
||||
final AxolotlService service = conversation.getAccount().getAxolotlService();
|
||||
final XmppAxolotlMessage xmppAxolotlMessage;
|
||||
|
@ -436,12 +343,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
}
|
||||
}
|
||||
}
|
||||
if (message != null) {
|
||||
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
||||
Conversation conversation = (Conversation) message.getConversation();
|
||||
conversation.endOtrIfNeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -597,20 +498,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
}
|
||||
}
|
||||
final Message message;
|
||||
if (body != null && body.content.startsWith("?OTR") && Config.supportOtr()) {
|
||||
if (!isForwarded && !isTypeGroupChat && isProperlyAddressed && !conversationMultiMode) {
|
||||
message = parseOtrChat(body.content, from, remoteMsgId, conversation);
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring OTR message from " + from + " isForwarded=" + Boolean.toString(isForwarded) + ", isProperlyAddressed=" + Boolean.valueOf(isProperlyAddressed));
|
||||
message = new Message(conversation, body.content, Message.ENCRYPTION_NONE, status);
|
||||
if (body.count > 1) {
|
||||
message.setBodyLanguage(body.language);
|
||||
}
|
||||
}
|
||||
} else if (xP1S3url != null) {
|
||||
if (xP1S3url != null) {
|
||||
message = new Message(conversation, xP1S3url.toString(), Message.ENCRYPTION_NONE, status);
|
||||
message.setOob(true);
|
||||
if (CryptoHelper.isPgpEncryptedUrl(xP1S3url.toString())) {
|
||||
|
@ -854,13 +742,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().getResource())) {
|
||||
conversation.endOtrIfNeeded();
|
||||
}
|
||||
|
||||
mXmppConnectionService.databaseBackend.createMessage(message);
|
||||
final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager();
|
||||
if (message.trusted() && message.treatAsDownloadable() && manager.getAutoAcceptFileSize() > 0) {
|
||||
|
|
|
@ -47,12 +47,6 @@ import androidx.core.content.ContextCompat;
|
|||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
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.conscrypt.Conscrypt;
|
||||
import org.openintents.openpgp.IOpenPgpService2;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
|
@ -145,6 +139,7 @@ import eu.siacs.conversations.utils.StringUtils;
|
|||
import eu.siacs.conversations.utils.WakeLockHelper;
|
||||
import eu.siacs.conversations.utils.XmppUri;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.OnBindListener;
|
||||
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
|
@ -158,7 +153,6 @@ import eu.siacs.conversations.xmpp.Patches;
|
|||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||
import eu.siacs.conversations.xmpp.forms.Data;
|
||||
import eu.siacs.conversations.xmpp.jid.OtrJidHelper;
|
||||
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
|
||||
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
|
||||
import eu.siacs.conversations.xmpp.jingle.Media;
|
||||
|
@ -170,7 +164,6 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
|||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
import static eu.siacs.conversations.ui.SettingsActivity.ALLOW_MESSAGE_CORRECTION;
|
||||
import static eu.siacs.conversations.ui.SettingsActivity.CHAT_STATES;
|
||||
|
@ -247,18 +240,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -378,9 +362,11 @@ public class XmppConnectionService extends Service {
|
|||
public void onStatusChanged(final Account account) {
|
||||
XmppConnection connection = account.getXmppConnection();
|
||||
updateAccountUi();
|
||||
|
||||
if (account.getStatus() == Account.State.ONLINE || account.getStatus().isError()) {
|
||||
mQuickConversationsService.signalAccountStateChange();
|
||||
}
|
||||
|
||||
if (account.getStatus() == Account.State.ONLINE) {
|
||||
synchronized (mLowPingTimeoutMode) {
|
||||
if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) {
|
||||
|
@ -413,9 +399,6 @@ public class XmppConnectionService extends Service {
|
|||
if (conversation.getAccount() == account
|
||||
&& !pendingJoin
|
||||
&& !inProgressJoin) {
|
||||
if (!conversation.startOtrIfNeeded()) {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": couldn't start OTR with " + conversation.getContact().getJid() + " when needed");
|
||||
}
|
||||
sendUnsentMessages(conversation);
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +450,6 @@ public class XmppConnectionService extends Service {
|
|||
getNotificationService().updateErrorNotification();
|
||||
}
|
||||
};
|
||||
|
||||
private OpenPgpServiceConnection pgpServiceConnection;
|
||||
private PgpEngine mPgpEngine = null;
|
||||
private WakeLock wakeLock;
|
||||
|
@ -1629,12 +1611,6 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
if (!resend && message.getEncryption() != Message.ENCRYPTION_OTR) {
|
||||
conversation.endOtrIfNeeded();
|
||||
conversation.findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR,
|
||||
message1 -> markMessage(message1, Message.STATUS_SEND_FAILED));
|
||||
}
|
||||
|
||||
final boolean inProgressJoin = isJoinInProgress(conversation);
|
||||
|
||||
if (account.isOnlineAndConnected() && !inProgressJoin) {
|
||||
|
@ -1666,30 +1642,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(OtrJidHelper.fromSessionID(otrSession.getSessionID()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
break;
|
||||
}
|
||||
if (message.needsUploading()) {
|
||||
mJingleConnectionManager.startJingleFileTransfer(message);
|
||||
} else {
|
||||
packet = mMessageGenerator.generateOtrChat(message);
|
||||
}
|
||||
} else if (otrSession == null) {
|
||||
if (message.fixCounterpart()) {
|
||||
conversation.startOtrSession(message.getCounterpart().getResource(), true);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not fix counterpart for OTR message to contact " + message.getCounterpart());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + " 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()) {
|
||||
|
@ -1742,12 +1694,6 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Message.ENCRYPTION_OTR:
|
||||
if (!conversation.hasValidOtrSession() && message.getCounterpart() != null) {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": create otr session without starting for " + message.getContact().getJid());
|
||||
conversation.startOtrSession(message.getCounterpart().getResource(), false);
|
||||
}
|
||||
break;
|
||||
case Message.ENCRYPTION_AXOLOTL:
|
||||
message.setFingerprint(account.getAxolotlService().getOwnFingerprint());
|
||||
break;
|
||||
|
@ -3582,12 +3528,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().asBareJid()
|
||||
+ ": ended otr session with "
|
||||
+ conversation.getJid());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3637,65 +3577,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().asBareJid() + " 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.of(id.getAccountID() + "/" + id.getUserID()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
if (message.needsUploading()) {
|
||||
mJingleConnectionManager.startJingleFileTransfer(message);
|
||||
} else {
|
||||
MessagePacket outPacket = mMessageGenerator.generateOtrChat(message);
|
||||
if (outPacket != null) {
|
||||
mMessageGenerator.addDelay(outPacket, message.getTimeSent());
|
||||
message.setStatus(Message.STATUS_SEND);
|
||||
databaseBackend.updateMessage(message, false);
|
||||
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);
|
||||
|
@ -4973,10 +4854,7 @@ public class XmppConnectionService extends Service {
|
|||
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) {
|
||||
|
|
|
@ -60,7 +60,6 @@ import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
|||
import eu.siacs.conversations.ui.util.GridManager;
|
||||
import eu.siacs.conversations.ui.util.JidDialog;
|
||||
import eu.siacs.conversations.utils.Compatibility;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.EmojiWrapper;
|
||||
import eu.siacs.conversations.utils.Emoticons;
|
||||
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||
|
@ -69,11 +68,11 @@ import eu.siacs.conversations.utils.Namespace;
|
|||
import eu.siacs.conversations.utils.TimeFrameUtils;
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import eu.siacs.conversations.utils.XmppUri;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import me.drakeet.support.toast.ToastCompat;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
import static eu.siacs.conversations.ui.util.IntroHelper.showIntro;
|
||||
|
||||
|
@ -577,26 +576,6 @@ 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 = view.findViewById(R.id.key);
|
||||
TextView keyType = view.findViewById(R.id.key_type);
|
||||
ImageButton removeButton = 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(v -> confirmToDeleteFingerprint(otrFingerprint));
|
||||
}
|
||||
}
|
||||
final AxolotlService axolotlService = contact.getAccount().getAxolotlService();
|
||||
if (Config.supportOmemo() && axolotlService != null) {
|
||||
final Collection<XmppAxolotlSession> sessions = axolotlService.findSessionsForContact(contact);
|
||||
|
@ -671,21 +650,6 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
|||
}
|
||||
}
|
||||
|
||||
protected void confirmToDeleteFingerprint(final String fingerprint) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.delete_fingerprint);
|
||||
builder.setMessage(R.string.sure_delete_fingerprint);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(R.string.delete,
|
||||
(dialog, which) -> {
|
||||
if (contact.deleteOtrFingerprint(fingerprint)) {
|
||||
populateView();
|
||||
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
public void onBackendConnected() {
|
||||
if (accountJid != null && contactJid != null) {
|
||||
Account account = xmppConnectionService.findAccountByJid(accountJid);
|
||||
|
|
|
@ -67,8 +67,6 @@ import androidx.databinding.DataBindingUtil;
|
|||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
import net.java.otr4j.session.SessionStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -202,12 +200,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
private Toast messageLoaderToast;
|
||||
private ConversationsActivity activity;
|
||||
private Menu mOptionsMenu;
|
||||
protected OnClickListener clickToVerify = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
activity.verifyOtrSessionDialog(conversation, v);
|
||||
}
|
||||
};
|
||||
|
||||
private boolean reInitRequiredOnStart = true;
|
||||
private MediaPreviewAdapter mediaPreviewAdapter;
|
||||
|
@ -426,18 +418,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
}
|
||||
}
|
||||
};
|
||||
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(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
|
||||
intent.putExtra(VerifyOTRActivity.EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
|
||||
intent.putExtra("mode", VerifyOTRActivity.MODE_ANSWER_QUESTION);
|
||||
startActivity(intent);
|
||||
activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
|
||||
}
|
||||
};
|
||||
|
||||
protected OnClickListener clickToDecryptListener = new OnClickListener() {
|
||||
|
||||
|
@ -908,9 +888,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
message.setUuid(UUID.randomUUID().toString());
|
||||
}
|
||||
switch (conversation.getNextEncryption()) {
|
||||
case Message.ENCRYPTION_OTR:
|
||||
sendOtrMessage(message);
|
||||
break;
|
||||
case Message.ENCRYPTION_PGP:
|
||||
sendPgpMessage(message);
|
||||
break;
|
||||
|
@ -1474,7 +1451,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
}
|
||||
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);
|
||||
|
@ -1666,10 +1642,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
updated = conversation.setNextEncryption(Message.ENCRYPTION_NONE);
|
||||
item.setChecked(true);
|
||||
break;
|
||||
case R.id.encryption_choice_otr:
|
||||
updated = conversation.setNextEncryption(Message.ENCRYPTION_OTR);
|
||||
item.setChecked(true);
|
||||
break;
|
||||
case R.id.encryption_choice_pgp:
|
||||
if (activity.hasPgp()) {
|
||||
if (conversation.getAccount().getPgpSignature() != null) {
|
||||
|
@ -1867,19 +1839,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
activity.xmppConnectionService.getHttpConnectionManager().createNewDownloadConnection(message, true);
|
||||
}
|
||||
|
||||
private OnClickListener OTRwarning = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
final Uri uri = Uri.parse("https://github.com/kriztan/Pix-Art-Messenger/blob/master/docs/encryption.md");
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
startActivity(browserIntent);
|
||||
} catch (Exception e) {
|
||||
ToastCompat.makeText(activity, R.string.no_application_found_to_open_link, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
protected void clearHistoryDialog(final Conversation conversation) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
@ -2685,27 +2644,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
}
|
||||
} 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.getNextEncryption() == Message.ENCRYPTION_OTR) {
|
||||
showSnackbar(R.string.otr_warning, R.string.readmore, OTRwarning);
|
||||
} 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
|
||||
&& !conversation.isBlocked()
|
||||
&& conversation.isWithStranger()) {
|
||||
showSnackbar(R.string.received_message_from_stranger, R.string.block, mBlockClickListener);
|
||||
} else if (activity.xmppConnectionService.warnUnecryptedChat()) {
|
||||
if (conversation.getNextEncryption() == Message.ENCRYPTION_NONE && conversation.isSingleOrPrivateAndNonAnonymous() && ((Config.supportOmemo() && Conversation.suitableForOmemoByDefault(conversation)) ||
|
||||
(Config.supportOpenPgp() && account.isPgpDecryptionServiceConnected()) || (
|
||||
mode == Conversation.MODE_SINGLE && Config.supportOtr()))) {
|
||||
(Config.supportOpenPgp() && account.isPgpDecryptionServiceConnected()))) {
|
||||
if (ENCRYPTION_EXCEPTIONS.contains(conversation.getJid().toString()) || conversation.getJid().toString().equals(account.getJid().getDomain())) {
|
||||
hideSnackbar();
|
||||
} else {
|
||||
|
@ -3082,17 +3023,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
builder.create().show();
|
||||
}
|
||||
|
||||
protected void sendOtrMessage(final Message message) {
|
||||
final ConversationsActivity activity = (ConversationsActivity) getActivity();
|
||||
final XmppConnectionService xmppService = activity.xmppConnectionService;
|
||||
activity.selectPresence(conversation,
|
||||
() -> {
|
||||
message.setCounterpart(conversation.getNextCounterpart());
|
||||
xmppService.sendMessage(message);
|
||||
messageSent();
|
||||
});
|
||||
}
|
||||
|
||||
public void appendText(String text, final boolean doNotAppend) {
|
||||
if (text == null) {
|
||||
return;
|
||||
|
|
|
@ -60,8 +60,6 @@ import androidx.appcompat.app.ActionBar;
|
|||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import net.java.otr4j.session.SessionStatus;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -808,33 +806,6 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
|
|||
}
|
||||
}
|
||||
|
||||
public void verifyOtrSessionDialog(final Conversation conversation, View view) {
|
||||
if (!conversation.hasValidOtrSession() || conversation.getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
|
||||
ToastCompat.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(menuItem -> {
|
||||
Intent intent = new Intent(ConversationsActivity.this, VerifyOTRActivity.class);
|
||||
intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
|
||||
intent.putExtra("contact", conversation.getContact().getJid().asBareJid().toString());
|
||||
intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.ask_question:
|
||||
intent.putExtra("mode", VerifyOTRActivity.MODE_ASK_QUESTION);
|
||||
break;
|
||||
}
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
|
||||
return true;
|
||||
});
|
||||
popup.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConversationArchived(Conversation conversation) {
|
||||
if (performRedirectIfNecessary(conversation, false)) {
|
||||
|
|
|
@ -1297,25 +1297,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
|||
} else {
|
||||
this.binding.pgpFingerprintBox.setVisibility(View.GONE);
|
||||
}
|
||||
final String otrFingerprint = this.mAccount.getOtrFingerprint();
|
||||
if (otrFingerprint != null && Config.supportOtr()) {
|
||||
if ("otr".equals(messageFingerprint)) {
|
||||
this.binding.otrFingerprintDesc.setTextColor(ContextCompat.getColor(this, R.color.accent));
|
||||
}
|
||||
this.binding.otrFingerprintBox.setVisibility(View.VISIBLE);
|
||||
this.binding.otrFingerprint.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
|
||||
this.binding.actionCopyToClipboard.setVisibility(View.VISIBLE);
|
||||
this.binding.actionCopyToClipboard.setOnClickListener(v -> {
|
||||
if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(otrFingerprint), R.string.otr_fingerprint)) {
|
||||
ToastCompat.makeText(
|
||||
EditAccountActivity.this,
|
||||
R.string.toast_message_otr_fingerprint,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.binding.otrFingerprintBox.setVisibility(View.GONE);
|
||||
}
|
||||
final String ownAxolotlFingerprint = this.mAccount.getAxolotlService().getOwnFingerprint();
|
||||
if (ownAxolotlFingerprint != null && Config.supportOmemo()) {
|
||||
this.binding.axolotlFingerprintBox.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -1,450 +0,0 @@
|
|||
package eu.siacs.conversations.ui;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
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 androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import net.java.otr4j.OtrException;
|
||||
import net.java.otr4j.session.Session;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
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.xmpp.Jid;
|
||||
import me.drakeet.support.toast.ToastCompat;
|
||||
|
||||
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());
|
||||
ToastCompat.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());
|
||||
ToastCompat.makeText(this, R.string.verified, Toast.LENGTH_SHORT).show();
|
||||
updateView();
|
||||
return true;
|
||||
} else {
|
||||
ToastCompat.makeText(this, R.string.could_not_verify_fingerprint, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAccountOnline() {
|
||||
if (this.mAccount.getStatus() != Account.State.ONLINE) {
|
||||
ToastCompat.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.of(intent.getExtras().getString("contact")));
|
||||
if (this.mConversation == null) {
|
||||
return false;
|
||||
}
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
ignored.printStackTrace();
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
this.mode = intent.getIntExtra("mode", MODE_MANUAL_VERIFICATION);
|
||||
// todo scan OTR fingerprint
|
||||
if (this.mode == MODE_SCAN_FINGERPRINT) {
|
||||
Log.d(Config.LOGTAG, "Scan OTR fingerprint is not implemented in this version");
|
||||
//new IntentIntegrator(this).initiateScan();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
// todo onActivityResult for OTR scan
|
||||
Log.d(Config.LOGTAG, "Scan OTR fingerprint result is not implemented in this version");
|
||||
/*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.setText(text);
|
||||
button.setOnClickListener(listener);
|
||||
}
|
||||
|
||||
protected void deactivateButton(Button button, int text) {
|
||||
button.setEnabled(false);
|
||||
button.setText(text);
|
||||
button.setOnClickListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_verify_otr);
|
||||
this.mRemoteFingerprint = findViewById(R.id.remote_fingerprint);
|
||||
this.mYourFingerprint = findViewById(R.id.your_fingerprint);
|
||||
this.mLeftButton = findViewById(R.id.left_button);
|
||||
this.mRightButton = findViewById(R.id.right_button);
|
||||
this.mVerificationExplain = findViewById(R.id.verification_explanation);
|
||||
this.mStatusMessage = findViewById(R.id.status_message);
|
||||
this.mSharedSecretSecret = findViewById(R.id.shared_secret_secret);
|
||||
this.mSharedSecretHintEditable = findViewById(R.id.shared_secret_hint_editable);
|
||||
this.mSharedSecretHint = findViewById(R.id.shared_secret_hint);
|
||||
this.mManualVerificationArea = findViewById(R.id.manual_verification_area);
|
||||
this.mSmpVerificationArea = 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() {
|
||||
final 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();
|
||||
}
|
||||
}
|
|
@ -39,7 +39,6 @@ import android.provider.Settings;
|
|||
import android.text.InputType;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -55,18 +54,13 @@ import androidx.appcompat.app.AppCompatDelegate;
|
|||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
|
@ -87,18 +81,16 @@ import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinde
|
|||
import eu.siacs.conversations.ui.util.PresenceSelector;
|
||||
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
|
||||
import eu.siacs.conversations.utils.AccountUtils;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.ExceptionHelper;
|
||||
import eu.siacs.conversations.utils.MenuDoubleTabUtil;
|
||||
import eu.siacs.conversations.utils.ThemeHelper;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import me.drakeet.support.toast.ToastCompat;
|
||||
import pl.droidsonroids.gif.GifDrawable;
|
||||
|
||||
import static eu.siacs.conversations.ui.SettingsActivity.ENABLE_OTR_ENCRYPTION;
|
||||
import static eu.siacs.conversations.ui.SettingsActivity.USE_BUNDLED_EMOJIS;
|
||||
import static eu.siacs.conversations.ui.SettingsActivity.USE_INTERNAL_UPDATER;
|
||||
|
||||
|
@ -455,10 +447,6 @@ public abstract class XmppActivity extends ActionBarActivity {
|
|||
return getBooleanPreference("unicolored_chatbg", R.bool.use_unicolored_chatbg);
|
||||
}
|
||||
|
||||
public boolean enableOTR() {
|
||||
return getBooleanPreference(ENABLE_OTR_ENCRYPTION, R.bool.enable_otr);
|
||||
}
|
||||
|
||||
public void setBubbleColor(final View v, final int backgroundColor, final int borderColor) {
|
||||
GradientDrawable shape = (GradientDrawable) v.getBackground();
|
||||
shape.setColor(backgroundColor);
|
||||
|
@ -868,19 +856,8 @@ public abstract class XmppActivity extends ActionBarActivity {
|
|||
|
||||
public void selectPresence(final Conversation conversation, final PresenceSelector.OnPresenceSelected listener) {
|
||||
final Contact contact = conversation.getContact();
|
||||
|
||||
if (conversation.hasValidOtrSession()) {
|
||||
SessionID id = conversation.getOtrSession().getSessionID();
|
||||
Jid jid;
|
||||
try {
|
||||
jid = Jid.of(id.getAccountID() + "/" + id.getUserID());
|
||||
} catch (IllegalArgumentException e) {
|
||||
jid = null;
|
||||
}
|
||||
conversation.setNextCounterpart(jid);
|
||||
listener.onPresenceSelected();
|
||||
} else if (!contact.showInRoster()) {
|
||||
showAddToRosterDialog(conversation);
|
||||
if (!contact.showInRoster()) {
|
||||
showAddToRosterDialog(conversation.getContact());
|
||||
} else {
|
||||
final Presences presences = contact.getPresences();
|
||||
if (presences.size() == 0) {
|
||||
|
@ -909,56 +886,6 @@ public abstract class XmppActivity extends ActionBarActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private void showPresenceSelectionDialog(Presences presences, final Conversation conversation, final OnPresenceSelected listener) {
|
||||
final Contact contact = conversation.getContact();
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(getString(R.string.choose_presence));
|
||||
final String[] resourceArray = presences.toResourceArray();
|
||||
Pair<Map<String, String>, Map<String, String>> typeAndName = presences.toTypeAndNameMap();
|
||||
final Map<String, String> resourceTypeMap = typeAndName.first;
|
||||
final Map<String, String> resourceNameMap = typeAndName.second;
|
||||
final String[] readableIdentities = new String[resourceArray.length];
|
||||
final AtomicInteger selectedResource = new AtomicInteger(0);
|
||||
for (int i = 0; i < resourceArray.length; ++i) {
|
||||
String resource = resourceArray[i];
|
||||
if (resource.equals(contact.getLastResource())) {
|
||||
selectedResource.set(i);
|
||||
}
|
||||
String type = resourceTypeMap.get(resource);
|
||||
String name = resourceNameMap.get(resource);
|
||||
if (type != null) {
|
||||
if (Collections.frequency(resourceTypeMap.values(), type) == 1) {
|
||||
readableIdentities[i] = PresenceSelector.translateType(this, type);
|
||||
} else if (name != null) {
|
||||
if (Collections.frequency(resourceNameMap.values(), name) == 1
|
||||
|| CryptoHelper.UUID_PATTERN.matcher(resource).matches()) {
|
||||
readableIdentities[i] = PresenceSelector.translateType(this, type) + " (" + name + ")";
|
||||
} else {
|
||||
readableIdentities[i] = PresenceSelector.translateType(this, type) + " (" + name + " / " + resource + ")";
|
||||
}
|
||||
} else {
|
||||
readableIdentities[i] = PresenceSelector.translateType(this, type) + " (" + resource + ")";
|
||||
}
|
||||
} else {
|
||||
readableIdentities[i] = resource;
|
||||
}
|
||||
}
|
||||
builder.setSingleChoiceItems(readableIdentities,
|
||||
selectedResource.get(),
|
||||
(dialog, which) -> selectedResource.set(which));
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(R.string.ok, (dialog, which) -> {
|
||||
try {
|
||||
Jid next = Jid.of(contact.getJid().getLocal(), contact.getJid().getDomain(), resourceArray[selectedResource.get()]);
|
||||
conversation.setNextCounterpart(next);
|
||||
} catch (IllegalArgumentException e) {
|
||||
conversation.setNextCounterpart(null);
|
||||
}
|
||||
listener.onPresenceSelected();
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) {
|
||||
|
|
|
@ -104,7 +104,6 @@ public class ConversationMenuConfigurator {
|
|||
return;
|
||||
}
|
||||
final MenuItem none = menu.findItem(R.id.encryption_choice_none);
|
||||
final MenuItem otr = menu.findItem(R.id.encryption_choice_otr);
|
||||
final MenuItem pgp = menu.findItem(R.id.encryption_choice_pgp);
|
||||
final MenuItem axolotl = menu.findItem(R.id.encryption_choice_axolotl);
|
||||
|
||||
|
@ -133,10 +132,6 @@ public class ConversationMenuConfigurator {
|
|||
menuSecure.setIcon(R.drawable.ic_lock_white_24dp);
|
||||
}
|
||||
|
||||
otr.setVisible(Config.supportOtr() && activity.enableOTR());
|
||||
if (conversation.getMode() == Conversation.MODE_MULTI) {
|
||||
otr.setVisible(false);
|
||||
}
|
||||
pgp.setVisible(Config.supportOpenPgp());
|
||||
none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI);
|
||||
axolotl.setVisible(Config.supportOmemo());
|
||||
|
@ -144,9 +139,6 @@ public class ConversationMenuConfigurator {
|
|||
case Message.ENCRYPTION_NONE:
|
||||
none.setChecked(true);
|
||||
break;
|
||||
case Message.ENCRYPTION_OTR:
|
||||
otr.setChecked(true);
|
||||
break;
|
||||
case Message.ENCRYPTION_PGP:
|
||||
pgp.setChecked(true);
|
||||
break;
|
||||
|
|
|
@ -567,8 +567,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)) {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package eu.siacs.conversations.xmpp.jid;
|
||||
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
public final class OtrJidHelper {
|
||||
|
||||
public static Jid fromSessionID(final SessionID id) throws IllegalArgumentException {
|
||||
if (id.getUserID().isEmpty()) {
|
||||
return Jid.of(id.getAccountID());
|
||||
} else {
|
||||
return Jid.of(id.getAccountID() + "/" + id.getUserID());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -729,58 +729,6 @@
|
|||
</LinearLayout>
|
||||
</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_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/key_actions"
|
||||
android:layout_toLeftOf="@+id/key_actions"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/otr_fingerprint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Fingerprint" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/otr_fingerprint_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/otr_fingerprint"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Caption" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/key_actions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_copy_to_clipboard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
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" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/axolotl_fingerprint_box"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/color_background_tertiary">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_above="@+id/button_bar">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/activity_vertical_margin"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/verification_explanation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manual_verification_area"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/your_fingerprint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeBody"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/your_fingerprint"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeInfo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/remote_fingerprint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:fontFamily="monospace"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeBody"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="@string/remote_fingerprint"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeInfo" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/smp_verification_area"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/verified"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeHeadline"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/shared_secret_hint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textSize="?attr/TextSizeBody"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/shared_secret_hint_editable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="@string/shared_secret_hint"
|
||||
android:inputType="textAutoComplete"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textColorHint="?attr/colorAccent"
|
||||
android:textSize="?attr/TextSizeBody" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/shared_secret_secret"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/shared_secret_secret"
|
||||
android:inputType="textPassword"
|
||||
android:textColor="?attr/text_Color_Main"
|
||||
android:textColorHint="?attr/colorAccent"
|
||||
android:textSize="?attr/TextSizeBody" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentBottom="true">
|
||||
|
||||
<Button
|
||||
android:id="@+id/left_button"
|
||||
style="@style/Widget.Conversations.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginTop="7dp"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:background="?attr/color_background_primary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/right_button"
|
||||
style="@style/Widget.Conversations.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/activatedBackgroundIndicator"
|
||||
android:padding="12dp"
|
||||
android:id="@+id/presence_template">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_toLeftOf="@+id/delete_button"
|
||||
android:layout_toStartOf="@+id/delete_button"
|
||||
android:layout_marginRight="8dp">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/presence_status_message"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingTop="1dp"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Tag"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
<ImageButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/image_button_padding"
|
||||
android:alpha="?attr/icon_alpha"
|
||||
android:src="?attr/icon_remove"/>
|
||||
</RelativeLayout>
|
|
@ -37,9 +37,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" />
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/ask_question"
|
||||
android:title="@string/ask_question" />
|
||||
|
||||
<item
|
||||
android:id="@+id/manual_verification"
|
||||
android:title="@string/manually_verify" />
|
||||
|
||||
</menu>
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_show_qr_code"
|
||||
android:title="@string/show_qr_code"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
app:showAsAction="never"
|
||||
android:title="@string/action_settings" />
|
||||
</menu>
|
|
@ -24,7 +24,6 @@
|
|||
\n\nhttps://github.com/ge0rg/MemorizingTrustManager\n(The MIT License (MIT))
|
||||
\n\nhttps://github.com/MiniDNS/minidns\n(WTFPL)
|
||||
\n\nhttps://github.com/open-keychain/openkeychain-api-lib\n(Apache License, Version 2.0)
|
||||
\n\nhttps://github.com/jitsi/otr4j\n(LGPL-3.0)
|
||||
\n\nhttps://developer.android.com/tools/support-library\n(Apache License, Version 2.0)
|
||||
\n\nhttps://github.com/google/material-design-icons\n(CC BY 4.0)
|
||||
\n\nhttps://github.com/leolin310148/ShortcutBadger\n(Apache License, Version 2.0)
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
<bool name="use_internal_updater">true</bool>
|
||||
<bool name="show_own_accounts">true</bool>
|
||||
<bool name="vibrate_in_chat">true</bool>
|
||||
<bool name="enable_otr">false</bool>
|
||||
<integer name="auto_accept_filesize_wifi">10485760</integer>
|
||||
<integer name="auto_accept_filesize_mobile">524288</integer>
|
||||
<integer name="auto_accept_filesize_roaming">0</integer>
|
||||
|
|
|
@ -8,4 +8,5 @@
|
|||
<item name="TAG_FINGERPRINT" type="id" />
|
||||
<item name="TAG_FINGERPRINT_STATUS" type="id" />
|
||||
<item name="TAG_AUDIO_PLAYER_VIEW_HOLDER" type="id" />
|
||||
<item name="status" type="id" />
|
||||
</resources>
|
|
@ -77,7 +77,6 @@
|
|||
<string name="choose_presence">Choose device</string>
|
||||
<string name="send_unencrypted_message">Send unencrypted message</string>
|
||||
<string name="send_message_to_x">Send message to %s</string>
|
||||
<string name="send_otr_message">Send OTR encrypted message</string>
|
||||
<string name="send_omemo_message">Send OMEMO encrypted message</string>
|
||||
<string name="send_omemo_x509_message">Send v\\OMEMO encrypted message</string>
|
||||
<string name="send_pgp_message">Send OpenPGP encrypted message</string>
|
||||
|
@ -184,11 +183,8 @@
|
|||
<string name="last_seen_day">1 day ago</string>
|
||||
<string name="last_seen_days">%d days ago</string>
|
||||
<string name="install_openkeychain">Encrypted message. Please install OpenKeychain to decrypt.</string>
|
||||
<string name="unknown_otr_fingerprint">Unknown OTR fingerprint</string>
|
||||
<string name="openpgp_messages_found">OpenPGP encrypted messages found</string>
|
||||
<string name="your_fingerprint">Your fingerprint</string>
|
||||
<string name="otr_fingerprint">OTR fingerprint</string>
|
||||
<string name="otr_fingerprint_selected_message">OTR fingerprint of message</string>
|
||||
<string name="openpgp_key_id">OpenPGP Key ID</string>
|
||||
<string name="omemo_fingerprint">OMEMO fingerprint</string>
|
||||
<string name="omemo_fingerprint_x509">v\\OMEMO fingerprint</string>
|
||||
|
@ -266,7 +262,6 @@
|
|||
<string name="pref_expert_options_other">Other</string>
|
||||
<string name="pref_autojoin">Synchronize with bookmarks</string>
|
||||
<string name="pref_autojoin_summary">Join and leave group chats according to auto-join flag in your bookmarks.</string>
|
||||
<string name="toast_message_otr_fingerprint">OTR fingerprint copied to clipboard!</string>
|
||||
<string name="toast_message_omemo_fingerprint">OMEMO fingerprint copied to clipboard!</string>
|
||||
<string name="conference_banned">You are banned from this group chat</string>
|
||||
<string name="conference_members_only">This group chat is members only</string>
|
||||
|
@ -286,7 +281,6 @@
|
|||
<string name="show_qr_code">Show QR code</string>
|
||||
<string name="show_block_list">Show block list</string>
|
||||
<string name="account_details">Account details</string>
|
||||
<string name="verify_otr">Verify OTR</string>
|
||||
<string name="remote_fingerprint">Remote Fingerprint</string>
|
||||
<string name="shared_secret_hint">Hint or Question</string>
|
||||
<string name="shared_secret_secret">Shared Secret</string>
|
||||
|
@ -299,7 +293,6 @@
|
|||
<string name="finish">Finish</string>
|
||||
<string name="verified">Verified!</string>
|
||||
<string name="smp_requested">Contact requested SMP verification</string>
|
||||
<string name="no_otr_session_found">No valid OTR session has been found!</string>
|
||||
<string name="conversations_foreground_service" translatable="false">Pix-Art Messenger</string>
|
||||
<string name="pref_create_backup">Create backup</string>
|
||||
<string name="pref_create_backup_summary">Write backup files to %s</string>
|
||||
|
@ -321,13 +314,11 @@
|
|||
<string name="no_application_found_to_open_file">No application found to open file</string>
|
||||
<string name="could_not_verify_fingerprint">Could not verify fingerprint</string>
|
||||
<string name="manually_verify">Manually verify</string>
|
||||
<string name="are_you_sure_verify_fingerprint">Are you sure that you want to verify your contacts OTR fingerprint?</string>
|
||||
<string name="pref_show_dynamic_tags">Show dynamic tags</string>
|
||||
<string name="pref_show_dynamic_tags_summary">Display read-only tags underneath contacts</string>
|
||||
<string name="no_conference_server_found">No group chat server found</string>
|
||||
<string name="conference_creation_failed">Group chat creation failed!</string>
|
||||
<string name="account_image_description">Account avatar</string>
|
||||
<string name="copy_otr_clipboard_description">Copy OTR fingerprint to clipboard</string>
|
||||
<string name="copy_omemo_clipboard_description">Copy OMEMO fingerprint to clipboard</string>
|
||||
<string name="regenerate_omemo_key">Regenerate OMEMO key</string>
|
||||
<string name="clear_other_devices">Clear devices</string>
|
||||
|
@ -341,7 +332,6 @@
|
|||
<string name="updating">Updating…</string>
|
||||
<string name="password_changed">Password changed!</string>
|
||||
<string name="could_not_change_password">Could not change password</string>
|
||||
<string name="otr_session_not_started">Send a message to start an encrypted chat</string>
|
||||
<string name="ask_question">Ask question</string>
|
||||
<string name="smp_explain_question">If you and your contact have a secret in common that no one else knows (like an inside joke or simply what you had for lunch the last time you met) you can use that secret to verify each other’s fingerprints.\n\nYou provide a hint or a question for your contact who will respond with a case-sensitive answer.</string>
|
||||
<string name="smp_explain_answer">Your contact would like to verify your fingerprint by challenging you with a shared secret. Your contact provided the following hint or question for that secret.</string>
|
||||
|
@ -989,8 +979,6 @@
|
|||
<string name="pref_theme_orange">Orange</string>
|
||||
<string name="pref_theme_color_options_summary">Select the theme color palette</string>
|
||||
<string name="pref_theme_color_options">Theme color</string>
|
||||
<string name="pref_enable_otr_summary">Enable OTR encryption for message encryption</string>
|
||||
<string name="pref_enable_otr">Enable OTR encryption</string>
|
||||
<string name="magic_create_text_on_x">You have been invited to %1$s. We will guide you through the process of creating an account.\nWhen picking %1$s as a provider you will be able to communicate with users of other providers by giving them your full XMPP address.</string>
|
||||
<string name="account_status_regis_invalid_token">Invalid registration token</string>
|
||||
<string name="magic_create_text_fixed">You have been invited to %1$s. A username has already been picked for you. We will guide you through the process of creating an account.\nYou will be able to communicate with users of other providers by giving them your full XMPP address.</string>
|
||||
|
@ -1048,7 +1036,6 @@
|
|||
<string name="only_one_call_at_a_time">You can only have one call at a time.</string>
|
||||
<string name="missed_call">Missed call</string>
|
||||
<string name="could_not_switch_camera">Could not switch camera</string>
|
||||
<string name="otr_warning">The support of OTR encryption will drop in June 2020. Click read more to get more information. A link in a browser will open.</string>
|
||||
<string name="readmore">Read more</string>
|
||||
<string name="add_to_favorites">Add to favorites</string>
|
||||
<string name="remove_from_favorites">Remove from favorites</string>
|
||||
|
|
|
@ -468,11 +468,6 @@
|
|||
android:key="delete_omemo_identities"
|
||||
android:summary="@string/pref_delete_omemo_identities_summary"
|
||||
android:title="@string/pref_delete_omemo_identities" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="@bool/enable_otr"
|
||||
android:key="enable_otr_encryption"
|
||||
android:summary="@string/pref_enable_otr_summary"
|
||||
android:title="@string/pref_enable_otr" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="@bool/dont_trust_system_cas"
|
||||
android:key="dont_trust_system_cas"
|
||||
|
|
Loading…
Reference in a new issue