Commit 50696697 authored by Grigory Fedorov's avatar Grigory Fedorov

Merge branch 'release/1.0.19'

parents a78c21b6 33030fb9
...@@ -7,8 +7,8 @@ android { ...@@ -7,8 +7,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 22
versionCode 184 versionCode 191
versionName '1.0.12' versionName '1.0.19'
} }
compileOptions { compileOptions {
...@@ -41,8 +41,8 @@ repositories { ...@@ -41,8 +41,8 @@ repositories {
} }
dependencies { dependencies {
compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:support-v13:22.0.0' compile 'com.android.support:support-v13:22.2.0'
compile 'com.github.ksoichiro:android-observablescrollview:1.5.0' compile 'com.github.ksoichiro:android-observablescrollview:1.5.0'
compile 'de.hdodenhof:circleimageview:1.2.2' compile 'de.hdodenhof:circleimageview:1.2.2'
compile 'com.melnykov:floatingactionbutton:1.2.0' compile 'com.melnykov:floatingactionbutton:1.2.0'
......
...@@ -74,22 +74,17 @@ import java.util.concurrent.ThreadFactory; ...@@ -74,22 +74,17 @@ import java.util.concurrent.ThreadFactory;
* @author alexander.ivanov * @author alexander.ivanov
*/ */
public class OTRManager implements OtrEngineHost, OtrEngineListener, public class OTRManager implements OtrEngineHost, OtrEngineListener,
OnLoadListener, OnAccountAddedListener, OnAccountRemovedListener, OnLoadListener, OnAccountAddedListener, OnAccountRemovedListener, OnCloseListener {
OnCloseListener {
private final static OTRManager instance; private final static OTRManager instance;
private static Map<SecurityOtrMode, OtrPolicy> POLICIES; private static Map<SecurityOtrMode, OtrPolicy> POLICIES;
static { static {
POLICIES = new HashMap<SettingsManager.SecurityOtrMode, OtrPolicy>(); POLICIES = new HashMap<>();
POLICIES.put(SecurityOtrMode.disabled, new OtrPolicy( POLICIES.put(SecurityOtrMode.disabled, new OtrPolicy(OtrPolicy.NEVER));
OtrPolicy.NEVER)); POLICIES.put(SecurityOtrMode.manual, new OtrPolicy(OtrPolicy.OTRL_POLICY_MANUAL & ~OtrPolicy.ALLOW_V1));
POLICIES.put(SecurityOtrMode.manual, new OtrPolicy( POLICIES.put(SecurityOtrMode.auto, new OtrPolicy(OtrPolicy.OPPORTUNISTIC & ~OtrPolicy.ALLOW_V1));
OtrPolicy.OTRL_POLICY_MANUAL & ~OtrPolicy.ALLOW_V1)); POLICIES.put(SecurityOtrMode.required, new OtrPolicy(OtrPolicy.OTRL_POLICY_ALWAYS & ~OtrPolicy.ALLOW_V1));
POLICIES.put(SecurityOtrMode.auto, new OtrPolicy(
OtrPolicy.OPPORTUNISTIC & ~OtrPolicy.ALLOW_V1));
POLICIES.put(SecurityOtrMode.required, new OtrPolicy(
OtrPolicy.OTRL_POLICY_ALWAYS & ~OtrPolicy.ALLOW_V1));
} }
static { static {
...@@ -104,8 +99,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -104,8 +99,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
*/ */
private final NestedNestedMaps<String, Boolean> fingerprints; private final NestedNestedMaps<String, Boolean> fingerprints;
/** /**
* Fingerprint of encrypted or encrypted and verified session for user in * Fingerprint of encrypted or encrypted and verified session for user in account.
* account.
*/ */
private final NestedMap<String> actives; private final NestedMap<String> actives;
/** /**
...@@ -122,21 +116,17 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -122,21 +116,17 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
private final ExecutorService keyPairGenerator; private final ExecutorService keyPairGenerator;
private OTRManager() { private OTRManager() {
smRequestProvider = new EntityNotificationProvider<SMRequest>( smRequestProvider = new EntityNotificationProvider<>(R.drawable.ic_stat_ic_help_black);
R.drawable.ic_stat_ic_help_black); smProgressProvider = new EntityNotificationProvider<>(R.drawable.ic_stat_ic_play_circle_fill);
smProgressProvider = new EntityNotificationProvider<SMProgress>(
R.drawable.ic_stat_ic_play_circle_fill);
smProgressProvider.setCanClearNotifications(false); smProgressProvider.setCanClearNotifications(false);
fingerprints = new NestedNestedMaps<String, Boolean>(); fingerprints = new NestedNestedMaps<>();
actives = new NestedMap<String>(); actives = new NestedMap<>();
finished = new NestedMap<Boolean>(); finished = new NestedMap<>();
sessions = new NestedMap<Session>(); sessions = new NestedMap<>();
keyPairGenerator = Executors keyPairGenerator = Executors.newSingleThreadExecutor(new ThreadFactory() {
.newSingleThreadExecutor(new ThreadFactory() {
@Override @Override
public Thread newThread(Runnable runnable) { public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, Thread thread = new Thread(runnable, "Key pair generator service");
"Key pair generator service");
thread.setPriority(Thread.MIN_PRIORITY); thread.setPriority(Thread.MIN_PRIORITY);
thread.setDaemon(true); thread.setDaemon(true);
return thread; return thread;
...@@ -150,7 +140,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -150,7 +140,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
@Override @Override
public void onLoad() { public void onLoad() {
final NestedNestedMaps<String, Boolean> fingerprints = new NestedNestedMaps<String, Boolean>(); final NestedNestedMaps<String, Boolean> fingerprints = new NestedNestedMaps<>();
Cursor cursor = OTRTable.getInstance().list(); Cursor cursor = OTRTable.getInstance().list();
try { try {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
...@@ -175,133 +165,120 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -175,133 +165,120 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
private void onLoaded(NestedNestedMaps<String, Boolean> fingerprints) { private void onLoaded(NestedNestedMaps<String, Boolean> fingerprints) {
this.fingerprints.addAll(fingerprints); this.fingerprints.addAll(fingerprints);
NotificationManager.getInstance().registerNotificationProvider( NotificationManager.getInstance().registerNotificationProvider(smRequestProvider);
smRequestProvider); NotificationManager.getInstance().registerNotificationProvider(smProgressProvider);
NotificationManager.getInstance().registerNotificationProvider(
smProgressProvider);
} }
private Session getOrCreateSession(String account, String user) { public void startSession(String account, String user) throws NetworkException {
Session session = sessions.get(account, user); LogManager.i(this, "Starting session for " + user);
if (session != null)
return session;
AccountItem accountItem = AccountManager.getInstance().getAccount(
account);
session = new Session(new SessionID(account, user,
accountItem == null ? "" : accountItem.getConnectionSettings()
.getProtocol().toString()), this);
session.addOtrEngineListener(this);
sessions.put(account, user, session);
return session;
}
public void startSession(String account, String user)
throws NetworkException {
try { try {
getOrCreateSession(account, user).startSession(); getOrCreateSession(account, user).startSession();
} catch (OtrException e) { } catch (OtrException e) {
throw new NetworkException(R.string.OTR_ERROR, e); throw new NetworkException(R.string.OTR_ERROR, e);
} }
LogManager.i(this, "Started session for " + user);
} }
public void refreshSession(String account, String user) public void refreshSession(String account, String user) throws NetworkException {
throws NetworkException { LogManager.i(this, "Refreshing session for " + user);
try { try {
getOrCreateSession(account, user).refreshSession(); getOrCreateSession(account, user).refreshSession();
} catch (OtrException e) { } catch (OtrException e) {
throw new NetworkException(R.string.OTR_ERROR, e); throw new NetworkException(R.string.OTR_ERROR, e);
} }
LogManager.i(this, "Refreshed session for " + user);
} }
public void endSession(String account, String user) throws NetworkException { public void endSession(String account, String user) throws NetworkException {
LogManager.i(this, "Ending session for " + user);
try { try {
getOrCreateSession(account, user).endSession(); getOrCreateSession(account, user).endSession();
} catch (OtrException e) { } catch (OtrException e) {
throw new NetworkException(R.string.OTR_ERROR, e); throw new NetworkException(R.string.OTR_ERROR, e);
} }
AbstractChat abstractChat = MessageManager.getInstance().getChat( AbstractChat abstractChat = MessageManager.getInstance().getChat(account, user);
account, user); MessageArchiveManager.getInstance().setSaveMode(account, user, abstractChat.getThreadId(), SaveMode.body);
MessageArchiveManager.getInstance().setSaveMode(account, user, SSNManager.getInstance().setSessionOtrMode(account, user, abstractChat.getThreadId(), OtrMode.concede);
abstractChat.getThreadId(), SaveMode.body); LogManager.i(this, "Ended session for " + user);
SSNManager.getInstance().setSessionOtrMode(account, user, }
abstractChat.getThreadId(), OtrMode.concede);
} private Session getOrCreateSession(String account, String user) {
Session session = sessions.get(account, user);
private void injectMessage(String account, String user, String msg) if (session != null) {
throws OtrException { LogManager.i(this, "Found session with id " + session.getSessionID() + " with status " + session.getSessionStatus() + " for user " + user);
AbstractChat abstractChat = MessageManager.getInstance().getChat( return session;
account, user); }
LogManager.i(this, "Creating new session for " + user);
AccountItem accountItem = AccountManager.getInstance().getAccount(account);
session = new Session(new SessionID(account, user,
accountItem == null ? "" : accountItem.getConnectionSettings().getProtocol().toString()), this);
session.addOtrEngineListener(this);
sessions.put(account, user, session);
return session;
}
@Override
public void injectMessage(SessionID sessionID, String msg) throws OtrException {
injectMessage(sessionID.getAccountID(), sessionID.getUserID(), msg);
}
private void injectMessage(String account, String user, String msg) throws OtrException {
LogManager.i(this, "injectMessage. user: " + user + " message: " + msg);
AbstractChat abstractChat = MessageManager.getInstance().getChat(account, user);
try { try {
MessageArchiveManager.getInstance().setSaveMode(account, user, MessageArchiveManager.getInstance().setSaveMode(account, user, abstractChat.getThreadId(), SaveMode.fls);
abstractChat.getThreadId(), SaveMode.fls);
} catch (NetworkException e) { } catch (NetworkException e) {
throw new OtrException(e); throw new OtrException(e);
} }
SSNManager.getInstance().setSessionOtrMode(account, user, SSNManager.getInstance().setSessionOtrMode(account, user, abstractChat.getThreadId(), OtrMode.prefer);
abstractChat.getThreadId(), OtrMode.prefer);
try { try {
ConnectionManager.getInstance().sendPacket( ConnectionManager.getInstance()
abstractChat.getAccount(), .sendPacket(abstractChat.getAccount(), abstractChat.createMessagePacket(msg));
abstractChat.createMessagePacket(msg));
} catch (NetworkException e) { } catch (NetworkException e) {
throw new OtrException(e); throw new OtrException(e);
} }
} }
@Override @Override
public void injectMessage(SessionID sessionID, String msg) public void unreadableMessageReceived(SessionID sessionID) throws OtrException {
throws OtrException { LogManager.i(this, "unreadableMessageReceived");
injectMessage(sessionID.getAccountID(), sessionID.getUserID(), msg); newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_unreadable);
} }
/** /**
* Creates new action in specified chat. * Creates new action in specified chat.
*
* @param account
* @param user
* @param text
* @param action
*/ */
private void newAction(String account, String user, String text, private void newAction(String account, String user, String text, ChatAction action) {
ChatAction action) { LogManager.i(this, "newAction. text: " + text + " action " + action);
MessageManager.getInstance().getChat(account, user) MessageManager.getInstance().getChat(account, user).newAction(null, text, action);
.newAction(null, text, action);
}
@Override
public void unreadableMessageReceived(SessionID sessionID)
throws OtrException {
newAction(sessionID.getAccountID(), sessionID.getUserID(), null,
ChatAction.otr_unreadable);
} }
@Override @Override
public String getReplyForUnreadableMessage(SessionID sessionID) { public String getReplyForUnreadableMessage(SessionID sessionID) {
return Application.getInstance().getString( return Application.getInstance().getString(R.string.otr_unreadable_message);
R.string.otr_unreadable_message);
} }
@Override @Override
public void unencryptedMessageReceived(SessionID sessionID, String msg) public void unencryptedMessageReceived(SessionID sessionID, String msg) throws OtrException {
throws OtrException { LogManager.i(this, "unencrypted Message Received. " + msg);
throw new OtrException(new OTRUnencryptedException(msg)); throw new OtrException(new OTRUnencryptedException(msg));
} }
@Override @Override
public void showError(SessionID sessionID, String error) public void showError(SessionID sessionID, String error) throws OtrException {
throws OtrException { LogManager.i(this, "ShowError: " + error);
newAction(sessionID.getAccountID(), sessionID.getUserID(), error, newAction(sessionID.getAccountID(), sessionID.getUserID(), error, ChatAction.otr_error);
ChatAction.otr_error);
} }
@Override @Override
public void smpError(SessionID sessionID, int tlvType, boolean cheated) public void smpError(SessionID sessionID, int tlvType, boolean cheated) throws OtrException {
throws OtrException {
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null,
cheated ? ChatAction.otr_smp_cheated cheated ? ChatAction.otr_smp_cheated : ChatAction.otr_smp_failed);
: ChatAction.otr_smp_failed); if (cheated) {
if (cheated)
removeSMProgress(sessionID.getAccountID(), sessionID.getUserID()); removeSMProgress(sessionID.getAccountID(), sessionID.getUserID());
}
} }
@Override @Override
...@@ -312,18 +289,14 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -312,18 +289,14 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
@Override @Override
public void finishedSessionMessage(SessionID sessionID, String msgText) throws OtrException { public void finishedSessionMessage(SessionID sessionID, String msgText) throws OtrException {
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_finished_session);
ChatAction.otr_finished_session); throw new OtrException(new IllegalStateException(
throw new OtrException(
new IllegalStateException(
"Prevent from null to be returned. Just process it as regular exception.")); "Prevent from null to be returned. Just process it as regular exception."));
} }
@Override @Override
public void requireEncryptedMessage(SessionID sessionID, String msgText) public void requireEncryptedMessage(SessionID sessionID, String msgText) throws OtrException {
throws OtrException { throw new OtrException(new IllegalStateException(
throw new OtrException(
new IllegalStateException(
"Prevent from null to be returned. Just process it as regular exception.")); "Prevent from null to be returned. Just process it as regular exception."));
} }
...@@ -333,11 +306,10 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -333,11 +306,10 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
} }
private KeyPair getLocalKeyPair(String account) throws OtrException { private KeyPair getLocalKeyPair(String account) throws OtrException {
KeyPair keyPair = AccountManager.getInstance().getAccount(account) KeyPair keyPair = AccountManager.getInstance().getAccount(account).getKeyPair();
.getKeyPair(); if (keyPair == null) {
if (keyPair == null) throw new OtrException(new IllegalStateException("KeyPair is not ready, yet."));
throw new OtrException(new IllegalStateException( }
"KeyPair is not ready, yet."));
return keyPair; return keyPair;
} }
...@@ -350,9 +322,11 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -350,9 +322,11 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
public void sessionStatusChanged(SessionID sessionID) { public void sessionStatusChanged(SessionID sessionID) {
removeSMRequest(sessionID.getAccountID(), sessionID.getUserID()); removeSMRequest(sessionID.getAccountID(), sessionID.getUserID());
removeSMProgress(sessionID.getAccountID(), sessionID.getUserID()); removeSMProgress(sessionID.getAccountID(), sessionID.getUserID());
Session session = sessions.get(sessionID.getAccountID(), Session session = sessions.get(sessionID.getAccountID(), sessionID.getUserID());
sessionID.getUserID());
SessionStatus sStatus = session.getSessionStatus(); SessionStatus sStatus = session.getSessionStatus();
LogManager.i(this, "session status changed " + sessionID.getUserID() + " status: " + sStatus);
if (sStatus == SessionStatus.ENCRYPTED) { if (sStatus == SessionStatus.ENCRYPTED) {
finished.remove(sessionID.getAccountID(), sessionID.getUserID()); finished.remove(sessionID.getAccountID(), sessionID.getUserID());
PublicKey remotePublicKey = session.getRemotePublicKey(); PublicKey remotePublicKey = session.getRemotePublicKey();
...@@ -364,66 +338,48 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -364,66 +338,48 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
value = null; value = null;
} }
if (value != null) { if (value != null) {
actives.put(sessionID.getAccountID(), sessionID.getUserID(), actives.put(sessionID.getAccountID(), sessionID.getUserID(), value);
value); if (fingerprints.get(sessionID.getAccountID(), sessionID.getUserID(), value) == null) {
if (fingerprints.get(sessionID.getAccountID(), fingerprints.put(sessionID.getAccountID(), sessionID.getUserID(), value, false);
sessionID.getUserID(), value) == null) { requestToWrite(sessionID.getAccountID(), sessionID.getUserID(), value, false);
fingerprints.put(sessionID.getAccountID(),
sessionID.getUserID(), value, false);
requestToWrite(sessionID.getAccountID(),
sessionID.getUserID(), value, false);
} }
} }
newAction( newAction(sessionID.getAccountID(), sessionID.getUserID(), null, isVerified(sessionID.getAccountID(),
sessionID.getAccountID(), sessionID.getUserID()) ? ChatAction.otr_verified : ChatAction.otr_encryption);
sessionID.getUserID(),
null,
isVerified(sessionID.getAccountID(), sessionID.getUserID()) ? ChatAction.otr_verified
: ChatAction.otr_encryption);
MessageManager.getInstance() MessageManager.getInstance()
.getChat(sessionID.getAccountID(), sessionID.getUserID()) .getChat(sessionID.getAccountID(), sessionID.getUserID()).sendMessages();
.sendMessages();
} else if (sStatus == SessionStatus.PLAINTEXT) { } else if (sStatus == SessionStatus.PLAINTEXT) {
actives.remove(sessionID.getAccountID(), sessionID.getUserID()); actives.remove(sessionID.getAccountID(), sessionID.getUserID());
sessions.remove(sessionID.getAccountID(), sessionID.getUserID());
finished.remove(sessionID.getAccountID(), sessionID.getUserID()); finished.remove(sessionID.getAccountID(), sessionID.getUserID());
try { try {
session.endSession(); session.endSession();
} catch (OtrException e) { } catch (OtrException e) {
LogManager.exception(this, e); LogManager.exception(this, e);
} }
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_plain);
ChatAction.otr_plain);
} else if (sStatus == SessionStatus.FINISHED) { } else if (sStatus == SessionStatus.FINISHED) {
actives.remove(sessionID.getAccountID(), sessionID.getUserID()); actives.remove(sessionID.getAccountID(), sessionID.getUserID());
sessions.remove(sessionID.getAccountID(), sessionID.getUserID());
finished.put(sessionID.getAccountID(), sessionID.getUserID(), true); finished.put(sessionID.getAccountID(), sessionID.getUserID(), true);
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_finish);
ChatAction.otr_finish); } else {
} else
throw new IllegalStateException(); throw new IllegalStateException();
RosterManager.getInstance().onContactChanged(sessionID.getAccountID(), }
sessionID.getUserID()); RosterManager.getInstance().onContactChanged(sessionID.getAccountID(), sessionID.getUserID());
} }
@Override @Override
public void askForSecret(SessionID sessionID, InstanceTag receiverTag, String question) { public void askForSecret(SessionID sessionID, InstanceTag receiverTag, String question) {
smRequestProvider.add( smRequestProvider.add(new SMRequest(sessionID.getAccountID(), sessionID.getUserID(), question), true);
new SMRequest(sessionID.getAccountID(), sessionID.getUserID(),
question), true);
} }
/** /**
* Transform outgoing message before sending. * Transform outgoing message before sending.
*
* @param account
* @param user
* @param content
* @return
* @throws OtrException
*/ */
public String transformSending(String account, String user, String content) public String transformSending(String account, String user, String content) throws OtrException {
throws OtrException { LogManager.i(this, "transform outgoing message... " + user);
String parts[] = getOrCreateSession(account, user) String parts[] = getOrCreateSession(account, user).transformSending(content, null);
.transformSending(content, null);
if (BuildConfig.DEBUG && parts.length != 1) { if (BuildConfig.DEBUG && parts.length != 1) {
throw new RuntimeException( throw new RuntimeException(
"We do not use fragmentation, so there must be only one otr fragment."); "We do not use fragmentation, so there must be only one otr fragment.");
...@@ -433,18 +389,14 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -433,18 +389,14 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
/** /**
* Transform incoming message after receiving. * Transform incoming message after receiving.
*
* @param account
* @param user
* @param content
* @return
* @throws OtrException
*/ */
public String transformReceiving(String account, String user, String content) public String transformReceiving(String account, String user, String content) throws OtrException {
throws OtrException { LogManager.i(this, "transform incoming message... " + content);
Session session = getOrCreateSession(account, user); Session session = getOrCreateSession(account, user);
try { try {
return session.transformReceiving(content); String s = session.transformReceiving(content);
LogManager.i(this, "transformed incoming message: " + s + " session status: " + session.getSessionStatus());
return s;
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
throw new OtrException(e); throw new OtrException(e);
} }
...@@ -452,73 +404,65 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -452,73 +404,65 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
public SecurityLevel getSecurityLevel(String account, String user) { public SecurityLevel getSecurityLevel(String account, String user) {
if (actives.get(account, user) == null) { if (actives.get(account, user) == null) {
if (finished.get(account, user) == null) if (finished.get(account, user) == null) {
return SecurityLevel.plain; return SecurityLevel.plain;
else } else {
return SecurityLevel.finished; return SecurityLevel.finished;
}
} else { } else {
if (isVerified(account, user)) if (isVerified(account, user)) {
return SecurityLevel.verified; return SecurityLevel.verified;
else } else {
return SecurityLevel.encrypted; return SecurityLevel.encrypted;
}
} }
} }
public boolean isVerified(String account, String user) { public boolean isVerified(String account, String user) {
String active = actives.get(account, user); String active = actives.get(account, user);
if (active == null) if (active == null) {
return false; return false;
}
Boolean value = fingerprints.get(account, user, active); Boolean value = fingerprints.get(account, user, active);
return value != null && value; return value != null && value;
} }
private void setVerifyWithoutNotification(String account, String user, private void setVerifyWithoutNotification(String account, String user, String fingerprint, boolean value) {
String fingerprint, boolean value) {
fingerprints.put(account, user, fingerprint, value); fingerprints.put(account, user, fingerprint, value);
requestToWrite(account, user, fingerprint, value); requestToWrite(account, user, fingerprint, value);
} }
/** /**
* Set whether fingerprint was verified. Add action to the chat history. * Set whether fingerprint was verified. Add action to the chat history.
*
* @param account
* @param user
* @param fingerprint
* @param value
*/ */
public void setVerify(String account, String user, String fingerprint, public void setVerify(String account, String user, String fingerprint, boolean value) {
boolean value) {
setVerifyWithoutNotification(account, user, fingerprint, value); setVerifyWithoutNotification(account, user, fingerprint, value);
if (value) if (value) {
newAction(account, user, null, ChatAction.otr_smp_verified); newAction(account, user, null, ChatAction.otr_smp_verified);
else if (actives.get(account, user) != null) } else if (actives.get(account, user) != null) {
newAction(account, user, null, ChatAction.otr_encryption); newAction(account, user, null, ChatAction.otr_encryption);
}
} }
private void setVerify(SessionID sessionID, boolean value) { private void setVerify(SessionID sessionID, boolean value) {
String active = actives.get(sessionID.getAccountID(), String active = actives.get(sessionID.getAccountID(), sessionID.getUserID());
sessionID.getUserID());
if (active == null) { if (active == null) {
LogManager.exception(this, new IllegalStateException( LogManager.exception(this, new IllegalStateException("There is no active fingerprint"));
"There is no active fingerprint"));
return; return;
} }
setVerifyWithoutNotification(sessionID.getAccountID(), setVerifyWithoutNotification(sessionID.getAccountID(), sessionID.getUserID(), active, value);
sessionID.getUserID(), active, value);
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null,
value ? ChatAction.otr_smp_verified value ? ChatAction.otr_smp_verified : ChatAction.otr_smp_unverified);
: ChatAction.otr_smp_unverified); RosterManager.getInstance().onContactChanged(sessionID.getAccountID(), sessionID.getUserID());
RosterManager.getInstance().onContactChanged(sessionID.getAccountID(),
sessionID.getUserID());
} }
@Override @Override
public void verify(SessionID sessionID, String fingerprint, boolean approved) { public void verify(SessionID sessionID, String fingerprint, boolean approved) {
if (approved) if (approved) {
setVerify(sessionID, true); setVerify(sessionID, true);
else if (isVerified(sessionID.getAccountID(), sessionID.getUserID())) } else if (isVerified(sessionID.getAccountID(), sessionID.getUserID())) {
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_smp_not_approved);
ChatAction.otr_smp_not_approved); }
removeSMProgress(sessionID.getAccountID(), sessionID.getUserID()); removeSMProgress(sessionID.getAccountID(), sessionID.getUserID());
} }
...@@ -534,10 +478,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -534,10 +478,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
public String getLocalFingerprint(String account) { public String getLocalFingerprint(String account) {
try { try {
return OtrCryptoEngine.getFingerprint(getLocalKeyPair( return OtrCryptoEngine.getFingerprint(getLocalKeyPair(account).getPublic());
account).getPublic());
} catch (OtrCryptoException e) {
LogManager.exception(this, e);
} catch (OtrException e) { } catch (OtrException e) {
LogManager.exception(this, e); LogManager.exception(this, e);
} }
...@@ -546,9 +487,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -546,9 +487,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
@Override @Override
public byte[] getLocalFingerprintRaw(SessionID sessionID) { public byte[] getLocalFingerprintRaw(SessionID sessionID) {
return SerializationUtils return SerializationUtils.hexStringToByteArray(getLocalFingerprint(sessionID.getAccountID()));
.hexStringToByteArray(getLocalFingerprint(sessionID
.getAccountID()));
} }
@Override @Override
...@@ -558,15 +497,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -558,15 +497,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
/** /**
* Respond using SM protocol. * Respond using SM protocol.
*
* @param account
* @param user
* @param question
* @param secret
* @throws NetworkException
*/ */
public void respondSmp(String account, String user, String question, public void respondSmp(String account, String user, String question, String secret) throws NetworkException {
String secret) throws NetworkException { LogManager.i(this, "responding smp... " + user);
removeSMRequest(account, user); removeSMRequest(account, user);
addSMProgress(account, user); addSMProgress(account, user);
try { try {
...@@ -578,15 +511,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -578,15 +511,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
/** /**
* Initiate request using SM protocol. * Initiate request using SM protocol.
*
* @param account
* @param user
* @param question
* @param secret
* @throws NetworkException
*/ */
public void initSmp(String account, String user, String question, public void initSmp(String account, String user, String question, String secret) throws NetworkException {
String secret) throws NetworkException { LogManager.i(this, "initializing smp... " + user);
removeSMRequest(account, user); removeSMRequest(account, user);
addSMProgress(account, user); addSMProgress(account, user);
try { try {
...@@ -598,12 +525,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -598,12 +525,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
/** /**
* Abort SM negotiation. * Abort SM negotiation.
*
* @param account
* @param user
* @throws NetworkException
*/ */
public void abortSmp(String account, String user) throws NetworkException { public void abortSmp(String account, String user) throws NetworkException {
LogManager.i(this, "aborting smp... " + user);
removeSMRequest(account, user); removeSMRequest(account, user);
removeSMProgress(account, user); removeSMProgress(account, user);
try { try {
...@@ -627,13 +551,13 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -627,13 +551,13 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
@Override @Override
public void onAccountAdded(final AccountItem accountItem) { public void onAccountAdded(final AccountItem accountItem) {
if (accountItem.getKeyPair() != null) if (accountItem.getKeyPair() != null) {
return; return;
}
keyPairGenerator.execute(new Runnable() { keyPairGenerator.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
LogManager.i(this, "KeyPair generation started for " LogManager.i(this, "KeyPair generation started for " + accountItem.getAccount());
+ accountItem.getAccount());
final KeyPair keyPair; final KeyPair keyPair;
try { try {
keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair(); keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair();
...@@ -649,12 +573,10 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -649,12 +573,10 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
Application.getInstance().runOnUiThread(new Runnable() { Application.getInstance().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LogManager.i(this, "KeyPair generation finished for " LogManager.i(this, "KeyPair generation finished for " + accountItem.getAccount());
+ accountItem.getAccount()); if (AccountManager.getInstance().getAccount(accountItem.getAccount()) != null) {
if (AccountManager.getInstance().getAccount( AccountManager.getInstance().setKeyPair(accountItem.getAccount(), keyPair);
accountItem.getAccount()) != null) }
AccountManager.getInstance().setKeyPair(
accountItem.getAccount(), keyPair);
} }
}); });
} }
...@@ -671,32 +593,28 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -671,32 +593,28 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
/** /**
* Save chat specific otr settings. * Save chat specific otr settings.
*
* @param account
* @param user
* @param fingerprint
* @param verified
*/ */
private void requestToWrite(final String account, final String user, private void requestToWrite(final String account, final String user,
final String fingerprint, final boolean verified) { final String fingerprint, final boolean verified) {
Application.getInstance().runInBackground(new Runnable() { Application.getInstance().runInBackground(new Runnable() {
@Override @Override
public void run() { public void run() {
OTRTable.getInstance().write(account, user, fingerprint, OTRTable.getInstance().write(account, user, fingerprint, verified);
verified);
} }
}); });
} }
private void endAllSessions() { private void endAllSessions() {
NestedMap<String> entities = new NestedMap<String>(); LogManager.i(this, "End all sessions");
NestedMap<String> entities = new NestedMap<>();
entities.addAll(actives); entities.addAll(actives);
for (Entry<String> entry : entities) for (Entry<String> entry : entities) {
try { try {
endSession(entry.getFirst(), entry.getSecond()); endSession(entry.getFirst(), entry.getSecond());
} catch (NetworkException e) { } catch (NetworkException e) {
LogManager.exception(this, e); LogManager.exception(this, e);
} }
}
} }
@Override @Override
...@@ -705,8 +623,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -705,8 +623,9 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
} }
public void onSettingsChanged() { public void onSettingsChanged() {
if (SettingsManager.securityOtrMode() == SecurityOtrMode.disabled) if (SettingsManager.securityOtrMode() == SecurityOtrMode.disabled) {
endAllSessions(); endAllSessions();
}
} }
@Override @Override
...@@ -725,8 +644,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener, ...@@ -725,8 +644,7 @@ public class OTRManager implements OtrEngineHost, OtrEngineListener,
public void messageFromAnotherInstanceReceived(SessionID sessionID) { public void messageFromAnotherInstanceReceived(SessionID sessionID) {
LogManager.i(this, "Message from another instance received on SessionID " LogManager.i(this, "Message from another instance received on SessionID "
+ sessionID + ". Restarting OTR session for this user."); + sessionID + ". Restarting OTR session for this user.");
newAction(sessionID.getAccountID(), sessionID.getUserID(), null, newAction(sessionID.getAccountID(), sessionID.getUserID(), null, ChatAction.otr_unreadable);
ChatAction.otr_unreadable);
} }
@Override @Override
......
...@@ -31,8 +31,7 @@ public class SMProgress extends BaseEntity implements EntityNotificationItem { ...@@ -31,8 +31,7 @@ public class SMProgress extends BaseEntity implements EntityNotificationItem {
@Override @Override
public Intent getIntent() { public Intent getIntent() {
return QuestionViewer.createCancelIntent( return QuestionViewer.createCancelIntent(Application.getInstance(), account, user);
Application.getInstance(), account, user);
} }
@Override @Override
...@@ -43,8 +42,7 @@ public class SMProgress extends BaseEntity implements EntityNotificationItem { ...@@ -43,8 +42,7 @@ public class SMProgress extends BaseEntity implements EntityNotificationItem {
@Override @Override
public String getText() { public String getText() {
return Application.getInstance().getString( return Application.getInstance().getString(R.string.otr_verification_in_progress);
R.string.otr_verification_in_progress);
} }
} }
...@@ -35,8 +35,7 @@ public class SMRequest extends BaseEntity implements EntityNotificationItem { ...@@ -35,8 +35,7 @@ public class SMRequest extends BaseEntity implements EntityNotificationItem {
@Override @Override
public Intent getIntent() { public Intent getIntent() {
return QuestionViewer.createIntent( return QuestionViewer.createIntent(
Application.getInstance(), account, user, question != null, Application.getInstance(), account, user, question != null, true, question);
true, question);
} }
@Override @Override
......
...@@ -14,14 +14,6 @@ ...@@ -14,14 +14,6 @@
*/ */
package com.xabber.android.data.message; package com.xabber.android.data.message;
import net.java.otr4j.OtrException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.packet.MUCUser;
import com.xabber.android.data.LogManager; import com.xabber.android.data.LogManager;
import com.xabber.android.data.NetworkException; import com.xabber.android.data.NetworkException;
import com.xabber.android.data.SettingsManager; import com.xabber.android.data.SettingsManager;
...@@ -35,6 +27,14 @@ import com.xabber.xmpp.archive.SaveMode; ...@@ -35,6 +27,14 @@ import com.xabber.xmpp.archive.SaveMode;
import com.xabber.xmpp.delay.Delay; import com.xabber.xmpp.delay.Delay;
import com.xabber.xmpp.muc.MUC; import com.xabber.xmpp.muc.MUC;
import net.java.otr4j.OtrException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.packet.MUCUser;
/** /**
* Represents normal chat. * Represents normal chat.
* *
...@@ -141,8 +141,7 @@ public class RegularChat extends AbstractChat { ...@@ -141,8 +141,7 @@ public class RegularChat extends AbstractChat {
updateThreadId(thread); updateThreadId(thread);
boolean unencrypted = false; boolean unencrypted = false;
try { try {
text = OTRManager.getInstance().transformReceiving(account, text = OTRManager.getInstance().transformReceiving(account, user, text);
user, text);
} catch (OtrException e) { } catch (OtrException e) {
if (e.getCause() instanceof OTRUnencryptedException) { if (e.getCause() instanceof OTRUnencryptedException) {
text = ((OTRUnencryptedException) e.getCause()).getText(); text = ((OTRUnencryptedException) e.getCause()).getText();
...@@ -154,7 +153,7 @@ public class RegularChat extends AbstractChat { ...@@ -154,7 +153,7 @@ public class RegularChat extends AbstractChat {
} }
} }
// System message received. // System message received.
if (text == null) if (text == null || text.trim().equals(""))
return true; return true;
if (!"".equals(resource)) if (!"".equals(resource))
this.resource = resource; this.resource = resource;
......
...@@ -356,21 +356,29 @@ public class ChatViewer extends ManagedActivity implements OnChatChangedListener ...@@ -356,21 +356,29 @@ public class ChatViewer extends ManagedActivity implements OnChatChangedListener
chatScrollIndicatorAdapter.update(chatViewerAdapter.getActiveChats()); chatScrollIndicatorAdapter.update(chatViewerAdapter.getActiveChats());
selectPage(); selectPage();
} else { } else {
updateRegisteredChats();
updateRegisteredRecentChatsFragments();
updateStatusBar();
for (ChatViewerFragment chat : registeredChats) { for (ChatViewerFragment chat : registeredChats) {
if (chat.isEqual(selectedChat) && incoming) { if (chat.isEqual(selectedChat)) {
chat.playIncomingAnimation(); chat.updateChat();
if (incoming) {
chat.playIncomingAnimation();
}
} }
} }
updateRegisteredRecentChatsFragments();
updateStatusBar();
} }
} }
@Override @Override
public void onContactsChanged(Collection<BaseEntity> entities) { public void onContactsChanged(Collection<BaseEntity> entities) {
updateRegisteredChats(); for (BaseEntity contact : entities) {
for (ChatViewerFragment chat : registeredChats) {
if (chat.isEqual(contact)) {
chat.updateChat();
}
}
}
updateRegisteredRecentChatsFragments(); updateRegisteredRecentChatsFragments();
updateStatusBar(); updateStatusBar();
} }
......
...@@ -5,12 +5,10 @@ import android.content.Context; ...@@ -5,12 +5,10 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.InputType; import android.text.InputType;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import com.xabber.android.R; import com.xabber.android.R;
...@@ -39,15 +37,6 @@ public class ContactEditor extends ContactViewer implements Toolbar.OnMenuItemCl ...@@ -39,15 +37,6 @@ public class ContactEditor extends ContactViewer implements Toolbar.OnMenuItemCl
toolbar.inflateMenu(R.menu.contact_viewer); toolbar.inflateMenu(R.menu.contact_viewer);
toolbar.setOnMenuItemClickListener(this); toolbar.setOnMenuItemClickListener(this);
} }
toolbar.setNavigationIcon(R.drawable.ic_arrow_left_white_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavUtils.navigateUpFromSameTask(ContactEditor.this);
}
});
} }
@Override @Override
......
...@@ -66,6 +66,7 @@ import com.xabber.android.ui.helper.BarPainter; ...@@ -66,6 +66,7 @@ import com.xabber.android.ui.helper.BarPainter;
import com.xabber.android.ui.helper.ManagedActivity; import com.xabber.android.ui.helper.ManagedActivity;
import com.xabber.android.ui.preferences.AboutViewer; import com.xabber.android.ui.preferences.AboutViewer;
import com.xabber.android.ui.preferences.AccountEditor; import com.xabber.android.ui.preferences.AccountEditor;
import com.xabber.android.ui.preferences.AccountList;
import com.xabber.android.ui.preferences.PreferenceEditor; import com.xabber.android.ui.preferences.PreferenceEditor;
import com.xabber.xmpp.address.Jid; import com.xabber.xmpp.address.Jid;
import com.xabber.xmpp.uri.XMPPUri; import com.xabber.xmpp.uri.XMPPUri;
...@@ -593,7 +594,9 @@ public class ContactList extends ManagedActivity implements OnAccountChangedList ...@@ -593,7 +594,9 @@ public class ContactList extends ManagedActivity implements OnAccountChangedList
case R.id.drawer_action_exit: case R.id.drawer_action_exit:
exit(); exit();
break; break;
case R.id.drawer_header_action_xmpp_accounts:
startActivity(AccountList.createIntent(this));
break;
} }
} }
......
...@@ -52,8 +52,8 @@ public class ContactListDrawerFragment extends Fragment implements View.OnClickL ...@@ -52,8 +52,8 @@ public class ContactListDrawerFragment extends Fragment implements View.OnClickL
View headerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)) View headerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.contact_list_drawer_header, listView, false); .inflate(R.layout.contact_list_drawer_header, listView, false);
headerTitle = headerView.findViewById(R.id.drawer_header_title); headerTitle = headerView.findViewById(R.id.drawer_header_action_xmpp_accounts);
headerTitle.setOnClickListener(this);
listView.addHeaderView(headerView); listView.addHeaderView(headerView);
......
...@@ -18,6 +18,8 @@ import android.content.Context; ...@@ -18,6 +18,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
...@@ -117,6 +119,15 @@ public class ContactViewer extends ManagedActivity implements ...@@ -117,6 +119,15 @@ public class ContactViewer extends ManagedActivity implements
contactTitleView.findViewById(R.id.status_icon).setVisibility(View.GONE); contactTitleView.findViewById(R.id.status_icon).setVisibility(View.GONE);
contactTitleView.findViewById(R.id.status_text).setVisibility(View.GONE); contactTitleView.findViewById(R.id.status_text).setVisibility(View.GONE);
contactNameView = (TextView) contactTitleView.findViewById(R.id.name); contactNameView = (TextView) contactTitleView.findViewById(R.id.name);
Toolbar toolbar = contactTitleExpandableToolbarInflater.getToolbar();
toolbar.setNavigationIcon(R.drawable.ic_arrow_left_white_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavUtils.navigateUpFromSameTask(ContactViewer.this);
}
});
} }
@Override @Override
......
...@@ -23,6 +23,7 @@ import android.widget.ImageView; ...@@ -23,6 +23,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.xabber.android.R; import com.xabber.android.R;
import com.xabber.android.data.LogManager;
import com.xabber.android.data.SettingsManager; import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.account.AccountItem; import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.account.AccountManager;
...@@ -139,6 +140,7 @@ public class ChatMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo ...@@ -139,6 +140,7 @@ public class ChatMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
incomingMessage.messageBalloon.setVisibility(View.GONE); incomingMessage.messageBalloon.setVisibility(View.GONE);
incomingMessage.messageTime.setVisibility(View.GONE); incomingMessage.messageTime.setVisibility(View.GONE);
incomingMessage.avatar.setVisibility(View.GONE); incomingMessage.avatar.setVisibility(View.GONE);
LogManager.w(this, "Empty message! Hidden, but need to correct");
} else { } else {
incomingMessage.messageBalloon.setVisibility(View.VISIBLE); incomingMessage.messageBalloon.setVisibility(View.VISIBLE);
incomingMessage.messageTime.setVisibility(View.VISIBLE); incomingMessage.messageTime.setVisibility(View.VISIBLE);
...@@ -285,7 +287,7 @@ public class ChatMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo ...@@ -285,7 +287,7 @@ public class ChatMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
return null; return null;
} }
public static class BasicMessage extends RecyclerView.ViewHolder { public static class BasicMessage extends RecyclerView.ViewHolder {
public TextView messageText; public TextView messageText;
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_header_title" android:id="@+id/drawer_header_action_xmpp_accounts"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingLeft="16dp" android:paddingLeft="16dp"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment