Detailed changes
@@ -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<String> 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<String> 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<Account> 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<String> callback) {
+ public void generateSignature(
+ Intent intent,
+ final Account account,
+ String status,
+ final UiCallback<String> 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<String> 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<String> 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<Contact> 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);
}
}
@@ -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);
}
}
@@ -2,7 +2,10 @@ package eu.siacs.conversations.crypto.axolotl;
import android.util.Base64;
import android.util.Log;
-
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.utils.Compatibility;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.Jid;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@@ -10,7 +13,6 @@ import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
-
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
@@ -20,11 +22,6 @@ import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.utils.Compatibility;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.Jid;
-
public class XmppAxolotlMessage {
public static final String CONTAINERTAG = "encrypted";
private static final String HEADER = "header";
@@ -45,7 +42,8 @@ public class XmppAxolotlMessage {
private byte[] authtagPlusInnerKey = null;
private byte[] iv = null;
- private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException {
+ private XmppAxolotlMessage(final Element axolotlMessage, final Jid from)
+ throws IllegalArgumentException {
this.from = from;
Element header = axolotlMessage.findChild(HEADER);
try {
@@ -62,7 +60,8 @@ public class XmppAxolotlMessage {
int recipientId = Integer.parseInt(keyElement.getAttribute(REMOTEID));
byte[] key = Base64.decode(keyElement.getContent().trim(), Base64.DEFAULT);
boolean isPreKey = keyElement.getAttributeAsBoolean("prekey");
- this.keys.add(new XmppAxolotlSession.AxolotlKey(recipientId, key, isPreKey));
+ this.keys.add(
+ new XmppAxolotlSession.AxolotlKey(recipientId, key, isPreKey));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("invalid remote id");
}
@@ -74,11 +73,12 @@ public class XmppAxolotlMessage {
iv = Base64.decode(keyElement.getContent().trim(), Base64.DEFAULT);
break;
default:
- Log.w(Config.LOGTAG, "Unexpected element in header: " + keyElement.toString());
+ Log.w(Config.LOGTAG, "Unexpected element in header: " + keyElement);
break;
}
}
- final Element payloadElement = axolotlMessage.findChildEnsureSingle(PAYLOAD, AxolotlService.PEP_PREFIX);
+ final Element payloadElement =
+ axolotlMessage.findChildEnsureSingle(PAYLOAD, AxolotlService.PEP_PREFIX);
if (payloadElement != null) {
ciphertext = Base64.decode(payloadElement.getContent().trim(), Base64.DEFAULT);
}
@@ -149,9 +149,16 @@ public class XmppAxolotlMessage {
try {
SecretKey secretKey = new SecretKeySpec(innerKey, KEYTYPE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
- Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
+ Cipher cipher =
+ Compatibility.twentyEight()
+ ? Cipher.getInstance(CIPHERMODE)
+ : Cipher.getInstance(CIPHERMODE, PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
- this.ciphertext = cipher.doFinal(Config.OMEMO_PADDING ? getPaddedBytes(plaintext) : plaintext.getBytes());
+ this.ciphertext =
+ cipher.doFinal(
+ Config.OMEMO_PADDING
+ ? getPaddedBytes(plaintext)
+ : plaintext.getBytes());
if (Config.PUT_AUTH_TAG_INTO_KEY && this.ciphertext != null) {
this.authtagPlusInnerKey = new byte[16 + 16];
byte[] ciphertext = new byte[this.ciphertext.length - 16];
@@ -160,8 +167,12 @@ public class XmppAxolotlMessage {
System.arraycopy(this.innerKey, 0, authtagPlusInnerKey, 0, this.innerKey.length);
this.ciphertext = ciphertext;
}
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException
+ } catch (NoSuchAlgorithmException
+ | NoSuchPaddingException
+ | InvalidKeyException
+ | IllegalBlockSizeException
+ | BadPaddingException
+ | NoSuchProviderException
| InvalidAlgorithmParameterException e) {
throw new CryptoFailedException(e);
}
@@ -220,7 +231,8 @@ public class XmppAxolotlMessage {
return encryptionElement;
}
- private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
+ private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId)
+ throws CryptoFailedException {
ArrayList<XmppAxolotlSession.AxolotlKey> possibleKeys = new ArrayList<>();
for (XmppAxolotlSession.AxolotlKey key : keys) {
if (key.deviceId == sourceDeviceId) {
@@ -233,17 +245,22 @@ public class XmppAxolotlMessage {
return session.processReceiving(possibleKeys);
}
- XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
- return new XmppAxolotlKeyTransportMessage(session.getFingerprint(), unpackKey(session, sourceDeviceId), getIV());
+ XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId)
+ throws CryptoFailedException {
+ return new XmppAxolotlKeyTransportMessage(
+ session.getFingerprint(), unpackKey(session, sourceDeviceId), getIV());
}
- public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
+ public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId)
+ throws CryptoFailedException {
XmppAxolotlPlaintextMessage plaintextMessage = null;
byte[] key = unpackKey(session, sourceDeviceId);
if (key != null) {
try {
if (key.length < 32) {
- throw new OutdatedSenderException("Key did not contain auth tag. Sender needs to update their OMEMO client");
+ throw new OutdatedSenderException(
+ "Key did not contain auth tag. Sender needs to update their OMEMO"
+ + " client");
}
final int authTagLength = key.length - 16;
byte[] newCipherText = new byte[key.length - 16 + ciphertext.length];
@@ -254,18 +271,28 @@ public class XmppAxolotlMessage {
ciphertext = newCipherText;
key = newKey;
- final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
+ final Cipher cipher =
+ Compatibility.twentyEight()
+ ? Cipher.getInstance(CIPHERMODE)
+ : Cipher.getInstance(CIPHERMODE, PROVIDER);
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String plaintext = new String(cipher.doFinal(ciphertext));
- plaintextMessage = new XmppAxolotlPlaintextMessage(Config.OMEMO_PADDING ? plaintext.trim() : plaintext, session.getFingerprint());
-
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | InvalidAlgorithmParameterException | IllegalBlockSizeException
- | BadPaddingException | NoSuchProviderException e) {
+ plaintextMessage =
+ new XmppAxolotlPlaintextMessage(
+ Config.OMEMO_PADDING ? plaintext.trim() : plaintext,
+ session.getFingerprint());
+
+ } catch (NoSuchAlgorithmException
+ | NoSuchPaddingException
+ | InvalidKeyException
+ | InvalidAlgorithmParameterException
+ | IllegalBlockSizeException
+ | BadPaddingException
+ | NoSuchProviderException e) {
throw new CryptoFailedException(e);
}
}
@@ -285,7 +312,6 @@ public class XmppAxolotlMessage {
return plaintext;
}
-
public String getFingerprint() {
return fingerprint;
}
@@ -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
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
public class MucOptions {
@@ -919,9 +920,8 @@ public class MucOptions {
if (role != user.role) return false;
if (affiliation != user.affiliation) return false;
- if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
- return false;
- return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
+ if (!Objects.equals(realJid, user.realJid)) return false;
+ return Objects.equals(fullJid, user.fullJid);
}
public boolean isDomain() {
@@ -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;
+ }
}
@@ -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<ReadByMarker> fromJson(final JSONArray jsonArray) {
- final Set<ReadByMarker> 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<ReadByMarker> from(Collection<MucOptions.User> users) {
- final Set<ReadByMarker> 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<ReadByMarker> fromJsonString(String json) {
- try {
- return fromJson(new JSONArray(json));
- } catch (final JSONException | NullPointerException e) {
- return new CopyOnWriteArraySet<>();
- }
- }
-
- public static JSONArray toJson(final Set<ReadByMarker> 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<ReadByMarker> 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<MucOptions.User> users, Set<ReadByMarker> markers) {
- for(MucOptions.User user : users) {
- if (!contains(from(user),markers)) {
- return false;
- }
- }
- return true;
- }
-
- public static boolean allUsersRepresented(Collection<MucOptions.User> users, Set<ReadByMarker> markers, ReadByMarker marker) {
- final Set<ReadByMarker> 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<ReadByMarker> fromJson(final JSONArray jsonArray) {
+ final Set<ReadByMarker> 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<ReadByMarker> from(Collection<MucOptions.User> users) {
+ final Set<ReadByMarker> 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<ReadByMarker> fromJsonString(String json) {
+ try {
+ return fromJson(new JSONArray(json));
+ } catch (final JSONException | NullPointerException e) {
+ return new CopyOnWriteArraySet<>();
+ }
+ }
+
+ public static JSONArray toJson(final Set<ReadByMarker> 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<ReadByMarker> 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<MucOptions.User> users, Set<ReadByMarker> markers) {
+ for (MucOptions.User user : users) {
+ if (!contains(from(user), markers)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean allUsersRepresented(
+ Collection<MucOptions.User> users, Set<ReadByMarker> markers, ReadByMarker marker) {
+ final Set<ReadByMarker> markersCopy = new CopyOnWriteArraySet<>(markers);
+ markersCopy.add(marker);
+ return allUsersRepresented(users, markersCopy);
+ }
}
@@ -79,7 +79,7 @@ public class SlotRequester {
response.getExtension(
im.conversations.android.xmpp.model.upload.Slot.class);
if (slot == null) {
- Log.d(Config.LOGTAG, "-->" + response.toString());
+ Log.d(Config.LOGTAG, "-->" + response);
throw new IllegalStateException("Slot not found in IQ response");
}
final var getUrl = slot.getGetUrl();
@@ -189,7 +189,7 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
+ "Encountered invalid <device> node in PEP ("
+ e.getMessage()
+ "):"
- + device.toString()
+ + device
+ ", skipping...");
}
}
@@ -313,7 +313,7 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
AxolotlService.LOGPREFIX
+ " : "
+ "could not parse preKeyId from preKey "
- + preKeyPublicElement.toString());
+ + preKeyPublicElement);
} catch (Throwable e) {
Log.e(
Config.LOGTAG,
@@ -332,7 +332,6 @@ public class MessageParser extends AbstractParser
}
} else if (Namespace.BOOKMARKS2.equals(node) && account.getJid().asBareJid().equals(from)) {
final var retractions = items.getRetractions();
- ;
for (final var item : items.getItemMap(Conference.class).entrySet()) {
final Bookmark bookmark =
Bookmark.parseFromItem(item.getKey(), item.getValue(), account);
@@ -346,7 +346,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
final SQLiteDatabase db = getWritableDatabase();
final Stopwatch stopwatch = Stopwatch.createStarted();
db.execSQL(COPY_PREEXISTING_ENTRIES);
- Log.d(Config.LOGTAG, "rebuilt message index in " + stopwatch.stop().toString());
+ Log.d(Config.LOGTAG, "rebuilt message index in " + stopwatch.stop());
}
public static synchronized DatabaseBackend getInstance(Context context) {
@@ -1561,7 +1561,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ " is not null and conversationUuid=(select uuid from conversations where"
+ " accountUuid=? and (contactJid=? or contactJid like ?)) order by"
+ " timeSent desc";
- final String[] args = {account, jid.toString(), jid.toString() + "/%"};
+ final String[] args = {account, jid.toString(), jid + "/%"};
Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + limit : ""), args);
List<FilePath> filesPaths = new ArrayList<>();
while (cursor.moveToNext()) {
@@ -425,9 +425,7 @@ public class FileBackend {
}
public static void updateFileParams(Message message, String url, long size) {
- final StringBuilder body = new StringBuilder();
- body.append(url).append('|').append(size);
- message.setBody(body.toString());
+ message.setBody(url + '|' + size);
}
public Bitmap getPreviewForUri(Attachment attachment, int size, boolean cacheOnly) {
@@ -1244,7 +1242,7 @@ public class FileBackend {
Log.d(Config.LOGTAG, "settled on char length " + chars + " with quality=" + quality);
final Avatar avatar = new Avatar();
avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest());
- avatar.image = new String(mByteArrayOutputStream.toByteArray());
+ avatar.image = mByteArrayOutputStream.toString();
if (format.equals(Bitmap.CompressFormat.WEBP)) {
avatar.type = "image/webp";
} else if (format.equals(Bitmap.CompressFormat.JPEG)) {
@@ -1289,7 +1287,7 @@ public class FileBackend {
os.flush();
os.close();
avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest());
- avatar.image = new String(mByteArrayOutputStream.toByteArray());
+ avatar.image = mByteArrayOutputStream.toString();
avatar.height = options.outHeight;
avatar.width = options.outWidth;
avatar.type = options.outMimeType;
@@ -540,10 +540,7 @@ public class CallIntegration extends Connection {
return false;
}
// SailfishOS's AppSupport do not support Call Integration
- if (Build.MODEL.endsWith("(AppSupport)")) {
- return false;
- }
- return true;
+ return !Build.MODEL.endsWith("(AppSupport)");
}
public static boolean notSelfManaged(final Context context) {
@@ -3,15 +3,7 @@ package eu.siacs.conversations.services;
import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
import android.util.Log;
-
import androidx.annotation.NonNull;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -25,6 +17,11 @@ import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.mam.MamReference;
import im.conversations.android.xmpp.model.stanza.Iq;
import im.conversations.android.xmpp.model.stanza.Message;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
@@ -90,7 +87,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
return null;
}
-
}
MessageArchiveService(final XmppConnectionService service) {
@@ -106,11 +102,13 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
}
}
- MamReference mamReference = MamReference.max(
- mXmppConnectionService.databaseBackend.getLastMessageReceived(account),
- mXmppConnectionService.databaseBackend.getLastClearDate(account)
- );
- mamReference = MamReference.max(mamReference, mXmppConnectionService.getAutomaticMessageDeletionDate());
+ MamReference mamReference =
+ MamReference.max(
+ mXmppConnectionService.databaseBackend.getLastMessageReceived(account),
+ mXmppConnectionService.databaseBackend.getLastClearDate(account));
+ mamReference =
+ MamReference.max(
+ mamReference, mXmppConnectionService.getAutomaticMessageDeletionDate());
long endCatchup = account.getXmppConnection().getLastSessionEstablished();
final Query query;
if (mamReference.getTimestamp() == 0) {
@@ -119,7 +117,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
long startCatchup = endCatchup - Config.MAM_MAX_CATCHUP;
List<Conversation> conversations = mXmppConnectionService.getConversations();
for (Conversation conversation : conversations) {
- if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account && startCatchup > conversation.getLastMessageTransmitted().getTimestamp()) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE
+ && conversation.getAccount() == account
+ && startCatchup > conversation.getLastMessageTransmitted().getTimestamp()) {
this.query(conversation, startCatchup, true);
}
}
@@ -134,27 +134,21 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
void catchupMUC(final Conversation conversation) {
- if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) {
- query(conversation,
- new MamReference(0),
- 0,
- true);
+ if (conversation.getLastMessageTransmitted().getTimestamp() < 0
+ && conversation.countMessages() == 0) {
+ query(conversation, new MamReference(0), 0, true);
} else {
- query(conversation,
- conversation.getLastMessageTransmitted(),
- 0,
- true);
+ query(conversation, conversation.getLastMessageTransmitted(), 0, true);
}
}
public Query query(final Conversation conversation) {
- if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) {
- return query(conversation,
- new MamReference(0),
- System.currentTimeMillis(),
- false);
+ if (conversation.getLastMessageTransmitted().getTimestamp() < 0
+ && conversation.countMessages() == 0) {
+ return query(conversation, new MamReference(0), System.currentTimeMillis(), false);
} else {
- return query(conversation,
+ return query(
+ conversation,
conversation.getLastMessageTransmitted(),
conversation.getAccount().getXmppConnection().getLastSessionEstablished(),
false);
@@ -168,7 +162,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
} else {
synchronized (this.queries) {
for (Query query : this.queries) {
- if (query.getAccount() == account && query.isCatchup() && ((conversation.getMode() == Conversation.MODE_SINGLE && query.getWith() == null) || query.getConversation() == conversation)) {
+ if (query.getAccount() == account
+ && query.isCatchup()
+ && ((conversation.getMode() == Conversation.MODE_SINGLE
+ && query.getWith() == null)
+ || query.getConversation() == conversation)) {
return true;
}
}
@@ -178,21 +176,33 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
public Query query(final Conversation conversation, long end, boolean allowCatchup) {
- return this.query(conversation, conversation.getLastMessageTransmitted(), end, allowCatchup);
+ return this.query(
+ conversation, conversation.getLastMessageTransmitted(), end, allowCatchup);
}
- public Query query(Conversation conversation, MamReference start, long end, boolean allowCatchup) {
+ public Query query(
+ Conversation conversation, MamReference start, long end, boolean allowCatchup) {
synchronized (this.queries) {
final Query query;
- final MamReference startActual = MamReference.max(start, mXmppConnectionService.getAutomaticMessageDeletionDate());
+ final MamReference startActual =
+ MamReference.max(
+ start, mXmppConnectionService.getAutomaticMessageDeletionDate());
if (start.getTimestamp() == 0) {
query = new Query(conversation, startActual, end, false);
query.reference = conversation.getFirstMamReference();
} else {
if (allowCatchup) {
- MamReference maxCatchup = MamReference.max(startActual, System.currentTimeMillis() - Config.MAM_MAX_CATCHUP);
+ MamReference maxCatchup =
+ MamReference.max(
+ startActual,
+ System.currentTimeMillis() - Config.MAM_MAX_CATCHUP);
if (maxCatchup.greaterThan(startActual)) {
- Query reverseCatchup = new Query(conversation, startActual, maxCatchup.getTimestamp(), false);
+ Query reverseCatchup =
+ new Query(
+ conversation,
+ startActual,
+ maxCatchup.getTimestamp(),
+ false);
this.queries.add(reverseCatchup);
this.execute(reverseCatchup);
}
@@ -231,40 +241,57 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
if (account.getStatus() == Account.State.ONLINE) {
final Conversation conversation = query.getConversation();
if (conversation != null && conversation.getStatus() == Conversation.STATUS_ARCHIVED) {
- throw new IllegalStateException("Attempted to run MAM query for archived conversation");
- }
- Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString());
- final Iq packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
- this.mXmppConnectionService.sendIqPacket(account, packet, (p) -> {
- final Element fin = p.findChild("fin", query.version.namespace);
- if (p.getType() == Iq.Type.TIMEOUT) {
- synchronized (this.queries) {
- this.queries.remove(query);
- if (query.hasCallback()) {
- query.callback(false);
+ throw new IllegalStateException(
+ "Attempted to run MAM query for archived conversation");
+ }
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid().toString() + ": running mam query " + query);
+ final Iq packet =
+ this.mXmppConnectionService
+ .getIqGenerator()
+ .queryMessageArchiveManagement(query);
+ this.mXmppConnectionService.sendIqPacket(
+ account,
+ packet,
+ (p) -> {
+ final Element fin = p.findChild("fin", query.version.namespace);
+ if (p.getType() == Iq.Type.TIMEOUT) {
+ synchronized (this.queries) {
+ this.queries.remove(query);
+ if (query.hasCallback()) {
+ query.callback(false);
+ }
+ }
+ } else if (p.getType() == Iq.Type.RESULT && fin != null) {
+ final boolean running;
+ synchronized (this.queries) {
+ running = this.queries.contains(query);
+ }
+ if (running) {
+ processFin(query, fin);
+ } else {
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid()
+ + ": ignoring MAM iq result because query had been"
+ + " killed");
+ }
+ } else if (p.getType() == Iq.Type.RESULT && query.isLegacy()) {
+ // do nothing
+ } else {
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid().toString()
+ + ": error executing mam: "
+ + p);
+ try {
+ finalizeQuery(query, true);
+ } catch (final IllegalStateException e) {
+ // ignored
+ }
}
- }
- } else if (p.getType() == Iq.Type.RESULT && fin != null) {
- final boolean running;
- synchronized (this.queries) {
- running = this.queries.contains(query);
- }
- if (running) {
- processFin(query, fin);
- } else {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring MAM iq result because query had been killed");
- }
- } else if (p.getType() == Iq.Type.RESULT && query.isLegacy()) {
- //do nothing
- } else {
- Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": error executing mam: " + p.toString());
- try {
- finalizeQuery(query, true);
- } catch (final IllegalStateException e) {
- //ignored
- }
- }
- });
+ });
} else {
synchronized (this.pendingQueries) {
this.pendingQueries.add(query);
@@ -320,7 +347,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
for (Query query : queries) {
if (query.account == conversation.getAccount() && query.isCatchup()) {
final Jid with = query.getWith() == null ? null : query.getWith().asBareJid();
- if ((conversation.getMode() == Conversational.MODE_SINGLE && with == null) || (conversation.getJid().asBareJid().equals(with))) {
+ if ((conversation.getMode() == Conversational.MODE_SINGLE && with == null)
+ || (conversation.getJid().asBareJid().equals(with))) {
return true;
}
}
@@ -329,7 +357,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
return false;
}
- boolean queryInProgress(Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) {
+ boolean queryInProgress(
+ Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) {
synchronized (this.queries) {
for (Query query : queries) {
if (query.conversation == conversation) {
@@ -361,12 +390,15 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
String count = set == null ? null : set.findChildContent("count");
Element first = set == null ? null : set.findChild("first");
Element relevant = query.getPagingOrder() == PagingOrder.NORMAL ? last : first;
- boolean abort = (!query.isCatchup() && query.getTotalCount() >= Config.PAGE_SIZE) || query.getTotalCount() >= Config.MAM_MAX_MESSAGES;
+ boolean abort =
+ (!query.isCatchup() && query.getTotalCount() >= Config.PAGE_SIZE)
+ || query.getTotalCount() >= Config.MAM_MAX_MESSAGES;
if (query.getConversation() != null) {
query.getConversation().setFirstMamReference(first == null ? null : first.getContent());
}
if (complete || relevant == null || abort) {
- //TODO: FIX done logic to look at complete. using count is probably unreliable because it can be ommited and doesn’t work with paging.
+ // TODO: FIX done logic to look at complete. using count is probably unreliable because
+ // it can be ommited and doesn’t work with paging.
boolean done;
if (query.isCatchup()) {
done = false;
@@ -384,9 +416,21 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
done = done || (query.getActualMessageCount() == 0 && !query.isCatchup());
this.finalizeQuery(query, done);
- Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": finished mam after " + query.getTotalCount() + "(" + query.getActualMessageCount() + ") messages. messages left=" + !done + " count=" + count);
+ Log.d(
+ Config.LOGTAG,
+ query.getAccount().getJid().asBareJid()
+ + ": finished mam after "
+ + query.getTotalCount()
+ + "("
+ + query.getActualMessageCount()
+ + ") messages. messages left="
+ + !done
+ + " count="
+ + count);
if (query.isCatchup() && query.getActualMessageCount() > 0) {
- mXmppConnectionService.getNotificationService().finishBacklog(true, query.getAccount());
+ mXmppConnectionService
+ .getNotificationService()
+ .finishBacklog(true, query.getAccount());
}
processPostponed(query);
} else {
@@ -407,11 +451,15 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
void kill(final Conversation conversation) {
final ArrayList<Query> toBeKilled = new ArrayList<>();
synchronized (this.pendingQueries) {
- for (final Iterator<Query> iterator = this.pendingQueries.iterator(); iterator.hasNext(); ) {
+ for (final Iterator<Query> iterator = this.pendingQueries.iterator();
+ iterator.hasNext(); ) {
final Query query = iterator.next();
if (query.getConversation() == conversation) {
iterator.remove();
- Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": killed pending MAM query for archived conversation");
+ Log.d(
+ Config.LOGTAG,
+ conversation.getAccount().getJid().asBareJid()
+ + ": killed pending MAM query for archived conversation");
}
}
}
@@ -428,7 +476,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
private void kill(Query query) {
- Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": killing mam query prematurely");
+ Log.d(
+ Config.LOGTAG,
+ query.getAccount().getJid().asBareJid() + ": killing mam query prematurely");
query.callback = null;
this.finalizeQuery(query, false);
if (query.isCatchup() && query.getActualMessageCount() > 0) {
@@ -440,11 +490,20 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
private void processPostponed(Query query) {
query.account.getAxolotlService().processPostponed();
query.pendingReceiptRequests.removeAll(query.receiptRequests);
- Log.d(Config.LOGTAG, query.getAccount().getJid().asBareJid() + ": found " + query.pendingReceiptRequests.size() + " pending receipt requests");
+ Log.d(
+ Config.LOGTAG,
+ query.getAccount().getJid().asBareJid()
+ + ": found "
+ + query.pendingReceiptRequests.size()
+ + " pending receipt requests");
Iterator<ReceiptRequest> iterator = query.pendingReceiptRequests.iterator();
while (iterator.hasNext()) {
ReceiptRequest rr = iterator.next();
- mXmppConnectionService.sendMessagePacket(query.account, mXmppConnectionService.getMessageGenerator().received(query.account, rr.getJid(), rr.getId()));
+ mXmppConnectionService.sendMessagePacket(
+ query.account,
+ mXmppConnectionService
+ .getMessageGenerator()
+ .received(query.account, rr.getJid(), rr.getId()));
iterator.remove();
}
}
@@ -465,7 +524,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
@Override
public void onAdvancedStreamFeaturesAvailable(Account account) {
- if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().mam()) {
+ if (account.getXmppConnection() != null
+ && account.getXmppConnection().getFeatures().mam()) {
this.catchup(account);
}
}
@@ -492,9 +552,12 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
private boolean catchup = true;
public final Version version;
-
Query(Conversation conversation, MamReference start, long end, boolean catchup) {
- this(conversation.getAccount(), Version.get(conversation.getAccount(), conversation), catchup ? start : start.timeOnly(), end);
+ this(
+ conversation.getAccount(),
+ Version.get(conversation.getAccount(), conversation),
+ catchup ? start : start.timeOnly(),
+ end);
this.conversation = conversation;
this.pagingOrder = catchup ? PagingOrder.NORMAL : PagingOrder.REVERSE;
this.catchup = catchup;
@@ -517,7 +580,12 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
private Query page(String reference) {
- Query query = new Query(this.account, this.version, new MamReference(this.start, reference), this.end);
+ Query query =
+ new Query(
+ this.account,
+ this.version,
+ new MamReference(this.start, reference),
+ this.end);
query.conversation = conversation;
query.totalCount = totalCount;
query.actualCount = actualCount;
@@ -507,7 +507,7 @@ public class XmppConnectionService extends Service {
private LruCache<String, Bitmap> mBitmapCache;
private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver();
private final BroadcastReceiver mInternalRestrictedEventReceiver =
- new RestrictedEventReceiver(Arrays.asList(TorServiceUtils.ACTION_STATUS));
+ new RestrictedEventReceiver(List.of(TorServiceUtils.ACTION_STATUS));
private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver();
private static String generateFetchKey(Account account, final Avatar avatar) {
@@ -4535,7 +4535,7 @@ public class XmppConnectionService extends Service {
if (packet.getType() == Iq.Type.RESULT) {
callback.onPushSucceeded();
} else {
- Log.d(Config.LOGTAG, "failed: " + packet.toString());
+ Log.d(Config.LOGTAG, "failed: " + packet);
callback.onPushFailed();
}
}
@@ -5125,7 +5125,7 @@ public class XmppConnectionService extends Service {
if (error == null) {
Log.d(Config.LOGTAG, ERROR + "(server error)");
} else {
- Log.d(Config.LOGTAG, ERROR + error.toString());
+ Log.d(Config.LOGTAG, ERROR + error);
}
}
if (callback != null) {
@@ -531,8 +531,7 @@ public class ConversationFragment extends XmppFragment
@Override
public void onClick(View v) {
Object tag = v.getTag();
- if (tag instanceof SendButtonAction) {
- SendButtonAction action = (SendButtonAction) tag;
+ if (tag instanceof SendButtonAction action) {
switch (action) {
case TAKE_PHOTO:
case RECORD_VIDEO:
@@ -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<String> 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");
}
}
@@ -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");
}
}
@@ -6,118 +6,136 @@ import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.AutoCompleteTextView;
-import android.widget.Spinner;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.DialogFragment;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogJoinConferenceBinding;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
import eu.siacs.conversations.ui.util.DelayedHintHelper;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
public class JoinConferenceDialog extends DialogFragment implements OnBackendConnected {
- private static final String PREFILLED_JID_KEY = "prefilled_jid";
- private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
- private JoinConferenceDialogListener mListener;
- private KnownHostsAdapter knownHostsAdapter;
-
- public static JoinConferenceDialog newInstance(String prefilledJid, List<String> accounts) {
- JoinConferenceDialog dialog = new JoinConferenceDialog();
- Bundle bundle = new Bundle();
- bundle.putString(PREFILLED_JID_KEY, prefilledJid);
- bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList<String>) accounts);
- dialog.setArguments(bundle);
- return dialog;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- setRetainInstance(true);
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
- builder.setTitle(R.string.join_public_channel);
- final DialogJoinConferenceBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.dialog_join_conference, null, false);
- DelayedHintHelper.setHint(R.string.channel_full_jid_example, binding.jid);
- this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
- binding.jid.setAdapter(knownHostsAdapter);
- String prefilledJid = getArguments().getString(PREFILLED_JID_KEY);
- if (prefilledJid != null) {
- binding.jid.append(prefilledJid);
- }
- StartConversationActivity.populateAccountSpinner(getActivity(), getArguments().getStringArrayList(ACCOUNTS_LIST_KEY), binding.account);
- builder.setView(binding.getRoot());
- builder.setPositiveButton(R.string.join, null);
- builder.setNegativeButton(R.string.cancel, null);
- AlertDialog dialog = builder.create();
- dialog.show();
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(view -> mListener.onJoinDialogPositiveClick(dialog, binding.account, binding.accountJidLayout, binding.jid));
- binding.jid.setOnEditorActionListener((v, actionId, event) -> {
- mListener.onJoinDialogPositiveClick(dialog, binding.account, binding.accountJidLayout, binding.jid);
- return true;
- });
- return dialog;
- }
-
- @Override
- public void onBackendConnected() {
- refreshKnownHosts();
- }
-
- private void refreshKnownHosts() {
- Activity activity = getActivity();
- if (activity instanceof XmppActivity) {
- Collection<String> hosts = ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts();
- this.knownHostsAdapter.refresh(hosts);
- }
- }
-
- @Override
- public void onAttach(@NonNull final Context context) {
- super.onAttach(context);
- try {
- mListener = (JoinConferenceDialogListener) context;
- } catch (ClassCastException e) {
- throw new ClassCastException(context.toString()
- + " must implement JoinConferenceDialogListener");
- }
- }
-
- @Override
- public void onDestroyView() {
- Dialog dialog = getDialog();
- if (dialog != null && getRetainInstance()) {
- dialog.setDismissMessage(null);
- }
- super.onDestroyView();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- final Activity activity = getActivity();
- if (activity instanceof XmppActivity && ((XmppActivity) activity).xmppConnectionService != null) {
- refreshKnownHosts();
- }
- }
-
- public interface JoinConferenceDialogListener {
- void onJoinDialogPositiveClick(Dialog dialog, AutoCompleteTextView spinner, TextInputLayout jidLayout, AutoCompleteTextView jid);
- }
+ private static final String PREFILLED_JID_KEY = "prefilled_jid";
+ private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
+ private JoinConferenceDialogListener mListener;
+ private KnownHostsAdapter knownHostsAdapter;
+
+ public static JoinConferenceDialog newInstance(String prefilledJid, List<String> accounts) {
+ JoinConferenceDialog dialog = new JoinConferenceDialog();
+ Bundle bundle = new Bundle();
+ bundle.putString(PREFILLED_JID_KEY, prefilledJid);
+ bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList<String>) accounts);
+ dialog.setArguments(bundle);
+ return dialog;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setRetainInstance(true);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final MaterialAlertDialogBuilder builder =
+ new MaterialAlertDialogBuilder(requireActivity());
+ builder.setTitle(R.string.join_public_channel);
+ final DialogJoinConferenceBinding binding =
+ DataBindingUtil.inflate(
+ getActivity().getLayoutInflater(),
+ R.layout.dialog_join_conference,
+ null,
+ false);
+ DelayedHintHelper.setHint(R.string.channel_full_jid_example, binding.jid);
+ this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
+ binding.jid.setAdapter(knownHostsAdapter);
+ String prefilledJid = getArguments().getString(PREFILLED_JID_KEY);
+ if (prefilledJid != null) {
+ binding.jid.append(prefilledJid);
+ }
+ StartConversationActivity.populateAccountSpinner(
+ getActivity(),
+ getArguments().getStringArrayList(ACCOUNTS_LIST_KEY),
+ binding.account);
+ builder.setView(binding.getRoot());
+ builder.setPositiveButton(R.string.join, null);
+ builder.setNegativeButton(R.string.cancel, null);
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .setOnClickListener(
+ view ->
+ mListener.onJoinDialogPositiveClick(
+ dialog,
+ binding.account,
+ binding.accountJidLayout,
+ binding.jid));
+ binding.jid.setOnEditorActionListener(
+ (v, actionId, event) -> {
+ mListener.onJoinDialogPositiveClick(
+ dialog, binding.account, binding.accountJidLayout, binding.jid);
+ return true;
+ });
+ return dialog;
+ }
+
+ @Override
+ public void onBackendConnected() {
+ refreshKnownHosts();
+ }
+
+ private void refreshKnownHosts() {
+ Activity activity = getActivity();
+ if (activity instanceof XmppActivity) {
+ Collection<String> 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);
+ }
}
@@ -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<String> BLACKLISTED_ACTIVITIES = Arrays.asList("com.teslacoilsw.launcher.ChooseActionIntentActivity");
+ private static final List<String> 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);
}
}
@@ -181,8 +181,7 @@ public abstract class XmppActivity extends ActionBarActivity {
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
- if (drawable instanceof AsyncDrawable) {
- final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+ if (drawable instanceof AsyncDrawable asyncDrawable) {
return asyncDrawable.getBitmapWorkerTask();
}
}
@@ -30,7 +30,7 @@ public class KnownHostsAdapter extends ArrayAdapter<String> {
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);
@@ -77,10 +77,8 @@ public class MediaAdapter extends RecyclerView.Adapter<MediaAdapter.MediaViewHol
this.mediaSize = Math.round(activity.getResources().getDimension(mediaSize));
}
- @SuppressWarnings("rawtypes")
- public static void setMediaSize(final RecyclerView recyclerView, int mediaSize) {
- final RecyclerView.Adapter adapter = recyclerView.getAdapter();
- if (adapter instanceof MediaAdapter mediaAdapter) {
+ public static void setMediaSize(final RecyclerView recyclerView, final int mediaSize) {
+ if (recyclerView.getAdapter() instanceof MediaAdapter mediaAdapter) {
mediaAdapter.setMediaSize(mediaSize);
}
}
@@ -137,6 +135,9 @@ public class MediaAdapter extends RecyclerView.Adapter<MediaAdapter.MediaViewHol
return R.drawable.ic_code_48dp;
} else if (mime.equals("message/rfc822")) {
return R.drawable.ic_email_48dp;
+ } else if (Arrays.asList("application/x-pcapng", "application/vnd.tcpdump.pcap")
+ .contains(mime)) {
+ return R.drawable.ic_lan_24dp;
} else {
return R.drawable.ic_help_center_48dp;
}
@@ -254,7 +255,7 @@ public class MediaAdapter extends RecyclerView.Adapter<MediaAdapter.MediaViewHol
}
}
- static class MediaViewHolder extends RecyclerView.ViewHolder {
+ public static class MediaViewHolder extends RecyclerView.ViewHolder {
private final ItemMediaBinding binding;
@@ -1485,7 +1485,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
private abstract static class MessageItemViewHolder /*extends RecyclerView.ViewHolder*/ {
- private View itemView;
+ private final View itemView;
private MessageItemViewHolder(@NonNull View itemView) {
this.itemView = itemView;
@@ -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<Camera.Size> numPixelComparator = new Comparator<Camera.Size>() {
- @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<Camera.Size> numPixelComparator =
+ new Comparator<Camera.Size>() {
+ @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<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
- if (rawSupportedSizes == null)
- return parameters.getPreviewSize();
+ if (rawSupportedSizes == null) return parameters.getPreviewSize();
// sort by size, descending
- final List<Camera.Size> supportedPreviewSizes = new ArrayList<Camera.Size>(rawSupportedSizes);
+ final List<Camera.Size> supportedPreviewSizes =
+ new ArrayList<Camera.Size>(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<String> 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<String> values, final String... valuesToFind) {
for (final String valueToFind : valuesToFind)
- if (values.contains(valueToFind))
- return valueToFind;
+ if (values.contains(valueToFind)) return valueToFind;
return null;
}
@@ -7,22 +7,18 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;
-
import androidx.annotation.DimenRes;
-
-import java.lang.ref.WeakReference;
-import java.util.concurrent.RejectedExecutionException;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.ui.XmppActivity;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.RejectedExecutionException;
public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private AvatarService.Avatarable avatarable = null;
- private @DimenRes
- final int size;
+ private @DimenRes final int size;
public AvatarWorkerTask(ImageView imageView, @DimenRes int size) {
imageViewReference = new WeakReference<>(imageView);
@@ -36,7 +32,8 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
if (activity == null) {
return null;
}
- return activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), isCancelled());
+ return activity.avatarService()
+ .get(avatarable, (int) activity.getResources().getDimension(size), isCancelled());
}
@Override
@@ -50,11 +47,12 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
}
}
- public static boolean cancelPotentialWork(AvatarService.Avatarable avatarable, ImageView imageView) {
+ public static boolean cancelPotentialWork(
+ AvatarService.Avatarable avatarable, ImageView imageView) {
final AvatarWorkerTask workerTask = getBitmapWorkerTask(imageView);
if (workerTask != null) {
- final AvatarService.Avatarable old= workerTask.avatarable;
+ final AvatarService.Avatarable old = workerTask.avatarable;
if (old == null || avatarable != old) {
workerTask.cancel(true);
} else {
@@ -67,21 +65,28 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
public static AvatarWorkerTask 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.getAvatarWorkerTask();
}
}
return null;
}
- public static void loadAvatar(final AvatarService.Avatarable avatarable, final ImageView imageView, final @DimenRes int size) {
+ public static void loadAvatar(
+ final AvatarService.Avatarable avatarable,
+ final ImageView imageView,
+ final @DimenRes int size) {
if (cancelPotentialWork(avatarable, imageView)) {
final XmppActivity activity = XmppActivity.find(imageView);
if (activity == null) {
return;
}
- final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
+ final Bitmap bm =
+ activity.avatarService()
+ .get(
+ avatarable,
+ (int) activity.getResources().getDimension(size),
+ true);
setContentDescription(avatarable, imageView);
if (bm != null) {
cancelPotentialWork(avatarable, imageView);
@@ -91,7 +96,8 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
imageView.setBackgroundColor(avatarable.getAvatarBackgroundColor());
imageView.setImageDrawable(null);
final AvatarWorkerTask task = new AvatarWorkerTask(imageView, size);
- final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
+ final AsyncDrawable asyncDrawable =
+ new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(avatarable);
@@ -101,12 +107,14 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
}
}
- private static void setContentDescription(final AvatarService.Avatarable avatarable, final ImageView imageView) {
+ private static void setContentDescription(
+ final AvatarService.Avatarable avatarable, final ImageView imageView) {
final Context context = imageView.getContext();
if (avatarable instanceof Account) {
imageView.setContentDescription(context.getString(R.string.your_avatar));
} else {
- imageView.setContentDescription(context.getString(R.string.avatar_for_x, avatarable.getAvatarName()));
+ imageView.setContentDescription(
+ context.getString(R.string.avatar_for_x, avatarable.getAvatarName()));
}
}
@@ -9,11 +9,7 @@ import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-
-import androidx.appcompat.app.AlertDialog;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -29,15 +25,13 @@ import eu.siacs.conversations.ui.MucUsersActivity;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.xmpp.Jid;
-
public final class MucDetailsContextMenuHelper {
public static void onCreateContextMenu(ContextMenu menu, View v) {
final XmppActivity activity = XmppActivity.find(v);
final Object tag = v.getTag();
- if (tag instanceof MucOptions.User && activity != null) {
+ if (tag instanceof User user && activity != null) {
activity.getMenuInflater().inflate(R.menu.muc_details_context, menu);
- final MucOptions.User user = (MucOptions.User) tag;
String name;
final Contact contact = user.getContact();
if (contact != null && contact.showInContactList()) {
@@ -48,13 +42,17 @@ public final class MucDetailsContextMenuHelper {
name = user.getName();
}
menu.setHeaderTitle(name);
- MucDetailsContextMenuHelper.configureMucDetailsContextMenu(activity, menu, user.getConversation(), user);
+ MucDetailsContextMenuHelper.configureMucDetailsContextMenu(
+ activity, menu, user.getConversation(), user);
}
}
- public static void configureMucDetailsContextMenu(Activity activity, Menu menu, Conversation conversation, User user) {
+ public static void configureMucDetailsContextMenu(
+ Activity 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 isGroupChat = mucOptions.isPrivateAndNonAnonymous();
MenuItem sendPrivateMessage = menu.findItem(R.id.send_private_message);
if (user != null && user.getRealJid() != null) {
@@ -68,21 +66,28 @@ public final class MucDetailsContextMenuHelper {
MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges);
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 banFromConference = menu.findItem(R.id.ban_from_conference);
- banFromConference.setTitle(isGroupChat ? R.string.ban_from_conference : R.string.ban_from_channel);
+ banFromConference.setTitle(
+ isGroupChat ? R.string.ban_from_conference : R.string.ban_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;
- if ((self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN) && self.getAffiliation().outranks(user.getAffiliation())) || self.getAffiliation() == MucOptions.Affiliation.OWNER) {
+ if ((self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN)
+ && self.getAffiliation().outranks(user.getAffiliation()))
+ || self.getAffiliation() == MucOptions.Affiliation.OWNER) {
if (advancedMode) {
if (!user.getAffiliation().ranks(MucOptions.Affiliation.MEMBER)) {
managePermissionsVisible = true;
@@ -102,16 +107,20 @@ public final class MucDetailsContextMenuHelper {
}
}
if (self.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
- if (isGroupChat || advancedMode || user.getAffiliation() == MucOptions.Affiliation.OWNER) {
+ if (isGroupChat
+ || advancedMode
+ || user.getAffiliation() == MucOptions.Affiliation.OWNER) {
if (!user.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
managePermissionsVisible = true;
giveOwnerPrivileges.setVisible(true);
- } else if (user.getAffiliation() == MucOptions.Affiliation.OWNER){
+ } else if (user.getAffiliation() == MucOptions.Affiliation.OWNER) {
managePermissionsVisible = true;
removeOwnerPrivileges.setVisible(true);
}
}
- if (!isGroupChat || advancedMode || user.getAffiliation() == MucOptions.Affiliation.ADMIN) {
+ if (!isGroupChat
+ || advancedMode
+ || user.getAffiliation() == MucOptions.Affiliation.ADMIN) {
if (!user.getAffiliation().ranks(MucOptions.Affiliation.ADMIN)) {
managePermissionsVisible = true;
giveAdminPrivileges.setVisible(true);
@@ -122,10 +131,16 @@ public final class MucDetailsContextMenuHelper {
}
}
managePermissions.setVisible(managePermissionsVisible);
- sendPrivateMessage.setVisible(!isGroupChat && mucOptions.allowPm() && user.getRole().ranks(MucOptions.Role.VISITOR));
+ sendPrivateMessage.setVisible(
+ !isGroupChat
+ && mucOptions.allowPm()
+ && user.getRole().ranks(MucOptions.Role.VISITOR));
} else {
sendPrivateMessage.setVisible(true);
- sendPrivateMessage.setEnabled(user != null && mucOptions.allowPm() && user.getRole().ranks(MucOptions.Role.VISITOR));
+ sendPrivateMessage.setEnabled(
+ user != null
+ && mucOptions.allowPm()
+ && user.getRole().ranks(MucOptions.Role.VISITOR));
}
}
@@ -133,15 +148,20 @@ public final class MucDetailsContextMenuHelper {
return onContextItemSelected(item, user, activity, null);
}
- 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);
}
@@ -150,26 +170,32 @@ public final class MucDetailsContextMenuHelper {
startConversation(user, activity);
return true;
case R.id.give_admin_privileges:
- activity.xmppConnectionService.changeAffiliationInConference(conversation, jid, MucOptions.Affiliation.ADMIN, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation, jid, MucOptions.Affiliation.ADMIN, onAffiliationChanged);
return true;
case R.id.give_membership:
case R.id.remove_admin_privileges:
case R.id.revoke_owner_privileges:
- activity.xmppConnectionService.changeAffiliationInConference(conversation, jid, MucOptions.Affiliation.MEMBER, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation, jid, MucOptions.Affiliation.MEMBER, onAffiliationChanged);
return true;
case R.id.give_owner_privileges:
- activity.xmppConnectionService.changeAffiliationInConference(conversation, jid, MucOptions.Affiliation.OWNER, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation, jid, MucOptions.Affiliation.OWNER, onAffiliationChanged);
return true;
case R.id.remove_membership:
- activity.xmppConnectionService.changeAffiliationInConference(conversation, jid, MucOptions.Affiliation.NONE, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation, jid, MucOptions.Affiliation.NONE, onAffiliationChanged);
return true;
case R.id.remove_from_room:
removeFromRoom(user, activity, onAffiliationChanged);
return true;
case R.id.ban_from_conference:
- activity.xmppConnectionService.changeAffiliationInConference(conversation, jid, MucOptions.Affiliation.OUTCAST, onAffiliationChanged);
+ activity.xmppConnectionService.changeAffiliationInConference(
+ conversation, jid, MucOptions.Affiliation.OUTCAST, 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);
}
return true;
case R.id.send_private_message:
@@ -195,38 +221,61 @@ 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);
}
}
-}
+}
@@ -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<Map.Entry<float[], Long>> i = dots.entrySet().iterator(); i.hasNext();) {
+ for (final Iterator<Map.Entry<float[], Long>> i = dots.entrySet().iterator();
+ i.hasNext(); ) {
final Map.Entry<float[], Long> entry = i.next();
final long age = now - entry.getValue();
if (age < DOT_TTL_MS) {
@@ -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 {
}
}
}
-
}
@@ -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);
}
@@ -35,11 +35,11 @@ import java.util.List;
public class ImStyleParser {
- private final static List<Character> KEYWORDS = Arrays.asList('*', '_', '~', '`');
- private final static List<Character> NO_SUB_PARSING_KEYWORDS = Arrays.asList('`');
- private final static List<Character> BLOCK_KEYWORDS = Arrays.asList('`');
- private final static boolean ALLOW_EMPTY = false;
- private final static boolean PARSE_HIGHER_ORDER_END = true;
+ private static final List<Character> KEYWORDS = Arrays.asList('*', '_', '~', '`');
+ private static final List<Character> NO_SUB_PARSING_KEYWORDS = List.of('`');
+ private static final List<Character> BLOCK_KEYWORDS = List.of('`');
+ private static final boolean ALLOW_EMPTY = false;
+ private static final boolean PARSE_HIGHER_ORDER_END = true;
public static List<Style> parse(CharSequence text) {
return parse(text, 0, text.length() - 1);
@@ -49,7 +49,9 @@ public class ImStyleParser {
List<Style> styles = new ArrayList<>();
for (int i = start; i <= end; ++i) {
char c = text.charAt(i);
- if (KEYWORDS.contains(c) && precededByWhiteSpace(text, i, start) && !followedByWhitespace(text, i, end)) {
+ if (KEYWORDS.contains(c)
+ && precededByWhiteSpace(text, i, start)
+ && !followedByWhitespace(text, i, end)) {
if (BLOCK_KEYWORDS.contains(c) && isCharRepeatedTwoTimes(text, c, i + 1, end)) {
int to = seekEndBlock(text, c, i + 3, end);
if (to != -1 && (to != i + 5 || ALLOW_EMPTY)) {
@@ -91,7 +93,8 @@ public class ImStyleParser {
if (!PARSE_HIGHER_ORDER_END || followedByWhitespace(text, i, end)) {
return i;
} else {
- int higherOrder = seekHigherOrderEndWithoutNewBeginning(text, needle, i + 1, end);
+ int higherOrder =
+ seekHigherOrderEndWithoutNewBeginning(text, needle, i + 1, end);
if (higherOrder != -1) {
return higherOrder;
}
@@ -104,12 +107,17 @@ public class ImStyleParser {
return -1;
}
- private static int seekHigherOrderEndWithoutNewBeginning(CharSequence text, char needle, int start, int end) {
+ private static int seekHigherOrderEndWithoutNewBeginning(
+ CharSequence text, char needle, int start, int end) {
for (int i = start; i <= end; ++i) {
char c = text.charAt(i);
- if (c == needle && precededByWhiteSpace(text, i, start) && !followedByWhitespace(text, i, end)) {
+ if (c == needle
+ && precededByWhiteSpace(text, i, start)
+ && !followedByWhitespace(text, i, end)) {
return -1; // new beginning
- } else if (c == needle && !Character.isWhitespace(text.charAt(i - 1)) && followedByWhitespace(text, i, end)) {
+ } else if (c == needle
+ && !Character.isWhitespace(text.charAt(i - 1))
+ && followedByWhitespace(text, i, end)) {
return i;
} else if (c == '\n') {
return -1;
@@ -145,6 +145,11 @@ public final class MimeUtils {
add("application/vnd.sun.xml.writer.global", "sxg");
add("application/vnd.sun.xml.writer.template", "stw");
add("application/vnd.visio", "vsd");
+ // https://www.iana.org/assignments/media-types/application/vnd.tcpdump.pcap
+ add("application/vnd.tcpdump.pcap", "pcap");
+ add("application/vnd.tcpdump.pcap", "cap");
+ add("application/vnd.tcpdump.pcap", "dmp");
+ add("application/x-pcapng", "pcapng");
add("application/x-7z-compressed", "7z");
add("application/x-abiword", "abw");
add("application/x-apple-diskimage", "dmg");
@@ -425,8 +430,7 @@ public final class MimeUtils {
}
// mime types that are more reliant by path
- private static final Collection<String> PATH_PRECEDENCE_MIME_TYPE =
- Arrays.asList("audio/x-m4b");
+ private static final Collection<String> PATH_PRECEDENCE_MIME_TYPE = List.of("audio/x-m4b");
private static void add(String mimeType, String extension) {
// If we have an existing x -> y mapping, we do not want to
@@ -67,8 +67,7 @@ public class Avatar {
@Override
public boolean equals(Object object) {
- if (object != null && object instanceof Avatar) {
- Avatar other = (Avatar) object;
+ if (object != null && object instanceof Avatar other) {
return other.getFilename().equals(this.getFilename());
} else {
return false;
@@ -5,5 +5,5 @@ public enum Affiliation {
ADMIN,
MEMBER,
OUTCAST,
- NONE;
+ NONE
}
@@ -42,10 +42,7 @@ public abstract class Stanza extends StreamElement {
public boolean isInvalid() {
final var to = getTo();
final var from = getFrom();
- if (to instanceof Jid.Invalid || from instanceof Jid.Invalid) {
- return true;
- }
- return false;
+ return to instanceof Jid.Invalid || from instanceof Jid.Invalid;
}
public boolean fromServer(final Account account) {
@@ -1,5 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="48dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="48dp">
-
- <path android:fillColor="@android:color/white" android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM12.01,18c-0.7,0 -1.26,-0.56 -1.26,-1.26c0,-0.71 0.56,-1.25 1.26,-1.25c0.71,0 1.25,0.54 1.25,1.25C13.25,17.43 12.72,18 12.01,18zM15.02,10.6c-0.76,1.11 -1.48,1.46 -1.87,2.17c-0.16,0.29 -0.22,0.48 -0.22,1.41h-1.82c0,-0.49 -0.08,-1.29 0.31,-1.98c0.49,-0.87 1.42,-1.39 1.96,-2.16c0.57,-0.81 0.25,-2.33 -1.37,-2.33c-1.06,0 -1.58,0.8 -1.8,1.48L8.56,8.49C9.01,7.15 10.22,6 11.99,6c1.48,0 2.49,0.67 3.01,1.52C15.44,8.24 15.7,9.59 15.02,10.6z"/>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:autoMirrored="true"
+ android:tint="?colorControlNormal"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM12.01,18c-0.7,0 -1.26,-0.56 -1.26,-1.26c0,-0.71 0.56,-1.25 1.26,-1.25c0.71,0 1.25,0.54 1.25,1.25C13.25,17.43 12.72,18 12.01,18zM15.02,10.6c-0.76,1.11 -1.48,1.46 -1.87,2.17c-0.16,0.29 -0.22,0.48 -0.22,1.41h-1.82c0,-0.49 -0.08,-1.29 0.31,-1.98c0.49,-0.87 1.42,-1.39 1.96,-2.16c0.57,-0.81 0.25,-2.33 -1.37,-2.33c-1.06,0 -1.58,0.8 -1.8,1.48L8.56,8.49C9.01,7.15 10.22,6 11.99,6c1.48,0 2.49,0.67 3.01,1.52C15.44,8.24 15.7,9.59 15.02,10.6z" />
+
</vector>
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:tint="?colorControlNormal"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h8v-7h-3v-4h-5V9h3V2H8v7h3v2H6v4H3v7h8v-7H8v-2h8v2h-3V22zM10,7V4h4v3H10zM9,17v3H5v-3H9zM19,17v3h-4v-3H19z" />
+
+</vector>