diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java index d3588a9952cc22cb0e5cb795181c7d09dda08f5f..e0ba84c73a08a9e84dd704279675514e34ecfba8 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java @@ -3,27 +3,10 @@ package eu.siacs.conversations.crypto; import android.app.PendingIntent; import android.content.Intent; import android.util.Log; - import androidx.annotation.StringRes; - import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; - -import org.openintents.openpgp.OpenPgpError; -import org.openintents.openpgp.OpenPgpSignatureResult; -import org.openintents.openpgp.util.OpenPgpApi; -import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; - -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.util.ArrayList; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -35,6 +18,18 @@ import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.utils.AsciiArmor; +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.util.ArrayList; +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.OpenPgpSignatureResult; +import org.openintents.openpgp.util.OpenPgpApi; +import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; public class PgpEngine { private final OpenPgpApi api; @@ -48,9 +43,20 @@ public class PgpEngine { private static void logError(Account account, OpenPgpError error) { if (error != null) { error.describeContents(); - Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": OpenKeychain error '" + error.getMessage() + "' code=" + error.getErrorId() + " class=" + error.getClass().getName()); + Log.d( + Config.LOGTAG, + account.getJid().asBareJid().toString() + + ": OpenKeychain error '" + + error.getMessage() + + "' code=" + + error.getErrorId() + + " class=" + + error.getClass().getName()); } else { - Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": OpenKeychain error with no message"); + Log.d( + Config.LOGTAG, + account.getJid().asBareJid().toString() + + ": OpenKeychain error with no message"); } } @@ -60,8 +66,7 @@ public class PgpEngine { final Conversation conversation = (Conversation) message.getConversation(); if (conversation.getMode() == Conversation.MODE_SINGLE) { long[] keys = { - conversation.getContact().getPgpKeyId(), - conversation.getAccount().getPgpId() + conversation.getContact().getPgpKeyId(), conversation.getAccount().getPgpId() }; params.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keys); } else { @@ -78,75 +83,95 @@ public class PgpEngine { } InputStream is = new ByteArrayInputStream(body.getBytes()); final OutputStream os = new ByteArrayOutputStream(); - api.executeApiAsync(params, is, os, result -> { - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: - try { - os.flush(); - final ArrayList encryptedMessageBody = new ArrayList<>(); - final String[] lines = os.toString().split("\n"); - for (int i = 2; i < lines.length - 1; ++i) { - if (!lines[i].contains("Version")) { - encryptedMessageBody.add(lines[i].trim()); + api.executeApiAsync( + params, + is, + os, + result -> { + switch (result.getIntExtra( + OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: + try { + os.flush(); + final ArrayList encryptedMessageBody = + new ArrayList<>(); + final String[] lines = os.toString().split("\n"); + for (int i = 2; i < lines.length - 1; ++i) { + if (!lines[i].contains("Version")) { + encryptedMessageBody.add(lines[i].trim()); + } + } + message.setEncryptedBody( + Joiner.on('\n').join(encryptedMessageBody)); + message.setEncryption(Message.ENCRYPTION_DECRYPTED); + mXmppConnectionService.sendMessage(message); + callback.success(message); + } catch (IOException e) { + callback.error(R.string.openpgp_error, message); } - } - message.setEncryptedBody(Joiner.on('\n').join(encryptedMessageBody)); - message.setEncryption(Message.ENCRYPTION_DECRYPTED); - mXmppConnectionService.sendMessage(message); - callback.success(message); - } catch (IOException e) { - callback.error(R.string.openpgp_error, message); - } - break; - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - callback.userInputRequired(result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), message); - break; - case OpenPgpApi.RESULT_CODE_ERROR: - OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); - String errorMessage = error != null ? error.getMessage() : null; - @StringRes final int res; - if (errorMessage != null && errorMessage.startsWith("Bad key for encryption")) { - res = R.string.bad_key_for_encryption; - } else { - res = R.string.openpgp_error; + break; + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: + callback.userInputRequired( + result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), + message); + break; + case OpenPgpApi.RESULT_CODE_ERROR: + OpenPgpError error = + result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + String errorMessage = error != null ? error.getMessage() : null; + @StringRes final int res; + if (errorMessage != null + && errorMessage.startsWith("Bad key for encryption")) { + res = R.string.bad_key_for_encryption; + } else { + res = R.string.openpgp_error; + } + logError(conversation.getAccount(), error); + callback.error(res, message); + break; } - logError(conversation.getAccount(), error); - callback.error(res, message); - break; - } - }); + }); } else { try { - DownloadableFile inputFile = this.mXmppConnectionService - .getFileBackend().getFile(message, true); - DownloadableFile outputFile = this.mXmppConnectionService - .getFileBackend().getFile(message, false); + DownloadableFile inputFile = + this.mXmppConnectionService.getFileBackend().getFile(message, true); + DownloadableFile outputFile = + this.mXmppConnectionService.getFileBackend().getFile(message, false); outputFile.getParentFile().mkdirs(); outputFile.createNewFile(); final InputStream is = new FileInputStream(inputFile); final OutputStream os = new FileOutputStream(outputFile); - api.executeApiAsync(params, is, os, result -> { - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: - try { - os.flush(); - } catch (IOException ignored) { - //ignored + api.executeApiAsync( + params, + is, + os, + result -> { + switch (result.getIntExtra( + OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: + try { + os.flush(); + } catch (IOException ignored) { + // ignored + } + FileBackend.close(os); + mXmppConnectionService.sendMessage(message); + callback.success(message); + break; + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: + callback.userInputRequired( + result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), + message); + break; + case OpenPgpApi.RESULT_CODE_ERROR: + logError( + conversation.getAccount(), + result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); + callback.error(R.string.openpgp_error, message); + break; } - FileBackend.close(os); - mXmppConnectionService.sendMessage(message); - callback.success(message); - break; - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - callback.userInputRequired(result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), message); - break; - case OpenPgpApi.RESULT_CODE_ERROR: - logError(conversation.getAccount(), result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); - callback.error(R.string.openpgp_error, message); - break; - } - }); + }); } catch (final IOException e) { callback.error(R.string.openpgp_error, message); } @@ -168,11 +193,11 @@ public class PgpEngine { final InputStream is = new ByteArrayInputStream(Strings.nullToEmpty(status).getBytes()); final ByteArrayOutputStream os = new ByteArrayOutputStream(); final Intent result = api.executeApi(params, is, os); - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, - OpenPgpApi.RESULT_CODE_ERROR)) { + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { case OpenPgpApi.RESULT_CODE_SUCCESS: - final OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); - //TODO unsure that sigResult.getResult() is either 1, 2 or 3 + final OpenPgpSignatureResult sigResult = + result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); + // TODO unsure that sigResult.getResult() is either 1, 2 or 3 if (sigResult != null) { return sigResult.getKeyId(); } else { @@ -190,22 +215,31 @@ public class PgpEngine { public void chooseKey(final Account account, final UiCallback callback) { Intent p = new Intent(); p.setAction(OpenPgpApi.ACTION_GET_SIGN_KEY_ID); - api.executeApiAsync(p, null, null, result -> { - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: - callback.success(account); - return; - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - callback.userInputRequired(result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), account); - return; - case OpenPgpApi.RESULT_CODE_ERROR: - logError(account, result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); - callback.error(R.string.openpgp_error, account); - } - }); + api.executeApiAsync( + p, + null, + null, + result -> { + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: + callback.success(account); + return; + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: + callback.userInputRequired( + result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), account); + return; + case OpenPgpApi.RESULT_CODE_ERROR: + logError(account, result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); + callback.error(R.string.openpgp_error, account); + } + }); } - public void generateSignature(Intent intent, final Account account, String status, final UiCallback callback) { + public void generateSignature( + Intent intent, + final Account account, + String status, + final UiCallback callback) { if (account.getPgpId() == 0) { return; } @@ -215,70 +249,86 @@ public class PgpEngine { params.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, account.getPgpId()); InputStream is = new ByteArrayInputStream(status.getBytes()); final OutputStream os = new ByteArrayOutputStream(); - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": signing status message \"" + status + "\""); - api.executeApiAsync(params, is, os, result -> { - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: - final ArrayList signature = new ArrayList<>(); - try { - os.flush(); - boolean sig = false; - for (final String line : Splitter.on('\n').split(os.toString())) { - if (sig) { - if (line.contains("END PGP SIGNATURE")) { - sig = false; - } else { - if (!line.contains("Version")) { - signature.add(line.trim()); + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + ": signing status message \"" + status + "\""); + api.executeApiAsync( + params, + is, + os, + result -> { + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: + final ArrayList signature = new ArrayList<>(); + try { + os.flush(); + boolean sig = false; + for (final String line : Splitter.on('\n').split(os.toString())) { + if (sig) { + if (line.contains("END PGP SIGNATURE")) { + sig = false; + } else { + if (!line.contains("Version")) { + signature.add(line.trim()); + } + } + } + if (line.contains("BEGIN PGP SIGNATURE")) { + sig = true; } } + } catch (IOException e) { + callback.error(R.string.openpgp_error, null); + return; } - if (line.contains("BEGIN PGP SIGNATURE")) { - sig = true; + callback.success(Joiner.on('\n').join(signature)); + return; + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: + callback.userInputRequired( + result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), status); + return; + case OpenPgpApi.RESULT_CODE_ERROR: + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + if (error != null + && "signing subkey not found!".equals(error.getMessage())) { + callback.error(0, null); + } else { + logError(account, error); + callback.error(R.string.unable_to_connect_to_keychain, null); } - } - } catch (IOException e) { - callback.error(R.string.openpgp_error, null); - return; } - callback.success(Joiner.on('\n').join(signature)); - return; - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - callback.userInputRequired(result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), status); - return; - case OpenPgpApi.RESULT_CODE_ERROR: - OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); - if (error != null && "signing subkey not found!".equals(error.getMessage())) { - callback.error(0, null); - } else { - logError(account, error); - callback.error(R.string.unable_to_connect_to_keychain, null); - } - } - }); + }); } public void hasKey(final Contact contact, final UiCallback callback) { Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_GET_KEY); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId()); - api.executeApiAsync(params, null, null, new IOpenPgpCallback() { + api.executeApiAsync( + params, + null, + null, + new IOpenPgpCallback() { - @Override - public void onReturn(Intent result) { - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: - callback.success(contact); - return; - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - callback.userInputRequired(result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), contact); - return; - case OpenPgpApi.RESULT_CODE_ERROR: - logError(contact.getAccount(), result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); - callback.error(R.string.openpgp_error, contact); - } - } - }); + @Override + public void onReturn(Intent result) { + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: + callback.success(contact); + return; + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: + callback.userInputRequired( + result.getParcelableExtra(OpenPgpApi.RESULT_INTENT), + contact); + return; + case OpenPgpApi.RESULT_CODE_ERROR: + logError( + contact.getAccount(), + result.getParcelableExtra(OpenPgpApi.RESULT_ERROR)); + callback.error(R.string.openpgp_error, contact); + } + } + }); } public PendingIntent getIntentForKey(long pgpKeyId) { @@ -288,6 +338,6 @@ public class PgpEngine { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[0]); Intent result = api.executeApi(params, inputStream, outputStream); - return (PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + return result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); } } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 53757f939072473856f5f8ea8cfbf39dabb66c0d..85f5695965b4578923c4cc646d772f5cbf08fdee 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -951,7 +951,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Config.LOGTAG, getLogprefix(account) + "Error received while publishing bundle: " - + response.toString()); + + response); } pepBroken = true; } @@ -1416,7 +1416,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already have session for " - + address.toString() + + address + ", adding to cache..."); XmppAxolotlSession session = new XmppAxolotlSession( @@ -1462,7 +1462,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already have session for " - + address.toString() + + address + ", adding to cache..."); XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey); @@ -1538,7 +1538,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already fetching bundle for " - + address.toString()); + + address); } } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index bba24d90b5a5c8899e7441135b66e29144b12925..8bad6a2fc409c578dc4a98c1ff269b2519c56a78 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -2,7 +2,10 @@ package eu.siacs.conversations.crypto.axolotl; import android.util.Base64; import android.util.Log; - +import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.Compatibility; +import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.Jid; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -10,7 +13,6 @@ import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; - import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; @@ -20,11 +22,6 @@ import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import eu.siacs.conversations.Config; -import eu.siacs.conversations.utils.Compatibility; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.Jid; - public class XmppAxolotlMessage { public static final String CONTAINERTAG = "encrypted"; private static final String HEADER = "header"; @@ -45,7 +42,8 @@ public class XmppAxolotlMessage { private byte[] authtagPlusInnerKey = null; private byte[] iv = null; - private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException { + private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) + throws IllegalArgumentException { this.from = from; Element header = axolotlMessage.findChild(HEADER); try { @@ -62,7 +60,8 @@ public class XmppAxolotlMessage { int recipientId = Integer.parseInt(keyElement.getAttribute(REMOTEID)); byte[] key = Base64.decode(keyElement.getContent().trim(), Base64.DEFAULT); boolean isPreKey = keyElement.getAttributeAsBoolean("prekey"); - this.keys.add(new XmppAxolotlSession.AxolotlKey(recipientId, key, isPreKey)); + this.keys.add( + new XmppAxolotlSession.AxolotlKey(recipientId, key, isPreKey)); } catch (NumberFormatException e) { throw new IllegalArgumentException("invalid remote id"); } @@ -74,11 +73,12 @@ public class XmppAxolotlMessage { iv = Base64.decode(keyElement.getContent().trim(), Base64.DEFAULT); break; default: - Log.w(Config.LOGTAG, "Unexpected element in header: " + keyElement.toString()); + Log.w(Config.LOGTAG, "Unexpected element in header: " + keyElement); break; } } - final Element payloadElement = axolotlMessage.findChildEnsureSingle(PAYLOAD, AxolotlService.PEP_PREFIX); + final Element payloadElement = + axolotlMessage.findChildEnsureSingle(PAYLOAD, AxolotlService.PEP_PREFIX); if (payloadElement != null) { ciphertext = Base64.decode(payloadElement.getContent().trim(), Base64.DEFAULT); } @@ -149,9 +149,16 @@ public class XmppAxolotlMessage { try { SecretKey secretKey = new SecretKeySpec(innerKey, KEYTYPE); IvParameterSpec ivSpec = new IvParameterSpec(iv); - Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); + Cipher cipher = + Compatibility.twentyEight() + ? Cipher.getInstance(CIPHERMODE) + : Cipher.getInstance(CIPHERMODE, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); - this.ciphertext = cipher.doFinal(Config.OMEMO_PADDING ? getPaddedBytes(plaintext) : plaintext.getBytes()); + this.ciphertext = + cipher.doFinal( + Config.OMEMO_PADDING + ? getPaddedBytes(plaintext) + : plaintext.getBytes()); if (Config.PUT_AUTH_TAG_INTO_KEY && this.ciphertext != null) { this.authtagPlusInnerKey = new byte[16 + 16]; byte[] ciphertext = new byte[this.ciphertext.length - 16]; @@ -160,8 +167,12 @@ public class XmppAxolotlMessage { System.arraycopy(this.innerKey, 0, authtagPlusInnerKey, 0, this.innerKey.length); this.ciphertext = ciphertext; } - } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException - | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException + } catch (NoSuchAlgorithmException + | NoSuchPaddingException + | InvalidKeyException + | IllegalBlockSizeException + | BadPaddingException + | NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new CryptoFailedException(e); } @@ -220,7 +231,8 @@ public class XmppAxolotlMessage { return encryptionElement; } - private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException { + private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) + throws CryptoFailedException { ArrayList possibleKeys = new ArrayList<>(); for (XmppAxolotlSession.AxolotlKey key : keys) { if (key.deviceId == sourceDeviceId) { @@ -233,17 +245,22 @@ public class XmppAxolotlMessage { return session.processReceiving(possibleKeys); } - XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException { - return new XmppAxolotlKeyTransportMessage(session.getFingerprint(), unpackKey(session, sourceDeviceId), getIV()); + XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) + throws CryptoFailedException { + return new XmppAxolotlKeyTransportMessage( + session.getFingerprint(), unpackKey(session, sourceDeviceId), getIV()); } - public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException { + public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) + throws CryptoFailedException { XmppAxolotlPlaintextMessage plaintextMessage = null; byte[] key = unpackKey(session, sourceDeviceId); if (key != null) { try { if (key.length < 32) { - throw new OutdatedSenderException("Key did not contain auth tag. Sender needs to update their OMEMO client"); + throw new OutdatedSenderException( + "Key did not contain auth tag. Sender needs to update their OMEMO" + + " client"); } final int authTagLength = key.length - 16; byte[] newCipherText = new byte[key.length - 16 + ciphertext.length]; @@ -254,18 +271,28 @@ public class XmppAxolotlMessage { ciphertext = newCipherText; key = newKey; - final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); + final Cipher cipher = + Compatibility.twentyEight() + ? Cipher.getInstance(CIPHERMODE) + : Cipher.getInstance(CIPHERMODE, PROVIDER); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); IvParameterSpec ivSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); String plaintext = new String(cipher.doFinal(ciphertext)); - plaintextMessage = new XmppAxolotlPlaintextMessage(Config.OMEMO_PADDING ? plaintext.trim() : plaintext, session.getFingerprint()); - - } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException - | InvalidAlgorithmParameterException | IllegalBlockSizeException - | BadPaddingException | NoSuchProviderException e) { + plaintextMessage = + new XmppAxolotlPlaintextMessage( + Config.OMEMO_PADDING ? plaintext.trim() : plaintext, + session.getFingerprint()); + + } catch (NoSuchAlgorithmException + | NoSuchPaddingException + | InvalidKeyException + | InvalidAlgorithmParameterException + | IllegalBlockSizeException + | BadPaddingException + | NoSuchProviderException e) { throw new CryptoFailedException(e); } } @@ -285,7 +312,6 @@ public class XmppAxolotlMessage { return plaintext; } - public String getFingerprint() { return fingerprint; } diff --git a/src/main/java/eu/siacs/conversations/entities/Edit.java b/src/main/java/eu/siacs/conversations/entities/Edit.java index a3865bdd08c808b10bd0d10968f6e724a15092d3..2357dc0105db72f4156da8f13c6e55fe9b4079f6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Edit.java +++ b/src/main/java/eu/siacs/conversations/entities/Edit.java @@ -1,12 +1,12 @@ package eu.siacs.conversations.entities; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; -import java.util.List; - public class Edit { private final String editedId; @@ -45,7 +45,8 @@ public class Edit { private static Edit fromJson(JSONObject jsonObject) throws JSONException { String edited = jsonObject.has("edited_id") ? jsonObject.getString("edited_id") : null; - String serverMsgId = jsonObject.has("server_msg_id") ? jsonObject.getString("server_msg_id") : null; + String serverMsgId = + jsonObject.has("server_msg_id") ? jsonObject.getString("server_msg_id") : null; return new Edit(edited, serverMsgId); } @@ -83,9 +84,8 @@ public class Edit { Edit edit = (Edit) o; - if (editedId != null ? !editedId.equals(edit.editedId) : edit.editedId != null) - return false; - return serverMsgId != null ? serverMsgId.equals(edit.serverMsgId) : edit.serverMsgId == null; + if (!Objects.equals(editedId, edit.editedId)) return false; + return Objects.equals(serverMsgId, edit.serverMsgId); } @Override diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 1b68acf0fceb5810d9e0df31ea333a80f242a9d0..7ba6f8a23276a8878c87e7735d2c10ff7871dd8b 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.Set; public class MucOptions { @@ -919,9 +920,8 @@ public class MucOptions { if (role != user.role) return false; if (affiliation != user.affiliation) return false; - if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null) - return false; - return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null; + if (!Objects.equals(realJid, user.realJid)) return false; + return Objects.equals(fullJid, user.fullJid); } public boolean isDomain() { diff --git a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java index 91741e674aaf93f1219ac4056f93e19adb6a754c..958891d34d4b8915fdc3309a4827c37b41001347 100644 --- a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java +++ b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java @@ -2,80 +2,77 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; - +import java.util.Objects; public class PresenceTemplate extends AbstractEntity { - public static final String TABELNAME = "presence_templates"; - public static final String LAST_USED = "last_used"; - public static final String MESSAGE = "message"; - public static final String STATUS = "status"; - - private long lastUsed = 0; - private String statusMessage; - private Presence.Status status = Presence.Status.ONLINE; - - public PresenceTemplate(Presence.Status status, String statusMessage) { - this.status = status; - this.statusMessage = statusMessage; - this.lastUsed = System.currentTimeMillis(); - this.uuid = java.util.UUID.randomUUID().toString(); - } - - private PresenceTemplate() { - - } - - @Override - public ContentValues getContentValues() { - final String show = status.toShowString(); - ContentValues values = new ContentValues(); - values.put(LAST_USED, lastUsed); - values.put(MESSAGE, statusMessage); - values.put(STATUS, show == null ? "" : show); - values.put(UUID, uuid); - return values; - } - - public static PresenceTemplate fromCursor(Cursor cursor) { - PresenceTemplate template = new PresenceTemplate(); - template.uuid = cursor.getString(cursor.getColumnIndex(UUID)); - template.lastUsed = cursor.getLong(cursor.getColumnIndex(LAST_USED)); - template.statusMessage = cursor.getString(cursor.getColumnIndex(MESSAGE)); - template.status = Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS))); - return template; - } - - public Presence.Status getStatus() { - return status; - } - - public String getStatusMessage() { - return statusMessage; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - PresenceTemplate template = (PresenceTemplate) o; - - if (statusMessage != null ? !statusMessage.equals(template.statusMessage) : template.statusMessage != null) - return false; - return status == template.status; - - } - - @Override - public int hashCode() { - int result = statusMessage != null ? statusMessage.hashCode() : 0; - result = 31 * result + status.hashCode(); - return result; - } - - @Override - public String toString() { - return statusMessage; - } + public static final String TABELNAME = "presence_templates"; + public static final String LAST_USED = "last_used"; + public static final String MESSAGE = "message"; + public static final String STATUS = "status"; + + private long lastUsed = 0; + private String statusMessage; + private Presence.Status status = Presence.Status.ONLINE; + + public PresenceTemplate(Presence.Status status, String statusMessage) { + this.status = status; + this.statusMessage = statusMessage; + this.lastUsed = System.currentTimeMillis(); + this.uuid = java.util.UUID.randomUUID().toString(); + } + + private PresenceTemplate() {} + + @Override + public ContentValues getContentValues() { + final String show = status.toShowString(); + ContentValues values = new ContentValues(); + values.put(LAST_USED, lastUsed); + values.put(MESSAGE, statusMessage); + values.put(STATUS, show == null ? "" : show); + values.put(UUID, uuid); + return values; + } + + public static PresenceTemplate fromCursor(Cursor cursor) { + PresenceTemplate template = new PresenceTemplate(); + template.uuid = cursor.getString(cursor.getColumnIndex(UUID)); + template.lastUsed = cursor.getLong(cursor.getColumnIndex(LAST_USED)); + template.statusMessage = cursor.getString(cursor.getColumnIndex(MESSAGE)); + template.status = + Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS))); + return template; + } + + public Presence.Status getStatus() { + return status; + } + + public String getStatusMessage() { + return statusMessage; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PresenceTemplate template = (PresenceTemplate) o; + + if (!Objects.equals(statusMessage, template.statusMessage)) return false; + return status == template.status; + } + + @Override + public int hashCode() { + int result = statusMessage != null ? statusMessage.hashCode() : 0; + result = 31 * result + status.hashCode(); + return result; + } + + @Override + public String toString() { + return statusMessage; + } } diff --git a/src/main/java/eu/siacs/conversations/entities/ReadByMarker.java b/src/main/java/eu/siacs/conversations/entities/ReadByMarker.java index 4b1254f0761bee318809cd90f0d5ded8b5a71260..f8e0ace1a1f90c4a587349d1e4ebd2a72eb1bfe4 100644 --- a/src/main/java/eu/siacs/conversations/entities/ReadByMarker.java +++ b/src/main/java/eu/siacs/conversations/entities/ReadByMarker.java @@ -1,171 +1,167 @@ package eu.siacs.conversations.entities; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - +import eu.siacs.conversations.xmpp.Jid; import java.util.Collection; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; - -import eu.siacs.conversations.xmpp.Jid; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; public class ReadByMarker { - private ReadByMarker() { - - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ReadByMarker marker = (ReadByMarker) o; - - if (fullJid != null ? !fullJid.equals(marker.fullJid) : marker.fullJid != null) - return false; - return realJid != null ? realJid.equals(marker.realJid) : marker.realJid == null; - - } - - @Override - public int hashCode() { - int result = fullJid != null ? fullJid.hashCode() : 0; - result = 31 * result + (realJid != null ? realJid.hashCode() : 0); - return result; - } - - private Jid fullJid; - private Jid realJid; - - public Jid getFullJid() { - return fullJid; - } - - public Jid getRealJid() { - return realJid; - } - - public JSONObject toJson() { - JSONObject jsonObject = new JSONObject(); - if (fullJid != null) { - try { - jsonObject.put("fullJid", fullJid.toString()); - } catch (JSONException e) { - //ignore - } - } - if (realJid != null) { - try { - jsonObject.put("realJid", realJid.toString()); - } catch (JSONException e) { - //ignore - } - } - return jsonObject; - } - - public static Set fromJson(final JSONArray jsonArray) { - final Set readByMarkers = new CopyOnWriteArraySet<>(); - for(int i = 0; i < jsonArray.length(); ++i) { - try { - readByMarkers.add(fromJson(jsonArray.getJSONObject(i))); - } catch (JSONException e) { - //ignored - } - } - return readByMarkers; - } - - public static ReadByMarker from(Jid fullJid, Jid realJid) { - final ReadByMarker marker = new ReadByMarker(); - marker.fullJid = fullJid; - marker.realJid = realJid == null ? null : realJid.asBareJid(); - return marker; - } - - public static ReadByMarker from(Message message) { - final ReadByMarker marker = new ReadByMarker(); - marker.fullJid = message.getCounterpart(); - marker.realJid = message.getTrueCounterpart(); - return marker; - } - - public static ReadByMarker from(MucOptions.User user) { - final ReadByMarker marker = new ReadByMarker(); - marker.fullJid = user.getFullJid(); - marker.realJid = user.getRealJid(); - return marker; - } - - public static Set from(Collection users) { - final Set markers = new CopyOnWriteArraySet<>(); - for(MucOptions.User user : users) { - markers.add(from(user)); - } - return markers; - } - - public static ReadByMarker fromJson(JSONObject jsonObject) { - ReadByMarker marker = new ReadByMarker(); - try { - marker.fullJid = Jid.of(jsonObject.getString("fullJid")); - } catch (JSONException | IllegalArgumentException e) { - marker.fullJid = null; - } - try { - marker.realJid = Jid.of(jsonObject.getString("realJid")); - } catch (JSONException | IllegalArgumentException e) { - marker.realJid = null; - } - return marker; - } - - public static Set fromJsonString(String json) { - try { - return fromJson(new JSONArray(json)); - } catch (final JSONException | NullPointerException e) { - return new CopyOnWriteArraySet<>(); - } - } - - public static JSONArray toJson(final Set readByMarkers) { - final JSONArray jsonArray = new JSONArray(); - for(final ReadByMarker marker : readByMarkers) { - jsonArray.put(marker.toJson()); - } - return jsonArray; - } - - public static boolean contains(ReadByMarker needle, final Set readByMarkers) { - for(final ReadByMarker marker : readByMarkers) { - if (marker.realJid != null && needle.realJid != null) { - if (marker.realJid.asBareJid().equals(needle.realJid.asBareJid())) { - return true; - } - } else if (marker.fullJid != null && needle.fullJid != null) { - if (marker.fullJid.equals(needle.fullJid)) { - return true; - } - } - } - return false; - } - - public static boolean allUsersRepresented(Collection users, Set markers) { - for(MucOptions.User user : users) { - if (!contains(from(user),markers)) { - return false; - } - } - return true; - } - - public static boolean allUsersRepresented(Collection users, Set markers, ReadByMarker marker) { - final Set markersCopy = new CopyOnWriteArraySet<>(markers); - markersCopy.add(marker); - return allUsersRepresented(users, markersCopy); - } - + private ReadByMarker() {} + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ReadByMarker marker = (ReadByMarker) o; + + if (!Objects.equals(fullJid, marker.fullJid)) return false; + return Objects.equals(realJid, marker.realJid); + } + + @Override + public int hashCode() { + int result = fullJid != null ? fullJid.hashCode() : 0; + result = 31 * result + (realJid != null ? realJid.hashCode() : 0); + return result; + } + + private Jid fullJid; + private Jid realJid; + + public Jid getFullJid() { + return fullJid; + } + + public Jid getRealJid() { + return realJid; + } + + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + if (fullJid != null) { + try { + jsonObject.put("fullJid", fullJid.toString()); + } catch (JSONException e) { + // ignore + } + } + if (realJid != null) { + try { + jsonObject.put("realJid", realJid.toString()); + } catch (JSONException e) { + // ignore + } + } + return jsonObject; + } + + public static Set fromJson(final JSONArray jsonArray) { + final Set readByMarkers = new CopyOnWriteArraySet<>(); + for (int i = 0; i < jsonArray.length(); ++i) { + try { + readByMarkers.add(fromJson(jsonArray.getJSONObject(i))); + } catch (JSONException e) { + // ignored + } + } + return readByMarkers; + } + + public static ReadByMarker from(Jid fullJid, Jid realJid) { + final ReadByMarker marker = new ReadByMarker(); + marker.fullJid = fullJid; + marker.realJid = realJid == null ? null : realJid.asBareJid(); + return marker; + } + + public static ReadByMarker from(Message message) { + final ReadByMarker marker = new ReadByMarker(); + marker.fullJid = message.getCounterpart(); + marker.realJid = message.getTrueCounterpart(); + return marker; + } + + public static ReadByMarker from(MucOptions.User user) { + final ReadByMarker marker = new ReadByMarker(); + marker.fullJid = user.getFullJid(); + marker.realJid = user.getRealJid(); + return marker; + } + + public static Set from(Collection users) { + final Set markers = new CopyOnWriteArraySet<>(); + for (MucOptions.User user : users) { + markers.add(from(user)); + } + return markers; + } + + public static ReadByMarker fromJson(JSONObject jsonObject) { + ReadByMarker marker = new ReadByMarker(); + try { + marker.fullJid = Jid.of(jsonObject.getString("fullJid")); + } catch (JSONException | IllegalArgumentException e) { + marker.fullJid = null; + } + try { + marker.realJid = Jid.of(jsonObject.getString("realJid")); + } catch (JSONException | IllegalArgumentException e) { + marker.realJid = null; + } + return marker; + } + + public static Set fromJsonString(String json) { + try { + return fromJson(new JSONArray(json)); + } catch (final JSONException | NullPointerException e) { + return new CopyOnWriteArraySet<>(); + } + } + + public static JSONArray toJson(final Set readByMarkers) { + final JSONArray jsonArray = new JSONArray(); + for (final ReadByMarker marker : readByMarkers) { + jsonArray.put(marker.toJson()); + } + return jsonArray; + } + + public static boolean contains(ReadByMarker needle, final Set readByMarkers) { + for (final ReadByMarker marker : readByMarkers) { + if (marker.realJid != null && needle.realJid != null) { + if (marker.realJid.asBareJid().equals(needle.realJid.asBareJid())) { + return true; + } + } else if (marker.fullJid != null && needle.fullJid != null) { + if (marker.fullJid.equals(needle.fullJid)) { + return true; + } + } + } + return false; + } + + public static boolean allUsersRepresented( + Collection users, Set markers) { + for (MucOptions.User user : users) { + if (!contains(from(user), markers)) { + return false; + } + } + return true; + } + + public static boolean allUsersRepresented( + Collection users, Set markers, ReadByMarker marker) { + final Set markersCopy = new CopyOnWriteArraySet<>(markers); + markersCopy.add(marker); + return allUsersRepresented(users, markersCopy); + } } diff --git a/src/main/java/eu/siacs/conversations/http/SlotRequester.java b/src/main/java/eu/siacs/conversations/http/SlotRequester.java index cc8e5ec2b091590bdc9d686987a90f6b64c3ed87..5bb5d7772b253857e7cc8eab81c60c4aedb9d1c2 100644 --- a/src/main/java/eu/siacs/conversations/http/SlotRequester.java +++ b/src/main/java/eu/siacs/conversations/http/SlotRequester.java @@ -79,7 +79,7 @@ public class SlotRequester { response.getExtension( im.conversations.android.xmpp.model.upload.Slot.class); if (slot == null) { - Log.d(Config.LOGTAG, "-->" + response.toString()); + Log.d(Config.LOGTAG, "-->" + response); throw new IllegalStateException("Slot not found in IQ response"); } final var getUrl = slot.getGetUrl(); diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 14efffd532f2846c388e364e9929a098bcf9a6db..7a7f9c3a0aa031e431991ef9398cde8b02e1d9c1 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -189,7 +189,7 @@ public class IqParser extends AbstractParser implements Consumer { + "Encountered invalid node in PEP (" + e.getMessage() + "):" - + device.toString() + + device + ", skipping..."); } } @@ -313,7 +313,7 @@ public class IqParser extends AbstractParser implements Consumer { AxolotlService.LOGPREFIX + " : " + "could not parse preKeyId from preKey " - + preKeyPublicElement.toString()); + + preKeyPublicElement); } catch (Throwable e) { Log.e( Config.LOGTAG, diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 83e817c2b5c95eaf42ab315d3b3291dc943bb0f4..ecf20048ce57c285c6be3b369369e7cce7dc0027 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -332,7 +332,6 @@ public class MessageParser extends AbstractParser } } else if (Namespace.BOOKMARKS2.equals(node) && account.getJid().asBareJid().equals(from)) { final var retractions = items.getRetractions(); - ; for (final var item : items.getItemMap(Conference.class).entrySet()) { final Bookmark bookmark = Bookmark.parseFromItem(item.getKey(), item.getValue(), account); diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index efbc1d7227ea3531b426b7405c4a42c1e6f325dc..e4787999c275e3fd7e546e70d3e0eccb081fd630 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -346,7 +346,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { final SQLiteDatabase db = getWritableDatabase(); final Stopwatch stopwatch = Stopwatch.createStarted(); db.execSQL(COPY_PREEXISTING_ENTRIES); - Log.d(Config.LOGTAG, "rebuilt message index in " + stopwatch.stop().toString()); + Log.d(Config.LOGTAG, "rebuilt message index in " + stopwatch.stop()); } public static synchronized DatabaseBackend getInstance(Context context) { @@ -1561,7 +1561,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + " is not null and conversationUuid=(select uuid from conversations where" + " accountUuid=? and (contactJid=? or contactJid like ?)) order by" + " timeSent desc"; - final String[] args = {account, jid.toString(), jid.toString() + "/%"}; + final String[] args = {account, jid.toString(), jid + "/%"}; Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + limit : ""), args); List filesPaths = new ArrayList<>(); while (cursor.moveToNext()) { diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index c7f4e0d24555bf573bf7833b3cef04fd798f1f0c..2b95a1cf8de62a2661cfd72015f32eb8e65d4ac9 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -425,9 +425,7 @@ public class FileBackend { } public static void updateFileParams(Message message, String url, long size) { - final StringBuilder body = new StringBuilder(); - body.append(url).append('|').append(size); - message.setBody(body.toString()); + message.setBody(url + '|' + size); } public Bitmap getPreviewForUri(Attachment attachment, int size, boolean cacheOnly) { @@ -1244,7 +1242,7 @@ public class FileBackend { Log.d(Config.LOGTAG, "settled on char length " + chars + " with quality=" + quality); final Avatar avatar = new Avatar(); avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); - avatar.image = new String(mByteArrayOutputStream.toByteArray()); + avatar.image = mByteArrayOutputStream.toString(); if (format.equals(Bitmap.CompressFormat.WEBP)) { avatar.type = "image/webp"; } else if (format.equals(Bitmap.CompressFormat.JPEG)) { @@ -1289,7 +1287,7 @@ public class FileBackend { os.flush(); os.close(); avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); - avatar.image = new String(mByteArrayOutputStream.toByteArray()); + avatar.image = mByteArrayOutputStream.toString(); avatar.height = options.outHeight; avatar.width = options.outWidth; avatar.type = options.outMimeType; diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegration.java b/src/main/java/eu/siacs/conversations/services/CallIntegration.java index 747f79fb31f2c14167ee9f6b00f6f5c0b57fec1f..3684e4f3ecd932005cb776452b8194ebc5da6848 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegration.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegration.java @@ -540,10 +540,7 @@ public class CallIntegration extends Connection { return false; } // SailfishOS's AppSupport do not support Call Integration - if (Build.MODEL.endsWith("(AppSupport)")) { - return false; - } - return true; + return !Build.MODEL.endsWith("(AppSupport)"); } public static boolean notSelfManaged(final Context context) { diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java index 2c342e6728a985b12a1bb7d28b8a41ec63e132cc..11580e20fa4442cb5ffc9ec0c0c3ffa7d19d9abc 100644 --- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java @@ -3,15 +3,7 @@ package eu.siacs.conversations.services; import static eu.siacs.conversations.utils.Random.SECURE_RANDOM; import android.util.Log; - import androidx.annotation.NonNull; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -25,6 +17,11 @@ import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded; import eu.siacs.conversations.xmpp.mam.MamReference; import im.conversations.android.xmpp.model.stanza.Iq; import im.conversations.android.xmpp.model.stanza.Message; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { @@ -90,7 +87,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } return null; } - } MessageArchiveService(final XmppConnectionService service) { @@ -106,11 +102,13 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } - MamReference mamReference = MamReference.max( - mXmppConnectionService.databaseBackend.getLastMessageReceived(account), - mXmppConnectionService.databaseBackend.getLastClearDate(account) - ); - mamReference = MamReference.max(mamReference, mXmppConnectionService.getAutomaticMessageDeletionDate()); + MamReference mamReference = + MamReference.max( + mXmppConnectionService.databaseBackend.getLastMessageReceived(account), + mXmppConnectionService.databaseBackend.getLastClearDate(account)); + mamReference = + MamReference.max( + mamReference, mXmppConnectionService.getAutomaticMessageDeletionDate()); long endCatchup = account.getXmppConnection().getLastSessionEstablished(); final Query query; if (mamReference.getTimestamp() == 0) { @@ -119,7 +117,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { long startCatchup = endCatchup - Config.MAM_MAX_CATCHUP; List conversations = mXmppConnectionService.getConversations(); for (Conversation conversation : conversations) { - if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account && startCatchup > conversation.getLastMessageTransmitted().getTimestamp()) { + if (conversation.getMode() == Conversation.MODE_SINGLE + && conversation.getAccount() == account + && startCatchup > conversation.getLastMessageTransmitted().getTimestamp()) { this.query(conversation, startCatchup, true); } } @@ -134,27 +134,21 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } void catchupMUC(final Conversation conversation) { - if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) { - query(conversation, - new MamReference(0), - 0, - true); + if (conversation.getLastMessageTransmitted().getTimestamp() < 0 + && conversation.countMessages() == 0) { + query(conversation, new MamReference(0), 0, true); } else { - query(conversation, - conversation.getLastMessageTransmitted(), - 0, - true); + query(conversation, conversation.getLastMessageTransmitted(), 0, true); } } public Query query(final Conversation conversation) { - if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) { - return query(conversation, - new MamReference(0), - System.currentTimeMillis(), - false); + if (conversation.getLastMessageTransmitted().getTimestamp() < 0 + && conversation.countMessages() == 0) { + return query(conversation, new MamReference(0), System.currentTimeMillis(), false); } else { - return query(conversation, + return query( + conversation, conversation.getLastMessageTransmitted(), conversation.getAccount().getXmppConnection().getLastSessionEstablished(), false); @@ -168,7 +162,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } else { synchronized (this.queries) { for (Query query : this.queries) { - if (query.getAccount() == account && query.isCatchup() && ((conversation.getMode() == Conversation.MODE_SINGLE && query.getWith() == null) || query.getConversation() == conversation)) { + if (query.getAccount() == account + && query.isCatchup() + && ((conversation.getMode() == Conversation.MODE_SINGLE + && query.getWith() == null) + || query.getConversation() == conversation)) { return true; } } @@ -178,21 +176,33 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } public Query query(final Conversation conversation, long end, boolean allowCatchup) { - return this.query(conversation, conversation.getLastMessageTransmitted(), end, allowCatchup); + return this.query( + conversation, conversation.getLastMessageTransmitted(), end, allowCatchup); } - public Query query(Conversation conversation, MamReference start, long end, boolean allowCatchup) { + public Query query( + Conversation conversation, MamReference start, long end, boolean allowCatchup) { synchronized (this.queries) { final Query query; - final MamReference startActual = MamReference.max(start, mXmppConnectionService.getAutomaticMessageDeletionDate()); + final MamReference startActual = + MamReference.max( + start, mXmppConnectionService.getAutomaticMessageDeletionDate()); if (start.getTimestamp() == 0) { query = new Query(conversation, startActual, end, false); query.reference = conversation.getFirstMamReference(); } else { if (allowCatchup) { - MamReference maxCatchup = MamReference.max(startActual, System.currentTimeMillis() - Config.MAM_MAX_CATCHUP); + MamReference maxCatchup = + MamReference.max( + startActual, + System.currentTimeMillis() - Config.MAM_MAX_CATCHUP); if (maxCatchup.greaterThan(startActual)) { - Query reverseCatchup = new Query(conversation, startActual, maxCatchup.getTimestamp(), false); + Query reverseCatchup = + new Query( + conversation, + startActual, + maxCatchup.getTimestamp(), + false); this.queries.add(reverseCatchup); this.execute(reverseCatchup); } @@ -231,40 +241,57 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { if (account.getStatus() == Account.State.ONLINE) { final Conversation conversation = query.getConversation(); if (conversation != null && conversation.getStatus() == Conversation.STATUS_ARCHIVED) { - throw new IllegalStateException("Attempted to run MAM query for archived conversation"); - } - Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString()); - final Iq packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query); - this.mXmppConnectionService.sendIqPacket(account, packet, (p) -> { - final Element fin = p.findChild("fin", query.version.namespace); - if (p.getType() == Iq.Type.TIMEOUT) { - synchronized (this.queries) { - this.queries.remove(query); - if (query.hasCallback()) { - query.callback(false); + throw new IllegalStateException( + "Attempted to run MAM query for archived conversation"); + } + Log.d( + Config.LOGTAG, + account.getJid().asBareJid().toString() + ": running mam query " + query); + final Iq packet = + this.mXmppConnectionService + .getIqGenerator() + .queryMessageArchiveManagement(query); + this.mXmppConnectionService.sendIqPacket( + account, + packet, + (p) -> { + final Element fin = p.findChild("fin", query.version.namespace); + if (p.getType() == Iq.Type.TIMEOUT) { + synchronized (this.queries) { + this.queries.remove(query); + if (query.hasCallback()) { + query.callback(false); + } + } + } else if (p.getType() == Iq.Type.RESULT && fin != null) { + final boolean running; + synchronized (this.queries) { + running = this.queries.contains(query); + } + if (running) { + processFin(query, fin); + } else { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": ignoring MAM iq result because query had been" + + " killed"); + } + } else if (p.getType() == Iq.Type.RESULT && query.isLegacy()) { + // do nothing + } else { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid().toString() + + ": error executing mam: " + + p); + try { + finalizeQuery(query, true); + } catch (final IllegalStateException e) { + // ignored + } } - } - } else if (p.getType() == Iq.Type.RESULT && fin != null) { - final boolean running; - synchronized (this.queries) { - running = this.queries.contains(query); - } - if (running) { - processFin(query, fin); - } else { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring MAM iq result because query had been killed"); - } - } else if (p.getType() == Iq.Type.RESULT && query.isLegacy()) { - //do nothing - } else { - Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": error executing mam: " + p.toString()); - try { - finalizeQuery(query, true); - } catch (final IllegalStateException e) { - //ignored - } - } - }); + }); } else { synchronized (this.pendingQueries) { this.pendingQueries.add(query); @@ -320,7 +347,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { for (Query query : queries) { if (query.account == conversation.getAccount() && query.isCatchup()) { final Jid with = query.getWith() == null ? null : query.getWith().asBareJid(); - if ((conversation.getMode() == Conversational.MODE_SINGLE && with == null) || (conversation.getJid().asBareJid().equals(with))) { + if ((conversation.getMode() == Conversational.MODE_SINGLE && with == null) + || (conversation.getJid().asBareJid().equals(with))) { return true; } } @@ -329,7 +357,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { return false; } - boolean queryInProgress(Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) { + boolean queryInProgress( + Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) { synchronized (this.queries) { for (Query query : queries) { if (query.conversation == conversation) { @@ -361,12 +390,15 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { String count = set == null ? null : set.findChildContent("count"); Element first = set == null ? null : set.findChild("first"); Element relevant = query.getPagingOrder() == PagingOrder.NORMAL ? last : first; - boolean abort = (!query.isCatchup() && query.getTotalCount() >= Config.PAGE_SIZE) || query.getTotalCount() >= Config.MAM_MAX_MESSAGES; + boolean abort = + (!query.isCatchup() && query.getTotalCount() >= Config.PAGE_SIZE) + || query.getTotalCount() >= Config.MAM_MAX_MESSAGES; if (query.getConversation() != null) { query.getConversation().setFirstMamReference(first == null ? null : first.getContent()); } if (complete || relevant == null || abort) { - //TODO: FIX done logic to look at complete. using count is probably unreliable because it can be ommited and doesn’t work with paging. + // TODO: FIX done logic to look at complete. using count is probably unreliable because + // it can be ommited and doesn’t work with paging. boolean done; if (query.isCatchup()) { done = false; @@ -384,9 +416,21 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { done = done || (query.getActualMessageCount() == 0 && !query.isCatchup()); this.finalizeQuery(query, done); - Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": finished mam after " + query.getTotalCount() + "(" + query.getActualMessageCount() + ") messages. messages left=" + !done + " count=" + count); + Log.d( + Config.LOGTAG, + query.getAccount().getJid().asBareJid() + + ": finished mam after " + + query.getTotalCount() + + "(" + + query.getActualMessageCount() + + ") messages. messages left=" + + !done + + " count=" + + count); if (query.isCatchup() && query.getActualMessageCount() > 0) { - mXmppConnectionService.getNotificationService().finishBacklog(true, query.getAccount()); + mXmppConnectionService + .getNotificationService() + .finishBacklog(true, query.getAccount()); } processPostponed(query); } else { @@ -407,11 +451,15 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { void kill(final Conversation conversation) { final ArrayList toBeKilled = new ArrayList<>(); synchronized (this.pendingQueries) { - for (final Iterator iterator = this.pendingQueries.iterator(); iterator.hasNext(); ) { + for (final Iterator iterator = this.pendingQueries.iterator(); + iterator.hasNext(); ) { final Query query = iterator.next(); if (query.getConversation() == conversation) { iterator.remove(); - Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": killed pending MAM query for archived conversation"); + Log.d( + Config.LOGTAG, + conversation.getAccount().getJid().asBareJid() + + ": killed pending MAM query for archived conversation"); } } } @@ -428,7 +476,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } private void kill(Query query) { - Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": killing mam query prematurely"); + Log.d( + Config.LOGTAG, + query.getAccount().getJid().asBareJid() + ": killing mam query prematurely"); query.callback = null; this.finalizeQuery(query, false); if (query.isCatchup() && query.getActualMessageCount() > 0) { @@ -440,11 +490,20 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private void processPostponed(Query query) { query.account.getAxolotlService().processPostponed(); query.pendingReceiptRequests.removeAll(query.receiptRequests); - Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": found " + query.pendingReceiptRequests.size() + " pending receipt requests"); + Log.d( + Config.LOGTAG, + query.getAccount().getJid().asBareJid() + + ": found " + + query.pendingReceiptRequests.size() + + " pending receipt requests"); Iterator iterator = query.pendingReceiptRequests.iterator(); while (iterator.hasNext()) { ReceiptRequest rr = iterator.next(); - mXmppConnectionService.sendMessagePacket(query.account, mXmppConnectionService.getMessageGenerator().received(query.account, rr.getJid(), rr.getId())); + mXmppConnectionService.sendMessagePacket( + query.account, + mXmppConnectionService + .getMessageGenerator() + .received(query.account, rr.getJid(), rr.getId())); iterator.remove(); } } @@ -465,7 +524,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { @Override public void onAdvancedStreamFeaturesAvailable(Account account) { - if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().mam()) { + if (account.getXmppConnection() != null + && account.getXmppConnection().getFeatures().mam()) { this.catchup(account); } } @@ -492,9 +552,12 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private boolean catchup = true; public final Version version; - Query(Conversation conversation, MamReference start, long end, boolean catchup) { - this(conversation.getAccount(), Version.get(conversation.getAccount(), conversation), catchup ? start : start.timeOnly(), end); + this( + conversation.getAccount(), + Version.get(conversation.getAccount(), conversation), + catchup ? start : start.timeOnly(), + end); this.conversation = conversation; this.pagingOrder = catchup ? PagingOrder.NORMAL : PagingOrder.REVERSE; this.catchup = catchup; @@ -517,7 +580,12 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } private Query page(String reference) { - Query query = new Query(this.account, this.version, new MamReference(this.start, reference), this.end); + Query query = + new Query( + this.account, + this.version, + new MamReference(this.start, reference), + this.end); query.conversation = conversation; query.totalCount = totalCount; query.actualCount = actualCount; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index e8fb3ddee314146616b56f84a3a22c388ecf85eb..ff38d2ed57d57de0d58ef928beba1465e282182e 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -507,7 +507,7 @@ public class XmppConnectionService extends Service { private LruCache mBitmapCache; private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver(); private final BroadcastReceiver mInternalRestrictedEventReceiver = - new RestrictedEventReceiver(Arrays.asList(TorServiceUtils.ACTION_STATUS)); + new RestrictedEventReceiver(List.of(TorServiceUtils.ACTION_STATUS)); private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver(); private static String generateFetchKey(Account account, final Avatar avatar) { @@ -4535,7 +4535,7 @@ public class XmppConnectionService extends Service { if (packet.getType() == Iq.Type.RESULT) { callback.onPushSucceeded(); } else { - Log.d(Config.LOGTAG, "failed: " + packet.toString()); + Log.d(Config.LOGTAG, "failed: " + packet); callback.onPushFailed(); } } @@ -5125,7 +5125,7 @@ public class XmppConnectionService extends Service { if (error == null) { Log.d(Config.LOGTAG, ERROR + "(server error)"); } else { - Log.d(Config.LOGTAG, ERROR + error.toString()); + Log.d(Config.LOGTAG, ERROR + error); } } if (callback != null) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index d58c7a0fc524730e2297edd7865e431a099f4f5f..459ef2f0be6248eab923febd321012cefe683722 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -531,8 +531,7 @@ public class ConversationFragment extends XmppFragment @Override public void onClick(View v) { Object tag = v.getTag(); - if (tag instanceof SendButtonAction) { - SendButtonAction action = (SendButtonAction) tag; + if (tag instanceof SendButtonAction action) { switch (action) { case TAKE_PHOTO: case RECORD_VIDEO: diff --git a/src/main/java/eu/siacs/conversations/ui/CreatePrivateGroupChatDialog.java b/src/main/java/eu/siacs/conversations/ui/CreatePrivateGroupChatDialog.java index ae3406a2d821b17fd6782bd236120b8a09dca636..88c378f9ba370a7ae03f59d6a7aeb6b43c31eba1 100644 --- a/src/main/java/eu/siacs/conversations/ui/CreatePrivateGroupChatDialog.java +++ b/src/main/java/eu/siacs/conversations/ui/CreatePrivateGroupChatDialog.java @@ -4,20 +4,15 @@ import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.widget.AutoCompleteTextView; - import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.DialogFragment; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.ArrayList; -import java.util.List; - import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.DialogCreateConferenceBinding; import eu.siacs.conversations.ui.util.DelayedHintHelper; +import java.util.ArrayList; +import java.util.List; public class CreatePrivateGroupChatDialog extends DialogFragment { @@ -41,23 +36,36 @@ public class CreatePrivateGroupChatDialog extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity()); + final MaterialAlertDialogBuilder builder = + new MaterialAlertDialogBuilder(requireActivity()); builder.setTitle(R.string.create_private_group_chat); - final DialogCreateConferenceBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.dialog_create_conference, null, false); + final DialogCreateConferenceBinding binding = + DataBindingUtil.inflate( + getActivity().getLayoutInflater(), + R.layout.dialog_create_conference, + null, + false); ArrayList mActivatedAccounts = getArguments().getStringArrayList(ACCOUNTS_LIST_KEY); - StartConversationActivity.populateAccountSpinner(getActivity(), mActivatedAccounts, binding.account); + StartConversationActivity.populateAccountSpinner( + getActivity(), mActivatedAccounts, binding.account); builder.setView(binding.getRoot()); - builder.setPositiveButton(R.string.choose_participants, (dialog, which) -> mListener.onCreateDialogPositiveClick(binding.account, binding.groupChatName.getText().toString().trim())); + builder.setPositiveButton( + R.string.choose_participants, + (dialog, which) -> + mListener.onCreateDialogPositiveClick( + binding.account, + binding.groupChatName.getText().toString().trim())); builder.setNegativeButton(R.string.cancel, null); DelayedHintHelper.setHint(R.string.providing_a_name_is_optional, binding.groupChatName); - binding.groupChatName.setOnEditorActionListener((v, actionId, event) -> { - mListener.onCreateDialogPositiveClick(binding.account, binding.groupChatName.getText().toString().trim()); - return true; - }); + binding.groupChatName.setOnEditorActionListener( + (v, actionId, event) -> { + mListener.onCreateDialogPositiveClick( + binding.account, binding.groupChatName.getText().toString().trim()); + return true; + }); return builder.create(); } - public interface CreateConferenceDialogListener { void onCreateDialogPositiveClick(AutoCompleteTextView spinner, String subject); } @@ -68,8 +76,8 @@ public class CreatePrivateGroupChatDialog extends DialogFragment { try { mListener = (CreateConferenceDialogListener) context; } catch (ClassCastException e) { - throw new ClassCastException(context.toString() - + " must implement CreateConferenceDialogListener"); + throw new ClassCastException( + context + " must implement CreateConferenceDialogListener"); } } diff --git a/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java b/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java index b12aba750cb0accb3a0ace23dccf6000425ba759..7351823f6708e2e87ad6073f092e64da84b04f8e 100644 --- a/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java +++ b/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java @@ -288,7 +288,7 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke mListener = (CreatePublicChannelDialogListener) context; } catch (ClassCastException e) { throw new ClassCastException( - context.toString() + " must implement CreateConferenceDialogListener"); + context + " must implement CreateConferenceDialogListener"); } } diff --git a/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java b/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java index 849554d87eadb5730a5479abefa496397bd38760..34261fa4d31fb1f0ae6e2b502ea51e5735882dc8 100644 --- a/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java +++ b/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java @@ -6,118 +6,136 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.widget.AutoCompleteTextView; -import android.widget.Spinner; - import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.DialogFragment; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.textfield.TextInputLayout; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.DialogJoinConferenceBinding; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.ui.interfaces.OnBackendConnected; import eu.siacs.conversations.ui.util.DelayedHintHelper; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; public class JoinConferenceDialog extends DialogFragment implements OnBackendConnected { - private static final String PREFILLED_JID_KEY = "prefilled_jid"; - private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list"; - private JoinConferenceDialogListener mListener; - private KnownHostsAdapter knownHostsAdapter; - - public static JoinConferenceDialog newInstance(String prefilledJid, List accounts) { - JoinConferenceDialog dialog = new JoinConferenceDialog(); - Bundle bundle = new Bundle(); - bundle.putString(PREFILLED_JID_KEY, prefilledJid); - bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList) accounts); - dialog.setArguments(bundle); - return dialog; - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setRetainInstance(true); - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity()); - builder.setTitle(R.string.join_public_channel); - final DialogJoinConferenceBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.dialog_join_conference, null, false); - DelayedHintHelper.setHint(R.string.channel_full_jid_example, binding.jid); - this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete); - binding.jid.setAdapter(knownHostsAdapter); - String prefilledJid = getArguments().getString(PREFILLED_JID_KEY); - if (prefilledJid != null) { - binding.jid.append(prefilledJid); - } - StartConversationActivity.populateAccountSpinner(getActivity(), getArguments().getStringArrayList(ACCOUNTS_LIST_KEY), binding.account); - builder.setView(binding.getRoot()); - builder.setPositiveButton(R.string.join, null); - builder.setNegativeButton(R.string.cancel, null); - AlertDialog dialog = builder.create(); - dialog.show(); - dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(view -> mListener.onJoinDialogPositiveClick(dialog, binding.account, binding.accountJidLayout, binding.jid)); - binding.jid.setOnEditorActionListener((v, actionId, event) -> { - mListener.onJoinDialogPositiveClick(dialog, binding.account, binding.accountJidLayout, binding.jid); - return true; - }); - return dialog; - } - - @Override - public void onBackendConnected() { - refreshKnownHosts(); - } - - private void refreshKnownHosts() { - Activity activity = getActivity(); - if (activity instanceof XmppActivity) { - Collection hosts = ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts(); - this.knownHostsAdapter.refresh(hosts); - } - } - - @Override - public void onAttach(@NonNull final Context context) { - super.onAttach(context); - try { - mListener = (JoinConferenceDialogListener) context; - } catch (ClassCastException e) { - throw new ClassCastException(context.toString() - + " must implement JoinConferenceDialogListener"); - } - } - - @Override - public void onDestroyView() { - Dialog dialog = getDialog(); - if (dialog != null && getRetainInstance()) { - dialog.setDismissMessage(null); - } - super.onDestroyView(); - } - - @Override - public void onStart() { - super.onStart(); - final Activity activity = getActivity(); - if (activity instanceof XmppActivity && ((XmppActivity) activity).xmppConnectionService != null) { - refreshKnownHosts(); - } - } - - public interface JoinConferenceDialogListener { - void onJoinDialogPositiveClick(Dialog dialog, AutoCompleteTextView spinner, TextInputLayout jidLayout, AutoCompleteTextView jid); - } + private static final String PREFILLED_JID_KEY = "prefilled_jid"; + private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list"; + private JoinConferenceDialogListener mListener; + private KnownHostsAdapter knownHostsAdapter; + + public static JoinConferenceDialog newInstance(String prefilledJid, List accounts) { + JoinConferenceDialog dialog = new JoinConferenceDialog(); + Bundle bundle = new Bundle(); + bundle.putString(PREFILLED_JID_KEY, prefilledJid); + bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList) accounts); + dialog.setArguments(bundle); + return dialog; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setRetainInstance(true); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final MaterialAlertDialogBuilder builder = + new MaterialAlertDialogBuilder(requireActivity()); + builder.setTitle(R.string.join_public_channel); + final DialogJoinConferenceBinding binding = + DataBindingUtil.inflate( + getActivity().getLayoutInflater(), + R.layout.dialog_join_conference, + null, + false); + DelayedHintHelper.setHint(R.string.channel_full_jid_example, binding.jid); + this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete); + binding.jid.setAdapter(knownHostsAdapter); + String prefilledJid = getArguments().getString(PREFILLED_JID_KEY); + if (prefilledJid != null) { + binding.jid.append(prefilledJid); + } + StartConversationActivity.populateAccountSpinner( + getActivity(), + getArguments().getStringArrayList(ACCOUNTS_LIST_KEY), + binding.account); + builder.setView(binding.getRoot()); + builder.setPositiveButton(R.string.join, null); + builder.setNegativeButton(R.string.cancel, null); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.getButton(DialogInterface.BUTTON_POSITIVE) + .setOnClickListener( + view -> + mListener.onJoinDialogPositiveClick( + dialog, + binding.account, + binding.accountJidLayout, + binding.jid)); + binding.jid.setOnEditorActionListener( + (v, actionId, event) -> { + mListener.onJoinDialogPositiveClick( + dialog, binding.account, binding.accountJidLayout, binding.jid); + return true; + }); + return dialog; + } + + @Override + public void onBackendConnected() { + refreshKnownHosts(); + } + + private void refreshKnownHosts() { + Activity activity = getActivity(); + if (activity instanceof XmppActivity) { + Collection hosts = + ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts(); + this.knownHostsAdapter.refresh(hosts); + } + } + + @Override + public void onAttach(@NonNull final Context context) { + super.onAttach(context); + try { + mListener = (JoinConferenceDialogListener) context; + } catch (ClassCastException e) { + throw new ClassCastException(context + " must implement JoinConferenceDialogListener"); + } + } + + @Override + public void onDestroyView() { + Dialog dialog = getDialog(); + if (dialog != null && getRetainInstance()) { + dialog.setDismissMessage(null); + } + super.onDestroyView(); + } + + @Override + public void onStart() { + super.onStart(); + final Activity activity = getActivity(); + if (activity instanceof XmppActivity + && ((XmppActivity) activity).xmppConnectionService != null) { + refreshKnownHosts(); + } + } + + public interface JoinConferenceDialogListener { + void onJoinDialogPositiveClick( + Dialog dialog, + AutoCompleteTextView spinner, + TextInputLayout jidLayout, + AutoCompleteTextView jid); + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java b/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java index 66b3fb886f93bdf5da2cce289f5eb37250fa8f96..eab1a705082feea4fca22488d21fd7abf436448b 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java @@ -5,50 +5,57 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.inputmethod.InputMethodManager; - import androidx.appcompat.app.ActionBar; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; +import java.util.Collections; +import java.util.List; public class ShortcutActivity extends AbstractSearchableListItemActivity { - private static final List BLACKLISTED_ACTIVITIES = Arrays.asList("com.teslacoilsw.launcher.ChooseActionIntentActivity"); + private static final List BLACKLISTED_ACTIVITIES = + List.of("com.teslacoilsw.launcher.ChooseActionIntentActivity"); @Override - protected void refreshUiReal() { - - } + protected void refreshUiReal() {} @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getListView().setOnItemClickListener((parent, view, position, id) -> { - - final ComponentName callingActivity = getCallingActivity(); + getListView() + .setOnItemClickListener( + (parent, view, position, id) -> { + final ComponentName callingActivity = getCallingActivity(); - final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY); + final InputMethodManager imm = + (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + getSearchEditText().getWindowToken(), + InputMethodManager.HIDE_IMPLICIT_ONLY); - ListItem listItem = getListItems().get(position); - final boolean legacy = BLACKLISTED_ACTIVITIES.contains(callingActivity == null ? null : callingActivity.getClassName()); - Intent shortcut = xmppConnectionService.getShortcutService().createShortcut(((Contact) listItem), legacy); - setResult(RESULT_OK,shortcut); - finish(); - }); + ListItem listItem = getListItems().get(position); + final boolean legacy = + BLACKLISTED_ACTIVITIES.contains( + callingActivity == null + ? null + : callingActivity.getClassName()); + Intent shortcut = + xmppConnectionService + .getShortcutService() + .createShortcut(((Contact) listItem), legacy); + setResult(RESULT_OK, shortcut); + finish(); + }); } @Override public void onStart() { super.onStart(); ActionBar bar = getSupportActionBar(); - if(bar != null){ + if (bar != null) { bar.setTitle(R.string.create_shortcut); } } @@ -63,8 +70,7 @@ public class ShortcutActivity extends AbstractSearchableListItemActivity { for (final Account account : xmppConnectionService.getAccounts()) { if (account.isEnabled()) { for (final Contact contact : account.getRoster().getContacts()) { - if (contact.showInContactList() - && contact.match(this, needle)) { + if (contact.showInContactList() && contact.match(this, needle)) { getListItems().add(contact); } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 8a3fc8a543f6fdd4f72a765029b2f89f8b8a9b15..d597599bd1c97a52441136275eb3da664479e19e 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -181,8 +181,7 @@ public abstract class XmppActivity extends ActionBarActivity { private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + if (drawable instanceof AsyncDrawable asyncDrawable) { return asyncDrawable.getBitmapWorkerTask(); } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java index 88f7636bfa612fecfe44661104fd717af37896e6..fd9869f6bfa3b8ac7caedba76183d9844bfcbbc3 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java @@ -30,7 +30,7 @@ public class KnownHostsAdapter extends ArrayAdapter { final String local = split[0].toLowerCase(Locale.ENGLISH); if (Config.QUICKSY_DOMAIN != null && E164_PATTERN.matcher(local).matches()) { - builder.add(local + '@' + Config.QUICKSY_DOMAIN.toString()); + builder.add(local + '@' + Config.QUICKSY_DOMAIN); } else { for (String domain : domains) { builder.add(local + '@' + domain); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java index 411dadf584295480e2eb8e29290df6a0ecdafdf3..4869f0d2d3a09cf63e4ee798655837ddf4031040 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java @@ -77,10 +77,8 @@ public class MediaAdapter extends RecyclerView.Adapter { private abstract static class MessageItemViewHolder /*extends RecyclerView.ViewHolder*/ { - private View itemView; + private final View itemView; private MessageItemViewHolder(@NonNull View itemView) { this.itemView = itemView; diff --git a/src/main/java/eu/siacs/conversations/ui/service/CameraManager.java b/src/main/java/eu/siacs/conversations/ui/service/CameraManager.java index f3af5d3ed0823f374cb4b9bd4aafa0337b4a905e..a0b3e216f7706dad5bc936bca5a5f38aa694764e 100644 --- a/src/main/java/eu/siacs/conversations/ui/service/CameraManager.java +++ b/src/main/java/eu/siacs/conversations/ui/service/CameraManager.java @@ -25,9 +25,8 @@ import android.hardware.Camera.CameraInfo; import android.hardware.Camera.PreviewCallback; import android.util.Log; import android.view.TextureView; - import com.google.zxing.PlanarYUVLuminanceSource; - +import eu.siacs.conversations.Config; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -35,8 +34,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import eu.siacs.conversations.Config; - /** * @author Andreas Schildbach */ @@ -69,7 +66,10 @@ public final class CameraManager { return cameraInfo.orientation; } - public Camera open(final TextureView textureView, final int displayOrientation, final boolean continuousAutoFocus) + public Camera open( + final TextureView textureView, + final int displayOrientation, + final boolean continuousAutoFocus) throws IOException { final int cameraId = determineCameraId(); Camera.getCameraInfo(cameraId, cameraInfo); @@ -80,8 +80,7 @@ public final class CameraManager { camera.setDisplayOrientation((720 - displayOrientation - cameraInfo.orientation) % 360); else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) camera.setDisplayOrientation((720 - displayOrientation + cameraInfo.orientation) % 360); - else - throw new IllegalStateException("facing: " + cameraInfo.facing); + else throw new IllegalStateException("facing: " + cameraInfo.facing); camera.setPreviewTexture(textureView.getSurfaceTexture()); @@ -105,18 +104,22 @@ public final class CameraManager { boolean isTexturePortrait = width < height; boolean isCameraPortrait = cameraResolution.width < cameraResolution.height; if (isTexturePortrait == isCameraPortrait) { - widthFactor = (float)cameraResolution.width / width; - heightFactor = (float)cameraResolution.height / height; + widthFactor = (float) cameraResolution.width / width; + heightFactor = (float) cameraResolution.height / height; orientedFrame = new Rect(frame); } else { - widthFactor = (float)cameraResolution.width / height; - heightFactor = (float)cameraResolution.height / width; + widthFactor = (float) cameraResolution.width / height; + heightFactor = (float) cameraResolution.height / width; // Swap X and Y coordinates to flip frame to the same orientation as cameraResolution orientedFrame = new Rect(frame.top, frame.left, frame.bottom, frame.right); } - framePreview = new RectF(orientedFrame.left * widthFactor, orientedFrame.top * heightFactor, - orientedFrame.right * widthFactor, orientedFrame.bottom * heightFactor); + framePreview = + new RectF( + orientedFrame.left * widthFactor, + orientedFrame.top * heightFactor, + orientedFrame.right * widthFactor, + orientedFrame.bottom * heightFactor); final String savedParameters = parameters == null ? null : parameters.flatten(); @@ -130,7 +133,7 @@ public final class CameraManager { camera.setParameters(parameters2); setDesiredCameraParameters(camera, cameraResolution, continuousAutoFocus); } catch (final RuntimeException x2) { - Log.d(Config.LOGTAG,"problem setting camera parameters", x2); + Log.d(Config.LOGTAG, "problem setting camera parameters", x2); } } } @@ -139,7 +142,7 @@ public final class CameraManager { camera.startPreview(); return camera; } catch (final RuntimeException x) { - Log.w(Config.LOGTAG,"something went wrong while starting camera preview", x); + Log.w(Config.LOGTAG, "something went wrong while starting camera preview", x); camera.release(); throw x; } @@ -152,15 +155,13 @@ public final class CameraManager { // prefer back-facing camera for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo); - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) - return i; + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) return i; } // fall back to front-facing camera for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo); - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) - return i; + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) return i; } return -1; @@ -171,29 +172,28 @@ public final class CameraManager { try { camera.stopPreview(); } catch (final RuntimeException x) { - Log.w(Config.LOGTAG,"something went wrong while stopping camera preview", x); + Log.w(Config.LOGTAG, "something went wrong while stopping camera preview", x); } camera.release(); } } - private static final Comparator numPixelComparator = new Comparator() { - @Override - public int compare(final Camera.Size size1, final Camera.Size size2) { - final int pixels1 = size1.height * size1.width; - final int pixels2 = size2.height * size2.width; - - if (pixels1 < pixels2) - return 1; - else if (pixels1 > pixels2) - return -1; - else - return 0; - } - }; + private static final Comparator numPixelComparator = + new Comparator() { + @Override + public int compare(final Camera.Size size1, final Camera.Size size2) { + final int pixels1 = size1.height * size1.width; + final int pixels2 = size2.height * size2.width; + + if (pixels1 < pixels2) return 1; + else if (pixels1 > pixels2) return -1; + else return 0; + } + }; - private static Camera.Size findBestPreviewSizeValue(final Camera.Parameters parameters, int width, int height) { + private static Camera.Size findBestPreviewSizeValue( + final Camera.Parameters parameters, int width, int height) { if (height > width) { final int temp = width; width = height; @@ -203,11 +203,11 @@ public final class CameraManager { final float screenAspectRatio = (float) width / (float) height; final List rawSupportedSizes = parameters.getSupportedPreviewSizes(); - if (rawSupportedSizes == null) - return parameters.getPreviewSize(); + if (rawSupportedSizes == null) return parameters.getPreviewSize(); // sort by size, descending - final List supportedPreviewSizes = new ArrayList(rawSupportedSizes); + final List supportedPreviewSizes = + new ArrayList(rawSupportedSizes); Collections.sort(supportedPreviewSizes, numPixelComparator); Camera.Size bestSize = null; @@ -217,8 +217,7 @@ public final class CameraManager { final int realWidth = supportedPreviewSize.width; final int realHeight = supportedPreviewSize.height; final int realPixels = realWidth * realHeight; - if (realPixels < MIN_PREVIEW_PIXELS || realPixels > MAX_PREVIEW_PIXELS) - continue; + if (realPixels < MIN_PREVIEW_PIXELS || realPixels > MAX_PREVIEW_PIXELS) continue; final boolean isCandidatePortrait = realWidth < realHeight; final int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth; @@ -234,27 +233,32 @@ public final class CameraManager { } } - if (bestSize != null) - return bestSize; - else - return parameters.getPreviewSize(); + if (bestSize != null) return bestSize; + else return parameters.getPreviewSize(); } @SuppressLint("InlinedApi") - private static void setDesiredCameraParameters(final Camera camera, final Camera.Size cameraResolution, + private static void setDesiredCameraParameters( + final Camera camera, + final Camera.Size cameraResolution, final boolean continuousAutoFocus) { final Camera.Parameters parameters = camera.getParameters(); - if (parameters == null) - return; + if (parameters == null) return; final List supportedFocusModes = parameters.getSupportedFocusModes(); - final String focusMode = continuousAutoFocus - ? findValue(supportedFocusModes, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, - Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, Camera.Parameters.FOCUS_MODE_AUTO, - Camera.Parameters.FOCUS_MODE_MACRO) - : findValue(supportedFocusModes, Camera.Parameters.FOCUS_MODE_AUTO, Camera.Parameters.FOCUS_MODE_MACRO); - if (focusMode != null) - parameters.setFocusMode(focusMode); + final String focusMode = + continuousAutoFocus + ? findValue( + supportedFocusModes, + Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, + Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, + Camera.Parameters.FOCUS_MODE_AUTO, + Camera.Parameters.FOCUS_MODE_MACRO) + : findValue( + supportedFocusModes, + Camera.Parameters.FOCUS_MODE_AUTO, + Camera.Parameters.FOCUS_MODE_MACRO); + if (focusMode != null) parameters.setFocusMode(focusMode); parameters.setPreviewSize(cameraResolution.width, cameraResolution.height); @@ -265,26 +269,31 @@ public final class CameraManager { try { camera.setOneShotPreviewCallback(callback); } catch (final RuntimeException x) { - Log.d(Config.LOGTAG,"problem requesting preview frame, callback won't be called", x); + Log.d(Config.LOGTAG, "problem requesting preview frame, callback won't be called", x); } } public PlanarYUVLuminanceSource buildLuminanceSource(final byte[] data) { - return new PlanarYUVLuminanceSource(data, cameraResolution.width, cameraResolution.height, - (int) framePreview.left, (int) framePreview.top, (int) framePreview.width(), - (int) framePreview.height(), false); + return new PlanarYUVLuminanceSource( + data, + cameraResolution.width, + cameraResolution.height, + (int) framePreview.left, + (int) framePreview.top, + (int) framePreview.width(), + (int) framePreview.height(), + false); } public void setTorch(final boolean enabled) { - if (enabled != getTorchEnabled(camera)) - setTorchEnabled(camera, enabled); + if (enabled != getTorchEnabled(camera)) setTorchEnabled(camera, enabled); } private static boolean getTorchEnabled(final Camera camera) { final Camera.Parameters parameters = camera.getParameters(); if (parameters != null) { final String flashMode = camera.getParameters().getFlashMode(); - return flashMode != null && (Camera.Parameters.FLASH_MODE_ON.equals(flashMode) + return (Camera.Parameters.FLASH_MODE_ON.equals(flashMode) || Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)); } @@ -298,10 +307,12 @@ public final class CameraManager { if (supportedFlashModes != null) { final String flashMode; if (enabled) - flashMode = findValue(supportedFlashModes, Camera.Parameters.FLASH_MODE_TORCH, - Camera.Parameters.FLASH_MODE_ON); - else - flashMode = findValue(supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF); + flashMode = + findValue( + supportedFlashModes, + Camera.Parameters.FLASH_MODE_TORCH, + Camera.Parameters.FLASH_MODE_ON); + else flashMode = findValue(supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF); if (flashMode != null) { camera.cancelAutoFocus(); // autofocus can cause conflict @@ -314,8 +325,7 @@ public final class CameraManager { private static String findValue(final Collection values, final String... valuesToFind) { for (final String valueToFind : valuesToFind) - if (values.contains(valueToFind)) - return valueToFind; + if (values.contains(valueToFind)) return valueToFind; return null; } diff --git a/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java b/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java index f5331c7a618341304ceafc263bee2706c2cf9067..9b5e749ca669b8fa01aa98e67f8b31c96c4ff279 100644 --- a/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java +++ b/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java @@ -7,22 +7,18 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.widget.ImageView; - import androidx.annotation.DimenRes; - -import java.lang.ref.WeakReference; -import java.util.concurrent.RejectedExecutionException; - import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.ui.XmppActivity; +import java.lang.ref.WeakReference; +import java.util.concurrent.RejectedExecutionException; public class AvatarWorkerTask extends AsyncTask { private final WeakReference imageViewReference; private AvatarService.Avatarable avatarable = null; - private @DimenRes - final int size; + private @DimenRes final int size; public AvatarWorkerTask(ImageView imageView, @DimenRes int size) { imageViewReference = new WeakReference<>(imageView); @@ -36,7 +32,8 @@ public class AvatarWorkerTask extends AsyncTask= 0) { - message.setSpan(new TypefaceSpan("monospace"), start, start + jid.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + message.setSpan( + new TypefaceSpan("monospace"), + start, + start + jid.length(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } builder.setMessage(message); builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.ban_now, (dialog, which) -> { - activity.xmppConnectionService.changeAffiliationInConference(conversation, user.getRealJid(), MucOptions.Affiliation.OUTCAST, onAffiliationChanged); - if (user.getRole() != MucOptions.Role.NONE) { - activity.xmppConnectionService.changeRoleInConference(conversation, user.getName(), MucOptions.Role.NONE); - } - }); + builder.setPositiveButton( + R.string.ban_now, + (dialog, which) -> { + activity.xmppConnectionService.changeAffiliationInConference( + conversation, + user.getRealJid(), + MucOptions.Affiliation.OUTCAST, + onAffiliationChanged); + if (user.getRole() != MucOptions.Role.NONE) { + activity.xmppConnectionService.changeRoleInConference( + conversation, user.getName(), MucOptions.Role.NONE); + } + }); builder.create().show(); } } private static void startConversation(User user, XmppActivity activity) { if (user.getRealJid() != null) { - Conversation newConversation = activity.xmppConnectionService.findOrCreateConversation(user.getAccount(), user.getRealJid().asBareJid(), false, true); + Conversation newConversation = + activity.xmppConnectionService.findOrCreateConversation( + user.getAccount(), user.getRealJid().asBareJid(), false, true); activity.switchToConversation(newConversation); } } -} \ No newline at end of file +} diff --git a/src/main/java/eu/siacs/conversations/ui/widget/ScannerView.java b/src/main/java/eu/siacs/conversations/ui/widget/ScannerView.java index b755ae516e7ba7b9ff24155583ce3f9b0868a344..826a637d256be8834c466089278d4bc473aea775 100644 --- a/src/main/java/eu/siacs/conversations/ui/widget/ScannerView.java +++ b/src/main/java/eu/siacs/conversations/ui/widget/ScannerView.java @@ -28,22 +28,18 @@ import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; - import androidx.core.content.ContextCompat; - import com.google.zxing.ResultPoint; - +import eu.siacs.conversations.R; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import eu.siacs.conversations.R; - /** * @author Andreas Schildbach */ public class ScannerView extends View { - private static final long LASER_ANIMATION_DELAY_MS = 100l; + private static final long LASER_ANIMATION_DELAY_MS = 100L; private static final int DOT_OPACITY = 0xa0; private static final int DOT_TTL_MS = 500; @@ -81,8 +77,12 @@ public class ScannerView extends View { dotPaint.setAntiAlias(true); } - public void setFraming(final Rect frame, final RectF framePreview, final int displayRotation, - final int cameraRotation, final boolean cameraFlip) { + public void setFraming( + final Rect frame, + final RectF framePreview, + final int displayRotation, + final int cameraRotation, + final boolean cameraFlip) { this.frame = frame; matrix.setRectToRect(framePreview, new RectF(frame), ScaleToFit.FILL); matrix.postRotate(-displayRotation, frame.exactCenterX(), frame.exactCenterY()); @@ -99,15 +99,14 @@ public class ScannerView extends View { } public void addDot(final ResultPoint dot) { - dots.put(new float[] { dot.getX(), dot.getY() }, System.currentTimeMillis()); + dots.put(new float[] {dot.getX(), dot.getY()}, System.currentTimeMillis()); invalidate(); } @Override public void onDraw(final Canvas canvas) { - if (frame == null) - return; + if (frame == null) return; final long now = System.currentTimeMillis(); @@ -142,7 +141,8 @@ public class ScannerView extends View { canvas.drawRect(frame, laserPaint); // draw points - for (final Iterator> i = dots.entrySet().iterator(); i.hasNext();) { + for (final Iterator> i = dots.entrySet().iterator(); + i.hasNext(); ) { final Map.Entry entry = i.next(); final long age = now - entry.getValue(); if (age < DOT_TTL_MS) { diff --git a/src/main/java/eu/siacs/conversations/utils/CursorUtils.java b/src/main/java/eu/siacs/conversations/utils/CursorUtils.java index 91befa22936a1912801662c9cd74e692c2ee9b7c..23e8401cd101988f38ee6b529db704a616537bcc 100644 --- a/src/main/java/eu/siacs/conversations/utils/CursorUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/CursorUtils.java @@ -9,8 +9,7 @@ public class CursorUtils { public static void upgradeCursorWindowSize(final Cursor cursor) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { - if (cursor instanceof AbstractWindowedCursor) { - final AbstractWindowedCursor windowedCursor = (AbstractWindowedCursor) cursor; + if (cursor instanceof AbstractWindowedCursor windowedCursor) { windowedCursor.setWindow(new CursorWindow("4M", 4 * 1024 * 1024)); } if (cursor instanceof SQLiteCursor) { @@ -18,5 +17,4 @@ public class CursorUtils { } } } - } diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java index 0616b11f5979693ad95b37f7fe3283ed26027e9b..0c4032eb26e0e9d581ae75e6ccdf4bbc6069f478 100644 --- a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java @@ -12,8 +12,8 @@ import eu.siacs.conversations.entities.Conversational; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ShareLocationActivity; import eu.siacs.conversations.ui.ShowLocationActivity; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.regex.Matcher; import org.osmdroid.util.GeoPoint; @@ -160,11 +160,8 @@ public class GeoHelper { private static String getLabel(Context context, Message message) { if (message.getStatus() == Message.STATUS_RECEIVED) { - try { - return URLEncoder.encode(UIHelper.getMessageDisplayName(message), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } + return URLEncoder.encode( + UIHelper.getMessageDisplayName(message), StandardCharsets.UTF_8); } else { return context.getString(R.string.me); } diff --git a/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java b/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java index d21bfadf133857fd0f15d359e812c503c441e671..dae03877589cebef224e53b00d95f24a7fc7831e 100644 --- a/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java +++ b/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java @@ -35,11 +35,11 @@ import java.util.List; public class ImStyleParser { - private final static List KEYWORDS = Arrays.asList('*', '_', '~', '`'); - private final static List NO_SUB_PARSING_KEYWORDS = Arrays.asList('`'); - private final static List BLOCK_KEYWORDS = Arrays.asList('`'); - private final static boolean ALLOW_EMPTY = false; - private final static boolean PARSE_HIGHER_ORDER_END = true; + private static final List KEYWORDS = Arrays.asList('*', '_', '~', '`'); + private static final List NO_SUB_PARSING_KEYWORDS = List.of('`'); + private static final List BLOCK_KEYWORDS = List.of('`'); + private static final boolean ALLOW_EMPTY = false; + private static final boolean PARSE_HIGHER_ORDER_END = true; public static List