diff --git a/fastlane/metadata/android/it-IT/changelogs/4214204.txt b/fastlane/metadata/android/it-IT/changelogs/4214204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..906a67ca8dc814e81241e3998fa8fa9474956a3d
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/4214204.txt
@@ -0,0 +1,2 @@
+* Supporto a 'Stato di interruzione del servizio'
+* Correzioni di sicurezza minori nella lettura di corpi multipli, id-occupanti e id-stanze
diff --git a/fastlane/metadata/android/pl-PL/changelogs/4214204.txt b/fastlane/metadata/android/pl-PL/changelogs/4214204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d10e24b966d13858cb9efe93c0ce8b30b4c5c2d4
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/4214204.txt
@@ -0,0 +1,2 @@
+* Obsługa statusu niedostępności usługi
+* Drobne poprawki bezpieczeństwa parsowania wielu elementów treści, identyfikatorów uczestników i stanz
diff --git a/src/conversations/res/values-ga/strings.xml b/src/conversations/res/values-ga/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee21d93fd943365566a149cdeee1e54576395699
--- /dev/null
+++ b/src/conversations/res/values-ga/strings.xml
@@ -0,0 +1,6 @@
+
+
+ Roghnaigh do freastalaí XMPP
+ Bain úsáid as conversations.im
+ Oscail cuntas nua
+
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 078661617a806379c8df46fd36bc5f8483f741f5..fcc140ee9b6c28e80b532be999f6f1cf9752b383 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 790e33bd65d764c21faa24d730720d53fcfdaf53..cb57be4719d0072efac7eadd9737170ec776ac29 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);
}
@@ -151,9 +151,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];
@@ -162,8 +169,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);
}
@@ -222,7 +233,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) {
@@ -235,17 +247,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];
@@ -256,18 +273,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);
}
}
@@ -287,7 +314,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 2643b8d8dcb5a32ce93b443fbdbbfe2d6ab7ce33..7c432f545f8e240b8faf87eb80b9f2dd11d984a8 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -33,6 +33,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 {
@@ -1094,9 +1095,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/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
index d648536699267bdfa7b68d10b719b1c777ef1cdb..2e95cfe69e88ac95d232dbe2c2308b1cd0833c7e 100644
--- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
@@ -18,6 +18,22 @@ import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.crypto.axolotl.AxolotlService;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.services.MessageArchiveService;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
+import eu.siacs.conversations.xmpp.Jid;
+import eu.siacs.conversations.xmpp.forms.Data;
+import eu.siacs.conversations.xmpp.pep.Avatar;
+import im.conversations.android.xmpp.model.stanza.Iq;
+import im.conversations.android.xmpp.model.upload.Request;
import java.nio.ByteBuffer;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
@@ -494,13 +510,13 @@ public class IqGenerator extends AbstractGenerator {
return packet;
}
- public Iq requestHttpUploadLegacySlot(Jid host, DownloadableFile file, String mime) {
+ public Iq requestHttpUploadSlot(
+ final Jid host, final DownloadableFile file, final String mime) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(host);
- Element request = packet.addChild("request", Namespace.HTTP_UPLOAD_LEGACY);
- request.addChild("filename").setContent(convertFilename(file.getName()));
- request.addChild("size").setContent(String.valueOf(file.getExpectedSize()));
- request.addChild("content-type").setContent(mime);
+ final var request = packet.addExtension(new Request());
+ request.setFilename(convertFilename(file.getName()));
+ request.setSize(file.getExpectedSize());
return packet;
}
diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java
index 33899242c1ff659db71d57972d278c222fefe859..86da4012f4d2c51d260d78c1ee95d597bd942b1c 100644
--- a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java
+++ b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java
@@ -127,10 +127,7 @@ public class HttpConnectionManager extends AbstractConnectionManager {
}
}
HttpUploadConnection connection =
- new HttpUploadConnection(
- message,
- Method.determine(message.getConversation().getAccount()),
- this, cb);
+ new HttpUploadConnection(message, this, cb);
connection.init(delay);
this.uploadConnections.add(connection);
}
diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
index f6df2639662c72203ca3de6457867dd1fadfc257..2ef2a3368c2f5dce4cbc0320e49db90688612295 100644
--- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
+++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
@@ -3,20 +3,12 @@ package eu.siacs.conversations.http;
import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Future;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile;
@@ -25,6 +17,10 @@ import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.services.AbstractConnectionManager;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Future;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
@@ -32,17 +28,14 @@ import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
-public class HttpUploadConnection implements Transferable, AbstractConnectionManager.ProgressListener {
+public class HttpUploadConnection
+ implements Transferable, AbstractConnectionManager.ProgressListener {
- static final List WHITE_LISTED_HEADERS = Arrays.asList(
- "Authorization",
- "Cookie",
- "Expires"
- );
+ static final List WHITE_LISTED_HEADERS =
+ Arrays.asList("Authorization", "Cookie", "Expires");
private final HttpConnectionManager mHttpConnectionManager;
private final XmppConnectionService mXmppConnectionService;
- private final Method method;
private boolean delayed = false;
private DownloadableFile file;
private final Message message;
@@ -54,9 +47,8 @@ public class HttpUploadConnection implements Transferable, AbstractConnectionMan
private ListenableFuture slotFuture;
private Runnable cb;
- public HttpUploadConnection(Message message, Method method, HttpConnectionManager httpConnectionManager, Runnable cb) {
+ public HttpUploadConnection(final Message message, final HttpConnectionManager httpConnectionManager, final Runnable cb) {
this.message = message;
- this.method = method;
this.mHttpConnectionManager = httpConnectionManager;
this.mXmppConnectionService = httpConnectionManager.getXmppConnectionService();
this.cb = cb;
@@ -90,13 +82,13 @@ public class HttpUploadConnection implements Transferable, AbstractConnectionMan
final ListenableFuture slotFuture = this.slotFuture;
if (slotFuture != null && !slotFuture.isDone()) {
if (slotFuture.cancel(true)) {
- Log.d(Config.LOGTAG,"cancelled slot requester");
+ Log.d(Config.LOGTAG, "cancelled slot requester");
}
}
final Call call = this.mostRecentCall;
if (call != null && !call.isCanceled()) {
call.cancel();
- Log.d(Config.LOGTAG,"cancelled HTTP request");
+ Log.d(Config.LOGTAG, "cancelled HTTP request");
}
}
@@ -104,8 +96,13 @@ public class HttpUploadConnection implements Transferable, AbstractConnectionMan
finish();
final Call call = this.mostRecentCall;
final Future slotFuture = this.slotFuture;
- final boolean cancelled = (call != null && call.isCanceled()) || (slotFuture != null && slotFuture.isCancelled());
- mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED, cancelled ? Message.ERROR_MESSAGE_CANCELLED : errorMessage);
+ final boolean cancelled =
+ (call != null && call.isCanceled())
+ || (slotFuture != null && slotFuture.isCancelled());
+ mXmppConnectionService.markMessage(
+ message,
+ Message.STATUS_SEND_FAILED,
+ cancelled ? Message.ERROR_MESSAGE_CANCELLED : errorMessage);
if (cb != null) cb.run();
}
@@ -118,7 +115,8 @@ public class HttpUploadConnection implements Transferable, AbstractConnectionMan
final Account account = message.getConversation().getAccount();
this.file = mXmppConnectionService.getFileBackend().getFile(message, false);
final String mime;
- if (message.getEncryption() == Message.ENCRYPTION_PGP || message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ if (message.getEncryption() == Message.ENCRYPTION_PGP
+ || message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
mime = "application/pgp-encrypted";
} else {
mime = this.file.getMimeType();
@@ -132,75 +130,86 @@ public class HttpUploadConnection implements Transferable, AbstractConnectionMan
this.file.setKeyAndIv(this.key);
}
this.file.setExpectedSize(originalFileSize + (file.getKey() != null ? 16 : 0));
- this.slotFuture = new SlotRequester(mXmppConnectionService).request(method, account, file, message.getFileParams().getName(), mime);
- Futures.addCallback(this.slotFuture, new FutureCallback() {
- @Override
- public void onSuccess(@Nullable SlotRequester.Slot result) {
- HttpUploadConnection.this.slot = result;
- try {
- HttpUploadConnection.this.upload();
- } catch (final Exception e) {
- fail(e.getMessage());
- }
- }
+ message.resetFileParams();
+ this.slotFuture = new SlotRequester(mXmppConnectionService).request(account, file, mime);
+ Futures.addCallback(
+ this.slotFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(@Nullable SlotRequester.Slot result) {
+ HttpUploadConnection.this.slot = result;
+ try {
+ HttpUploadConnection.this.upload();
+ } catch (final Exception e) {
+ fail(e.getMessage());
+ }
+ }
- @Override
- public void onFailure(@NonNull final Throwable throwable) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to request slot", throwable);
- // TODO consider fall back to jingle in 1-on-1 chats with exactly one online presence
- fail(throwable.getMessage());
- }
- }, MoreExecutors.directExecutor());
+ @Override
+ public void onFailure(@NonNull final Throwable throwable) {
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid() + ": unable to request slot",
+ throwable);
+ // TODO consider fall back to jingle in 1-on-1 chats with exactly one online
+ // presence
+ fail(throwable.getMessage());
+ }
+ },
+ MoreExecutors.directExecutor());
message.setTransferable(this);
mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
}
private void upload() {
- final OkHttpClient client = mHttpConnectionManager.buildHttpClient(
- slot.put,
- message.getConversation().getAccount(),
- 0,
- true
- );
+ final OkHttpClient client =
+ mHttpConnectionManager.buildHttpClient(
+ slot.put, message.getConversation().getAccount(), 0, true);
final RequestBody requestBody = AbstractConnectionManager.requestBody(file, this);
- final Request request = new Request.Builder()
- .url(slot.put)
- .put(requestBody)
- .headers(slot.headers)
- .build();
+ final Request request =
+ new Request.Builder().url(slot.put).put(requestBody).headers(slot.headers).build();
Log.d(Config.LOGTAG, "uploading file to " + slot.put);
this.mostRecentCall = client.newCall(request);
- this.mostRecentCall.enqueue(new Callback() {
- @Override
- public void onFailure(@NonNull Call call, IOException e) {
- Log.d(Config.LOGTAG, "http upload failed", e);
- fail(e.getMessage());
- }
-
- @Override
- public void onResponse(@NonNull Call call, @NonNull Response response) {
- final int code = response.code();
- if (code == 200 || code == 201) {
- Log.d(Config.LOGTAG, "finished uploading file");
- final String get;
- if (key != null) {
- get = AesGcmURL.toAesGcmUrl(slot.get.newBuilder().fragment(CryptoHelper.bytesToHex(key)).build());
- } else {
- get = slot.get.toString();
+ this.mostRecentCall.enqueue(
+ new Callback() {
+ @Override
+ public void onFailure(@NonNull Call call, IOException e) {
+ Log.d(Config.LOGTAG, "http upload failed", e);
+ fail(e.getMessage());
}
- mXmppConnectionService.getFileBackend().updateFileParams(message, get);
- mXmppConnectionService.getFileBackend().updateMediaScanner(file);
- finish();
- if (!message.isPrivateMessage()) {
- message.setCounterpart(message.getConversation().getJid().asBareJid());
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+ final int code = response.code();
+ if (code == 200 || code == 201) {
+ Log.d(Config.LOGTAG, "finished uploading file");
+ final String get;
+ if (key != null) {
+ get =
+ AesGcmURL.toAesGcmUrl(
+ slot.get
+ .newBuilder()
+ .fragment(CryptoHelper.bytesToHex(key))
+ .build());
+ } else {
+ get = slot.get.toString();
+ }
+ mXmppConnectionService.getFileBackend().updateFileParams(message, get);
+ mXmppConnectionService.getFileBackend().updateMediaScanner(file);
+ finish();
+ if (!message.isPrivateMessage()) {
+ message.setCounterpart(
+ message.getConversation().getJid().asBareJid());
+ }
+ mXmppConnectionService.resendMessage(message, delayed, cb);
+ } else {
+ Log.d(
+ Config.LOGTAG,
+ "http upload failed because response code was " + code);
+ fail("http upload failed because response code was " + code);
+ }
}
- mXmppConnectionService.resendMessage(message, delayed, cb);
- } else {
- Log.d(Config.LOGTAG, "http upload failed because response code was " + code);
- fail("http upload failed because response code was " + code);
- }
- }
- });
+ });
}
public Message getMessage() {
diff --git a/src/main/java/eu/siacs/conversations/http/Method.java b/src/main/java/eu/siacs/conversations/http/Method.java
deleted file mode 100644
index 47dae2b30cea010df7ba1f6a5c4f004c21fcf96d..0000000000000000000000000000000000000000
--- a/src/main/java/eu/siacs/conversations/http/Method.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2018, Daniel Gultsch All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package eu.siacs.conversations.http;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.XmppConnection;
-
-public enum Method {
- HTTP_UPLOAD, HTTP_UPLOAD_LEGACY;
-
- public static Method determine(Account account) {
- XmppConnection.Features features = account.getXmppConnection() == null ? null : account.getXmppConnection().getFeatures();
- if (features == null) {
- return HTTP_UPLOAD;
- }
- if (features.useLegacyHttpUpload()) {
- return HTTP_UPLOAD_LEGACY;
- } else if (features.httpUpload(0)) {
- return HTTP_UPLOAD;
- } else {
- return HTTP_UPLOAD;
- }
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/http/SlotRequester.java b/src/main/java/eu/siacs/conversations/http/SlotRequester.java
index b3af132b7e44b148257d8c5d68217bbb24ea2820..5bb5d7772b253857e7cc8eab81c60c4aedb9d1c2 100644
--- a/src/main/java/eu/siacs/conversations/http/SlotRequester.java
+++ b/src/main/java/eu/siacs/conversations/http/SlotRequester.java
@@ -29,21 +29,22 @@
package eu.siacs.conversations.http;
+import android.util.Log;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-
-import java.util.Map;
-
+import com.google.common.util.concurrent.MoreExecutors;
+import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile;
-import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.IqResponseException;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Iq;
+import im.conversations.android.xmpp.model.upload.Header;
+import im.conversations.android.xmpp.model.upload.Slot;
+import java.util.Map;
import okhttp3.Headers;
import okhttp3.HttpUrl;
@@ -55,83 +56,54 @@ public class SlotRequester {
this.service = service;
}
- public ListenableFuture request(Method method, Account account, DownloadableFile file, String name, String mime) {
- if (method == Method.HTTP_UPLOAD_LEGACY) {
- final Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD_LEGACY);
- return requestHttpUploadLegacy(account, host, file, mime);
- } else {
- final Jid host = account.getXmppConnection().findDiscoItemByFeature(Namespace.HTTP_UPLOAD);
- return requestHttpUpload(account, host, file, name, mime);
+ public ListenableFuture request(
+ final Account account, final DownloadableFile file, final String mime) {
+ final var result =
+ account.getXmppConnection()
+ .getServiceDiscoveryResultByFeature(Namespace.HTTP_UPLOAD);
+ if (result == null) {
+ return Futures.immediateFailedFuture(
+ new IllegalStateException("No HTTP upload host found"));
}
+ return requestHttpUpload(account, result.getKey(), file, mime);
}
- private ListenableFuture requestHttpUploadLegacy(Account account, Jid host, DownloadableFile file, String mime) {
- final SettableFuture future = SettableFuture.create();
- final Iq request = service.getIqGenerator().requestHttpUploadLegacySlot(host, file, mime);
- service.sendIqPacket(account, request, (packet) -> {
- if (packet.getType() == Iq.Type.RESULT) {
- final Element slotElement = packet.findChild("slot", Namespace.HTTP_UPLOAD_LEGACY);
- if (slotElement != null) {
- try {
- final String putUrl = slotElement.findChildContent("put");
- final String getUrl = slotElement.findChildContent("get");
- if (getUrl != null && putUrl != null) {
- final Slot slot = new Slot(
- HttpUrl.get(putUrl),
- HttpUrl.get(getUrl),
- Headers.of("Content-Type", mime == null ? "application/octet-stream" : mime)
- );
- future.set(slot);
- return;
- }
- } catch (final IllegalArgumentException e) {
- future.setException(e);
- return;
+ private ListenableFuture requestHttpUpload(
+ final Account account, final Jid host, final DownloadableFile file, final String mime) {
+ final Iq request = service.getIqGenerator().requestHttpUploadSlot(host, file, mime);
+ final var iqFuture = service.sendIqPacket(account, request);
+ return Futures.transform(
+ iqFuture,
+ response -> {
+ final var slot =
+ response.getExtension(
+ im.conversations.android.xmpp.model.upload.Slot.class);
+ if (slot == null) {
+ Log.d(Config.LOGTAG, "-->" + response);
+ throw new IllegalStateException("Slot not found in IQ response");
}
- }
- }
- future.setException(new IqResponseException(IqParser.extractErrorMessage(packet)));
- });
- return future;
- }
-
- private ListenableFuture requestHttpUpload(Account account, Jid host, DownloadableFile file, String fname, String mime) {
- final SettableFuture future = SettableFuture.create();
- final Iq request = service.getIqGenerator().requestHttpUploadSlot(host, file, fname, mime);
- service.sendIqPacket(account, request, (packet) -> {
- if (packet.getType() == Iq.Type.RESULT) {
- final Element slotElement = packet.findChild("slot", Namespace.HTTP_UPLOAD);
- if (slotElement != null) {
- try {
- final Element put = slotElement.findChild("put");
- final Element get = slotElement.findChild("get");
- final String putUrl = put == null ? null : put.getAttribute("url");
- final String getUrl = get == null ? null : get.getAttribute("url");
- if (getUrl != null && putUrl != null) {
- final ImmutableMap.Builder headers = new ImmutableMap.Builder<>();
- for (final Element child : put.getChildren()) {
- if ("header".equals(child.getName())) {
- final String name = child.getAttribute("name");
- final String value = child.getContent();
- if (HttpUploadConnection.WHITE_LISTED_HEADERS.contains(name) && value != null && !value.trim().contains("\n")) {
- headers.put(name, value.trim());
- }
- }
- }
- headers.put("Content-Type", mime == null ? "application/octet-stream" : mime);
- final Slot slot = new Slot(HttpUrl.get(putUrl), HttpUrl.get(getUrl), headers.build());
- future.set(slot);
- return;
+ final var getUrl = slot.getGetUrl();
+ final var put = slot.getPut();
+ if (getUrl == null || put == null) {
+ throw new IllegalStateException("Missing get or put in slot response");
+ }
+ final var putUrl = put.getUrl();
+ if (putUrl == null) {
+ throw new IllegalStateException("Missing put url");
+ }
+ final var headers = new ImmutableMap.Builder();
+ for (final Header header : put.getHeaders()) {
+ final String name = header.getHeaderName();
+ final String value = header.getContent();
+ if (Strings.isNullOrEmpty(value) || value.contains("\n")) {
+ continue;
}
- } catch (final IllegalArgumentException e) {
- future.setException(e);
- return;
+ headers.put(name, value.trim());
}
- }
- }
- future.setException(new IqResponseException(IqParser.extractErrorMessage(packet)));
- });
- return future;
+ headers.put("Content-Type", mime == null ? "application/octet-stream" : mime);
+ return new Slot(putUrl, getUrl, headers.buildKeepingLast());
+ },
+ MoreExecutors.directExecutor());
}
public static class Slot {
diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java
index c562da2ebc601ffa1a9c2dac393bb58c1846263a..eaf9ad6c583e7daeb0a3d1a33cceb864d76ccb62 100644
--- a/src/main/java/eu/siacs/conversations/parser/IqParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java
@@ -204,7 +204,7 @@ public class IqParser extends AbstractParser implements Consumer {
+ "Encountered invalid node in PEP ("
+ e.getMessage()
+ "):"
- + device.toString()
+ + device
+ ", skipping...");
}
}
@@ -328,7 +328,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 3b6ba66545da06bdfb17edac16b9c8af7a402894..8be9c02c10e556e9dddc7797950d8db4b1093857 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -361,7 +361,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 53d1e25730f643c765a60db2ff04190ca1e3cf59..d4736e5888d3a273a54f8dc11f2979e1ca883ef4 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -390,7 +390,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) {
@@ -1978,7 +1978,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 fddaf86e3cb88c4d365fcc65237665150829981e..2a681837fc09f318686c2ac5cb9243265073262a 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -1722,7 +1722,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)) {
@@ -1767,7 +1767,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 01534fb08ce3d9b78401d0673af555def1182629..19e6175b6673b4f4990359484a7d8b5a737e7572 100644
--- a/src/main/java/eu/siacs/conversations/services/CallIntegration.java
+++ b/src/main/java/eu/siacs/conversations/services/CallIntegration.java
@@ -545,10 +545,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 b03670feb592121acb9b7312e6040be78fa3a444..dcf388cea3d72656801440995d0508bd34a96c33 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,10 +102,13 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
}
}
- MamReference mamReference = MamReference.max(
- mXmppConnectionService.databaseBackend.getLastMessageReceived(account),
- mXmppConnectionService.databaseBackend.getLastClearDate(account)
- );
+ 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) {
@@ -118,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);
}
}
@@ -133,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);
@@ -167,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;
}
}
@@ -177,10 +176,12 @@ 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 = start;
@@ -189,9 +190,17 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
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);
}
@@ -230,40 +239,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);
@@ -319,7 +345,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;
}
}
@@ -328,7 +355,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) {
@@ -360,12 +388,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;
@@ -383,9 +414,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());
}
if (query.isCatchup() && query.getPagingOrder() == PagingOrder.NORMAL && !complete && query.getConversation() != null) {
// Going forward we stopped without completing due to limits
@@ -415,11 +458,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");
}
}
}
@@ -436,7 +483,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) {
@@ -448,11 +497,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();
}
}
@@ -473,7 +531,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);
}
}
@@ -500,14 +559,17 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
private boolean catchup = true;
public final Version version;
-
Query(Conversation conversation, MamReference start, long end, boolean catchup, PagingOrder order) {
this(conversation, start, end, catchup);
this.pagingOrder = order;
}
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;
@@ -530,7 +592,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 db94d0d42377377a99303a5b0b939d0577d58e48..add704c44e8e9b737d5713918894751c3f83630f 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -117,6 +117,7 @@ import io.ipfs.cid.Cid;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
@@ -234,6 +235,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@@ -583,7 +585,7 @@ public class XmppConnectionService extends Service {
private LruCache mDrawableCache;
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 EmojiSearch emojiSearch = null;
@@ -5136,7 +5138,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();
}
}
@@ -5761,7 +5763,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) {
@@ -6671,6 +6673,14 @@ public class XmppConnectionService extends Service {
connection.sendCreateAccountWithCaptchaPacket(id, data);
}
+ public ListenableFuture sendIqPacket(final Account account, final Iq request) {
+ final XmppConnection connection = account.getXmppConnection();
+ if (connection == null) {
+ return Futures.immediateFailedFuture(new TimeoutException());
+ }
+ return connection.sendIqPacket(request);
+ }
+
public void sendIqPacket(final Account account, final Iq packet, final Consumer callback) {
sendIqPacket(account, packet, 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 994dd65c7863ff91c086a79d0effa161fe63963a..851068d14fdab6aca46975cb830e582ed254a55f 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -604,8 +604,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 b78199c15e09fb1f3608ce573dc42656d43f0b5f..3057749a317b74aa072ec443c203eab1d9e64d7a 100644
--- a/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/JoinConferenceDialog.java
@@ -6,120 +6,140 @@ 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 PREFILLED_PASSWORD_KEY = "prefilled_password";
- private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
- private JoinConferenceDialogListener mListener;
- private KnownHostsAdapter knownHostsAdapter;
-
- public static JoinConferenceDialog newInstance(String prefilledJid, String password, List accounts) {
- JoinConferenceDialog dialog = new JoinConferenceDialog();
- Bundle bundle = new Bundle();
- bundle.putString(PREFILLED_JID_KEY, prefilledJid);
- bundle.putString(PREFILLED_PASSWORD_KEY, password);
- 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.getText().toString().equals(getArguments().getString(PREFILLED_JID_KEY)) ? getArguments().getString(PREFILLED_PASSWORD_KEY) : null));
- binding.jid.setOnEditorActionListener((v, actionId, event) -> {
- mListener.onJoinDialogPositiveClick(dialog, binding.account, binding.accountJidLayout, binding.jid, binding.jid.getText().toString().equals(getArguments().getString(PREFILLED_JID_KEY)) ? getArguments().getString(PREFILLED_PASSWORD_KEY) : null);
- 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, String password);
- }
+ private static final String PREFILLED_JID_KEY = "prefilled_jid";
+ private static final String PREFILLED_PASSWORD_KEY = "prefilled_password";
+ private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
+ private JoinConferenceDialogListener mListener;
+ private KnownHostsAdapter knownHostsAdapter;
+
+ public static JoinConferenceDialog newInstance(String prefilledJid, String password, List accounts) {
+ JoinConferenceDialog dialog = new JoinConferenceDialog();
+ Bundle bundle = new Bundle();
+ bundle.putString(PREFILLED_JID_KEY, prefilledJid);
+ bundle.putString(PREFILLED_PASSWORD_KEY, password);
+ 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.getText().toString().equals(getArguments().getString(PREFILLED_JID_KEY)) ? getArguments().getString(PREFILLED_PASSWORD_KEY) : null));
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .setOnClickListener(
+ view ->
+ mListener.onJoinDialogPositiveClick(
+ dialog,
+ binding.account,
+ binding.accountJidLayout,
+ binding.jid,
+ binding.jid.getText().toString().equals(getArguments().getString(PREFILLED_JID_KEY)) ? getArguments().getString(PREFILLED_PASSWORD_KEY) : null
+ ));
+ binding.jid.setOnEditorActionListener(
+ (v, actionId, event) -> {
+ mListener.onJoinDialogPositiveClick(
+ dialog, binding.account, binding.accountJidLayout, binding.jid,
+ binding.jid.getText().toString().equals(getArguments().getString(PREFILLED_JID_KEY)) ? getArguments().getString(PREFILLED_PASSWORD_KEY) : null
+ );
+ 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, String password);
+ }
}
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 1d09685e1fcfc69e9df27d147a19c0928899c13d..f8278558ca67d8c9d2bf2aed08f3c3fc960a2c75 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -216,8 +216,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 91048df4e3e03efa1bce05a77f2ecddbf7103746..066588844670d9f7817ce1d13276b6ce04924c88 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java
@@ -79,10 +79,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 51617da155dffe77cf7421a75687f3a691b030be..4ea40751e9fc3e5500354f911a35c9e4cf563968 100644
--- a/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java
+++ b/src/main/java/eu/siacs/conversations/ui/util/AvatarWorkerTask.java
@@ -9,23 +9,19 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
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 final WeakReference activityReference;
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);
@@ -47,7 +43,8 @@ public class AvatarWorkerTask extends AsyncTask(items.toArray(new CharSequence[items.size()]), actions.toArray(new Integer[actions.size()]));
}
- public static void configureMucDetailsContextMenu(XmppActivity activity, Menu menu, Conversation conversation, User user) {
+ public static void configureMucDetailsContextMenu(
+ XmppActivity activity, Menu menu, Conversation conversation, User user) {
final MucOptions mucOptions = conversation.getMucOptions();
- final boolean advancedMode = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean("advanced_muc_mode", false);
+ final boolean advancedMode =
+ PreferenceManager.getDefaultSharedPreferences(activity)
+ .getBoolean("advanced_muc_mode", false);
final boolean showMucPm = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean("show_muc_pm", false);
final boolean isGroupChat = mucOptions.isPrivateAndNonAnonymous();
MenuItem sendPrivateMessage = menu.findItem(R.id.send_private_message);
@@ -136,15 +138,19 @@ public final class MucDetailsContextMenuHelper {
MenuItem startConversation = menu.findItem(R.id.start_conversation);
MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room);
MenuItem managePermissions = menu.findItem(R.id.manage_permissions);
- removeFromRoom.setTitle(isGroupChat ? R.string.remove_from_room : R.string.remove_from_channel);
+ removeFromRoom.setTitle(
+ isGroupChat ? R.string.remove_from_room : R.string.remove_from_channel);
MenuItem invite = menu.findItem(R.id.invite);
startConversation.setVisible(true);
final Contact contact = user.getContact();
final User self = conversation.getMucOptions().getSelf();
- if ((contact != null && contact.showInRoster()) || mucOptions.isPrivateAndNonAnonymous()) {
+ if ((contact != null && contact.showInRoster())
+ || mucOptions.isPrivateAndNonAnonymous()) {
showContactDetails.setVisible(contact == null || !contact.isSelf());
}
- if ((activity instanceof ConferenceDetailsActivity || activity instanceof MucUsersActivity) && user.getRole() == MucOptions.Role.NONE) {
+ if ((activity instanceof ConferenceDetailsActivity
+ || activity instanceof MucUsersActivity)
+ && user.getRole() == MucOptions.Role.NONE) {
invite.setVisible(true);
}
boolean managePermissionsVisible = false;
@@ -202,15 +208,20 @@ public final class MucDetailsContextMenuHelper {
.setNegativeButton(R.string.no, null).show();
}
- public static boolean onContextItemSelected(MenuItem item, User user, XmppActivity activity, final String fingerprint) {
+ public static boolean onContextItemSelected(
+ MenuItem item, User user, XmppActivity activity, final String fingerprint) {
final Conversation conversation = user.getConversation();
- final XmppConnectionService.OnAffiliationChanged onAffiliationChanged = activity instanceof XmppConnectionService.OnAffiliationChanged ? (XmppConnectionService.OnAffiliationChanged) activity : null;
+ final XmppConnectionService.OnAffiliationChanged onAffiliationChanged =
+ activity instanceof XmppConnectionService.OnAffiliationChanged
+ ? (XmppConnectionService.OnAffiliationChanged) activity
+ : null;
Jid jid = user.getRealJid();
switch (item.getItemId()) {
case R.id.action_contact_details:
final Jid realJid = user.getRealJid();
final Account account = conversation.getAccount();
- final Contact contact = realJid == null ? null : account.getRoster().getContact(realJid);
+ final Contact contact =
+ realJid == null ? null : account.getRoster().getContact(realJid);
if (contact != null) {
activity.switchToContactDetails(contact, fingerprint);
}
@@ -320,37 +331,60 @@ public final class MucDetailsContextMenuHelper {
}
}
- private static void removeFromRoom(final User user, XmppActivity activity, XmppConnectionService.OnAffiliationChanged onAffiliationChanged) {
+ private static void removeFromRoom(
+ final User user,
+ XmppActivity activity,
+ XmppConnectionService.OnAffiliationChanged onAffiliationChanged) {
final Conversation conversation = user.getConversation();
if (conversation.getMucOptions().membersOnly()) {
- activity.xmppConnectionService.changeAffiliationInConference(conversation, user.getRealJid(), MucOptions.Affiliation.NONE, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation,
+ user.getRealJid(),
+ MucOptions.Affiliation.NONE,
+ onAffiliationChanged);
if (user.getRole() != MucOptions.Role.NONE) {
- activity.xmppConnectionService.changeRoleInConference(conversation, user.getName(), MucOptions.Role.NONE);
+ activity.xmppConnectionService.changeRoleInConference(
+ conversation, user.getName(), MucOptions.Role.NONE);
}
} else {
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity);
builder.setTitle(R.string.ban_from_conference);
String jid = user.getRealJid().asBareJid().toString();
- SpannableString message = new SpannableString(activity.getString(R.string.removing_from_public_conference, jid));
+ SpannableString message =
+ new SpannableString(
+ activity.getString(R.string.removing_from_public_conference, jid));
int start = message.toString().indexOf(jid);
if (start >= 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);
}
}
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 648ad049b5761592ba0e525a747edd916846d9b2..db8e3136e7d9269cab72bfb8e3323ea932a96467 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 28910d4d9a5a47dfdda712332dc9ac9ae80d4415..199c18b3baaa17389e65963c0ce3e3f14010f6f7 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