refactored pgp decryption
This commit is contained in:
parent
490a1ca3cf
commit
587fb3cca3
|
@ -1,162 +1,181 @@
|
|||
package eu.siacs.conversations.crypto;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.ui.UiCallback;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
import eu.siacs.conversations.entities.DownloadableFile;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.http.HttpConnectionManager;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
|
||||
public class PgpDecryptionService {
|
||||
|
||||
private final XmppConnectionService xmppConnectionService;
|
||||
private final ConcurrentHashMap<String, List<Message>> messages = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Boolean> decryptingMessages = new ConcurrentHashMap<>();
|
||||
private Boolean keychainLocked = false;
|
||||
private final Object keychainLockedLock = new Object();
|
||||
private final XmppConnectionService mXmppConnectionService;
|
||||
private OpenPgpApi openPgpApi = null;
|
||||
|
||||
public PgpDecryptionService(XmppConnectionService xmppConnectionService) {
|
||||
this.xmppConnectionService = xmppConnectionService;
|
||||
protected final ArrayDeque<Message> messages = new ArrayDeque();
|
||||
Message currentMessage;
|
||||
private PendingIntent pendingIntent;
|
||||
|
||||
|
||||
public PgpDecryptionService(XmppConnectionService service) {
|
||||
this.mXmppConnectionService = service;
|
||||
}
|
||||
|
||||
public void add(Message message) {
|
||||
if (isRunning()) {
|
||||
decryptDirectly(message);
|
||||
} else {
|
||||
store(message);
|
||||
public synchronized void decrypt(final Message message) {
|
||||
messages.add(message);
|
||||
continueDecryption();
|
||||
}
|
||||
|
||||
public synchronized void decrypt(final List<Message> list) {
|
||||
for(Message message : list) {
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
messages.add(message);
|
||||
}
|
||||
}
|
||||
continueDecryption();
|
||||
}
|
||||
|
||||
protected synchronized void decryptNext() {
|
||||
if (pendingIntent == null
|
||||
&& getOpenPgpApi() != null
|
||||
&& (currentMessage = messages.poll()) != null) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
executeApi(currentMessage);
|
||||
decryptNext();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAll(List<Message> messagesList) {
|
||||
if (!messagesList.isEmpty()) {
|
||||
String conversationUuid = messagesList.get(0).getConversation().getUuid();
|
||||
if (!messages.containsKey(conversationUuid)) {
|
||||
List<Message> list = Collections.synchronizedList(new LinkedList<Message>());
|
||||
messages.put(conversationUuid, list);
|
||||
public synchronized void continueDecryption(boolean resetPending) {
|
||||
if (resetPending) {
|
||||
this.pendingIntent = null;
|
||||
}
|
||||
synchronized (messages.get(conversationUuid)) {
|
||||
messages.get(conversationUuid).addAll(messagesList);
|
||||
continueDecryption();
|
||||
}
|
||||
decryptAllMessages();
|
||||
|
||||
public synchronized void continueDecryption() {
|
||||
if (currentMessage == null) {
|
||||
decryptNext();
|
||||
}
|
||||
}
|
||||
|
||||
public void onKeychainUnlocked() {
|
||||
synchronized (keychainLockedLock) {
|
||||
keychainLocked = false;
|
||||
private synchronized OpenPgpApi getOpenPgpApi() {
|
||||
if (openPgpApi == null) {
|
||||
this.openPgpApi = mXmppConnectionService.getOpenPgpApi();
|
||||
}
|
||||
decryptAllMessages();
|
||||
return this.openPgpApi;
|
||||
}
|
||||
|
||||
public void onKeychainLocked() {
|
||||
synchronized (keychainLockedLock) {
|
||||
keychainLocked = true;
|
||||
private void executeApi(Message message) {
|
||||
Intent params = new Intent();
|
||||
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
if (message.getType() == Message.TYPE_TEXT) {
|
||||
InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
|
||||
final OutputStream os = new ByteArrayOutputStream();
|
||||
Intent result = getOpenPgpApi().executeApi(params, is, os);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
try {
|
||||
os.flush();
|
||||
message.setBody(os.toString());
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
|
||||
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
|
||||
if (message.trusted()
|
||||
&& message.treatAsDownloadable() != Message.Decision.NEVER
|
||||
&& manager.getAutoAcceptFileSize() > 0) {
|
||||
manager.createNewDownloadConnection(message);
|
||||
}
|
||||
xmppConnectionService.updateConversationUi();
|
||||
}
|
||||
|
||||
public void onOpenPgpServiceBound() {
|
||||
decryptAllMessages();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
synchronized (keychainLockedLock) {
|
||||
return !keychainLocked;
|
||||
}
|
||||
}
|
||||
|
||||
private void store(Message message) {
|
||||
if (messages.containsKey(message.getConversation().getUuid())) {
|
||||
messages.get(message.getConversation().getUuid()).add(message);
|
||||
} else {
|
||||
List<Message> messageList = Collections.synchronizedList(new LinkedList<Message>());
|
||||
messageList.add(message);
|
||||
messages.put(message.getConversation().getUuid(), messageList);
|
||||
}
|
||||
}
|
||||
|
||||
private void decryptAllMessages() {
|
||||
for (String uuid : messages.keySet()) {
|
||||
decryptMessages(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void decryptMessages(final String uuid) {
|
||||
synchronized (decryptingMessages) {
|
||||
Boolean decrypting = decryptingMessages.get(uuid);
|
||||
if ((decrypting != null && !decrypting) || decrypting == null) {
|
||||
decryptingMessages.put(uuid, true);
|
||||
decryptMessage(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void decryptMessage(final String uuid) {
|
||||
Message message = null;
|
||||
synchronized (messages.get(uuid)) {
|
||||
while (!messages.get(uuid).isEmpty()) {
|
||||
if (messages.get(uuid).get(0).getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
if (isRunning()) {
|
||||
message = messages.get(uuid).remove(0);
|
||||
} catch (IOException e) {
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
|
||||
}
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
break;
|
||||
} else {
|
||||
messages.get(uuid).remove(0);
|
||||
}
|
||||
}
|
||||
if (message != null && xmppConnectionService.getPgpEngine() != null) {
|
||||
xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
|
||||
|
||||
@Override
|
||||
public void userInputRequried(PendingIntent pi, Message message) {
|
||||
messages.get(uuid).add(0, message);
|
||||
decryptingMessages.put(uuid, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(Message message) {
|
||||
xmppConnectionService.updateConversationUi();
|
||||
decryptMessage(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(int error, Message message) {
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
messages.addFirst(message);
|
||||
currentMessage = null;
|
||||
storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
|
||||
break;
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
|
||||
xmppConnectionService.updateConversationUi();
|
||||
decryptMessage(uuid);
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
break;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
decryptingMessages.put(uuid, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void decryptDirectly(final Message message) {
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP && xmppConnectionService.getPgpEngine() != null) {
|
||||
xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
|
||||
|
||||
@Override
|
||||
public void userInputRequried(PendingIntent pi, Message message) {
|
||||
store(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(Message message) {
|
||||
xmppConnectionService.updateConversationUi();
|
||||
xmppConnectionService.getNotificationService().updateNotification(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(int error, Message message) {
|
||||
} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
|
||||
try {
|
||||
final DownloadableFile inputFile = mXmppConnectionService.getFileBackend().getFile(message, false);
|
||||
final DownloadableFile outputFile = mXmppConnectionService.getFileBackend().getFile(message, true);
|
||||
outputFile.getParentFile().mkdirs();
|
||||
outputFile.createNewFile();
|
||||
InputStream is = new FileInputStream(inputFile);
|
||||
OutputStream os = new FileOutputStream(outputFile);
|
||||
Intent result = getOpenPgpApi().executeApi(params, is, os);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
URL url = message.getFileParams().url;
|
||||
mXmppConnectionService.getFileBackend().updateFileParams(message,url);
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
|
||||
inputFile.delete();
|
||||
mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile);
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
break;
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
messages.addFirst(message);
|
||||
currentMessage = null;
|
||||
storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
|
||||
break;
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
|
||||
xmppConnectionService.updateConversationUi();
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
break;
|
||||
}
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void storePendingIntent(PendingIntent pendingIntent) {
|
||||
this.pendingIntent = pendingIntent;
|
||||
mXmppConnectionService.updateConversationUi();
|
||||
}
|
||||
|
||||
public synchronized boolean hasPendingIntent(Conversation conversation) {
|
||||
if (pendingIntent == null) {
|
||||
return false;
|
||||
} else {
|
||||
for(Message message : messages) {
|
||||
if (message.getConversation() == conversation) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
return pendingIntent;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return getOpenPgpApi() != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,96 +38,6 @@ public class PgpEngine {
|
|||
this.mXmppConnectionService = service;
|
||||
}
|
||||
|
||||
public void decrypt(final Message message, final UiCallback<Message> callback) {
|
||||
Intent params = new Intent();
|
||||
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
final String uuid = message.getUuid();
|
||||
if (message.getType() == Message.TYPE_TEXT) {
|
||||
InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
|
||||
final OutputStream os = new ByteArrayOutputStream();
|
||||
api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
|
||||
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
try {
|
||||
os.flush();
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP
|
||||
&& message.getUuid().equals(uuid)) {
|
||||
message.setBody(os.toString());
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
|
||||
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
|
||||
if (message.trusted()
|
||||
&& message.treatAsDownloadable() != Message.Decision.NEVER
|
||||
&& manager.getAutoAcceptFileSize() > 0) {
|
||||
manager.createNewDownloadConnection(message);
|
||||
}
|
||||
mXmppConnectionService.updateMessage(message);
|
||||
callback.success(message);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
callback.error(R.string.openpgp_error, message);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
callback.userInputRequried((PendingIntent) result
|
||||
.getParcelableExtra(OpenPgpApi.RESULT_INTENT),
|
||||
message);
|
||||
return;
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
callback.error(R.string.openpgp_error, message);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
|
||||
try {
|
||||
final DownloadableFile inputFile = this.mXmppConnectionService
|
||||
.getFileBackend().getFile(message, false);
|
||||
final DownloadableFile outputFile = this.mXmppConnectionService
|
||||
.getFileBackend().getFile(message, true);
|
||||
outputFile.getParentFile().mkdirs();
|
||||
outputFile.createNewFile();
|
||||
InputStream is = new FileInputStream(inputFile);
|
||||
OutputStream os = new FileOutputStream(outputFile);
|
||||
api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
|
||||
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
|
||||
OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
URL url = message.getFileParams().url;
|
||||
mXmppConnectionService.getFileBackend().updateFileParams(message,url);
|
||||
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
|
||||
PgpEngine.this.mXmppConnectionService
|
||||
.updateMessage(message);
|
||||
inputFile.delete();
|
||||
mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile);
|
||||
callback.success(message);
|
||||
return;
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
callback.userInputRequried(
|
||||
(PendingIntent) result
|
||||
.getParcelableExtra(OpenPgpApi.RESULT_INTENT),
|
||||
message);
|
||||
return;
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
callback.error(R.string.openpgp_error, message);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
callback.error(R.string.error_decrypting_file, message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void encrypt(final Message message, final UiCallback<Message> callback) {
|
||||
Intent params = new Intent();
|
||||
params.setAction(OpenPgpApi.ACTION_ENCRYPT);
|
||||
|
@ -156,7 +66,6 @@ public class PgpEngine {
|
|||
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
|
||||
OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
|
@ -202,7 +111,6 @@ public class PgpEngine {
|
|||
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
|
||||
OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
|
@ -257,7 +165,6 @@ public class PgpEngine {
|
|||
InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
Intent result = api.executeApi(params, is, os);
|
||||
notifyPgpDecryptionService(account, OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
|
||||
OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
|
@ -315,7 +222,6 @@ public class PgpEngine {
|
|||
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
notifyPgpDecryptionService(account, OpenPgpApi.ACTION_SIGN, result);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
StringBuilder signatureBuilder = new StringBuilder();
|
||||
|
@ -397,17 +303,4 @@ public class PgpEngine {
|
|||
return (PendingIntent) result
|
||||
.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||
}
|
||||
|
||||
private void notifyPgpDecryptionService(Account account, String action, final Intent result) {
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
if (OpenPgpApi.ACTION_SIGN.equals(action)) {
|
||||
account.getPgpDecryptionService().onKeychainUnlocked();
|
||||
}
|
||||
break;
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
account.getPgpDecryptionService().onKeychainLocked();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.os.SystemClock;
|
|||
import android.util.Pair;
|
||||
|
||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||
|
||||
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
|
||||
import net.java.otr4j.crypto.OtrCryptoException;
|
||||
|
||||
|
@ -20,7 +21,6 @@ import java.util.List;
|
|||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
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.axolotl.AxolotlService;
|
||||
|
@ -83,6 +83,14 @@ public class Account extends AbstractEntity {
|
|||
return getRoster().getContact(jid);
|
||||
}
|
||||
|
||||
public boolean hasPendingPgpIntent(Conversation conversation) {
|
||||
return pgpDecryptionService != null && pgpDecryptionService.hasPendingIntent(conversation);
|
||||
}
|
||||
|
||||
public boolean isPgpDecryptionServiceConnected() {
|
||||
return pgpDecryptionService != null && pgpDecryptionService.isConnected();
|
||||
}
|
||||
|
||||
public enum State {
|
||||
DISABLED,
|
||||
OFFLINE,
|
||||
|
@ -398,10 +406,10 @@ public class Account extends AbstractEntity {
|
|||
public void initAccountServices(final XmppConnectionService context) {
|
||||
this.mOtrService = new OtrService(context, this);
|
||||
this.axolotlService = new AxolotlService(this, context);
|
||||
this.pgpDecryptionService = new PgpDecryptionService(context);
|
||||
if (xmppConnection != null) {
|
||||
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
|
||||
}
|
||||
this.pgpDecryptionService = new PgpDecryptionService(context);
|
||||
}
|
||||
|
||||
public OtrService getOtrService() {
|
||||
|
@ -409,7 +417,7 @@ public class Account extends AbstractEntity {
|
|||
}
|
||||
|
||||
public PgpDecryptionService getPgpDecryptionService() {
|
||||
return pgpDecryptionService;
|
||||
return this.pgpDecryptionService;
|
||||
}
|
||||
|
||||
public XmppConnection getXmppConnection() {
|
||||
|
|
|
@ -932,7 +932,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
synchronized (this.messages) {
|
||||
this.messages.addAll(index, messages);
|
||||
}
|
||||
account.getPgpDecryptionService().addAll(messages);
|
||||
account.getPgpDecryptionService().decrypt(messages);
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
|
|
|
@ -127,7 +127,7 @@ public class HttpDownloadConnection implements Transferable {
|
|||
message.setTransferable(null);
|
||||
mHttpConnectionManager.finishConnection(this);
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
message.getConversation().getAccount().getPgpDecryptionService().add(message);
|
||||
message.getConversation().getAccount().getPgpDecryptionService().decrypt(message);
|
||||
}
|
||||
mXmppConnectionService.updateConversationUi();
|
||||
if (acceptedAutomatically) {
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.util.Pair;
|
|||
import net.java.otr4j.session.Session;
|
||||
import net.java.otr4j.session.SessionStatus;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -32,7 +31,6 @@ import eu.siacs.conversations.http.HttpConnectionManager;
|
|||
import eu.siacs.conversations.services.MessageArchiveService;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.Xmlns;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||
|
@ -484,7 +482,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
sendMessageReceipts(account, packet);
|
||||
}
|
||||
if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
conversation.getAccount().getPgpDecryptionService().add(replacedMessage);
|
||||
conversation.getAccount().getPgpDecryptionService().decrypt(replacedMessage);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
@ -508,7 +506,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
}
|
||||
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
conversation.getAccount().getPgpDecryptionService().add(message);
|
||||
conversation.getAccount().getPgpDecryptionService().decrypt(message);
|
||||
}
|
||||
|
||||
if (query == null || query.getWith() == null) { //either no mam or catchup
|
||||
|
|
|
@ -49,7 +49,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
|
@ -62,6 +61,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
||||
|
@ -383,6 +383,16 @@ public class XmppConnectionService extends Service {
|
|||
|
||||
}
|
||||
|
||||
public OpenPgpApi getOpenPgpApi() {
|
||||
if (!Config.supportOpenPgp()) {
|
||||
return null;
|
||||
} else if (pgpServiceConnection != null && pgpServiceConnection.isBound()) {
|
||||
return new OpenPgpApi(this, pgpServiceConnection.getService());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public FileBackend getFileBackend() {
|
||||
return this.fileBackend;
|
||||
}
|
||||
|
@ -754,8 +764,9 @@ public class XmppConnectionService extends Service {
|
|||
@Override
|
||||
public void onBound(IOpenPgpService2 service) {
|
||||
for (Account account : accounts) {
|
||||
if (account.getPgpDecryptionService() != null) {
|
||||
account.getPgpDecryptionService().onOpenPgpServiceBound();
|
||||
final PgpDecryptionService pgp = account.getPgpDecryptionService();
|
||||
if(pgp != null) {
|
||||
pgp.continueDecryption(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,9 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.Gravity;
|
||||
|
@ -214,49 +211,25 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private final int KEYCHAIN_UNLOCK_NOT_REQUIRED = 0;
|
||||
private final int KEYCHAIN_UNLOCK_REQUIRED = 1;
|
||||
private final int KEYCHAIN_UNLOCK_PENDING = 2;
|
||||
private int keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
protected OnClickListener clickToDecryptListener = new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED
|
||||
&& activity.hasPgp() && !conversation.getAccount().getPgpDecryptionService().isRunning()) {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_PENDING;
|
||||
updateSnackBar(conversation);
|
||||
Message message = getLastPgpDecryptableMessage();
|
||||
if (message != null) {
|
||||
activity.xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
|
||||
@Override
|
||||
public void success(Message object) {
|
||||
conversation.getAccount().getPgpDecryptionService().onKeychainUnlocked();
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(int errorCode, Message object) {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userInputRequried(PendingIntent pi, Message object) {
|
||||
PendingIntent pendingIntent = conversation.getAccount().getPgpDecryptionService().getPendingIntent();
|
||||
if (pendingIntent != null) {
|
||||
try {
|
||||
activity.startIntentSenderForResult(pi.getIntentSender(),
|
||||
ConversationActivity.REQUEST_DECRYPT_PGP, null, 0, 0, 0);
|
||||
activity.startIntentSenderForResult(pendingIntent.getIntentSender(),
|
||||
ConversationActivity.REQUEST_DECRYPT_PGP,
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
} catch (SendIntentException e) {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
updatePgpMessages();
|
||||
Toast.makeText(activity,R.string.unable_to_connect_to_keychain, Toast.LENGTH_SHORT).show();
|
||||
conversation.getAccount().getPgpDecryptionService().continueDecryption(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
updatePgpMessages();
|
||||
}
|
||||
updateSnackBar(conversation);
|
||||
}
|
||||
};
|
||||
protected OnClickListener clickToVerify = new OnClickListener() {
|
||||
|
@ -722,7 +695,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
message.setEncryption(Message.ENCRYPTION_PGP);
|
||||
activity.updateConversationList();
|
||||
updateMessages();
|
||||
conversation.getAccount().getPgpDecryptionService().add(message);
|
||||
conversation.getAccount().getPgpDecryptionService().decrypt(message);
|
||||
}
|
||||
|
||||
protected void privateMessageWith(final Jid counterpart) {
|
||||
|
@ -789,7 +762,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
this.conversation.trim();
|
||||
}
|
||||
|
||||
this.keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
this.conversation = conversation;
|
||||
boolean canWrite = this.conversation.getMode() == Conversation.MODE_SINGLE || this.conversation.getMucOptions().participating();
|
||||
this.mEditMessage.setEnabled(canWrite);
|
||||
|
@ -909,7 +881,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED) {
|
||||
} else if (account.hasPendingPgpIntent(conversation)) {
|
||||
showSnackbar(R.string.openpgp_messages_found, R.string.decrypt, clickToDecryptListener);
|
||||
} else if (mode == Conversation.MODE_SINGLE
|
||||
&& conversation.smpRequested()) {
|
||||
|
@ -932,7 +904,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
final ConversationActivity activity = (ConversationActivity) getActivity();
|
||||
if (this.conversation != null) {
|
||||
conversation.populateWithMessages(ConversationFragment.this.messageList);
|
||||
updatePgpMessages();
|
||||
updateSnackBar(conversation);
|
||||
updateStatusMessages();
|
||||
this.messageListAdapter.notifyDataSetChanged();
|
||||
|
@ -945,29 +916,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
}
|
||||
}
|
||||
|
||||
public void updatePgpMessages() {
|
||||
if (keychainUnlock != KEYCHAIN_UNLOCK_PENDING) {
|
||||
if (getLastPgpDecryptableMessage() != null
|
||||
&& !conversation.getAccount().getPgpDecryptionService().isRunning()) {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_REQUIRED;
|
||||
} else {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Message getLastPgpDecryptableMessage() {
|
||||
for (final Message message : this.messageList) {
|
||||
if (message.getEncryption() == Message.ENCRYPTION_PGP
|
||||
&& (message.getStatus() == Message.STATUS_RECEIVED || message.getStatus() >= Message.STATUS_SEND)
|
||||
&& message.getTransferable() == null) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void messageSent() {
|
||||
mEditMessage.setText("");
|
||||
updateChatMsgHint();
|
||||
|
@ -1424,9 +1372,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
final Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
|
||||
activity.getSelectedConversation().getAccount().getPgpDecryptionService().onKeychainUnlocked();
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
updatePgpMessages();
|
||||
activity.getSelectedConversation().getAccount().getPgpDecryptionService().continueDecryption(true);
|
||||
} else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) {
|
||||
final String body = mEditMessage.getText().toString();
|
||||
Message message = new Message(conversation, body, conversation.getNextEncryption());
|
||||
|
@ -1435,11 +1381,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
|||
int choice = data.getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID);
|
||||
activity.selectPresenceToAttachFile(choice, conversation.getNextEncryption());
|
||||
}
|
||||
} else {
|
||||
if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
|
||||
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
|
||||
updatePgpMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -631,8 +631,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
displayOpenableMessage(viewHolder, message);
|
||||
}
|
||||
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||
if (activity.hasPgp()) {
|
||||
if (account.getPgpDecryptionService().isRunning()) {
|
||||
if (account.isPgpDecryptionServiceConnected()) {
|
||||
if (!account.hasPendingPgpIntent(conversation)) {
|
||||
displayInfoMessage(viewHolder, activity.getString(R.string.message_decrypting), darkBackground);
|
||||
} else {
|
||||
displayInfoMessage(viewHolder, activity.getString(R.string.pgp_message), darkBackground);
|
||||
|
|
|
@ -110,7 +110,7 @@ public class JingleConnection implements Transferable {
|
|||
if (message.getEncryption() != Message.ENCRYPTION_PGP) {
|
||||
mXmppConnectionService.getFileBackend().updateMediaScanner(file);
|
||||
} else {
|
||||
account.getPgpDecryptionService().add(message);
|
||||
account.getPgpDecryptionService().decrypt(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -662,4 +662,5 @@
|
|||
<string name="pref_theme_dark">Dark theme</string>
|
||||
<string name="pref_use_green_background">Green Background</string>
|
||||
<string name="pref_use_green_background_summary">Use green background for received messages</string>
|
||||
<string name="unable_to_connect_to_keychain">Unable to connect to OpenKeychain</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue