Detailed changes
@@ -5,7 +5,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
-
import eu.siacs.conversations.xmpp.Jid;
public class AccountConfiguration {
@@ -17,7 +16,7 @@ public class AccountConfiguration {
public String password;
public Jid getJid() {
- return Jid.ofEscaped(address);
+ return Jid.of(address);
}
public static AccountConfiguration parse(final String input) {
@@ -27,24 +26,17 @@ public class AccountConfiguration {
} catch (JsonSyntaxException e) {
throw new IllegalArgumentException("Not a valid JSON string", e);
}
- Preconditions.checkArgument(
- c.protocol == Protocol.XMPP,
- "Protocol must be XMPP"
- );
+ Preconditions.checkArgument(c.protocol == Protocol.XMPP, "Protocol must be XMPP");
Preconditions.checkArgument(
c.address != null && c.getJid().isBareJid() && !c.getJid().isDomainJid(),
- "Invalid XMPP address"
- );
+ "Invalid XMPP address");
Preconditions.checkArgument(
- c.password != null && c.password.length() > 0,
- "No password specified"
- );
+ c.password != null && !c.password.isEmpty(), "No password specified");
return c;
}
public enum Protocol {
- @SerializedName("xmpp") XMPP,
+ @SerializedName("xmpp")
+ XMPP,
}
-
}
-
@@ -16,10 +16,8 @@ import android.os.Binder;
import android.os.IBinder;
import android.provider.OpenableColumns;
import android.util.Log;
-
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
-
import com.google.common.base.Charsets;
import com.google.common.base.Stopwatch;
import com.google.common.io.CountingInputStream;
@@ -27,7 +25,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
@@ -41,14 +38,6 @@ import eu.siacs.conversations.utils.BackupFileHeader;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.worker.ExportBackupWorker;
import eu.siacs.conversations.xmpp.Jid;
-
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.io.CipherInputStream;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
@@ -72,8 +61,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipException;
-
import javax.crypto.BadPaddingException;
+import org.bouncycastle.crypto.engines.AESEngine;
+import org.bouncycastle.crypto.io.CipherInputStream;
+import org.bouncycastle.crypto.modes.AEADBlockCipher;
+import org.bouncycastle.crypto.modes.GCMBlockCipher;
+import org.bouncycastle.crypto.params.AEADParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
public class ImportBackupService extends Service {
@@ -314,10 +308,11 @@ public class ImportBackupService extends Service {
final Jid jid = backupFileHeader.getJid();
final Cursor countCursor =
db.rawQuery(
- "select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?",
- new String[] {
- jid.getEscapedLocal(), jid.getDomain().toEscapedString()
- });
+ "select count(messages.uuid) from messages join conversations on"
+ + " conversations.uuid=messages.conversationUuid join accounts on"
+ + " conversations.accountUuid=accounts.uuid where"
+ + " accounts.username=? and accounts.server=?",
+ new String[] {jid.getLocal(), jid.getDomain().toString()});
countCursor.moveToFirst();
final int count = countCursor.getInt(0);
Log.d(
@@ -11,13 +11,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.color.MaterialColors;
import com.google.common.base.Strings;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityEasyInviteBinding;
@@ -153,7 +150,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity
}
final Intent launchIntent = getIntent();
final String accountExtra = launchIntent.getStringExtra(EXTRA_ACCOUNT);
- final Jid jid = accountExtra == null ? null : Jid.ofEscaped(accountExtra);
+ final Jid jid = accountExtra == null ? null : Jid.of(accountExtra);
if (jid == null) {
return;
}
@@ -163,7 +160,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity
public static void launch(final Account account, final Activity context) {
final Intent intent = new Intent(context, EasyOnboardingInviteActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
context.startActivity(intent);
}
@@ -7,9 +7,7 @@ import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Toast;
-
import androidx.databinding.DataBindingUtil;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityMagicCreateBinding;
@@ -17,7 +15,6 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.InstallReferrerUtils;
import eu.siacs.conversations.xmpp.Jid;
-
import java.security.SecureRandom;
public class MagicCreateActivity extends XmppActivity implements TextWatcher {
@@ -68,15 +65,15 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
final boolean fixedUsername;
if (this.domain != null && this.username != null) {
fixedUsername = true;
- jid = Jid.ofLocalAndDomainEscaped(this.username, this.domain);
+ jid = Jid.ofLocalAndDomain(this.username, this.domain);
} else if (this.domain != null) {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
} else {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
}
- if (!jid.getEscapedLocal().equals(jid.getLocal())
+ if (!jid.getLocal().equals(jid.getLocal())
|| (this.username == null && username.length() < 3)) {
binding.usernameLayout.setError(getString(R.string.invalid_username));
binding.username.requestFocus();
@@ -146,12 +143,11 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
binding.fullJid.setVisibility(View.VISIBLE);
final Jid jid;
if (this.domain == null) {
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
} else {
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
}
- binding.fullJid.setText(
- getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
+ binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toString()));
binding.usernameLayout.setError(null);
} catch (final IllegalArgumentException e) {
binding.fullJid.setVisibility(View.INVISIBLE);
@@ -17,13 +17,10 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.databinding.DataBindingUtil;
-
import com.google.common.base.Strings;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityManageAccountsBinding;
@@ -34,12 +31,10 @@ import eu.siacs.conversations.ui.adapter.AccountAdapter;
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
-
-import org.openintents.openpgp.util.OpenPgpApi;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.openintents.openpgp.util.OpenPgpApi;
public class ManageAccountActivity extends XmppActivity
implements OnAccountUpdate,
@@ -95,7 +90,7 @@ public class ManageAccountActivity extends XmppActivity
String jid = savedInstanceState.getString(STATE_SELECTED_ACCOUNT);
if (jid != null) {
try {
- this.selectedAccountJid = Jid.ofEscaped(jid);
+ this.selectedAccountJid = Jid.of(jid);
} catch (IllegalArgumentException e) {
this.selectedAccountJid = null;
}
@@ -113,7 +108,7 @@ public class ManageAccountActivity extends XmppActivity
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
if (selectedAccount != null) {
savedInstanceState.putString(
- STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toEscapedString());
+ STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toString());
}
super.onSaveInstanceState(savedInstanceState);
}
@@ -132,7 +127,7 @@ public class ManageAccountActivity extends XmppActivity
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
}
- menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toEscapedString());
+ menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toString());
}
@Override
@@ -297,7 +292,7 @@ public class ManageAccountActivity extends XmppActivity
private void publishAvatar(Account account) {
Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
startActivity(intent);
}
@@ -357,7 +352,8 @@ public class ManageAccountActivity extends XmppActivity
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
- + ": quick start disabled. account will regain this capability on the next connect");
+ + ": quick start disabled. account will regain this capability on the"
+ + " next connect");
}
if (!xmppConnectionService.updateAccount(account)) {
Toast.makeText(this, R.string.unable_to_update_account, Toast.LENGTH_SHORT).show();
@@ -1,5 +1,8 @@
package eu.siacs.conversations.ui;
+import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
+import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
+
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
@@ -12,14 +15,10 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
-
-import java.util.Arrays;
-import java.util.List;
-
+import com.google.common.base.Strings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
@@ -30,11 +29,8 @@ import eu.siacs.conversations.utils.InstallReferrerUtils;
import eu.siacs.conversations.utils.SignupUtils;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
-
-import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
-import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
-
-import com.google.common.base.Strings;
+import java.util.Arrays;
+import java.util.List;
public class WelcomeActivity extends XmppActivity
implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
@@ -196,7 +192,7 @@ public class WelcomeActivity extends XmppActivity
@Override
public void onAccountCreated(final Account account) {
final Intent intent = new Intent(this, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", account.getJid().asBareJid().toString());
intent.putExtra("init", true);
addInviteUri(intent);
startActivity(intent);
@@ -3,15 +3,13 @@ package eu.siacs.conversations.utils;
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
-
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.AccountConfiguration;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.EditAccountActivity;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.List;
public class ProvisioningUtils {
@@ -20,7 +18,8 @@ public class ProvisioningUtils {
try {
accountConfiguration = AccountConfiguration.parse(json);
} catch (final IllegalArgumentException e) {
- Toast.makeText(activity, R.string.improperly_formatted_provisioning, Toast.LENGTH_LONG).show();
+ Toast.makeText(activity, R.string.improperly_formatted_provisioning, Toast.LENGTH_LONG)
+ .show();
return;
}
final Jid jid = accountConfiguration.getJid();
@@ -31,13 +30,12 @@ public class ProvisioningUtils {
}
final Intent serviceIntent = new Intent(activity, XmppConnectionService.class);
serviceIntent.setAction(XmppConnectionService.ACTION_PROVISION_ACCOUNT);
- serviceIntent.putExtra("address", jid.asBareJid().toEscapedString());
+ serviceIntent.putExtra("address", jid.asBareJid().toString());
serviceIntent.putExtra("password", accountConfiguration.password);
Compatibility.startService(activity, serviceIntent);
final Intent intent = new Intent(activity, EditAccountActivity.class);
- intent.putExtra("jid", jid.asBareJid().toEscapedString());
+ intent.putExtra("jid", jid.asBareJid().toString());
intent.putExtra("init", true);
activity.startActivity(intent);
}
-
}
@@ -2,7 +2,6 @@ package eu.siacs.conversations.utils;
import android.app.Activity;
import android.content.Intent;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
@@ -21,13 +20,14 @@ public class SignupUtils {
return true;
}
- public static Intent getTokenRegistrationIntent(final Activity activity, Jid jid, String preAuth) {
+ public static Intent getTokenRegistrationIntent(
+ final Activity activity, Jid jid, String preAuth) {
final Intent intent = new Intent(activity, MagicCreateActivity.class);
if (jid.isDomainJid()) {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
} else {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
- intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getEscapedLocal());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
+ intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getLocal());
}
intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preAuth);
return intent;
@@ -55,7 +55,9 @@ public class SignupUtils {
intent = new Intent(activity, EditAccountActivity.class);
intent.putExtra("jid", pendingAccount.getJid().asBareJid().toString());
if (!pendingAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
- intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, pendingAccount.isOptionSet(Account.OPTION_REGISTER));
+ intent.putExtra(
+ EditAccountActivity.EXTRA_FORCE_REGISTER,
+ pendingAccount.isOptionSet(Account.OPTION_REGISTER));
}
} else {
if (service.getAccounts().size() == 0) {
@@ -74,4 +76,4 @@ public class SignupUtils {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent;
}
-}
+}
@@ -1,10 +1,8 @@
package eu.siacs.conversations.crypto.sasl;
import android.util.Base64;
-
-import javax.net.ssl.SSLSocket;
-
import eu.siacs.conversations.entities.Account;
+import javax.net.ssl.SSLSocket;
public class External extends SaslMechanism {
@@ -27,6 +25,6 @@ public class External extends SaslMechanism {
@Override
public String getClientFirstMessage(final SSLSocket sslSocket) {
return Base64.encodeToString(
- account.getJid().asBareJid().toEscapedString().getBytes(), Base64.NO_WRAP);
+ account.getJid().asBareJid().toString().getBytes(), Base64.NO_WRAP);
}
}
@@ -268,7 +268,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
}
public String getUsername() {
- return jid.getEscapedLocal();
+ return jid.getLocal();
}
public boolean setJid(final Jid next) {
@@ -292,7 +292,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
}
public String getServer() {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
public String getPassword() {
@@ -508,7 +508,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
final ContentValues values = new ContentValues();
values.put(UUID, uuid);
values.put(USERNAME, jid.getLocal());
- values.put(SERVER, jid.getDomain().toEscapedString());
+ values.put(SERVER, jid.getDomain().toString());
values.put(PASSWORD, password);
values.put(OPTIONS, options);
synchronized (this.keys) {
@@ -698,11 +698,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
public String getShareableUri() {
List<XmppUri.Fingerprint> fingerprints = this.getFingerprints();
- String uri = "xmpp:" + this.getJid().asBareJid().toEscapedString();
- if (fingerprints.size() > 0) {
- return XmppUri.getFingerprintUri(uri, fingerprints, ';');
- } else {
+ final String uri = "xmpp:" + this.getJid().asBareJid().toString();
+ if (fingerprints.isEmpty()) {
return uri;
+ } else {
+ return XmppUri.getFingerprintUri(uri, fingerprints, ';');
}
}
@@ -710,11 +710,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
List<XmppUri.Fingerprint> fingerprints = this.getFingerprints();
String uri =
"https://conversations.im/i/"
- + XmppUri.lameUrlEncode(this.getJid().asBareJid().toEscapedString());
- if (fingerprints.size() > 0) {
- return XmppUri.getFingerprintUri(uri, fingerprints, '&');
- } else {
+ + XmppUri.lameUrlEncode(this.getJid().asBareJid().toString());
+ if (fingerprints.isEmpty()) {
return uri;
+ } else {
+ return XmppUri.getFingerprintUri(uri, fingerprints, '&');
}
}
@@ -1,13 +1,15 @@
package eu.siacs.conversations.entities;
import android.content.Context;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
-
+import eu.siacs.conversations.utils.StringUtils;
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
+import eu.siacs.conversations.xmpp.Jid;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashMap;
@@ -15,265 +17,260 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-import eu.siacs.conversations.utils.StringUtils;
-import eu.siacs.conversations.utils.UIHelper;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
-import eu.siacs.conversations.xmpp.Jid;
-
public class Bookmark extends Element implements ListItem {
- private final Account account;
- private WeakReference<Conversation> conversation;
- private Jid jid;
- protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2);
-
- public Bookmark(final Account account, final Jid jid) {
- super("conference");
- this.jid = jid;
- this.setAttribute("jid", jid);
- this.account = account;
- }
-
- private Bookmark(Account account) {
- super("conference");
- this.account = account;
- }
-
- public static Map<Jid, Bookmark> parseFromStorage(Element storage, Account account) {
- if (storage == null) {
- return Collections.emptyMap();
- }
- final HashMap<Jid, Bookmark> bookmarks = new HashMap<>();
- for (final Element item : storage.getChildren()) {
- if (item.getName().equals("conference")) {
- final Bookmark bookmark = Bookmark.parse(item, account);
- if (bookmark != null) {
- final Bookmark old = bookmarks.put(bookmark.jid, bookmark);
- if (old != null && old.getBookmarkName() != null && bookmark.getBookmarkName() == null) {
- bookmark.setBookmarkName(old.getBookmarkName());
- }
- }
- }
- }
- return bookmarks;
- }
-
- public static Map<Jid, Bookmark> parseFromPubSub(final Element pubSub, final Account account) {
- if (pubSub == null) {
- return Collections.emptyMap();
- }
- final Element items = pubSub.findChild("items");
- if (items != null && Namespace.BOOKMARKS2.equals(items.getAttribute("node"))) {
- final Map<Jid, Bookmark> bookmarks = new HashMap<>();
- for(Element item : items.getChildren()) {
- if (item.getName().equals("item")) {
- final Bookmark bookmark = Bookmark.parseFromItem(item, account);
- if (bookmark != null) {
- bookmarks.put(bookmark.jid, bookmark);
- }
- }
- }
- return bookmarks;
- }
- return Collections.emptyMap();
- }
-
- public static Bookmark parse(Element element, Account account) {
- Bookmark bookmark = new Bookmark(account);
- bookmark.setAttributes(element.getAttributes());
- bookmark.setChildren(element.getChildren());
- bookmark.jid = InvalidJid.getNullForInvalid(bookmark.getAttributeAsJid("jid"));
- if (bookmark.jid == null) {
- return null;
- }
- return bookmark;
- }
-
- public static Bookmark parseFromItem(Element item, Account account) {
- final Element conference = item.findChild("conference", Namespace.BOOKMARKS2);
- if (conference == null) {
- return null;
- }
- final Bookmark bookmark = new Bookmark(account);
- bookmark.jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("id"));
- // TODO verify that we only use bare jids and ignore full jids
- if (bookmark.jid == null) {
- return null;
- }
- bookmark.setBookmarkName(conference.getAttribute("name"));
- bookmark.setAutojoin(conference.getAttributeAsBoolean("autojoin"));
- bookmark.setNick(conference.findChildContent("nick"));
- bookmark.setPassword(conference.findChildContent("password"));
- final Element extensions = conference.findChild("extensions", Namespace.BOOKMARKS2);
- if (extensions != null) {
- bookmark.extensions = extensions;
- }
- return bookmark;
- }
-
- public Element getExtensions() {
- return extensions;
- }
-
- public void setAutojoin(boolean autojoin) {
- if (autojoin) {
- this.setAttribute("autojoin", "true");
- } else {
- this.setAttribute("autojoin", "false");
- }
- }
-
- @Override
- public int compareTo(final @NonNull ListItem another) {
- return this.getDisplayName().compareToIgnoreCase(
- another.getDisplayName());
- }
-
- @Override
- public String getDisplayName() {
- final Conversation c = getConversation();
- final String name = getBookmarkName();
- if (c != null) {
- return c.getName().toString();
- } else if (printableValue(name, false)) {
- return name.trim();
- } else {
- Jid jid = this.getJid();
- return jid != null && jid.getLocal() != null ? jid.getLocal() : "";
- }
- }
-
- public static boolean printableValue(@Nullable String value, boolean permitNone) {
- return value != null && !value.trim().isEmpty() && (permitNone || !"None".equals(value));
- }
-
- public static boolean printableValue(@Nullable String value) {
- return printableValue(value, true);
- }
-
- @Override
- public Jid getJid() {
- return this.jid;
- }
-
- public Jid getFullJid() {
- final String nick = Strings.nullToEmpty(getNick()).trim();
- if (jid == null || nick.isEmpty()) {
- return jid;
- }
- try {
- return jid.withResource(nick);
- } catch (final IllegalArgumentException e) {
- return jid;
- }
- }
-
- @Override
- public List<Tag> getTags(final Context context) {
- final ImmutableList.Builder<Tag> tags = new ImmutableList.Builder<>();
- for (final Element element : getChildren()) {
- final String content = element.getContent();
- if (Strings.isNullOrEmpty(content)) {
- continue;
- }
- if (element.getName().equals("group")) {
- tags.add(new Tag(content));
- }
- }
- return tags.build();
- }
-
- public String getNick() {
- return Strings.emptyToNull(this.findChildContent("nick"));
- }
-
- public void setNick(String nick) {
- Element element = this.findChild("nick");
- if (element == null) {
- element = this.addChild("nick");
- }
- element.setContent(nick);
- }
-
- public boolean autojoin() {
- return this.getAttributeAsBoolean("autojoin");
- }
-
- public String getPassword() {
- return this.findChildContent("password");
- }
-
- public void setPassword(String password) {
- Element element = this.findChild("password");
- if (element != null) {
- element.setContent(password);
- }
- }
-
- @Override
- public boolean match(Context context, String needle) {
- if (needle == null) {
- return true;
- }
- needle = needle.toLowerCase(Locale.US);
- final Jid jid = getJid();
- return (jid != null && jid.toString().contains(needle)) ||
- getDisplayName().toLowerCase(Locale.US).contains(needle) ||
- matchInTag(context, needle);
- }
-
- private boolean matchInTag(Context context, String needle) {
- needle = needle.toLowerCase(Locale.US);
- for (Tag tag : getTags(context)) {
- if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
- return true;
- }
- }
- return false;
- }
-
- public Account getAccount() {
- return this.account;
- }
-
- public synchronized Conversation getConversation() {
- return this.conversation != null ? this.conversation.get() : null;
- }
-
- public synchronized void setConversation(Conversation conversation) {
- if (this.conversation != null) {
- this.conversation.clear();
- }
- if (conversation == null) {
- this.conversation = null;
- } else {
- this.conversation = new WeakReference<>(conversation);
- }
- }
-
- public String getBookmarkName() {
- return this.getAttribute("name");
- }
-
- public boolean setBookmarkName(String name) {
- String before = getBookmarkName();
- if (name != null) {
- this.setAttribute("name", name);
- } else {
- this.removeAttribute("name");
- }
- return StringUtils.changed(before, name);
- }
-
- @Override
- public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
- }
-
- @Override
- public String getAvatarName() {
- return getDisplayName();
- }
+ private final Account account;
+ private WeakReference<Conversation> conversation;
+ private Jid jid;
+ protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2);
+
+ public Bookmark(final Account account, final Jid jid) {
+ super("conference");
+ this.jid = jid;
+ this.setAttribute("jid", jid);
+ this.account = account;
+ }
+
+ private Bookmark(Account account) {
+ super("conference");
+ this.account = account;
+ }
+
+ public static Map<Jid, Bookmark> parseFromStorage(Element storage, Account account) {
+ if (storage == null) {
+ return Collections.emptyMap();
+ }
+ final HashMap<Jid, Bookmark> bookmarks = new HashMap<>();
+ for (final Element item : storage.getChildren()) {
+ if (item.getName().equals("conference")) {
+ final Bookmark bookmark = Bookmark.parse(item, account);
+ if (bookmark != null) {
+ final Bookmark old = bookmarks.put(bookmark.jid, bookmark);
+ if (old != null
+ && old.getBookmarkName() != null
+ && bookmark.getBookmarkName() == null) {
+ bookmark.setBookmarkName(old.getBookmarkName());
+ }
+ }
+ }
+ }
+ return bookmarks;
+ }
+
+ public static Map<Jid, Bookmark> parseFromPubSub(final Element pubSub, final Account account) {
+ if (pubSub == null) {
+ return Collections.emptyMap();
+ }
+ final Element items = pubSub.findChild("items");
+ if (items != null && Namespace.BOOKMARKS2.equals(items.getAttribute("node"))) {
+ final Map<Jid, Bookmark> bookmarks = new HashMap<>();
+ for (Element item : items.getChildren()) {
+ if (item.getName().equals("item")) {
+ final Bookmark bookmark = Bookmark.parseFromItem(item, account);
+ if (bookmark != null) {
+ bookmarks.put(bookmark.jid, bookmark);
+ }
+ }
+ }
+ return bookmarks;
+ }
+ return Collections.emptyMap();
+ }
+
+ public static Bookmark parse(Element element, Account account) {
+ Bookmark bookmark = new Bookmark(account);
+ bookmark.setAttributes(element.getAttributes());
+ bookmark.setChildren(element.getChildren());
+ bookmark.jid = Jid.Invalid.getNullForInvalid(bookmark.getAttributeAsJid("jid"));
+ if (bookmark.jid == null) {
+ return null;
+ }
+ return bookmark;
+ }
+
+ public static Bookmark parseFromItem(Element item, Account account) {
+ final Element conference = item.findChild("conference", Namespace.BOOKMARKS2);
+ if (conference == null) {
+ return null;
+ }
+ final Bookmark bookmark = new Bookmark(account);
+ bookmark.jid = Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("id"));
+ // TODO verify that we only use bare jids and ignore full jids
+ if (bookmark.jid == null) {
+ return null;
+ }
+ bookmark.setBookmarkName(conference.getAttribute("name"));
+ bookmark.setAutojoin(conference.getAttributeAsBoolean("autojoin"));
+ bookmark.setNick(conference.findChildContent("nick"));
+ bookmark.setPassword(conference.findChildContent("password"));
+ final Element extensions = conference.findChild("extensions", Namespace.BOOKMARKS2);
+ if (extensions != null) {
+ bookmark.extensions = extensions;
+ }
+ return bookmark;
+ }
+
+ public Element getExtensions() {
+ return extensions;
+ }
+
+ public void setAutojoin(boolean autojoin) {
+ if (autojoin) {
+ this.setAttribute("autojoin", "true");
+ } else {
+ this.setAttribute("autojoin", "false");
+ }
+ }
+
+ @Override
+ public int compareTo(final @NonNull ListItem another) {
+ return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
+ }
+
+ @Override
+ public String getDisplayName() {
+ final Conversation c = getConversation();
+ final String name = getBookmarkName();
+ if (c != null) {
+ return c.getName().toString();
+ } else if (printableValue(name, false)) {
+ return name.trim();
+ } else {
+ Jid jid = this.getJid();
+ return jid != null && jid.getLocal() != null ? jid.getLocal() : "";
+ }
+ }
+
+ public static boolean printableValue(@Nullable String value, boolean permitNone) {
+ return value != null && !value.trim().isEmpty() && (permitNone || !"None".equals(value));
+ }
+
+ public static boolean printableValue(@Nullable String value) {
+ return printableValue(value, true);
+ }
+
+ @Override
+ public Jid getJid() {
+ return this.jid;
+ }
+
+ public Jid getFullJid() {
+ final String nick = Strings.nullToEmpty(getNick()).trim();
+ if (jid == null || nick.isEmpty()) {
+ return jid;
+ }
+ try {
+ return jid.withResource(nick);
+ } catch (final IllegalArgumentException e) {
+ return jid;
+ }
+ }
+
+ @Override
+ public List<Tag> getTags(final Context context) {
+ final ImmutableList.Builder<Tag> tags = new ImmutableList.Builder<>();
+ for (final Element element : getChildren()) {
+ final String content = element.getContent();
+ if (Strings.isNullOrEmpty(content)) {
+ continue;
+ }
+ if (element.getName().equals("group")) {
+ tags.add(new Tag(content));
+ }
+ }
+ return tags.build();
+ }
+
+ public String getNick() {
+ return Strings.emptyToNull(this.findChildContent("nick"));
+ }
+
+ public void setNick(String nick) {
+ Element element = this.findChild("nick");
+ if (element == null) {
+ element = this.addChild("nick");
+ }
+ element.setContent(nick);
+ }
+
+ public boolean autojoin() {
+ return this.getAttributeAsBoolean("autojoin");
+ }
+
+ public String getPassword() {
+ return this.findChildContent("password");
+ }
+
+ public void setPassword(String password) {
+ Element element = this.findChild("password");
+ if (element != null) {
+ element.setContent(password);
+ }
+ }
+
+ @Override
+ public boolean match(Context context, String needle) {
+ if (needle == null) {
+ return true;
+ }
+ needle = needle.toLowerCase(Locale.US);
+ final Jid jid = getJid();
+ return (jid != null && jid.toString().contains(needle))
+ || getDisplayName().toLowerCase(Locale.US).contains(needle)
+ || matchInTag(context, needle);
+ }
+
+ private boolean matchInTag(Context context, String needle) {
+ needle = needle.toLowerCase(Locale.US);
+ for (Tag tag : getTags(context)) {
+ if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Account getAccount() {
+ return this.account;
+ }
+
+ public synchronized Conversation getConversation() {
+ return this.conversation != null ? this.conversation.get() : null;
+ }
+
+ public synchronized void setConversation(Conversation conversation) {
+ if (this.conversation != null) {
+ this.conversation.clear();
+ }
+ if (conversation == null) {
+ this.conversation = null;
+ } else {
+ this.conversation = new WeakReference<>(conversation);
+ }
+ }
+
+ public String getBookmarkName() {
+ return this.getAttribute("name");
+ }
+
+ public boolean setBookmarkName(String name) {
+ String before = getBookmarkName();
+ if (name != null) {
+ this.setAttribute("name", name);
+ } else {
+ this.removeAttribute("name");
+ }
+ return StringUtils.changed(before, name);
+ }
+
+ @Override
+ public int getAvatarBackgroundColor() {
+ return UIHelper.getColorForName(
+ jid != null ? jid.asBareJid().toString() : getDisplayName());
+ }
+
+ @Override
+ public String getAvatarName() {
+ return getDisplayName();
+ }
}
@@ -5,22 +5,8 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.Strings;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.android.AbstractPhoneContact;
import eu.siacs.conversations.android.JabberIdContact;
@@ -31,6 +17,15 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import eu.siacs.conversations.xmpp.pep.Avatar;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
public class Contact implements ListItem, Blockable {
public static final String TABLENAME = "contacts";
@@ -69,10 +64,21 @@ public class Contact implements ListItem, Blockable {
private String mLastPresence = null;
private RtpCapability.Capability rtpCapability;
- public Contact(final String account, final String systemName, final String serverName, final String presenceName,
- final Jid jid, final int subscription, final String photoUri,
- final Uri systemAccount, final String keys, final String avatar, final long lastseen,
- final String presence, final String groups, final RtpCapability.Capability rtpCapability) {
+ public Contact(
+ final String account,
+ final String systemName,
+ final String serverName,
+ final String presenceName,
+ final Jid jid,
+ final int subscription,
+ final String photoUri,
+ final Uri systemAccount,
+ final String keys,
+ final String avatar,
+ final long lastseen,
+ final String presence,
+ final String groups,
+ final RtpCapability.Capability rtpCapability) {
this.accountUuid = account;
this.systemName = systemName;
this.serverName = serverName;
@@ -91,7 +97,7 @@ public class Contact implements ListItem, Blockable {
if (avatar != null) {
this.avatar = new Avatar();
this.avatar.sha1sum = avatar;
- this.avatar.origin = Avatar.Origin.VCARD; //always assume worst
+ this.avatar.origin = Avatar.Origin.VCARD; // always assume worst
}
try {
this.groups = (groups == null ? new JSONArray() : new JSONArray(groups));
@@ -122,7 +128,8 @@ public class Contact implements ListItem, Blockable {
} catch (Exception e) {
systemAccount = null;
}
- return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
+ return new Contact(
+ cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(PRESENCE_NAME)),
@@ -135,7 +142,8 @@ public class Contact implements ListItem, Blockable {
cursor.getLong(cursor.getColumnIndex(LAST_TIME)),
cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)),
cursor.getString(cursor.getColumnIndex(GROUPS)),
- RtpCapability.Capability.of(cursor.getString(cursor.getColumnIndex(RTP_CAPABILITY))));
+ RtpCapability.Capability.of(
+ cursor.getString(cursor.getColumnIndex(RTP_CAPABILITY))));
}
public String getDisplayName() {
@@ -151,12 +159,15 @@ public class Contact implements ListItem, Blockable {
return this.systemName;
} else if (!TextUtils.isEmpty(this.serverName)) {
return this.serverName;
- } else if (!TextUtils.isEmpty(this.presenceName) && ((QuickConversationsService.isQuicksy() && JidHelper.isQuicksyDomain(jid.getDomain())) || mutualPresenceSubscription())) {
+ } else if (!TextUtils.isEmpty(this.presenceName)
+ && ((QuickConversationsService.isQuicksy()
+ && JidHelper.isQuicksyDomain(jid.getDomain()))
+ || mutualPresenceSubscription())) {
return this.presenceName;
} else if (jid.getLocal() != null) {
return JidHelper.localPartOrFallback(jid);
} else {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
}
@@ -166,7 +177,7 @@ public class Contact implements ListItem, Blockable {
} else if (jid.getLocal() != null) {
return JidHelper.localPartOrFallback(jid);
} else {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
}
@@ -201,9 +212,9 @@ public class Contact implements ListItem, Blockable {
}
return true;
} else {
- return jid.toString().contains(needle) ||
- getDisplayName().toLowerCase(Locale.US).contains(needle) ||
- matchInTag(context, needle);
+ return jid.toString().contains(needle)
+ || getDisplayName().toLowerCase(Locale.US).contains(needle)
+ || matchInTag(context, needle);
}
}
@@ -354,8 +365,8 @@ public class Contact implements ListItem, Blockable {
}
public boolean showInRoster() {
- return (this.getOption(Contact.Options.IN_ROSTER) && (!this
- .getOption(Contact.Options.DIRTY_DELETE)))
+ return (this.getOption(Contact.Options.IN_ROSTER)
+ && (!this.getOption(Contact.Options.DIRTY_DELETE)))
|| (this.getOption(Contact.Options.DIRTY_PUSH));
}
@@ -430,12 +441,11 @@ public class Contact implements ListItem, Blockable {
@Override
public int compareTo(@NonNull final ListItem another) {
- return this.getDisplayName().compareToIgnoreCase(
- another.getDisplayName());
+ return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
}
public String getServer() {
- return getJid().getDomain().toEscapedString();
+ return getJid().getDomain().toString();
}
public void setAvatar(Avatar avatar) {
@@ -446,7 +456,10 @@ public class Contact implements ListItem, Blockable {
if (this.avatar != null && this.avatar.equals(avatar)) {
return;
}
- if (!previouslyOmittedPepFetch && this.avatar != null && this.avatar.origin == Avatar.Origin.PEP && avatar.origin == Avatar.Origin.VCARD) {
+ if (!previouslyOmittedPepFetch
+ && this.avatar != null
+ && this.avatar.origin == Avatar.Origin.PEP
+ && avatar.origin == Avatar.Origin.VCARD) {
return;
}
this.avatar = avatar;
@@ -561,7 +574,8 @@ public class Contact implements ListItem, Blockable {
@Override
public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
+ return UIHelper.getColorForName(
+ jid != null ? jid.asBareJid().toString() : getDisplayName());
}
@Override
@@ -137,8 +137,7 @@ public class Conversation extends AbstractEntity
cursor.getString(cursor.getColumnIndexOrThrow(NAME)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTACT)),
cursor.getString(cursor.getColumnIndexOrThrow(ACCOUNT)),
- JidHelper.parseOrFallbackToInvalid(
- cursor.getString(cursor.getColumnIndexOrThrow(CONTACTJID))),
+ Jid.ofOrInvalid(cursor.getString(cursor.getColumnIndexOrThrow(CONTACTJID))),
cursor.getLong(cursor.getColumnIndexOrThrow(CREATED)),
cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)),
cursor.getInt(cursor.getColumnIndexOrThrow(MODE)),
@@ -1,14 +1,10 @@
package eu.siacs.conversations.entities;
-import android.text.TextUtils;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.services.AvatarService;
@@ -21,7 +17,6 @@ import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.forms.Field;
import eu.siacs.conversations.xmpp.pep.Avatar;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -68,7 +63,8 @@ public class MucOptions {
public boolean setSelf(User user) {
this.self = user;
final boolean roleChanged = this.conversation.setAttribute("role", user.role.toString());
- final boolean affiliationChanged = this.conversation.setAttribute("affiliation", user.affiliation.toString());
+ final boolean affiliationChanged =
+ this.conversation.setAttribute("affiliation", user.affiliation.toString());
return roleChanged || affiliationChanged;
}
@@ -123,21 +119,30 @@ public class MucOptions {
final var identities = serviceDiscoveryResult.getIdentities();
final String identityName = !identities.isEmpty() ? identities.get(0).getName() : null;
final Jid jid = conversation.getJid();
- if (identityName != null && !identityName.equals(jid == null ? null : jid.getEscapedLocal())) {
+ if (identityName != null && !identityName.equals(jid == null ? null : jid.getLocal())) {
name = identityName;
} else {
name = null;
}
}
boolean changed = conversation.setAttribute("muc_name", name);
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
return changed;
}
private Data getRoomInfoForm() {
- final List<Data> forms = serviceDiscoveryResult == null ? Collections.emptyList() : serviceDiscoveryResult.forms;
+ final List<Data> forms =
+ serviceDiscoveryResult == null
+ ? Collections.emptyList()
+ : serviceDiscoveryResult.forms;
return forms.isEmpty() ? new Data() : forms.get(0);
}
@@ -146,7 +151,8 @@ public class MucOptions {
}
public boolean hasFeature(String feature) {
- return this.serviceDiscoveryResult != null && this.serviceDiscoveryResult.features.contains(feature);
+ return this.serviceDiscoveryResult != null
+ && this.serviceDiscoveryResult.features.contains(feature);
}
public boolean hasVCards() {
@@ -154,7 +160,8 @@ public class MucOptions {
}
public boolean canInvite() {
- final boolean hasPermission = !membersOnly() || self.getRole().ranks(Role.MODERATOR) || allowInvites();
+ final boolean hasPermission =
+ !membersOnly() || self.getRole().ranks(Role.MODERATOR) || allowInvites();
return hasPermission && online();
}
@@ -177,7 +184,7 @@ public class MucOptions {
public boolean allowPm() {
final Field field = getRoomInfoForm().getFieldByName("muc#roomconfig_allowpm");
if (field == null) {
- return true; //fall back if field does not exists
+ return true; // fall back if field does not exists
}
if ("anyone".equals(field.getValue())) {
return true;
@@ -192,7 +199,7 @@ public class MucOptions {
public boolean allowPmRaw() {
final Field field = getRoomInfoForm().getFieldByName("muc#roomconfig_allowpm");
- return field == null || Arrays.asList("anyone","participants").contains(field.getValue());
+ return field == null || Arrays.asList("anyone", "participants").contains(field.getValue());
}
public boolean participating() {
@@ -204,7 +211,9 @@ public class MucOptions {
}
public List<String> getFeatures() {
- return this.serviceDiscoveryResult != null ? this.serviceDiscoveryResult.features : Collections.emptyList();
+ return this.serviceDiscoveryResult != null
+ ? this.serviceDiscoveryResult.features
+ : Collections.emptyList();
}
public boolean nonanonymous() {
@@ -240,7 +249,8 @@ public class MucOptions {
break;
}
}
- boolean self = user.realJid != null && user.realJid.equals(account.getJid().asBareJid());
+ boolean self =
+ user.realJid != null && user.realJid.equals(account.getJid().asBareJid());
if (membersOnly()
&& nonanonymous()
&& user.affiliation.ranks(Affiliation.MEMBER)
@@ -257,7 +267,7 @@ public class MucOptions {
return user;
}
- //returns true if real jid was new;
+ // returns true if real jid was new;
public boolean updateUser(User user) {
User old;
boolean realJidFound = false;
@@ -266,7 +276,7 @@ public class MucOptions {
realJidFound = old != null;
if (old != null) {
if (old.fullJid != null) {
- return false; //don't add. user already exists
+ return false; // don't add. user already exists
} else {
synchronized (users) {
users.remove(old);
@@ -288,7 +298,10 @@ public class MucOptions {
if (old != null) {
users.remove(old);
}
- boolean fullJidIsSelf = isOnline && user.getFullJid() != null && user.getFullJid().equals(self.getFullJid());
+ boolean fullJidIsSelf =
+ isOnline
+ && user.getFullJid() != null
+ && user.getFullJid().equals(self.getFullJid());
if ((!membersOnly() || user.getAffiliation().ranks(Affiliation.MEMBER))
&& user.getAffiliation().outranks(Affiliation.OUTCAST)
&& !fullJidIsSelf) {
@@ -329,7 +342,9 @@ public class MucOptions {
public User findUserByOccupantId(final String occupantId) {
synchronized (this.users) {
- return Strings.isNullOrEmpty(occupantId) ? null : Iterables.find(this.users, u -> occupantId.equals(u.occupantId),null);
+ return Strings.isNullOrEmpty(occupantId)
+ ? null
+ : Iterables.find(this.users, u -> occupantId.equals(u.occupantId), null);
}
}
@@ -345,7 +360,8 @@ public class MucOptions {
public User findUser(ReadByMarker readByMarker) {
if (readByMarker.getRealJid() != null) {
- return findOrCreateUserByRealJid(readByMarker.getRealJid().asBareJid(), readByMarker.getFullJid());
+ return findOrCreateUserByRealJid(
+ readByMarker.getRealJid().asBareJid(), readByMarker.getFullJid());
} else if (readByMarker.getFullJid() != null) {
return findUserByFullJid(readByMarker.getFullJid());
} else {
@@ -361,7 +377,7 @@ public class MucOptions {
if (existing != null) {
return existing;
} else if (reaction.from != null) {
- return new User(this,reaction.from);
+ return new User(this, reaction.from);
} else {
return null;
}
@@ -369,7 +385,7 @@ public class MucOptions {
public List<User> findUsers(final Collection<Reaction> reactions) {
final ImmutableList.Builder<User> builder = new ImmutableList.Builder<>();
- for(final Reaction reaction : reactions) {
+ for (final Reaction reaction : reactions) {
final var user = findUser(reaction);
if (user != null) {
builder.add(user);
@@ -400,7 +416,8 @@ public class MucOptions {
synchronized (users) {
ArrayList<User> users = new ArrayList<>();
for (User user : this.users) {
- if (!user.isDomain() && (includeOffline || user.getRole().ranks(Role.PARTICIPANT))) {
+ if (!user.isDomain()
+ && (includeOffline || user.getRole().ranks(Role.PARTICIPANT))) {
users.add(user);
}
}
@@ -429,7 +446,8 @@ public class MucOptions {
jids.add(account.getJid().asBareJid());
synchronized (users) {
for (User user : users) {
- if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
+ if (user.getRealJid() == null
+ || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
subset.add(user);
}
if (subset.size() >= max) {
@@ -445,7 +463,8 @@ public class MucOptions {
HashSet<Jid> jids = new HashSet<>();
for (User user : users) {
jids.add(user.getAccount().getJid().asBareJid());
- if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
+ if (user.getRealJid() == null
+ || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
subset.add(user);
}
if (subset.size() >= max) {
@@ -477,7 +496,8 @@ public class MucOptions {
public String getProposedNickPure() {
final Bookmark bookmark = this.conversation.getBookmark();
- final String bookmarkedNick = normalize(account.getJid(), bookmark == null ? null : bookmark.getNick());
+ final String bookmarkedNick =
+ normalize(account.getJid(), bookmark == null ? null : bookmark.getNick());
if (bookmarkedNick != null) {
return bookmarkedNick;
} else {
@@ -503,7 +523,6 @@ public class MucOptions {
} catch (final IllegalArgumentException e) {
return null;
}
-
}
public String getActualNick() {
@@ -649,7 +668,8 @@ public class MucOptions {
public String getPassword() {
this.password = conversation.getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
- if (this.password == null && conversation.getBookmark() != null
+ if (this.password == null
+ && conversation.getBookmark() != null
&& conversation.getBookmark().getPassword() != null) {
return conversation.getBookmark().getPassword();
} else {
@@ -674,7 +694,12 @@ public class MucOptions {
ArrayList<Jid> members = new ArrayList<>();
synchronized (users) {
for (User user : users) {
- if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null && !user.realJid.asBareJid().equals(conversation.account.getJid().asBareJid()) && (!user.isDomain() || includeDomains)) {
+ if (user.affiliation.ranks(Affiliation.MEMBER)
+ && user.realJid != null
+ && !user.realJid
+ .asBareJid()
+ .equals(conversation.account.getJid().asBareJid())
+ && (!user.isDomain() || includeDomains)) {
members.add(user.realJid);
}
}
@@ -790,9 +815,7 @@ public class MucOptions {
void onFailure();
}
- public interface OnRenameListener extends OnEventListener {
-
- }
+ public interface OnRenameListener extends OnEventListener {}
public static class User implements Comparable<User>, AvatarService.Avatarable {
private Role role = Role.NONE;
@@ -867,7 +890,10 @@ public class MucOptions {
if (avatar != null) {
return avatar.getFilename();
}
- Avatar avatar = realJid != null ? getAccount().getRoster().getContact(realJid).getAvatar() : null;
+ Avatar avatar =
+ realJid != null
+ ? getAccount().getRoster().getContact(realJid).getAvatar()
+ : null;
return avatar == null ? null : avatar.getFilename();
}
@@ -895,7 +921,6 @@ public class MucOptions {
if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
return false;
return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
-
}
public boolean isDomain() {
@@ -913,7 +938,13 @@ public class MucOptions {
@Override
public String toString() {
- return "[fulljid:" + fullJid + ",realjid:" + realJid + ",affiliation" + affiliation.toString() + "]";
+ return "[fulljid:"
+ + fullJid
+ + ",realjid:"
+ + realJid
+ + ",affiliation"
+ + affiliation.toString()
+ + "]";
}
public boolean realJidMatchesAccount() {
@@ -2,14 +2,12 @@ package eu.siacs.conversations.entities;
import android.content.Context;
import android.text.TextUtils;
-
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xmpp.Jid;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import eu.siacs.conversations.utils.UIHelper;
-import eu.siacs.conversations.xmpp.Jid;
-
public class RawBlockable implements ListItem, Blockable {
private final Account account;
@@ -40,7 +38,7 @@ public class RawBlockable implements ListItem, Blockable {
if (jid.isFullJid()) {
return jid.getResource();
} else {
- return jid.toEscapedString();
+ return jid.toString();
}
}
@@ -62,7 +60,7 @@ public class RawBlockable implements ListItem, Blockable {
needle = needle.toLowerCase(Locale.US).trim();
String[] parts = needle.split("\\s+");
for (String part : parts) {
- if (!jid.toEscapedString().contains(part)) {
+ if (!jid.toString().contains(part)) {
return false;
}
}
@@ -76,7 +74,7 @@ public class RawBlockable implements ListItem, Blockable {
@Override
public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid.toEscapedString());
+ return UIHelper.getColorForName(jid.toString());
}
@Override
@@ -86,7 +84,6 @@ public class RawBlockable implements ListItem, Blockable {
@Override
public int compareTo(ListItem o) {
- return this.getDisplayName().compareToIgnoreCase(
- o.getDisplayName());
+ return this.getDisplayName().compareToIgnoreCase(o.getDisplayName());
}
-}
+}
@@ -1,9 +1,7 @@
package eu.siacs.conversations.entities;
import android.util.Log;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
@@ -20,11 +18,9 @@ import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.xmpp.Jid;
-
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
@@ -137,7 +133,7 @@ public class Reaction {
if (value == null) {
out.nullValue();
} else {
- out.value(value.toEscapedString());
+ out.value(value.toString());
}
}
@@ -148,7 +144,7 @@ public class Reaction {
return null;
} else if (in.peek() == JsonToken.STRING) {
final String value = in.nextString();
- return Jid.ofEscaped(value);
+ return Jid.of(value);
}
throw new IOException("Unexpected token");
}
@@ -3,7 +3,6 @@ package eu.siacs.conversations.entities;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
-
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.utils.LanguageUtils;
import eu.siacs.conversations.utils.UIHelper;
@@ -25,9 +24,7 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
this.nusers = nusers;
}
- public Room() {
-
- }
+ public Room() {}
public String getName() {
return name;
@@ -52,7 +49,7 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
@Override
public int getAvatarBackgroundColor() {
Jid room = getRoom();
- return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name);
+ return UIHelper.getColorForName(room != null ? room.asBareJid().toString() : name);
}
@Override
@@ -65,9 +62,9 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Room room = (Room) o;
- return Objects.equal(address, room.address) &&
- Objects.equal(name, room.name) &&
- Objects.equal(description, room.description);
+ return Objects.equal(address, room.address)
+ && Objects.equal(name, room.name)
+ && Objects.equal(description, room.description);
}
@Override
@@ -75,7 +72,6 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
return Objects.hashCode(address, name, description);
}
-
public boolean contains(String needle) {
return Strings.nullToEmpty(name).contains(needle)
|| Strings.nullToEmpty(description).contains(needle)
@@ -90,4 +86,4 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
.compare(Strings.nullToEmpty(address), Strings.nullToEmpty(o.address))
.result();
}
-}
+}
@@ -1,25 +1,8 @@
package eu.siacs.conversations.generator;
-
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
-
-import org.whispersystems.libsignal.IdentityKey;
-import org.whispersystems.libsignal.ecc.ECPublicKey;
-import org.whispersystems.libsignal.state.PreKeyRecord;
-import org.whispersystems.libsignal.state.SignedPreKeyRecord;
-
-import java.nio.ByteBuffer;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.UUID;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@@ -35,6 +18,19 @@ import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.pep.Avatar;
import im.conversations.android.xmpp.model.stanza.Iq;
+import java.nio.ByteBuffer;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.UUID;
+import org.whispersystems.libsignal.IdentityKey;
+import org.whispersystems.libsignal.ecc.ECPublicKey;
+import org.whispersystems.libsignal.state.PreKeyRecord;
+import org.whispersystems.libsignal.state.SignedPreKeyRecord;
public class IqGenerator extends AbstractGenerator {
@@ -152,7 +148,7 @@ public class IqGenerator extends AbstractGenerator {
final Element pubsub = packet.addChild("pubsub", Namespace.PUBSUB);
final Element retract = pubsub.addChild("retract");
retract.setAttribute("node", node);
- retract.setAttribute("notify","true");
+ retract.setAttribute("notify", "true");
retract.addChild("item").setAttribute("id", id);
return packet;
}
@@ -165,7 +161,8 @@ public class IqGenerator extends AbstractGenerator {
return publish(Namespace.AVATAR_DATA, item, options);
}
- public Iq publishElement(final String namespace, final Element element, String id, final Bundle options) {
+ public Iq publishElement(
+ final String namespace, final Element element, String id, final Bundle options) {
final Element item = new Element("item");
item.setAttribute("id", id);
item.addChild(element);
@@ -175,8 +172,7 @@ public class IqGenerator extends AbstractGenerator {
public Iq publishAvatarMetadata(final Avatar avatar, final Bundle options) {
final Element item = new Element("item");
item.setAttribute("id", avatar.sha1sum);
- final Element metadata = item
- .addChild("metadata", Namespace.AVATAR_METADATA);
+ final Element metadata = item.addChild("metadata", Namespace.AVATAR_METADATA);
final Element info = metadata.addChild("info");
info.setAttribute("bytes", avatar.size);
info.setAttribute("id", avatar.sha1sum);
@@ -263,7 +259,7 @@ public class IqGenerator extends AbstractGenerator {
if (password != null) {
conference.addChild("password").setContent(password);
}
- conference.setAttribute("autojoin",String.valueOf(autojoin));
+ conference.setAttribute("autojoin", String.valueOf(autojoin));
conference.addChild(bookmark.getExtensions());
return conference;
}
@@ -286,8 +282,12 @@ public class IqGenerator extends AbstractGenerator {
return displayed;
}
- public Iq publishBundles(final SignedPreKeyRecord signedPreKeyRecord, final IdentityKey identityKey,
- final Set<PreKeyRecord> preKeyRecords, final int deviceId, Bundle publishOptions) {
+ public Iq publishBundles(
+ final SignedPreKeyRecord signedPreKeyRecord,
+ final IdentityKey identityKey,
+ final Set<PreKeyRecord> preKeyRecords,
+ final int deviceId,
+ Bundle publishOptions) {
final Element item = new Element("item");
item.setAttribute("id", "current");
final Element bundle = item.addChild("bundle", AxolotlService.PEP_PREFIX);
@@ -296,21 +296,26 @@ public class IqGenerator extends AbstractGenerator {
ECPublicKey publicKey = signedPreKeyRecord.getKeyPair().getPublicKey();
signedPreKeyPublic.setContent(Base64.encodeToString(publicKey.serialize(), Base64.NO_WRAP));
final Element signedPreKeySignature = bundle.addChild("signedPreKeySignature");
- signedPreKeySignature.setContent(Base64.encodeToString(signedPreKeyRecord.getSignature(), Base64.NO_WRAP));
+ signedPreKeySignature.setContent(
+ Base64.encodeToString(signedPreKeyRecord.getSignature(), Base64.NO_WRAP));
final Element identityKeyElement = bundle.addChild("identityKey");
- identityKeyElement.setContent(Base64.encodeToString(identityKey.serialize(), Base64.NO_WRAP));
+ identityKeyElement.setContent(
+ Base64.encodeToString(identityKey.serialize(), Base64.NO_WRAP));
final Element prekeys = bundle.addChild("prekeys", AxolotlService.PEP_PREFIX);
for (PreKeyRecord preKeyRecord : preKeyRecords) {
final Element prekey = prekeys.addChild("preKeyPublic");
prekey.setAttribute("preKeyId", preKeyRecord.getId());
- prekey.setContent(Base64.encodeToString(preKeyRecord.getKeyPair().getPublicKey().serialize(), Base64.NO_WRAP));
+ prekey.setContent(
+ Base64.encodeToString(
+ preKeyRecord.getKeyPair().getPublicKey().serialize(), Base64.NO_WRAP));
}
return publish(AxolotlService.PEP_BUNDLES + ":" + deviceId, item, publishOptions);
}
- public Iq publishVerification(byte[] signature, X509Certificate[] certificates, final int deviceId) {
+ public Iq publishVerification(
+ byte[] signature, X509Certificate[] certificates, final int deviceId) {
final Element item = new Element("item");
item.setAttribute("id", "current");
final Element verification = item.addChild("verification", AxolotlService.PEP_PREFIX);
@@ -318,13 +323,16 @@ public class IqGenerator extends AbstractGenerator {
for (int i = 0; i < certificates.length; ++i) {
try {
Element certificate = chain.addChild("certificate");
- certificate.setContent(Base64.encodeToString(certificates[i].getEncoded(), Base64.NO_WRAP));
+ certificate.setContent(
+ Base64.encodeToString(certificates[i].getEncoded(), Base64.NO_WRAP));
certificate.setAttribute("index", i);
} catch (CertificateEncodingException e) {
Log.d(Config.LOGTAG, "could not encode certificate");
}
}
- verification.addChild("signature").setContent(Base64.encodeToString(signature, Base64.NO_WRAP));
+ verification
+ .addChild("signature")
+ .setContent(Base64.encodeToString(signature, Base64.NO_WRAP));
return publish(AxolotlService.PEP_VERIFICATION + ":" + deviceId, item);
}
@@ -337,7 +345,7 @@ public class IqGenerator extends AbstractGenerator {
if (mam.muc()) {
packet.setTo(mam.getWith());
} else if (mam.getWith() != null) {
- data.put("with", mam.getWith().toEscapedString());
+ data.put("with", mam.getWith().toString());
}
final long start = mam.getStart();
final long end = mam.getEnd();
@@ -366,7 +374,8 @@ public class IqGenerator extends AbstractGenerator {
return iq;
}
- public Iq generateSetBlockRequest(final Jid jid, final boolean reportSpam, final String serverMsgId) {
+ public Iq generateSetBlockRequest(
+ final Jid jid, final boolean reportSpam, final String serverMsgId) {
final Iq iq = new Iq(Iq.Type.SET);
final Element block = iq.addChild("block", Namespace.BLOCKING);
final Element item = block.addChild("item").setAttribute("jid", jid);
@@ -457,7 +466,9 @@ public class IqGenerator extends AbstractGenerator {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
- return Base64.encodeToString(bb.array(), Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP) + name.substring(pos);
+ return Base64.encodeToString(
+ bb.array(), Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP)
+ + name.substring(pos);
} catch (Exception e) {
return name;
}
@@ -466,7 +477,8 @@ public class IqGenerator extends AbstractGenerator {
}
}
- public static Iq generateCreateAccountWithCaptcha(final Account account, final String id, final Data data) {
+ public static Iq generateCreateAccountWithCaptcha(
+ final Account account, final String id, final Data data) {
final Iq register = new Iq(Iq.Type.SET);
register.setFrom(account.getJid().asBareJid());
register.setTo(account.getDomain());
@@ -492,7 +504,7 @@ public class IqGenerator extends AbstractGenerator {
data.put("token", token);
data.put("android-id", deviceId);
if (muc != null) {
- data.put("muc", muc.toEscapedString());
+ data.put("muc", muc.toString());
}
data.submit();
command.addChild(data);
@@ -539,7 +551,9 @@ public class IqGenerator extends AbstractGenerator {
public Iq queryAffiliation(Conversation conversation, String affiliation) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(conversation.getJid().asBareJid());
- packet.query("http://jabber.org/protocol/muc#admin").addChild("item").setAttribute("affiliation", affiliation);
+ packet.query("http://jabber.org/protocol/muc#admin")
+ .addChild("item")
+ .setAttribute("affiliation", affiliation);
return packet;
}
@@ -551,9 +565,9 @@ public class IqGenerator extends AbstractGenerator {
options.putString("muc#roomconfig_whois", "anyone");
options.putString("muc#roomconfig_changesubject", "0");
options.putString("muc#roomconfig_allowinvites", "0");
- options.putString("muc#roomconfig_enablearchiving", "1"); //prosody
- options.putString("mam", "1"); //ejabberd community
- options.putString("muc#roomconfig_mam", "1"); //ejabberd saas
+ options.putString("muc#roomconfig_enablearchiving", "1"); // prosody
+ options.putString("mam", "1"); // ejabberd community
+ options.putString("muc#roomconfig_mam", "1"); // ejabberd saas
return options;
}
@@ -564,9 +578,9 @@ public class IqGenerator extends AbstractGenerator {
options.putString("muc#roomconfig_publicroom", "1");
options.putString("muc#roomconfig_whois", "moderators");
options.putString("muc#roomconfig_changesubject", "0");
- options.putString("muc#roomconfig_enablearchiving", "1"); //prosody
- options.putString("mam", "1"); //ejabberd community
- options.putString("muc#roomconfig_mam", "1"); //ejabberd saas
+ options.putString("muc#roomconfig_enablearchiving", "1"); // prosody
+ options.putString("mam", "1"); // ejabberd community
+ options.putString("muc#roomconfig_mam", "1"); // ejabberd saas
return options;
}
@@ -592,14 +606,14 @@ public class IqGenerator extends AbstractGenerator {
public Iq queryDiscoItems(final Jid jid) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(jid);
- packet.addChild("query",Namespace.DISCO_ITEMS);
+ packet.addChild("query", Namespace.DISCO_ITEMS);
return packet;
}
public Iq queryDiscoInfo(final Jid jid) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(jid);
- packet.addChild("query",Namespace.DISCO_INFO);
+ packet.addChild("query", Namespace.DISCO_INFO);
return packet;
}
}
@@ -1,93 +1,93 @@
package eu.siacs.conversations.parser;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Stanza;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
public abstract class AbstractParser {
- protected final XmppConnectionService mXmppConnectionService;
- protected final Account account;
-
- protected AbstractParser(final XmppConnectionService service, final Account account) {
- this.mXmppConnectionService = service;
- this.account = account;
- }
-
- public static Long parseTimestamp(Element element, Long d) {
- return parseTimestamp(element,d,false);
- }
-
- public static Long parseTimestamp(Element element, Long d, boolean ignoreCsiAndSm) {
- long min = Long.MAX_VALUE;
- boolean returnDefault = true;
- final Jid to;
- if (ignoreCsiAndSm && element instanceof Stanza stanza) {
- to = stanza.getTo();
- } else {
- to = null;
- }
- for(Element child : element.getChildren()) {
- if ("delay".equals(child.getName()) && "urn:xmpp:delay".equals(child.getNamespace())) {
- final Jid f = to == null ? null : InvalidJid.getNullForInvalid(child.getAttributeAsJid("from"));
- if (f != null && (to.asBareJid().equals(f) || to.getDomain().equals(f))) {
- continue;
- }
- final String stamp = child.getAttribute("stamp");
- if (stamp != null) {
- try {
- min = Math.min(min,AbstractParser.parseTimestamp(stamp));
- returnDefault = false;
- } catch (Throwable t) {
- //ignore
- }
- }
- }
- }
- if (returnDefault) {
- return d;
- } else {
- return min;
- }
- }
-
- public static long parseTimestamp(Element element) {
- return parseTimestamp(element, System.currentTimeMillis());
- }
-
- public static long parseTimestamp(String timestamp) throws ParseException {
- timestamp = timestamp.replace("Z", "+0000");
- SimpleDateFormat dateFormat;
- long ms;
- if (timestamp.length() >= 25 && timestamp.charAt(19) == '.') {
- String millis = timestamp.substring(19,timestamp.length() - 5);
- try {
- double fractions = Double.parseDouble("0" + millis);
- ms = Math.round(1000 * fractions);
- } catch (NumberFormatException e) {
- ms = 0;
- }
- } else {
- ms = 0;
- }
- timestamp = timestamp.substring(0,19)+timestamp.substring(timestamp.length() -5);
- dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US);
- return Math.min(dateFormat.parse(timestamp).getTime()+ms, System.currentTimeMillis());
- }
+ protected final XmppConnectionService mXmppConnectionService;
+ protected final Account account;
+
+ protected AbstractParser(final XmppConnectionService service, final Account account) {
+ this.mXmppConnectionService = service;
+ this.account = account;
+ }
+
+ public static Long parseTimestamp(Element element, Long d) {
+ return parseTimestamp(element, d, false);
+ }
+
+ public static Long parseTimestamp(Element element, Long d, boolean ignoreCsiAndSm) {
+ long min = Long.MAX_VALUE;
+ boolean returnDefault = true;
+ final Jid to;
+ if (ignoreCsiAndSm && element instanceof Stanza stanza) {
+ to = stanza.getTo();
+ } else {
+ to = null;
+ }
+ for (Element child : element.getChildren()) {
+ if ("delay".equals(child.getName()) && "urn:xmpp:delay".equals(child.getNamespace())) {
+ final Jid f =
+ to == null
+ ? null
+ : Jid.Invalid.getNullForInvalid(child.getAttributeAsJid("from"));
+ if (f != null && (to.asBareJid().equals(f) || to.getDomain().equals(f))) {
+ continue;
+ }
+ final String stamp = child.getAttribute("stamp");
+ if (stamp != null) {
+ try {
+ min = Math.min(min, AbstractParser.parseTimestamp(stamp));
+ returnDefault = false;
+ } catch (Throwable t) {
+ // ignore
+ }
+ }
+ }
+ }
+ if (returnDefault) {
+ return d;
+ } else {
+ return min;
+ }
+ }
+
+ public static long parseTimestamp(Element element) {
+ return parseTimestamp(element, System.currentTimeMillis());
+ }
+
+ public static long parseTimestamp(String timestamp) throws ParseException {
+ timestamp = timestamp.replace("Z", "+0000");
+ SimpleDateFormat dateFormat;
+ long ms;
+ if (timestamp.length() >= 25 && timestamp.charAt(19) == '.') {
+ String millis = timestamp.substring(19, timestamp.length() - 5);
+ try {
+ double fractions = Double.parseDouble("0" + millis);
+ ms = Math.round(1000 * fractions);
+ } catch (NumberFormatException e) {
+ ms = 0;
+ }
+ } else {
+ ms = 0;
+ }
+ timestamp = timestamp.substring(0, 19) + timestamp.substring(timestamp.length() - 5);
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
+ return Math.min(dateFormat.parse(timestamp).getTime() + ms, System.currentTimeMillis());
+ }
public static long getTimestamp(final String input) throws ParseException {
if (input == null) {
@@ -120,93 +120,94 @@ public abstract class AbstractParser {
}
}
- protected void updateLastseen(final Account account, final Jid from) {
- final Contact contact = account.getRoster().getContact(from);
- contact.setLastResource(from.isBareJid() ? "" : from.getResource());
- }
-
- protected static String avatarData(Element items) {
- Element item = items.findChild("item");
- if (item == null) {
- return null;
- }
- return item.findChildContent("data", "urn:xmpp:avatar:data");
- }
-
- public static MucOptions.User parseItem(Conversation conference, Element item) {
- return parseItem(conference,item, null);
- }
-
- public static MucOptions.User parseItem(final Conversation conference, Element item, Jid fullJid) {
- final String local = conference.getJid().getLocal();
- final String domain = conference.getJid().getDomain().toEscapedString();
- String affiliation = item.getAttribute("affiliation");
- String role = item.getAttribute("role");
- String nick = item.getAttribute("nick");
- if (nick != null && fullJid == null) {
- try {
- fullJid = Jid.of(local, domain, nick);
- } catch (IllegalArgumentException e) {
- fullJid = null;
- }
- }
- final Jid realJid = item.getAttributeAsJid("jid");
- MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid);
- if (InvalidJid.isValid(realJid)) {
- user.setRealJid(realJid);
- }
- user.setAffiliation(affiliation);
- user.setRole(role);
- return user;
- }
-
- public static String extractErrorMessage(final Element packet) {
- final Element error = packet.findChild("error");
- if (error != null && error.getChildren().size() > 0) {
- final List<String> errorNames = orderedElementNames(error.getChildren());
- final String text = error.findChildContent("text");
- if (text != null && !text.trim().isEmpty()) {
- return prefixError(errorNames)+text;
- } else if (errorNames.size() > 0){
- return prefixError(errorNames)+errorNames.get(0).replace("-"," ");
- }
- }
- return null;
- }
-
- public static String errorMessage(Element packet) {
- final Element error = packet.findChild("error");
- if (error != null && error.getChildren().size() > 0) {
- final List<String> errorNames = orderedElementNames(error.getChildren());
- final String text = error.findChildContent("text");
- if (text != null && !text.trim().isEmpty()) {
- return text;
- } else if (errorNames.size() > 0){
- return errorNames.get(0).replace("-"," ");
- }
- }
- return null;
- }
-
- private static String prefixError(List<String> errorNames) {
- if (errorNames.size() > 0) {
- return errorNames.get(0)+'\u001f';
- }
- return "";
- }
-
- private static List<String> orderedElementNames(List<Element> children) {
- List<String> names = new ArrayList<>();
- for(Element child : children) {
- final String name = child.getName();
- if (name != null && !name.equals("text")) {
- if ("urn:ietf:params:xml:ns:xmpp-stanzas".equals(child.getNamespace())) {
- names.add(name);
- } else {
- names.add(0, name);
- }
- }
- }
- return names;
- }
+ protected void updateLastseen(final Account account, final Jid from) {
+ final Contact contact = account.getRoster().getContact(from);
+ contact.setLastResource(from.isBareJid() ? "" : from.getResource());
+ }
+
+ protected static String avatarData(Element items) {
+ Element item = items.findChild("item");
+ if (item == null) {
+ return null;
+ }
+ return item.findChildContent("data", "urn:xmpp:avatar:data");
+ }
+
+ public static MucOptions.User parseItem(Conversation conference, Element item) {
+ return parseItem(conference, item, null);
+ }
+
+ public static MucOptions.User parseItem(
+ final Conversation conference, Element item, Jid fullJid) {
+ final String local = conference.getJid().getLocal();
+ final String domain = conference.getJid().getDomain().toString();
+ String affiliation = item.getAttribute("affiliation");
+ String role = item.getAttribute("role");
+ String nick = item.getAttribute("nick");
+ if (nick != null && fullJid == null) {
+ try {
+ fullJid = Jid.of(local, domain, nick);
+ } catch (IllegalArgumentException e) {
+ fullJid = null;
+ }
+ }
+ final Jid realJid = item.getAttributeAsJid("jid");
+ MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid);
+ if (Jid.Invalid.isValid(realJid)) {
+ user.setRealJid(realJid);
+ }
+ user.setAffiliation(affiliation);
+ user.setRole(role);
+ return user;
+ }
+
+ public static String extractErrorMessage(final Element packet) {
+ final Element error = packet.findChild("error");
+ if (error != null && error.getChildren().size() > 0) {
+ final List<String> errorNames = orderedElementNames(error.getChildren());
+ final String text = error.findChildContent("text");
+ if (text != null && !text.trim().isEmpty()) {
+ return prefixError(errorNames) + text;
+ } else if (errorNames.size() > 0) {
+ return prefixError(errorNames) + errorNames.get(0).replace("-", " ");
+ }
+ }
+ return null;
+ }
+
+ public static String errorMessage(Element packet) {
+ final Element error = packet.findChild("error");
+ if (error != null && error.getChildren().size() > 0) {
+ final List<String> errorNames = orderedElementNames(error.getChildren());
+ final String text = error.findChildContent("text");
+ if (text != null && !text.trim().isEmpty()) {
+ return text;
+ } else if (errorNames.size() > 0) {
+ return errorNames.get(0).replace("-", " ");
+ }
+ }
+ return null;
+ }
+
+ private static String prefixError(List<String> errorNames) {
+ if (errorNames.size() > 0) {
+ return errorNames.get(0) + '\u001f';
+ }
+ return "";
+ }
+
+ private static List<String> orderedElementNames(List<Element> children) {
+ List<String> names = new ArrayList<>();
+ for (Element child : children) {
+ final String name = child.getName();
+ if (name != null && !name.equals("text")) {
+ if ("urn:ietf:params:xml:ns:xmpp-stanzas".equals(child.getNamespace())) {
+ names.add(name);
+ } else {
+ names.add(0, name);
+ }
+ }
+ }
+ return names;
+ }
}
@@ -3,31 +3,9 @@ package eu.siacs.conversations.parser;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;
-
-import org.whispersystems.libsignal.IdentityKey;
-import org.whispersystems.libsignal.InvalidKeyException;
-import org.whispersystems.libsignal.ecc.Curve;
-import org.whispersystems.libsignal.ecc.ECPublicKey;
-import org.whispersystems.libsignal.state.PreKeyBundle;
-
-import java.io.ByteArrayInputStream;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.entities.Account;
@@ -36,11 +14,27 @@ import eu.siacs.conversations.entities.Room;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.forms.Data;
import im.conversations.android.xmpp.model.stanza.Iq;
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import org.whispersystems.libsignal.IdentityKey;
+import org.whispersystems.libsignal.InvalidKeyException;
+import org.whispersystems.libsignal.ecc.Curve;
+import org.whispersystems.libsignal.ecc.ECPublicKey;
+import org.whispersystems.libsignal.state.PreKeyBundle;
public class IqParser extends AbstractParser implements Consumer<Iq> {
@@ -94,8 +88,7 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
TextUtils.isEmpty(roomName) ? name : roomName,
description,
language,
- nusers
- );
+ nusers);
}
private void rosterItems(final Account account, final Element query) {
@@ -105,14 +98,16 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
}
for (final Element item : query.getChildren()) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid = Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid == null) {
continue;
}
final String name = item.getAttribute("name");
final String subscription = item.getAttribute("subscription");
final Contact contact = account.getRoster().getContact(jid);
- boolean bothPre = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM);
+ boolean bothPre =
+ contact.getOption(Contact.Options.TO)
+ && contact.getOption(Contact.Options.FROM);
if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
contact.setServerName(name);
contact.parseGroupsFromElement(item);
@@ -126,9 +121,15 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
contact.resetOption(Contact.Options.DIRTY_PUSH);
contact.parseSubscriptionFromElement(item);
}
- boolean both = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM);
+ boolean both =
+ contact.getOption(Contact.Options.TO)
+ && contact.getOption(Contact.Options.FROM);
if ((both != bothPre) && both) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": gained mutual presence subscription with " + contact.getJid());
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid()
+ + ": gained mutual presence subscription with "
+ + contact.getJid());
AxolotlService axolotlService = account.getAxolotlService();
if (axolotlService != null) {
axolotlService.clearErrorsInFetchStatusMap(contact.getJid());
@@ -181,7 +182,15 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
Integer id = Integer.valueOf(device.getAttribute("id"));
deviceIds.add(id);
} catch (NumberFormatException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Encountered invalid <device> node in PEP (" + e.getMessage() + "):" + device.toString() + ", skipping...");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Encountered invalid <device> node in PEP ("
+ + e.getMessage()
+ + "):"
+ + device.toString()
+ + ", skipping...");
}
}
}
@@ -210,7 +219,12 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
try {
publicKey = Curve.decodePoint(base64decode(signedPreKeyPublic), 0);
} catch (final IllegalArgumentException | InvalidKeyException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid signedPreKeyPublic in PEP: " + e.getMessage());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid signedPreKeyPublic in PEP: "
+ + e.getMessage());
}
return publicKey;
}
@@ -223,7 +237,9 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
try {
return base64decode(signedPreKeySignature);
} catch (final IllegalArgumentException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : Invalid base64 in signedPreKeySignature");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX + " : Invalid base64 in signedPreKeySignature");
return null;
}
}
@@ -236,7 +252,12 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
try {
return new IdentityKey(base64decode(identityKey), 0);
} catch (final IllegalArgumentException | InvalidKeyException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid identityKey in PEP: " + e.getMessage());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid identityKey in PEP: "
+ + e.getMessage());
return null;
}
}
@@ -245,7 +266,12 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
Map<Integer, ECPublicKey> preKeyRecords = new HashMap<>();
Element item = getItem(packet);
if (item == null) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Couldn't find <item> in bundle IQ packet: " + packet);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Couldn't find <item> in bundle IQ packet: "
+ + packet);
return null;
}
final Element bundleElement = item.findChild("bundle");
@@ -254,12 +280,22 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
}
final Element prekeysElement = bundleElement.findChild("prekeys");
if (prekeysElement == null) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Couldn't find <prekeys> in bundle IQ packet: " + packet);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Couldn't find <prekeys> in bundle IQ packet: "
+ + packet);
return null;
}
for (Element preKeyPublicElement : prekeysElement.getChildren()) {
if (!preKeyPublicElement.getName().equals("preKeyPublic")) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Encountered unexpected tag in prekeys list: " + preKeyPublicElement);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Encountered unexpected tag in prekeys list: "
+ + preKeyPublicElement);
continue;
}
final String preKey = preKeyPublicElement.getContent();
@@ -272,9 +308,22 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
final ECPublicKey preKeyPublic = Curve.decodePoint(base64decode(preKey), 0);
preKeyRecords.put(preKeyId, preKeyPublic);
} catch (NumberFormatException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "could not parse preKeyId from preKey " + preKeyPublicElement.toString());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "could not parse preKeyId from preKey "
+ + preKeyPublicElement.toString());
} catch (Throwable e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid preKeyPublic (ID=" + preKeyId + ") in PEP: " + e.getMessage() + ", skipping...");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid preKeyPublic (ID="
+ + preKeyId
+ + ") in PEP: "
+ + e.getMessage()
+ + ", skipping...");
}
}
return preKeyRecords;
@@ -286,7 +335,8 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
public static Pair<X509Certificate[], byte[]> verification(final Iq packet) {
Element item = getItem(packet);
- Element verification = item != null ? item.findChild("verification", AxolotlService.PEP_PREFIX) : null;
+ Element verification =
+ item != null ? item.findChild("verification", AxolotlService.PEP_PREFIX) : null;
Element chain = verification != null ? verification.findChild("chain") : null;
String signature = verification != null ? verification.findChildContent("signature") : null;
if (chain != null && signature != null) {
@@ -300,7 +350,11 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
if (cert == null) {
continue;
}
- certificates[i] = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(BaseEncoding.base64().decode(cert)));
+ certificates[i] =
+ (X509Certificate)
+ certificateFactory.generateCertificate(
+ new ByteArrayInputStream(
+ BaseEncoding.base64().decode(cert)));
++i;
}
return new Pair<>(certificates, BaseEncoding.base64().decode(signature));
@@ -332,8 +386,15 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
|| signedPreKeySignature.length == 0) {
return null;
}
- return new PreKeyBundle(0, 0, 0, null,
- signedPreKeyId, signedPreKeyPublic, signedPreKeySignature, identityKey);
+ return new PreKeyBundle(
+ 0,
+ 0,
+ 0,
+ null,
+ signedPreKeyId,
+ signedPreKeyPublic,
+ signedPreKeySignature,
+ identityKey);
}
public static List<PreKeyBundle> preKeys(final Iq preKeys) {
@@ -342,8 +403,7 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
if (preKeyPublics != null) {
for (Integer preKeyId : preKeyPublics.keySet()) {
ECPublicKey preKeyPublic = preKeyPublics.get(preKeyId);
- bundles.add(new PreKeyBundle(0, 0, preKeyId, preKeyPublic,
- 0, null, null, null));
+ bundles.add(new PreKeyBundle(0, 0, preKeyId, preKeyPublic, 0, null, null, null));
}
}
@@ -363,15 +423,19 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
account.getRoster().markAllAsNotInRoster();
}
this.rosterItems(account, query);
- } else if ((packet.hasChild("block", Namespace.BLOCKING) || packet.hasChild("blocklist", Namespace.BLOCKING)) &&
- packet.fromServer(account)) {
+ } else if ((packet.hasChild("block", Namespace.BLOCKING)
+ || packet.hasChild("blocklist", Namespace.BLOCKING))
+ && packet.fromServer(account)) {
// Block list or block push.
Log.d(Config.LOGTAG, "Received blocklist update from server");
final Element blocklist = packet.findChild("blocklist", Namespace.BLOCKING);
final Element block = packet.findChild("block", Namespace.BLOCKING);
- final Collection<Element> items = blocklist != null ? blocklist.getChildren() :
- (block != null ? block.getChildren() : null);
- // If this is a response to a blocklist query, clear the block list and replace with the new one.
+ final Collection<Element> items =
+ blocklist != null
+ ? blocklist.getChildren()
+ : (block != null ? block.getChildren() : null);
+ // If this is a response to a blocklist query, clear the block list and replace with the
+ // new one.
// Otherwise, just update the existing blocklist.
if (packet.getType() == Iq.Type.RESULT) {
account.clearBlocklist();
@@ -382,7 +446,8 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
// Create a collection of Jids from the packet
for (final Element item : items) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid =
+ Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid != null) {
jids.add(jid);
}
@@ -405,10 +470,12 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
final Iq response = packet.generateResponse(Iq.Type.RESULT);
mXmppConnectionService.sendIqPacket(account, response, null);
}
- } else if (packet.hasChild("unblock", Namespace.BLOCKING) &&
- packet.fromServer(account) && packet.getType() == Iq.Type.SET) {
+ } else if (packet.hasChild("unblock", Namespace.BLOCKING)
+ && packet.fromServer(account)
+ && packet.getType() == Iq.Type.SET) {
Log.d(Config.LOGTAG, "Received unblock update from server");
- final Collection<Element> items = packet.findChild("unblock", Namespace.BLOCKING).getChildren();
+ final Collection<Element> items =
+ packet.findChild("unblock", Namespace.BLOCKING).getChildren();
if (items.isEmpty()) {
// No children to unblock == unblock all
account.getBlocklist().clear();
@@ -416,7 +483,8 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
final Collection<Jid> jids = new ArrayList<>(items.size());
for (final Element item : items) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid =
+ Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid != null) {
jids.add(jid);
}
@@ -430,10 +498,10 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
} else if (packet.hasChild("open", "http://jabber.org/protocol/ibb")
|| packet.hasChild("data", "http://jabber.org/protocol/ibb")
|| packet.hasChild("close", "http://jabber.org/protocol/ibb")) {
- mXmppConnectionService.getJingleConnectionManager()
- .deliverIbbPacket(account, packet);
+ mXmppConnectionService.getJingleConnectionManager().deliverIbbPacket(account, packet);
} else if (packet.hasChild("query", "http://jabber.org/protocol/disco#info")) {
- final Iq response = mXmppConnectionService.getIqGenerator().discoResponse(account, packet);
+ final Iq response =
+ mXmppConnectionService.getIqGenerator().discoResponse(account, packet);
mXmppConnectionService.sendIqPacket(account, response, null);
} else if (packet.hasChild("query", "jabber:iq:version") && isGet) {
final Iq response = mXmppConnectionService.getIqGenerator().versionResponse(packet);
@@ -452,7 +520,8 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
response = mXmppConnectionService.getIqGenerator().entityTimeResponse(packet);
}
mXmppConnectionService.sendIqPacket(account, response, null);
- } else if (packet.hasChild("push", Namespace.UNIFIED_PUSH) && packet.getType() == Iq.Type.SET) {
+ } else if (packet.hasChild("push", Namespace.UNIFIED_PUSH)
+ && packet.getType() == Iq.Type.SET) {
final Jid transport = packet.getFrom();
final Element push = packet.findChild("push", Namespace.UNIFIED_PUSH);
final boolean success =
@@ -480,5 +549,4 @@ public class IqParser extends AbstractParser implements Consumer<Iq> {
}
}
}
-
}
@@ -31,7 +31,6 @@ import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.LocalizedContent;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
@@ -95,7 +94,7 @@ public class MessageParser extends AbstractParser
for (Element child : packet.getChildren()) {
if (child.getName().equals("stanza-id")
&& Namespace.STANZA_IDS.equals(child.getNamespace())
- && by.equals(InvalidJid.getNullForInvalid(child.getAttributeAsJid("by")))) {
+ && by.equals(Jid.Invalid.getNullForInvalid(child.getAttributeAsJid("by")))) {
return child.getAttribute("id");
}
}
@@ -105,7 +104,7 @@ public class MessageParser extends AbstractParser
private static Jid getTrueCounterpart(Element mucUserElement, Jid fallback) {
final Element item = mucUserElement == null ? null : mucUserElement.findChild("item");
Jid result =
- item == null ? null : InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ item == null ? null : Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
return result != null ? result : fallback;
}
@@ -154,7 +153,7 @@ public class MessageParser extends AbstractParser
final XmppAxolotlMessage xmppAxolotlMessage;
try {
xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.asBareJid());
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.d(
Config.LOGTAG,
conversation.getAccount().getJid().asBareJid()
@@ -224,13 +223,13 @@ public class MessageParser extends AbstractParser
final Element invite = mucUser.findChild("invite");
if (invite != null) {
final String password = mucUser.findChildContent("password");
- final Jid from = InvalidJid.getNullForInvalid(invite.getAttributeAsJid("from"));
- final Jid to = InvalidJid.getNullForInvalid(invite.getAttributeAsJid("to"));
+ final Jid from = Jid.Invalid.getNullForInvalid(invite.getAttributeAsJid("from"));
+ final Jid to = Jid.Invalid.getNullForInvalid(invite.getAttributeAsJid("to"));
if (to != null && from == null) {
Log.d(Config.LOGTAG, "do not parse outgoing mediated invite " + message);
return null;
}
- final Jid room = InvalidJid.getNullForInvalid(message.getAttributeAsJid("from"));
+ final Jid room = Jid.Invalid.getNullForInvalid(message.getAttributeAsJid("from"));
if (room == null) {
return null;
}
@@ -239,8 +238,8 @@ public class MessageParser extends AbstractParser
}
final Element conference = message.findChild("x", "jabber:x:conference");
if (conference != null) {
- Jid from = InvalidJid.getNullForInvalid(message.getAttributeAsJid("from"));
- Jid room = InvalidJid.getNullForInvalid(conference.getAttributeAsJid("jid"));
+ Jid from = Jid.Invalid.getNullForInvalid(message.getAttributeAsJid("from"));
+ Jid room = Jid.Invalid.getNullForInvalid(conference.getAttributeAsJid("jid"));
if (room == null) {
return null;
}
@@ -333,7 +332,7 @@ public class MessageParser extends AbstractParser
}
}
if (retract != null) {
- final Jid id = InvalidJid.getNullForInvalid(retract.getAttributeAsJid("id"));
+ final Jid id = Jid.Invalid.getNullForInvalid(retract.getAttributeAsJid("id"));
if (id != null) {
account.removeBookmark(id);
Log.d(
@@ -567,7 +566,7 @@ public class MessageParser extends AbstractParser
}
boolean notify = false;
- if (from == null || !InvalidJid.isValid(from) || !InvalidJid.isValid(to)) {
+ if (from == null || !Jid.Invalid.isValid(from) || !Jid.Invalid.isValid(to)) {
Log.e(Config.LOGTAG, "encountered invalid message from='" + from + "' to='" + to + "'");
return;
}
@@ -607,7 +606,7 @@ public class MessageParser extends AbstractParser
occupant = null;
}
boolean isMucStatusMessage =
- InvalidJid.hasValidFrom(packet)
+ Jid.Invalid.hasValidFrom(packet)
&& from.isBareJid()
&& mucUserElement != null
&& mucUserElement.hasChild("status");
@@ -668,7 +667,7 @@ public class MessageParser extends AbstractParser
|| mucUserElement != null
|| account.getXmppConnection()
.getMucServersWithholdAccount()
- .contains(counterpart.getDomain().toEscapedString());
+ .contains(counterpart.getDomain().toString());
final Conversation conversation =
mXmppConnectionService.findOrCreateConversation(
account,
@@ -1161,7 +1160,7 @@ public class MessageParser extends AbstractParser
}
if (conversation != null
&& mucUserElement != null
- && InvalidJid.hasValidFrom(packet)
+ && Jid.Invalid.hasValidFrom(packet)
&& from.isBareJid()) {
for (Element child : mucUserElement.getChildren()) {
if ("status".equals(child.getName())) {
@@ -1381,7 +1380,7 @@ public class MessageParser extends AbstractParser
final Element event =
original.findChild("event", "http://jabber.org/protocol/pubsub#event");
- if (event != null && InvalidJid.hasValidFrom(original) && original.getFrom().isBareJid()) {
+ if (event != null && Jid.Invalid.hasValidFrom(original) && original.getFrom().isBareJid()) {
if (event.hasChild("items")) {
parseEvent(event, original.getFrom(), account);
} else if (event.hasChild("delete")) {
@@ -1392,7 +1391,7 @@ public class MessageParser extends AbstractParser
}
final String nick = packet.findChildContent("nick", Namespace.NICK);
- if (nick != null && InvalidJid.hasValidFrom(original)) {
+ if (nick != null && Jid.Invalid.hasValidFrom(original)) {
if (mXmppConnectionService.isMuc(account, from)) {
return;
}
@@ -1444,7 +1443,7 @@ public class MessageParser extends AbstractParser
Jid from) {
final var id = displayed.getId();
// TODO we don’t even use 'sender' any more. Remove this!
- final Jid sender = InvalidJid.getNullForInvalid(displayed.getAttributeAsJid("sender"));
+ final Jid sender = Jid.Invalid.getNullForInvalid(displayed.getAttributeAsJid("sender"));
if (packet.fromAccount(account) && !selfAddressed) {
final Conversation c = mXmppConnectionService.find(account, counterpart.asBareJid());
final Message message =
@@ -1,7 +1,6 @@
package eu.siacs.conversations.parser;
import android.util.Log;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@@ -17,24 +16,23 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import im.conversations.android.xmpp.model.occupant.OccupantId;
-
-import org.openintents.openpgp.util.OpenPgpUtils;
-
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
+import org.openintents.openpgp.util.OpenPgpUtils;
-public class PresenceParser extends AbstractParser implements Consumer<im.conversations.android.xmpp.model.stanza.Presence> {
+public class PresenceParser extends AbstractParser
+ implements Consumer<im.conversations.android.xmpp.model.stanza.Presence> {
public PresenceParser(final XmppConnectionService service, final Account account) {
super(service, account);
}
- public void parseConferencePresence(final im.conversations.android.xmpp.model.stanza.Presence packet, Account account) {
+ public void parseConferencePresence(
+ final im.conversations.android.xmpp.model.stanza.Presence packet, Account account) {
final Conversation conversation =
packet.getFrom() == null
? null
@@ -58,7 +56,9 @@ public class PresenceParser extends AbstractParser implements Consumer<im.conver
}
}
- private void processConferencePresence(final im.conversations.android.xmpp.model.stanza.Presence packet, Conversation conversation) {
+ private void processConferencePresence(
+ final im.conversations.android.xmpp.model.stanza.Presence packet,
+ Conversation conversation) {
final Account account = conversation.getAccount();
final MucOptions mucOptions = conversation.getMucOptions();
final Jid jid = conversation.getAccount().getJid();
@@ -75,12 +75,15 @@ public class PresenceParser extends AbstractParser implements Consumer<im.conver
mucOptions.setError(MucOptions.Error.NONE);
final MucOptions.User user = parseItem(conversation, item, from);
final var occupant = packet.getExtension(OccupantId.class);
- final String occupantId = mucOptions.occupantId() && occupant != null ? occupant.getId() : null;
+ final String occupantId =
+ mucOptions.occupantId() && occupant != null
+ ? occupant.getId()
+ : null;
user.setOccupantId(occupantId);
if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE)
|| (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED)
&& jid.equals(
- InvalidJid.getNullForInvalid(
+ Jid.Invalid.getNullForInvalid(
item.getAttributeAsJid("jid"))))) {
if (mucOptions.setOnline()) {
mXmppConnectionService.getAvatarService().clear(mucOptions);
@@ -91,7 +94,8 @@ public class PresenceParser extends AbstractParser implements Consumer<im.conver
mXmppConnectionService.databaseBackend.updateConversation(
conversation);
}
- final var modified = current == null || !current.equals(user.getFullJid());
+ final var modified =
+ current == null || !current.equals(user.getFullJid());
mXmppConnectionService.persistSelfNick(user, modified);
invokeRenameListener(mucOptions, true);
}
@@ -166,7 +170,7 @@ public class PresenceParser extends AbstractParser implements Consumer<im.conver
final Jid alternate =
destroy == null
? null
- : InvalidJid.getNullForInvalid(
+ : Jid.Invalid.getNullForInvalid(
destroy.getAttributeAsJid("jid"));
mucOptions.setError(MucOptions.Error.DESTROYED);
if (alternate != null) {
@@ -301,7 +305,9 @@ public class PresenceParser extends AbstractParser implements Consumer<im.conver
return codes;
}
- private void parseContactPresence(final im.conversations.android.xmpp.model.stanza.Presence packet, final Account account) {
+ private void parseContactPresence(
+ final im.conversations.android.xmpp.model.stanza.Presence packet,
+ final Account account) {
final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator();
final Jid from = packet.getFrom();
if (from == null || from.equals(account.getJid())) {
@@ -29,7 +29,6 @@ import eu.siacs.conversations.utils.CursorUtils;
import eu.siacs.conversations.utils.FtsUtils;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.Resolver;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.mam.MamReference;
import java.io.ByteArrayInputStream;
@@ -1142,7 +1141,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
cursor.getString(cursor.getColumnIndex(Account.SERVER)),
null)
.getDomain()
- .toEscapedString();
+ .toString();
} catch (IllegalArgumentException ignored) {
Log.e(
Config.LOGTAG,
@@ -1307,7 +1306,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
selectionArgs);
while (cursor.moveToNext()) {
final Conversation conversation = Conversation.fromCursor(cursor);
- if (conversation.getJid() instanceof InvalidJid) {
+ if (conversation.getJid() instanceof Jid.Invalid) {
continue;
}
list.add(conversation);
@@ -1616,7 +1615,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
cursor.moveToFirst();
final Conversation conversation = Conversation.fromCursor(cursor);
- if (conversation.getJid() instanceof InvalidJid) {
+ if (conversation.getJid() instanceof Jid.Invalid) {
return null;
}
return conversation;
@@ -1649,7 +1648,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
cursor.moveToFirst();
final Conversation conversation = Conversation.fromCursor(cursor);
- if (conversation.getJid() instanceof InvalidJid) {
+ if (conversation.getJid() instanceof Jid.Invalid) {
return null;
}
conversation.setAccount(account);
@@ -6,19 +6,15 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.services.UnifiedPushBroker;
+import java.util.List;
public class UnifiedPushDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "unified-push-distributor";
@@ -42,7 +38,9 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
@Override
public void onCreate(final SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(
- "CREATE TABLE push (account TEXT, transport TEXT, application TEXT NOT NULL, instance TEXT NOT NULL UNIQUE, endpoint TEXT, expiration NUMBER DEFAULT 0)");
+ "CREATE TABLE push (account TEXT, transport TEXT, application TEXT NOT NULL,"
+ + " instance TEXT NOT NULL UNIQUE, endpoint TEXT, expiration NUMBER DEFAULT"
+ + " 0)");
}
public boolean register(final String application, final String instance) {
@@ -113,7 +111,8 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
sqLiteDatabase.query(
"push",
new String[] {"application", "endpoint"},
- "account = ? AND transport = ? AND instance = ? AND endpoint IS NOT NULL AND expiration >= "
+ "account = ? AND transport = ? AND instance = ? AND endpoint IS NOT NULL"
+ + " AND expiration >= "
+ expiration,
new String[] {account, transport, instance},
null,
@@ -131,17 +130,26 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
public List<PushTarget> deletePushTargets() {
final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
final ImmutableList.Builder<PushTarget> builder = new ImmutableList.Builder<>();
- try (final Cursor cursor = sqLiteDatabase.query("push",new String[]{"application","instance"},null,null,null,null,null)) {
+ try (final Cursor cursor =
+ sqLiteDatabase.query(
+ "push",
+ new String[] {"application", "instance"},
+ null,
+ null,
+ null,
+ null,
+ null)) {
if (cursor != null && cursor.moveToFirst()) {
- builder.add(new PushTarget(
- cursor.getString(cursor.getColumnIndexOrThrow("application")),
- cursor.getString(cursor.getColumnIndexOrThrow("instance"))));
+ builder.add(
+ new PushTarget(
+ cursor.getString(cursor.getColumnIndexOrThrow("application")),
+ cursor.getString(cursor.getColumnIndexOrThrow("instance"))));
}
} catch (final Exception e) {
- Log.d(Config.LOGTAG,"unable to retrieve push targets",e);
+ Log.d(Config.LOGTAG, "unable to retrieve push targets", e);
return builder.build();
}
- sqLiteDatabase.delete("push",null,null);
+ sqLiteDatabase.delete("push", null, null);
return builder.build();
}
@@ -149,9 +157,10 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
try (final Cursor cursor =
sqLiteDatabase.rawQuery(
- "SELECT EXISTS(SELECT endpoint FROM push WHERE account = ? AND transport = ?)",
+ "SELECT EXISTS(SELECT endpoint FROM push WHERE account = ? AND transport ="
+ + " ?)",
new String[] {
- transport.account.getUuid(), transport.transport.toEscapedString()
+ transport.account.getUuid(), transport.transport.toString()
})) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0) > 0;
@@ -16,17 +16,9 @@ import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LruCache;
-
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -43,647 +35,706 @@ import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.XmppConnection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
- private static final int FG_COLOR = 0xFFFAFAFA;
- private static final int TRANSPARENT = 0x00000000;
- private static final int PLACEHOLDER_COLOR = 0xFF202020;
-
- public static final int SYSTEM_UI_AVATAR_SIZE = 48;
-
- private static final String PREFIX_CONTACT = "contact";
- private static final String PREFIX_CONVERSATION = "conversation";
- private static final String PREFIX_ACCOUNT = "account";
- private static final String PREFIX_GENERIC = "generic";
-
- private static final String CHANNEL_SYMBOL = "#";
-
- final private Set<Integer> sizes = new HashSet<>();
- final private HashMap<String, Set<String>> conversationDependentKeys = new HashMap<>();
-
- protected XmppConnectionService mXmppConnectionService = null;
-
- AvatarService(XmppConnectionService service) {
- this.mXmppConnectionService = service;
- }
-
- public static int getSystemUiAvatarSize(final Context context) {
- return (int) (SYSTEM_UI_AVATAR_SIZE * context.getResources().getDisplayMetrics().density);
- }
-
- public Bitmap get(final Avatarable avatarable, final int size, final boolean cachedOnly) {
- if (avatarable instanceof Account) {
- return get((Account) avatarable,size,cachedOnly);
- } else if (avatarable instanceof Conversation) {
- return get((Conversation) avatarable, size, cachedOnly);
- } else if (avatarable instanceof Message) {
- return get((Message) avatarable, size, cachedOnly);
- } else if (avatarable instanceof ListItem) {
- return get((ListItem) avatarable, size, cachedOnly);
- } else if (avatarable instanceof MucOptions.User) {
- return get((MucOptions.User) avatarable, size, cachedOnly);
- } else if (avatarable instanceof Room) {
- return get((Room) avatarable, size, cachedOnly);
- }
- throw new AssertionError("AvatarService does not know how to generate avatar from "+avatarable.getClass().getName());
-
- }
-
- private Bitmap get(final Room result, final int size, boolean cacheOnly) {
- final Jid room = result.getRoom();
- Conversation conversation = room != null ? mXmppConnectionService.findFirstMuc(room) : null;
- if (conversation != null) {
- return get(conversation,size,cacheOnly);
- }
- return get(CHANNEL_SYMBOL, room != null ? room.asBareJid().toEscapedString() : result.getName(), size, cacheOnly);
- }
-
- private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
- if (contact.isSelf()) {
- return get(contact.getAccount(), size, cachedOnly);
- }
- final String KEY = key(contact, size);
- Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
- if (avatar != null || cachedOnly) {
- return avatar;
- }
- if (contact.getAvatarFilename() != null && QuickConversationsService.isQuicksy()) {
- avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
- }
- if (avatar == null && contact.getProfilePhoto() != null) {
- avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size);
- }
- if (avatar == null && contact.getAvatarFilename() != null) {
- avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
- }
- if (avatar == null) {
- avatar = get(contact.getDisplayName(), contact.getJid().asBareJid().toString(), size, false);
- }
- this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
- return avatar;
- }
-
- public Bitmap getRoundedShortcut(final MucOptions mucOptions) {
- final DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics();
- final int size = Math.round(metrics.density * 48);
- final Bitmap bitmap = get(mucOptions, size, false);
- final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
- drawAvatar(bitmap, canvas, paint);
- return output;
- }
-
- public Bitmap getRoundedShortcut(final Contact contact) {
- return getRoundedShortcut(contact, false);
- }
-
- public Bitmap getRoundedShortcutWithIcon(final Contact contact) {
- return getRoundedShortcut(contact, true);
- }
-
- private Bitmap getRoundedShortcut(final Contact contact, boolean withIcon) {
- DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics();
- int size = Math.round(metrics.density * 48);
- Bitmap bitmap = get(contact, size);
- Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
-
- drawAvatar(bitmap, canvas, paint);
- if (withIcon) {
- drawIcon(canvas, paint);
- }
- return output;
- }
-
- private static void drawAvatar(Bitmap bitmap, Canvas canvas, Paint paint) {
- final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
- paint.setAntiAlias(true);
- canvas.drawARGB(0, 0, 0, 0);
- canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(bitmap, rect, rect, paint);
- }
-
- private void drawIcon(Canvas canvas, Paint paint) {
- final Resources resources = mXmppConnectionService.getResources();
- final Bitmap icon = getRoundLauncherIcon(resources);
- if (icon == null) {
- return;
- }
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
-
- int iconSize = Math.round(canvas.getHeight() / 2.6f);
-
- int left = canvas.getWidth() - iconSize;
- int top = canvas.getHeight() - iconSize;
- final Rect rect = new Rect(left, top, left + iconSize, top + iconSize);
- canvas.drawBitmap(icon, null, rect, paint);
- }
-
- private static Bitmap getRoundLauncherIcon(Resources resources) {
-
- final Drawable drawable = ResourcesCompat.getDrawable(resources, R.mipmap.new_launcher_round,null);
- if (drawable == null) {
- return null;
- }
-
- if (drawable instanceof BitmapDrawable) {
- return ((BitmapDrawable)drawable).getBitmap();
- }
-
- Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- drawable.draw(canvas);
-
- return bitmap;
- }
-
- public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) {
- Contact c = user.getContact();
- if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null || user.getAvatar() == null)) {
- return get(c, size, cachedOnly);
- } else {
- return getImpl(user, size, cachedOnly);
- }
- }
-
- private Bitmap getImpl(final MucOptions.User user, final int size, boolean cachedOnly) {
- final String KEY = key(user, size);
- Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
- if (avatar != null || cachedOnly) {
- return avatar;
- }
- if (user.getAvatar() != null) {
- avatar = mXmppConnectionService.getFileBackend().getAvatar(user.getAvatar(), size);
- }
- if (avatar == null) {
- Contact contact = user.getContact();
- if (contact != null) {
- avatar = get(contact, size, false);
- } else {
- String seed = user.getRealJid() != null ? user.getRealJid().asBareJid().toString() : null;
- avatar = get(user.getName(), seed, size, false);
- }
- }
- this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
- return avatar;
- }
-
- public void clear(Contact contact) {
- synchronized (this.sizes) {
- for (final Integer size : sizes) {
- this.mXmppConnectionService.getBitmapCache().remove(key(contact, size));
- }
- }
- for (Conversation conversation : mXmppConnectionService.findAllConferencesWith(contact)) {
- MucOptions.User user = conversation.getMucOptions().findUserByRealJid(contact.getJid().asBareJid());
- if (user != null) {
- clear(user);
- }
- clear(conversation);
- }
- }
-
- private String key(Contact contact, int size) {
- synchronized (this.sizes) {
- this.sizes.add(size);
- }
- return PREFIX_CONTACT +
- '\0' +
- contact.getAccount().getJid().asBareJid() +
- '\0' +
- emptyOnNull(contact.getJid()) +
- '\0' +
- size;
- }
-
- private String key(MucOptions.User user, int size) {
- synchronized (this.sizes) {
- this.sizes.add(size);
- }
- return PREFIX_CONTACT +
- '\0' +
- user.getAccount().getJid().asBareJid() +
- '\0' +
- emptyOnNull(user.getFullJid()) +
- '\0' +
- emptyOnNull(user.getRealJid()) +
- '\0' +
- size;
- }
-
- public Bitmap get(ListItem item, int size) {
- return get(item, size, false);
- }
-
- public Bitmap get(ListItem item, int size, boolean cachedOnly) {
- if (item instanceof RawBlockable) {
- return get(item.getDisplayName(), item.getJid().toEscapedString(), size, cachedOnly);
- } else if (item instanceof Contact) {
- return get((Contact) item, size, cachedOnly);
- } else if (item instanceof Bookmark) {
- Bookmark bookmark = (Bookmark) item;
- if (bookmark.getConversation() != null) {
- return get(bookmark.getConversation(), size, cachedOnly);
- } else {
- Jid jid = bookmark.getJid();
- Account account = bookmark.getAccount();
- Contact contact = jid == null ? null : account.getRoster().getContact(jid);
- if (contact != null && contact.getAvatarFilename() != null) {
- return get(contact, size, cachedOnly);
- }
- String seed = jid != null ? jid.asBareJid().toString() : null;
- return get(bookmark.getDisplayName(), seed, size, cachedOnly);
- }
- } else {
- String seed = item.getJid() != null ? item.getJid().asBareJid().toString() : null;
- return get(item.getDisplayName(), seed, size, cachedOnly);
- }
- }
-
- public Bitmap get(Conversation conversation, int size) {
- return get(conversation, size, false);
- }
-
- public Bitmap get(Conversation conversation, int size, boolean cachedOnly) {
- if (conversation.getMode() == Conversation.MODE_SINGLE) {
- return get(conversation.getContact(), size, cachedOnly);
- } else {
- return get(conversation.getMucOptions(), size, cachedOnly);
- }
- }
-
- public void clear(Conversation conversation) {
- if (conversation.getMode() == Conversation.MODE_SINGLE) {
- clear(conversation.getContact());
- } else {
- clear(conversation.getMucOptions());
- synchronized (this.conversationDependentKeys) {
- Set<String> keys = this.conversationDependentKeys.get(conversation.getUuid());
- if (keys == null) {
- return;
- }
- LruCache<String, Bitmap> cache = this.mXmppConnectionService.getBitmapCache();
- for (String key : keys) {
- cache.remove(key);
- }
- keys.clear();
- }
- }
- }
-
- private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) {
- final String KEY = key(mucOptions, size);
- Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
- if (bitmap != null || cachedOnly) {
- return bitmap;
- }
-
- bitmap = mXmppConnectionService.getFileBackend().getAvatar(mucOptions.getAvatar(), size);
-
- if (bitmap == null) {
- Conversation c = mucOptions.getConversation();
- if (mucOptions.isPrivateAndNonAnonymous()) {
- final List<MucOptions.User> users = mucOptions.getUsersRelevantForNameAndAvatar();
- if (users.size() == 0) {
- bitmap = getImpl(c.getName().toString(), c.getJid().asBareJid().toString(), size);
- } else {
- bitmap = getImpl(users, size);
- }
- } else {
- bitmap = getImpl(CHANNEL_SYMBOL, c.getJid().asBareJid().toString(), size);
- }
- }
-
- this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
-
- return bitmap;
- }
-
- private Bitmap get(List<MucOptions.User> users, int size, boolean cachedOnly) {
- final String KEY = key(users, size);
- Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
- if (bitmap != null || cachedOnly) {
- return bitmap;
- }
- bitmap = getImpl(users, size);
- this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
- return bitmap;
- }
-
- private Bitmap getImpl(List<MucOptions.User> users, int size) {
- int count = users.size();
- Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- bitmap.eraseColor(TRANSPARENT);
- if (count == 0) {
- throw new AssertionError("Unable to draw tiles for 0 users");
- } else if (count == 1) {
- drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
- drawTile(canvas, users.get(0).getAccount(), size / 2 + 1, 0, size, size);
- } else if (count == 2) {
- drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
- drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size);
- } else if (count == 3) {
- drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
- drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size / 2 - 1);
- drawTile(canvas, users.get(2), size / 2 + 1, size / 2 + 1, size,
- size);
- } else if (count == 4) {
- drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
- drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
- drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
- drawTile(canvas, users.get(3), size / 2 + 1, size / 2 + 1, size,
- size);
- } else {
- drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
- drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
- drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
- drawTile(canvas, "\u2026", PLACEHOLDER_COLOR, size / 2 + 1, size / 2 + 1,
- size, size);
- }
- return bitmap;
- }
-
- public void clear(final MucOptions options) {
- if (options == null) {
- return;
- }
- synchronized (this.sizes) {
- for (Integer size : sizes) {
- this.mXmppConnectionService.getBitmapCache().remove(key(options, size));
- }
- }
- }
-
- private String key(final MucOptions options, int size) {
- synchronized (this.sizes) {
- this.sizes.add(size);
- }
- return PREFIX_CONVERSATION + "_" + options.getConversation().getUuid() + "_" + size;
- }
-
- private String key(List<MucOptions.User> users, int size) {
- final Conversation conversation = users.get(0).getConversation();
- StringBuilder builder = new StringBuilder("TILE_");
- builder.append(conversation.getUuid());
-
- for (MucOptions.User user : users) {
- builder.append("\0");
- builder.append(emptyOnNull(user.getRealJid()));
- builder.append("\0");
- builder.append(emptyOnNull(user.getFullJid()));
- }
- builder.append('\0');
- builder.append(size);
- final String key = builder.toString();
- synchronized (this.conversationDependentKeys) {
- Set<String> keys;
- if (this.conversationDependentKeys.containsKey(conversation.getUuid())) {
- keys = this.conversationDependentKeys.get(conversation.getUuid());
- } else {
- keys = new HashSet<>();
- this.conversationDependentKeys.put(conversation.getUuid(), keys);
- }
- keys.add(key);
- }
- return key;
- }
-
- public Bitmap get(Account account, int size) {
- return get(account, size, false);
- }
-
- public Bitmap get(Account account, int size, boolean cachedOnly) {
- final String KEY = key(account, size);
- Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY);
- if (avatar != null || cachedOnly) {
- return avatar;
- }
- avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size);
- if (avatar == null) {
- final String displayName = account.getDisplayName();
- final String jid = account.getJid().asBareJid().toEscapedString();
- if (QuickConversationsService.isQuicksy() && !TextUtils.isEmpty(displayName)) {
- avatar = get(displayName, jid, size, false);
- } else {
- avatar = get(jid, null, size, false);
- }
- }
- mXmppConnectionService.getBitmapCache().put(KEY, avatar);
- return avatar;
- }
-
- public Bitmap get(Message message, int size, boolean cachedOnly) {
- final Conversational conversation = message.getConversation();
- if (message.getType() == Message.TYPE_STATUS && message.getCounterparts() != null && message.getCounterparts().size() > 1) {
- return get(message.getCounterparts(), size, cachedOnly);
- } else if (message.getStatus() == Message.STATUS_RECEIVED) {
- Contact c = message.getContact();
- if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null)) {
- return get(c, size, cachedOnly);
- } else if (conversation instanceof Conversation && message.getConversation().getMode() == Conversation.MODE_MULTI) {
- final Jid trueCounterpart = message.getTrueCounterpart();
- final MucOptions mucOptions = ((Conversation) conversation).getMucOptions();
- MucOptions.User user;
- if (trueCounterpart != null) {
- user = mucOptions.findOrCreateUserByRealJid(trueCounterpart, message.getCounterpart());
- } else {
- user = mucOptions.findUserByFullJid(message.getCounterpart());
- }
- if (user != null) {
- return getImpl(user, size, cachedOnly);
- }
- } else if (c != null) {
- return get(c, size, cachedOnly);
- }
- Jid tcp = message.getTrueCounterpart();
- String seed = tcp != null ? tcp.asBareJid().toString() : null;
- return get(UIHelper.getMessageDisplayName(message), seed, size, cachedOnly);
- } else {
- return get(conversation.getAccount(), size, cachedOnly);
- }
- }
-
- public void clear(Account account) {
- synchronized (this.sizes) {
- for (Integer size : sizes) {
- this.mXmppConnectionService.getBitmapCache().remove(key(account, size));
- }
- }
- }
-
- public void clear(MucOptions.User user) {
- synchronized (this.sizes) {
- for (Integer size : sizes) {
- this.mXmppConnectionService.getBitmapCache().remove(key(user, size));
- }
- }
- }
-
- private String key(Account account, int size) {
- synchronized (this.sizes) {
- this.sizes.add(size);
- }
- return PREFIX_ACCOUNT + "_" + account.getUuid() + "_"
- + size;
- }
-
- /*public Bitmap get(String name, int size) {
- return get(name,null, size,false);
- }*/
-
- public Bitmap get(final String name, String seed, final int size, boolean cachedOnly) {
- final String KEY = key(seed == null ? name : name+"\0"+seed, size);
- Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
- if (bitmap != null || cachedOnly) {
- return bitmap;
- }
- bitmap = getImpl(name, seed, size);
- mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
- return bitmap;
- }
-
- public static Bitmap get(final Jid jid, final int size) {
- return getImpl(jid.asBareJid().toEscapedString(), null, size);
- }
-
- private static Bitmap getImpl(final String name, final String seed, final int size) {
- Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- final String trimmedName = name == null ? "" : name.trim();
- drawTile(canvas, trimmedName, seed, 0, 0, size, size);
- return bitmap;
- }
-
- private String key(String name, int size) {
- synchronized (this.sizes) {
- this.sizes.add(size);
- }
- return PREFIX_GENERIC + "_" + name + "_" + size;
- }
-
- private static boolean drawTile(Canvas canvas, String letter, int tileColor, int left, int top, int right, int bottom) {
- letter = letter.toUpperCase(Locale.getDefault());
- Paint tilePaint = new Paint(), textPaint = new Paint();
- tilePaint.setColor(tileColor);
- textPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- textPaint.setColor(FG_COLOR);
- textPaint.setTypeface(Typeface.create("sans-serif-light",
- Typeface.NORMAL));
- textPaint.setTextSize((float) ((right - left) * 0.8));
- Rect rect = new Rect();
-
- canvas.drawRect(new Rect(left, top, right, bottom), tilePaint);
- textPaint.getTextBounds(letter, 0, 1, rect);
- float width = textPaint.measureText(letter);
- canvas.drawText(letter, (right + left) / 2 - width / 2, (top + bottom)
- / 2 + rect.height() / 2, textPaint);
- return true;
- }
-
- private boolean drawTile(Canvas canvas, MucOptions.User user, int left, int top, int right, int bottom) {
- Contact contact = user.getContact();
- if (contact != null) {
- Uri uri = null;
- if (contact.getAvatarFilename() != null && QuickConversationsService.isQuicksy()) {
- uri = mXmppConnectionService.getFileBackend().getAvatarUri(contact.getAvatarFilename());
- } else if (contact.getProfilePhoto() != null) {
- uri = Uri.parse(contact.getProfilePhoto());
- } else if (contact.getAvatarFilename() != null) {
- uri = mXmppConnectionService.getFileBackend().getAvatarUri(contact.getAvatarFilename());
- }
- if (drawTile(canvas, uri, left, top, right, bottom)) {
- return true;
- }
- } else if (user.getAvatar() != null) {
- Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(user.getAvatar());
- if (drawTile(canvas, uri, left, top, right, bottom)) {
- return true;
- }
- }
- if (contact != null) {
- String seed = contact.getJid().asBareJid().toString();
- drawTile(canvas, contact.getDisplayName(), seed, left, top, right, bottom);
- } else {
- String seed = user.getRealJid() == null ? null : user.getRealJid().asBareJid().toString();
- drawTile(canvas, user.getName(), seed, left, top, right, bottom);
- }
- return true;
- }
-
- private boolean drawTile(Canvas canvas, Account account, int left, int top, int right, int bottom) {
- String avatar = account.getAvatar();
- if (avatar != null) {
- Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(avatar);
- if (uri != null) {
- if (drawTile(canvas, uri, left, top, right, bottom)) {
- return true;
- }
- }
- }
- String name = account.getJid().asBareJid().toString();
- return drawTile(canvas, name, name, left, top, right, bottom);
- }
-
- private static boolean drawTile(Canvas canvas, String name, String seed, int left, int top, int right, int bottom) {
- if (name != null) {
- final String letter = name.equals(CHANNEL_SYMBOL) ? name : getFirstLetter(name);
- final int color = UIHelper.getColorForName(seed == null ? name : seed);
- drawTile(canvas, letter, color, left, top, right, bottom);
- return true;
- }
- return false;
- }
-
- private static String getFirstLetter(String name) {
- for (Character c : name.toCharArray()) {
- if (Character.isLetterOrDigit(c)) {
- return c.toString();
- }
- }
- return "X";
- }
-
- private boolean drawTile(Canvas canvas, Uri uri, int left, int top, int right, int bottom) {
- if (uri != null) {
- Bitmap bitmap = mXmppConnectionService.getFileBackend()
- .cropCenter(uri, bottom - top, right - left);
- if (bitmap != null) {
- drawTile(canvas, bitmap, left, top, right, bottom);
- return true;
- }
- }
- return false;
- }
-
- private boolean drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop, int dstright, int dstbottom) {
- Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom);
- canvas.drawBitmap(bm, null, dst, null);
- return true;
- }
-
- @Override
- public void onAdvancedStreamFeaturesAvailable(Account account) {
- XmppConnection.Features features = account.getXmppConnection().getFeatures();
- if (features.pep() && !features.pepPersistent()) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": has pep but is not persistent");
- if (account.getAvatar() != null) {
- mXmppConnectionService.republishAvatarIfNeeded(account);
- }
- }
- }
-
- private static String emptyOnNull(@Nullable Jid value) {
- return value == null ? "" : value.toString();
- }
-
- public interface Avatarable {
- @ColorInt int getAvatarBackgroundColor();
- String getAvatarName();
- }
+ private static final int FG_COLOR = 0xFFFAFAFA;
+ private static final int TRANSPARENT = 0x00000000;
+ private static final int PLACEHOLDER_COLOR = 0xFF202020;
+
+ public static final int SYSTEM_UI_AVATAR_SIZE = 48;
+
+ private static final String PREFIX_CONTACT = "contact";
+ private static final String PREFIX_CONVERSATION = "conversation";
+ private static final String PREFIX_ACCOUNT = "account";
+ private static final String PREFIX_GENERIC = "generic";
+
+ private static final String CHANNEL_SYMBOL = "#";
+
+ private final Set<Integer> sizes = new HashSet<>();
+ private final HashMap<String, Set<String>> conversationDependentKeys = new HashMap<>();
+
+ protected XmppConnectionService mXmppConnectionService = null;
+
+ AvatarService(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ public static int getSystemUiAvatarSize(final Context context) {
+ return (int) (SYSTEM_UI_AVATAR_SIZE * context.getResources().getDisplayMetrics().density);
+ }
+
+ public Bitmap get(final Avatarable avatarable, final int size, final boolean cachedOnly) {
+ if (avatarable instanceof Account) {
+ return get((Account) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof Conversation) {
+ return get((Conversation) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof Message) {
+ return get((Message) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof ListItem) {
+ return get((ListItem) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof MucOptions.User) {
+ return get((MucOptions.User) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof Room) {
+ return get((Room) avatarable, size, cachedOnly);
+ }
+ throw new AssertionError(
+ "AvatarService does not know how to generate avatar from "
+ + avatarable.getClass().getName());
+ }
+
+ private Bitmap get(final Room result, final int size, boolean cacheOnly) {
+ final Jid room = result.getRoom();
+ Conversation conversation = room != null ? mXmppConnectionService.findFirstMuc(room) : null;
+ if (conversation != null) {
+ return get(conversation, size, cacheOnly);
+ }
+ return get(
+ CHANNEL_SYMBOL,
+ room != null ? room.asBareJid().toString() : result.getName(),
+ size,
+ cacheOnly);
+ }
+
+ private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
+ if (contact.isSelf()) {
+ return get(contact.getAccount(), size, cachedOnly);
+ }
+ final String KEY = key(contact, size);
+ Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (avatar != null || cachedOnly) {
+ return avatar;
+ }
+ if (contact.getAvatarFilename() != null && QuickConversationsService.isQuicksy()) {
+ avatar =
+ mXmppConnectionService
+ .getFileBackend()
+ .getAvatar(contact.getAvatarFilename(), size);
+ }
+ if (avatar == null && contact.getProfilePhoto() != null) {
+ avatar =
+ mXmppConnectionService
+ .getFileBackend()
+ .cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size);
+ }
+ if (avatar == null && contact.getAvatarFilename() != null) {
+ avatar =
+ mXmppConnectionService
+ .getFileBackend()
+ .getAvatar(contact.getAvatarFilename(), size);
+ }
+ if (avatar == null) {
+ avatar =
+ get(
+ contact.getDisplayName(),
+ contact.getJid().asBareJid().toString(),
+ size,
+ false);
+ }
+ this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+ return avatar;
+ }
+
+ public Bitmap getRoundedShortcut(final MucOptions mucOptions) {
+ final DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics();
+ final int size = Math.round(metrics.density * 48);
+ final Bitmap bitmap = get(mucOptions, size, false);
+ final Bitmap output =
+ Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(output);
+ final Paint paint = new Paint();
+ drawAvatar(bitmap, canvas, paint);
+ return output;
+ }
+
+ public Bitmap getRoundedShortcut(final Contact contact) {
+ return getRoundedShortcut(contact, false);
+ }
+
+ public Bitmap getRoundedShortcutWithIcon(final Contact contact) {
+ return getRoundedShortcut(contact, true);
+ }
+
+ private Bitmap getRoundedShortcut(final Contact contact, boolean withIcon) {
+ DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics();
+ int size = Math.round(metrics.density * 48);
+ Bitmap bitmap = get(contact, size);
+ Bitmap output =
+ Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+ final Paint paint = new Paint();
+
+ drawAvatar(bitmap, canvas, paint);
+ if (withIcon) {
+ drawIcon(canvas, paint);
+ }
+ return output;
+ }
+
+ private static void drawAvatar(Bitmap bitmap, Canvas canvas, Paint paint) {
+ final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ paint.setAntiAlias(true);
+ canvas.drawARGB(0, 0, 0, 0);
+ canvas.drawCircle(
+ bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(bitmap, rect, rect, paint);
+ }
+
+ private void drawIcon(Canvas canvas, Paint paint) {
+ final Resources resources = mXmppConnectionService.getResources();
+ final Bitmap icon = getRoundLauncherIcon(resources);
+ if (icon == null) {
+ return;
+ }
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
+
+ int iconSize = Math.round(canvas.getHeight() / 2.6f);
+
+ int left = canvas.getWidth() - iconSize;
+ int top = canvas.getHeight() - iconSize;
+ final Rect rect = new Rect(left, top, left + iconSize, top + iconSize);
+ canvas.drawBitmap(icon, null, rect, paint);
+ }
+
+ private static Bitmap getRoundLauncherIcon(Resources resources) {
+
+ final Drawable drawable =
+ ResourcesCompat.getDrawable(resources, R.mipmap.new_launcher_round, null);
+ if (drawable == null) {
+ return null;
+ }
+
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+
+ Bitmap bitmap =
+ Bitmap.createBitmap(
+ drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+
+ return bitmap;
+ }
+
+ public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) {
+ Contact c = user.getContact();
+ if (c != null
+ && (c.getProfilePhoto() != null
+ || c.getAvatarFilename() != null
+ || user.getAvatar() == null)) {
+ return get(c, size, cachedOnly);
+ } else {
+ return getImpl(user, size, cachedOnly);
+ }
+ }
+
+ private Bitmap getImpl(final MucOptions.User user, final int size, boolean cachedOnly) {
+ final String KEY = key(user, size);
+ Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (avatar != null || cachedOnly) {
+ return avatar;
+ }
+ if (user.getAvatar() != null) {
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(user.getAvatar(), size);
+ }
+ if (avatar == null) {
+ Contact contact = user.getContact();
+ if (contact != null) {
+ avatar = get(contact, size, false);
+ } else {
+ String seed =
+ user.getRealJid() != null ? user.getRealJid().asBareJid().toString() : null;
+ avatar = get(user.getName(), seed, size, false);
+ }
+ }
+ this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+ return avatar;
+ }
+
+ public void clear(Contact contact) {
+ synchronized (this.sizes) {
+ for (final Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(key(contact, size));
+ }
+ }
+ for (Conversation conversation : mXmppConnectionService.findAllConferencesWith(contact)) {
+ MucOptions.User user =
+ conversation.getMucOptions().findUserByRealJid(contact.getJid().asBareJid());
+ if (user != null) {
+ clear(user);
+ }
+ clear(conversation);
+ }
+ }
+
+ private String key(Contact contact, int size) {
+ synchronized (this.sizes) {
+ this.sizes.add(size);
+ }
+ return PREFIX_CONTACT
+ + '\0'
+ + contact.getAccount().getJid().asBareJid()
+ + '\0'
+ + emptyOnNull(contact.getJid())
+ + '\0'
+ + size;
+ }
+
+ private String key(MucOptions.User user, int size) {
+ synchronized (this.sizes) {
+ this.sizes.add(size);
+ }
+ return PREFIX_CONTACT
+ + '\0'
+ + user.getAccount().getJid().asBareJid()
+ + '\0'
+ + emptyOnNull(user.getFullJid())
+ + '\0'
+ + emptyOnNull(user.getRealJid())
+ + '\0'
+ + size;
+ }
+
+ public Bitmap get(ListItem item, int size) {
+ return get(item, size, false);
+ }
+
+ public Bitmap get(ListItem item, int size, boolean cachedOnly) {
+ if (item instanceof RawBlockable) {
+ return get(item.getDisplayName(), item.getJid().toString(), size, cachedOnly);
+ } else if (item instanceof Contact) {
+ return get((Contact) item, size, cachedOnly);
+ } else if (item instanceof Bookmark bookmark) {
+ if (bookmark.getConversation() != null) {
+ return get(bookmark.getConversation(), size, cachedOnly);
+ } else {
+ Jid jid = bookmark.getJid();
+ Account account = bookmark.getAccount();
+ Contact contact = jid == null ? null : account.getRoster().getContact(jid);
+ if (contact != null && contact.getAvatarFilename() != null) {
+ return get(contact, size, cachedOnly);
+ }
+ String seed = jid != null ? jid.asBareJid().toString() : null;
+ return get(bookmark.getDisplayName(), seed, size, cachedOnly);
+ }
+ } else {
+ String seed = item.getJid() != null ? item.getJid().asBareJid().toString() : null;
+ return get(item.getDisplayName(), seed, size, cachedOnly);
+ }
+ }
+
+ public Bitmap get(Conversation conversation, int size) {
+ return get(conversation, size, false);
+ }
+
+ public Bitmap get(Conversation conversation, int size, boolean cachedOnly) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ return get(conversation.getContact(), size, cachedOnly);
+ } else {
+ return get(conversation.getMucOptions(), size, cachedOnly);
+ }
+ }
+
+ public void clear(Conversation conversation) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ clear(conversation.getContact());
+ } else {
+ clear(conversation.getMucOptions());
+ synchronized (this.conversationDependentKeys) {
+ Set<String> keys = this.conversationDependentKeys.get(conversation.getUuid());
+ if (keys == null) {
+ return;
+ }
+ LruCache<String, Bitmap> cache = this.mXmppConnectionService.getBitmapCache();
+ for (String key : keys) {
+ cache.remove(key);
+ }
+ keys.clear();
+ }
+ }
+ }
+
+ private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) {
+ final String KEY = key(mucOptions, size);
+ Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (bitmap != null || cachedOnly) {
+ return bitmap;
+ }
+
+ bitmap = mXmppConnectionService.getFileBackend().getAvatar(mucOptions.getAvatar(), size);
+
+ if (bitmap == null) {
+ Conversation c = mucOptions.getConversation();
+ if (mucOptions.isPrivateAndNonAnonymous()) {
+ final List<MucOptions.User> users = mucOptions.getUsersRelevantForNameAndAvatar();
+ if (users.size() == 0) {
+ bitmap =
+ getImpl(
+ c.getName().toString(),
+ c.getJid().asBareJid().toString(),
+ size);
+ } else {
+ bitmap = getImpl(users, size);
+ }
+ } else {
+ bitmap = getImpl(CHANNEL_SYMBOL, c.getJid().asBareJid().toString(), size);
+ }
+ }
+
+ this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+
+ return bitmap;
+ }
+
+ private Bitmap get(List<MucOptions.User> users, int size, boolean cachedOnly) {
+ final String KEY = key(users, size);
+ Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (bitmap != null || cachedOnly) {
+ return bitmap;
+ }
+ bitmap = getImpl(users, size);
+ this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+ return bitmap;
+ }
+
+ private Bitmap getImpl(List<MucOptions.User> users, int size) {
+ int count = users.size();
+ Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ bitmap.eraseColor(TRANSPARENT);
+ if (count == 0) {
+ throw new AssertionError("Unable to draw tiles for 0 users");
+ } else if (count == 1) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
+ drawTile(canvas, users.get(0).getAccount(), size / 2 + 1, 0, size, size);
+ } else if (count == 2) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
+ drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size);
+ } else if (count == 3) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
+ drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, users.get(2), size / 2 + 1, size / 2 + 1, size, size);
+ } else if (count == 4) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
+ drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
+ drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, users.get(3), size / 2 + 1, size / 2 + 1, size, size);
+ } else {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
+ drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
+ drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, "\u2026", PLACEHOLDER_COLOR, size / 2 + 1, size / 2 + 1, size, size);
+ }
+ return bitmap;
+ }
+
+ public void clear(final MucOptions options) {
+ if (options == null) {
+ return;
+ }
+ synchronized (this.sizes) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(key(options, size));
+ }
+ }
+ }
+
+ private String key(final MucOptions options, int size) {
+ synchronized (this.sizes) {
+ this.sizes.add(size);
+ }
+ return PREFIX_CONVERSATION + "_" + options.getConversation().getUuid() + "_" + size;
+ }
+
+ private String key(List<MucOptions.User> users, int size) {
+ final Conversation conversation = users.get(0).getConversation();
+ StringBuilder builder = new StringBuilder("TILE_");
+ builder.append(conversation.getUuid());
+
+ for (MucOptions.User user : users) {
+ builder.append("\0");
+ builder.append(emptyOnNull(user.getRealJid()));
+ builder.append("\0");
+ builder.append(emptyOnNull(user.getFullJid()));
+ }
+ builder.append('\0');
+ builder.append(size);
+ final String key = builder.toString();
+ synchronized (this.conversationDependentKeys) {
+ Set<String> keys;
+ if (this.conversationDependentKeys.containsKey(conversation.getUuid())) {
+ keys = this.conversationDependentKeys.get(conversation.getUuid());
+ } else {
+ keys = new HashSet<>();
+ this.conversationDependentKeys.put(conversation.getUuid(), keys);
+ }
+ keys.add(key);
+ }
+ return key;
+ }
+
+ public Bitmap get(Account account, int size) {
+ return get(account, size, false);
+ }
+
+ public Bitmap get(Account account, int size, boolean cachedOnly) {
+ final String KEY = key(account, size);
+ Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY);
+ if (avatar != null || cachedOnly) {
+ return avatar;
+ }
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size);
+ if (avatar == null) {
+ final String displayName = account.getDisplayName();
+ final String jid = account.getJid().asBareJid().toString();
+ if (QuickConversationsService.isQuicksy() && !TextUtils.isEmpty(displayName)) {
+ avatar = get(displayName, jid, size, false);
+ } else {
+ avatar = get(jid, null, size, false);
+ }
+ }
+ mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+ return avatar;
+ }
+
+ public Bitmap get(Message message, int size, boolean cachedOnly) {
+ final Conversational conversation = message.getConversation();
+ if (message.getType() == Message.TYPE_STATUS
+ && message.getCounterparts() != null
+ && message.getCounterparts().size() > 1) {
+ return get(message.getCounterparts(), size, cachedOnly);
+ } else if (message.getStatus() == Message.STATUS_RECEIVED) {
+ Contact c = message.getContact();
+ if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null)) {
+ return get(c, size, cachedOnly);
+ } else if (conversation instanceof Conversation
+ && message.getConversation().getMode() == Conversation.MODE_MULTI) {
+ final Jid trueCounterpart = message.getTrueCounterpart();
+ final MucOptions mucOptions = ((Conversation) conversation).getMucOptions();
+ MucOptions.User user;
+ if (trueCounterpart != null) {
+ user =
+ mucOptions.findOrCreateUserByRealJid(
+ trueCounterpart, message.getCounterpart());
+ } else {
+ user = mucOptions.findUserByFullJid(message.getCounterpart());
+ }
+ if (user != null) {
+ return getImpl(user, size, cachedOnly);
+ }
+ } else if (c != null) {
+ return get(c, size, cachedOnly);
+ }
+ Jid tcp = message.getTrueCounterpart();
+ String seed = tcp != null ? tcp.asBareJid().toString() : null;
+ return get(UIHelper.getMessageDisplayName(message), seed, size, cachedOnly);
+ } else {
+ return get(conversation.getAccount(), size, cachedOnly);
+ }
+ }
+
+ public void clear(Account account) {
+ synchronized (this.sizes) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(key(account, size));
+ }
+ }
+ }
+
+ public void clear(MucOptions.User user) {
+ synchronized (this.sizes) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(key(user, size));
+ }
+ }
+ }
+
+ private String key(Account account, int size) {
+ synchronized (this.sizes) {
+ this.sizes.add(size);
+ }
+ return PREFIX_ACCOUNT + "_" + account.getUuid() + "_" + size;
+ }
+
+ /*public Bitmap get(String name, int size) {
+ return get(name,null, size,false);
+ }*/
+
+ public Bitmap get(final String name, String seed, final int size, boolean cachedOnly) {
+ final String KEY = key(seed == null ? name : name + "\0" + seed, size);
+ Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
+ if (bitmap != null || cachedOnly) {
+ return bitmap;
+ }
+ bitmap = getImpl(name, seed, size);
+ mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+ return bitmap;
+ }
+
+ public static Bitmap get(final Jid jid, final int size) {
+ return getImpl(jid.asBareJid().toString(), null, size);
+ }
+
+ private static Bitmap getImpl(final String name, final String seed, final int size) {
+ Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ final String trimmedName = name == null ? "" : name.trim();
+ drawTile(canvas, trimmedName, seed, 0, 0, size, size);
+ return bitmap;
+ }
+
+ private String key(String name, int size) {
+ synchronized (this.sizes) {
+ this.sizes.add(size);
+ }
+ return PREFIX_GENERIC + "_" + name + "_" + size;
+ }
+
+ private static boolean drawTile(
+ Canvas canvas, String letter, int tileColor, int left, int top, int right, int bottom) {
+ letter = letter.toUpperCase(Locale.getDefault());
+ Paint tilePaint = new Paint(), textPaint = new Paint();
+ tilePaint.setColor(tileColor);
+ textPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ textPaint.setColor(FG_COLOR);
+ textPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
+ textPaint.setTextSize((float) ((right - left) * 0.8));
+ Rect rect = new Rect();
+
+ canvas.drawRect(new Rect(left, top, right, bottom), tilePaint);
+ textPaint.getTextBounds(letter, 0, 1, rect);
+ float width = textPaint.measureText(letter);
+ canvas.drawText(
+ letter,
+ (right + left) / 2 - width / 2,
+ (top + bottom) / 2 + rect.height() / 2,
+ textPaint);
+ return true;
+ }
+
+ private boolean drawTile(
+ Canvas canvas, MucOptions.User user, int left, int top, int right, int bottom) {
+ Contact contact = user.getContact();
+ if (contact != null) {
+ Uri uri = null;
+ if (contact.getAvatarFilename() != null && QuickConversationsService.isQuicksy()) {
+ uri =
+ mXmppConnectionService
+ .getFileBackend()
+ .getAvatarUri(contact.getAvatarFilename());
+ } else if (contact.getProfilePhoto() != null) {
+ uri = Uri.parse(contact.getProfilePhoto());
+ } else if (contact.getAvatarFilename() != null) {
+ uri =
+ mXmppConnectionService
+ .getFileBackend()
+ .getAvatarUri(contact.getAvatarFilename());
+ }
+ if (drawTile(canvas, uri, left, top, right, bottom)) {
+ return true;
+ }
+ } else if (user.getAvatar() != null) {
+ Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(user.getAvatar());
+ if (drawTile(canvas, uri, left, top, right, bottom)) {
+ return true;
+ }
+ }
+ if (contact != null) {
+ String seed = contact.getJid().asBareJid().toString();
+ drawTile(canvas, contact.getDisplayName(), seed, left, top, right, bottom);
+ } else {
+ String seed =
+ user.getRealJid() == null ? null : user.getRealJid().asBareJid().toString();
+ drawTile(canvas, user.getName(), seed, left, top, right, bottom);
+ }
+ return true;
+ }
+
+ private boolean drawTile(
+ Canvas canvas, Account account, int left, int top, int right, int bottom) {
+ String avatar = account.getAvatar();
+ if (avatar != null) {
+ Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(avatar);
+ if (uri != null) {
+ if (drawTile(canvas, uri, left, top, right, bottom)) {
+ return true;
+ }
+ }
+ }
+ String name = account.getJid().asBareJid().toString();
+ return drawTile(canvas, name, name, left, top, right, bottom);
+ }
+
+ private static boolean drawTile(
+ Canvas canvas, String name, String seed, int left, int top, int right, int bottom) {
+ if (name != null) {
+ final String letter = name.equals(CHANNEL_SYMBOL) ? name : getFirstLetter(name);
+ final int color = UIHelper.getColorForName(seed == null ? name : seed);
+ drawTile(canvas, letter, color, left, top, right, bottom);
+ return true;
+ }
+ return false;
+ }
+
+ private static String getFirstLetter(String name) {
+ for (Character c : name.toCharArray()) {
+ if (Character.isLetterOrDigit(c)) {
+ return c.toString();
+ }
+ }
+ return "X";
+ }
+
+ private boolean drawTile(Canvas canvas, Uri uri, int left, int top, int right, int bottom) {
+ if (uri != null) {
+ Bitmap bitmap =
+ mXmppConnectionService
+ .getFileBackend()
+ .cropCenter(uri, bottom - top, right - left);
+ if (bitmap != null) {
+ drawTile(canvas, bitmap, left, top, right, bottom);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean drawTile(
+ Canvas canvas, Bitmap bm, int dstleft, int dsttop, int dstright, int dstbottom) {
+ Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom);
+ canvas.drawBitmap(bm, null, dst, null);
+ return true;
+ }
+
+ @Override
+ public void onAdvancedStreamFeaturesAvailable(Account account) {
+ XmppConnection.Features features = account.getXmppConnection().getFeatures();
+ if (features.pep() && !features.pepPersistent()) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": has pep but is not persistent");
+ if (account.getAvatar() != null) {
+ mXmppConnectionService.republishAvatarIfNeeded(account);
+ }
+ }
+ }
+
+ private static String emptyOnNull(@Nullable Jid value) {
+ return value == null ? "" : value.toString();
+ }
+
+ public interface Avatarable {
+ @ColorInt
+ int getAvatarBackgroundColor();
+
+ String getAvatarName();
+ }
}
@@ -455,7 +455,7 @@ public class CallIntegration extends Connection {
}
public static Uri address(final Jid contact) {
- return Uri.parse(String.format("xmpp:%s", contact.toEscapedString()));
+ return Uri.parse(String.format("xmpp:%s", contact.toString()));
}
public void verifyDisconnected() {
@@ -20,14 +20,11 @@ import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
-
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -40,7 +37,6 @@ import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
import eu.siacs.conversations.xmpp.jingle.Media;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -91,7 +87,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
if (service == null) {
Log.d(
Config.LOGTAG,
- "CallIntegrationConnection service was unable to bind to XmppConnectionService");
+ "CallIntegrationConnection service was unable to bind to"
+ + " XmppConnectionService");
return Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "service connection not found"));
}
@@ -107,8 +104,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
Log.d(Config.LOGTAG, "create outgoing rtp connection!");
final Intent intent = new Intent(service, RtpSessionActivity.class);
intent.setAction(Intent.ACTION_VIEW);
- intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
- intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
final Connection callIntegration;
@@ -135,7 +132,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
return Connection.createFailedConnection(
new DisconnectCause(
DisconnectCause.ERROR,
- "Phone is busy. Probably race condition. Try again in a moment"));
+ "Phone is busy. Probably race condition. Try again in a"
+ + " moment"));
}
if (proposal == null) {
// TODO instead of just null checking try to get the sessionID
@@ -187,9 +185,9 @@ public class CallIntegrationConnectionService extends ConnectionService {
}
final Jid jid;
if ("tel".equals(uri.getScheme())) {
- jid = Jid.ofEscaped(extras.getString(EXTRA_ADDRESS));
+ jid = Jid.of(extras.getString(EXTRA_ADDRESS));
} else {
- jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
+ jid = Jid.of(uri.getSchemeSpecificPart());
}
final int videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE);
final Set<Media> media =
@@ -226,7 +224,7 @@ public class CallIntegrationConnectionService extends ConnectionService {
return Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "service connection not found"));
}
- final var jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
+ final var jid = Jid.of(uri.getSchemeSpecificPart());
final Account account = service.findAccountByUuid(phoneAccountHandle.getId());
final var weakReference =
service.getJingleConnectionManager().findJingleRtpConnection(account, jid, sid);
@@ -365,7 +363,7 @@ public class CallIntegrationConnectionService extends ConnectionService {
} else {
// for Android 8 we need to put in a fake tel uri
final var outgoingCallExtras = new Bundle();
- outgoingCallExtras.putString(EXTRA_ADDRESS, with.toEscapedString());
+ outgoingCallExtras.putString(EXTRA_ADDRESS, with.toString());
extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, outgoingCallExtras);
address = Uri.parse("tel:0");
}
@@ -1,14 +1,10 @@
package eu.siacs.conversations.services;
-
import android.util.Log;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Room;
@@ -17,18 +13,7 @@ import eu.siacs.conversations.http.services.MuclumbusService;
import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
-
import im.conversations.android.xmpp.model.stanza.Iq;
-
-import okhttp3.OkHttpClient;
-import okhttp3.ResponseBody;
-
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +23,13 @@ import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import okhttp3.OkHttpClient;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
public class ChannelDiscoveryService {
@@ -57,7 +49,8 @@ public class ChannelDiscoveryService {
this.muclumbusService = null;
return;
}
- final OkHttpClient.Builder builder = HttpConnectionManager.okHttpClient(service).newBuilder();
+ final OkHttpClient.Builder builder =
+ HttpConnectionManager.okHttpClient(service).newBuilder();
if (service.useTorToConnect()) {
builder.proxy(HttpConnectionManager.getProxy());
}
@@ -205,10 +198,8 @@ public class ChannelDiscoveryService {
account,
infoRequest,
infoResponse -> {
- if (infoResponse.getType()
- == Iq.Type.RESULT) {
- final Room room =
- IqParser.parseRoom(infoResponse);
+ if (infoResponse.getType() == Iq.Type.RESULT) {
+ final Room room = IqParser.parseRoom(infoResponse);
if (room != null) {
rooms.add(room);
}
@@ -260,7 +251,7 @@ public class ChannelDiscoveryService {
continue;
}
for (final String mucService : xmppConnection.getMucServers()) {
- Jid jid = Jid.ofEscaped(mucService);
+ final Jid jid = Jid.of(mucService);
if (!localMucServices.containsKey(jid)) {
localMucServices.put(jid, account);
}
@@ -573,9 +573,8 @@ public class NotificationService {
final Intent fullScreenIntent =
new Intent(mXmppConnectionService, RtpSessionActivity.class);
fullScreenIntent.putExtra(
- RtpSessionActivity.EXTRA_ACCOUNT,
- id.account.getJid().asBareJid().toEscapedString());
- fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
+ RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toString());
+ fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -702,9 +701,8 @@ public class NotificationService {
new Intent(mXmppConnectionService, RtpSessionActivity.class);
fullScreenIntent.setAction(action);
fullScreenIntent.putExtra(
- RtpSessionActivity.EXTRA_ACCOUNT,
- id.account.getJid().asBareJid().toEscapedString());
- fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
+ RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toString());
+ fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
return PendingIntent.getActivity(
mXmppConnectionService,
@@ -1902,7 +1900,7 @@ public class NotificationService {
} else if (errors.size() == 1) {
mBuilder.setContentTitle(
mXmppConnectionService.getString(R.string.problem_connecting_to_account));
- mBuilder.setContentText(errors.get(0).getJid().asBareJid().toEscapedString());
+ mBuilder.setContentText(errors.get(0).getJid().asBareJid().toString());
} else {
mBuilder.setContentTitle(
mXmppConnectionService.getString(R.string.problem_connecting_to_accounts));
@@ -1961,7 +1959,7 @@ public class NotificationService {
intent = new Intent(mXmppConnectionService, AccountUtils.MANAGE_ACCOUNT_ACTIVITY);
} else {
intent = new Intent(mXmppConnectionService, EditAccountActivity.class);
- intent.putExtra("jid", errors.get(0).getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", errors.get(0).getJid().asBareJid().toString());
intent.putExtra(EditAccountActivity.EXTRA_OPENED_FROM_NOTIFICATION, true);
}
mBuilder.setContentIntent(
@@ -159,17 +159,15 @@ public class ShortcutService {
}
private static String getShortcutId(final Contact contact) {
- return contact.getAccount().getJid().asBareJid().toEscapedString()
+ return contact.getAccount().getJid().asBareJid().toString()
+ "#"
- + contact.getJid().asBareJid().toEscapedString();
+ + contact.getJid().asBareJid().toString();
}
private static String getShortcutId(final MucOptions mucOptions) {
final Account account = mucOptions.getAccount();
final Jid jid = mucOptions.getConversation().getJid();
- return account.getJid().asBareJid().toEscapedString()
- + "#"
- + jid.asBareJid().toEscapedString();
+ return account.getJid().asBareJid().toString() + "#" + jid.asBareJid().toString();
}
private Intent getShortcutIntent(final MucOptions mucOptions) {
@@ -179,17 +177,12 @@ public class ShortcutService {
Uri.parse(
String.format(
"xmpp:%s?join",
- mucOptions
- .getConversation()
- .getJid()
- .asBareJid()
- .toEscapedString())));
+ mucOptions.getConversation().getJid().asBareJid().toString())));
}
private Intent getShortcutIntent(final Contact contact) {
return getShortcutIntent(
- contact.getAccount(),
- Uri.parse("xmpp:" + contact.getJid().asBareJid().toEscapedString()));
+ contact.getAccount(), Uri.parse("xmpp:" + contact.getJid().asBareJid().toString()));
}
private Intent getShortcutIntent(final Account account, final Uri uri) {
@@ -10,10 +10,8 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
@@ -22,7 +20,6 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -34,7 +31,6 @@ import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Iq;
import im.conversations.android.xmpp.model.stanza.Presence;
-
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.List;
@@ -92,7 +88,8 @@ public class UnifiedPushBroker {
renewUnifiedPushEndpoints(null);
}
- public Optional<Transport> renewUnifiedPushEndpoints(@Nullable final PushTargetMessenger pushTargetMessenger) {
+ public Optional<Transport> renewUnifiedPushEndpoints(
+ @Nullable final PushTargetMessenger pushTargetMessenger) {
final Optional<Transport> transportOptional = getTransport();
if (transportOptional.isPresent()) {
final Transport transport = transportOptional.get();
@@ -100,13 +97,13 @@ public class UnifiedPushBroker {
renewUnifiedEndpoint(transportOptional.get(), pushTargetMessenger);
} else {
if (pushTargetMessenger != null && pushTargetMessenger.messenger != null) {
- sendRegistrationDelayed(pushTargetMessenger.messenger,"account is disabled");
+ sendRegistrationDelayed(pushTargetMessenger.messenger, "account is disabled");
}
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled");
}
} else {
if (pushTargetMessenger != null && pushTargetMessenger.messenger != null) {
- sendRegistrationDelayed(pushTargetMessenger.messenger,"no transport selected");
+ sendRegistrationDelayed(pushTargetMessenger.messenger, "no transport selected");
}
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. No transport selected");
}
@@ -121,16 +118,16 @@ public class UnifiedPushBroker {
try {
messenger.send(message);
} catch (final RemoteException e) {
- Log.d(Config.LOGTAG,"unable to tell messenger of delayed registration",e);
+ Log.d(Config.LOGTAG, "unable to tell messenger of delayed registration", e);
}
}
- private void renewUnifiedEndpoint(final Transport transport, final PushTargetMessenger pushTargetMessenger) {
+ private void renewUnifiedEndpoint(
+ final Transport transport, final PushTargetMessenger pushTargetMessenger) {
final Account account = transport.account;
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
final List<UnifiedPushDatabase.PushTarget> renewals =
- unifiedPushDatabase.getRenewals(
- account.getUuid(), transport.transport.toEscapedString());
+ unifiedPushDatabase.getRenewals(account.getUuid(), transport.transport.toString());
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
@@ -142,7 +139,11 @@ public class UnifiedPushBroker {
Log.d(
Config.LOGTAG,
account.getJid().asBareJid() + ": try to renew UnifiedPush " + renewal);
- UnifiedPushDistributor.quickLog(service,String.format("%s: try to renew UnifiedPush %s", account.getJid(), renewal.toString()));
+ UnifiedPushDistributor.quickLog(
+ service,
+ String.format(
+ "%s: try to renew UnifiedPush %s",
+ account.getJid(), renewal.toString()));
final String hashedApplication =
UnifiedPushDistributor.hash(account.getUuid(), renewal.application);
final String hashedInstance =
@@ -205,7 +206,7 @@ public class UnifiedPushBroker {
unifiedPushDatabase.updateEndpoint(
renewal.instance,
transport.account.getUuid(),
- transport.transport.toEscapedString(),
+ transport.transport.toString(),
endpoint,
expiration);
if (modified) {
@@ -231,15 +232,21 @@ public class UnifiedPushBroker {
}
}
- private void sendEndpoint(final Messenger messenger, String instance, final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) {
+ private void sendEndpoint(
+ final Messenger messenger,
+ String instance,
+ final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) {
if (messenger != null) {
- Log.d(Config.LOGTAG,"using messenger instead of broadcast to communicate endpoint to "+applicationEndpoint.application);
+ Log.d(
+ Config.LOGTAG,
+ "using messenger instead of broadcast to communicate endpoint to "
+ + applicationEndpoint.application);
final Message message = new Message();
message.obj = endpointIntent(instance, applicationEndpoint);
try {
messenger.send(message);
} catch (final RemoteException e) {
- Log.d(Config.LOGTAG,"messenger failed. falling back to broadcast");
+ Log.d(Config.LOGTAG, "messenger failed. falling back to broadcast");
broadcastEndpoint(instance, applicationEndpoint);
}
} else {
@@ -281,8 +288,7 @@ public class UnifiedPushBroker {
future,
new FutureCallback<>() {
@Override
- public void onSuccess(
- final List<UnifiedPushDatabase.PushTarget> pushTargets) {
+ public void onSuccess(final List<UnifiedPushDatabase.PushTarget> pushTargets) {
broadcastUnregistered(pushTargets);
}
@@ -290,19 +296,21 @@ public class UnifiedPushBroker {
public void onFailure(@NonNull Throwable throwable) {
Log.d(
Config.LOGTAG,
- "could not delete endpoints after UnifiedPushDistributor was disabled");
+ "could not delete endpoints after UnifiedPushDistributor was"
+ + " disabled");
}
},
MoreExecutors.directExecutor());
}
private ListenableFuture<List<UnifiedPushDatabase.PushTarget>> deletePushTargets() {
- return Futures.submit(() -> UnifiedPushDatabase.getInstance(service).deletePushTargets(),SCHEDULER);
+ return Futures.submit(
+ () -> UnifiedPushDatabase.getInstance(service).deletePushTargets(), SCHEDULER);
}
private void broadcastUnregistered(final List<UnifiedPushDatabase.PushTarget> pushTargets) {
- for(final UnifiedPushDatabase.PushTarget pushTarget : pushTargets) {
- Log.d(Config.LOGTAG,"sending unregistered to "+pushTarget);
+ for (final UnifiedPushDatabase.PushTarget pushTarget : pushTargets) {
+ Log.d(Config.LOGTAG, "sending unregistered to " + pushTarget);
broadcastUnregistered(pushTarget);
}
}
@@ -368,8 +376,8 @@ public class UnifiedPushBroker {
final Jid transport;
final Jid jid;
try {
- transport = Jid.ofEscaped(Strings.nullToEmpty(pushServerPreference).trim());
- jid = Jid.ofEscaped(Strings.nullToEmpty(accountPreference).trim());
+ transport = Jid.of(Strings.nullToEmpty(pushServerPreference).trim());
+ jid = Jid.of(Strings.nullToEmpty(accountPreference).trim());
} catch (final IllegalArgumentException e) {
return Optional.absent();
}
@@ -390,8 +398,7 @@ public class UnifiedPushBroker {
}
final String uuid = account.getUuid();
final List<UnifiedPushDatabase.PushTarget> pushTargets =
- UnifiedPushDatabase.getInstance(service)
- .getPushTargets(uuid, transport.toEscapedString());
+ UnifiedPushDatabase.getInstance(service).getPushTargets(uuid, transport.toString());
return Iterables.tryFind(
pushTargets,
pt ->
@@ -422,7 +429,8 @@ public class UnifiedPushBroker {
service.sendBroadcast(updateIntent);
}
- private Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
+ private Intent endpointIntent(
+ final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
final Intent intent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT);
intent.setPackage(endpoint.application);
intent.putExtra("token", instance);
@@ -449,13 +457,12 @@ public class UnifiedPushBroker {
return intent;
}
- public void rebroadcastEndpoint(final Messenger messenger, final String instance, final Transport transport) {
+ public void rebroadcastEndpoint(
+ final Messenger messenger, final String instance, final Transport transport) {
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
final UnifiedPushDatabase.ApplicationEndpoint endpoint =
unifiedPushDatabase.getEndpoint(
- transport.account.getUuid(),
- transport.transport.toEscapedString(),
- instance);
+ transport.account.getUuid(), transport.transport.toString(), instance);
if (endpoint != null) {
sendEndpoint(messenger, instance, endpoint);
}
@@ -120,7 +120,6 @@ import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.LocalizedContent;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
@@ -2069,7 +2068,7 @@ public class XmppConnectionService extends Service {
if (uri != null) {
final EasyOnboardingInvite invite =
new EasyOnboardingInvite(
- jid.getDomain().toEscapedString(), uri, landingUrl);
+ jid.getDomain().toString(), uri, landingUrl);
callback.inviteRequested(invite);
return;
}
@@ -2145,7 +2144,7 @@ public class XmppConnectionService extends Service {
public void processMdsItem(final Account account, final Element item) {
final Jid jid =
- item == null ? null : InvalidJid.getNullForInvalid(item.getAttributeAsJid("id"));
+ item == null ? null : Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("id"));
if (jid == null) {
return;
}
@@ -2306,7 +2305,7 @@ public class XmppConnectionService extends Service {
account,
Namespace.BOOKMARKS2,
item,
- bookmark.getJid().asBareJid().toEscapedString(),
+ bookmark.getJid().asBareJid().toString(),
PublishOptions.persistentWhitelistAccessMaxItems());
} else if (connection.getFeatures().bookmarksConversion()) {
pushBookmarksPep(account);
@@ -2321,7 +2320,7 @@ public class XmppConnectionService extends Service {
if (connection.getFeatures().bookmarks2()) {
final Iq request =
mIqGenerator.deleteItem(
- Namespace.BOOKMARKS2, bookmark.getJid().asBareJid().toEscapedString());
+ Namespace.BOOKMARKS2, bookmark.getJid().asBareJid().toString());
Log.d(
Config.LOGTAG,
account.getJid().asBareJid() + ": removing bookmark via Bookmarks 2");
@@ -3027,10 +3026,10 @@ public class XmppConnectionService extends Service {
}
private void provisionAccount(final String address, final String password) {
- final Jid jid = Jid.ofEscaped(address);
+ final Jid jid = Jid.of(address);
final Account account = new Account(jid, password);
account.setOption(Account.OPTION_DISABLED, true);
- Log.d(Config.LOGTAG, jid.asBareJid().toEscapedString() + ": provisioning account");
+ Log.d(Config.LOGTAG, jid.asBareJid().toString() + ": provisioning account");
createAccount(account);
}
@@ -5704,7 +5703,7 @@ public class XmppConnectionService extends Service {
account,
Namespace.MDS_DISPLAYED,
item,
- itemId.toEscapedString(),
+ itemId.toString(),
PublishOptions.persistentWhitelistAccessMaxItems());
}
@@ -5819,7 +5818,7 @@ public class XmppConnectionService extends Service {
if (Config.QUICKSY_DOMAIN != null) {
hosts.remove(
Config.QUICKSY_DOMAIN
- .toEscapedString()); // we only want to show this when we type a e164
+ .toString()); // we only want to show this when we type a e164
// number
}
if (Config.MAGIC_CREATE_DOMAIN != null) {
@@ -5835,7 +5834,7 @@ public class XmppConnectionService extends Service {
mucServers.addAll(account.getXmppConnection().getMucServers());
for (final Bookmark bookmark : account.getBookmarks()) {
final Jid jid = bookmark.getJid();
- final String s = jid == null ? null : jid.getDomain().toEscapedString();
+ final String s = jid == null ? null : jid.getDomain().toString();
if (s != null) {
mucServers.add(s);
}
@@ -2,13 +2,9 @@ package eu.siacs.conversations.ui;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.StringRes;
-import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogBlockContactBinding;
import eu.siacs.conversations.entities.Blockable;
@@ -17,43 +13,56 @@ import eu.siacs.conversations.ui.util.JidDialog;
public final class BlockContactDialog {
- public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
- show(xmppActivity, blockable, null);
- }
- public static void show(final XmppActivity xmppActivity, final Blockable blockable, final String serverMsgId) {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(xmppActivity);
- final boolean isBlocked = blockable.isBlocked();
- builder.setNegativeButton(R.string.cancel, null);
- DialogBlockContactBinding binding = DataBindingUtil.inflate(xmppActivity.getLayoutInflater(), R.layout.dialog_block_contact, null, false);
- final boolean reporting = blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
- if (reporting && !isBlocked) {
- binding.reportSpam.setVisibility(View.VISIBLE);
- if (serverMsgId != null) {
- binding.reportSpam.setChecked(true);
- binding.reportSpam.setEnabled(false);
- } else {
- binding.reportSpam.setEnabled(true);
- }
- } else {
- binding.reportSpam.setVisibility(View.GONE);
- }
- builder.setView(binding.getRoot());
+ public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
+ show(xmppActivity, blockable, null);
+ }
+
+ public static void show(
+ final XmppActivity xmppActivity, final Blockable blockable, final String serverMsgId) {
+ final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(xmppActivity);
+ final boolean isBlocked = blockable.isBlocked();
+ builder.setNegativeButton(R.string.cancel, null);
+ DialogBlockContactBinding binding =
+ DataBindingUtil.inflate(
+ xmppActivity.getLayoutInflater(),
+ R.layout.dialog_block_contact,
+ null,
+ false);
+ final boolean reporting =
+ blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
+ if (reporting && !isBlocked) {
+ binding.reportSpam.setVisibility(View.VISIBLE);
+ if (serverMsgId != null) {
+ binding.reportSpam.setChecked(true);
+ binding.reportSpam.setEnabled(false);
+ } else {
+ binding.reportSpam.setEnabled(true);
+ }
+ } else {
+ binding.reportSpam.setVisibility(View.GONE);
+ }
+ builder.setView(binding.getRoot());
- final String value;
- @StringRes int res;
- if (blockable.getJid().isFullJid()) {
- builder.setTitle(isBlocked ? R.string.action_unblock_participant : R.string.action_block_participant);
- value = blockable.getJid().toEscapedString();
- res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
- } else if (blockable.getJid().getLocal() == null || blockable.getAccount().isBlocked(blockable.getJid().getDomain())) {
- builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
- value =blockable.getJid().getDomain().toEscapedString();
- res = isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text;
- } else {
- if (isBlocked) {
- builder.setTitle(R.string.action_unblock_contact);
- } else if (serverMsgId != null) {
- builder.setTitle(R.string.report_spam_and_block);
+ final String value;
+ @StringRes int res;
+ if (blockable.getJid().isFullJid()) {
+ builder.setTitle(
+ isBlocked
+ ? R.string.action_unblock_participant
+ : R.string.action_block_participant);
+ value = blockable.getJid().toString();
+ res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
+ } else if (blockable.getJid().getLocal() == null
+ || blockable.getAccount().isBlocked(blockable.getJid().getDomain())) {
+ builder.setTitle(
+ isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
+ value = blockable.getJid().getDomain().toString();
+ res = isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text;
+ } else {
+ if (isBlocked) {
+ builder.setTitle(R.string.action_unblock_contact);
+ } else if (serverMsgId != null) {
+ builder.setTitle(R.string.report_spam_and_block);
} else {
final int resBlockAction =
blockable instanceof Conversation
@@ -61,28 +70,39 @@ public final class BlockContactDialog {
? R.string.block_stranger
: R.string.action_block_contact;
builder.setTitle(resBlockAction);
- }
- value = blockable.getJid().asBareJid().toEscapedString();
- res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
- }
- binding.text.setText(JidDialog.style(xmppActivity, res, value));
- builder.setPositiveButton(isBlocked ? R.string.unblock : R.string.block, (dialog, which) -> {
- if (isBlocked) {
- xmppActivity.xmppConnectionService.sendUnblockRequest(blockable);
- } else {
- boolean toastShown = false;
- if (xmppActivity.xmppConnectionService.sendBlockRequest(blockable, binding.reportSpam.isChecked(), serverMsgId)) {
- Toast.makeText(xmppActivity, R.string.corresponding_chats_closed, Toast.LENGTH_SHORT).show();
- toastShown = true;
- }
- if (xmppActivity instanceof ContactDetailsActivity) {
- if (!toastShown) {
- Toast.makeText(xmppActivity, R.string.contact_blocked_past_tense, Toast.LENGTH_SHORT).show();
- }
- xmppActivity.finish();
- }
- }
- });
- builder.create().show();
- }
+ }
+ value = blockable.getJid().asBareJid().toString();
+ res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
+ }
+ binding.text.setText(JidDialog.style(xmppActivity, res, value));
+ builder.setPositiveButton(
+ isBlocked ? R.string.unblock : R.string.block,
+ (dialog, which) -> {
+ if (isBlocked) {
+ xmppActivity.xmppConnectionService.sendUnblockRequest(blockable);
+ } else {
+ boolean toastShown = false;
+ if (xmppActivity.xmppConnectionService.sendBlockRequest(
+ blockable, binding.reportSpam.isChecked(), serverMsgId)) {
+ Toast.makeText(
+ xmppActivity,
+ R.string.corresponding_chats_closed,
+ Toast.LENGTH_SHORT)
+ .show();
+ toastShown = true;
+ }
+ if (xmppActivity instanceof ContactDetailsActivity) {
+ if (!toastShown) {
+ Toast.makeText(
+ xmppActivity,
+ R.string.contact_blocked_past_tense,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ xmppActivity.finish();
+ }
+ }
+ });
+ builder.create().show();
+ }
}
@@ -3,12 +3,8 @@ package eu.siacs.conversations.ui;
import android.os.Bundle;
import android.text.Editable;
import android.widget.Toast;
-
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
-
-import java.util.Collections;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Blockable;
@@ -17,97 +13,107 @@ import eu.siacs.conversations.entities.RawBlockable;
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
+import java.util.Collections;
-public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
-
- private Account account = null;
+public class BlocklistActivity extends AbstractSearchableListItemActivity
+ implements OnUpdateBlocklist {
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getListView().setOnItemLongClickListener((parent, view, position, id) -> {
- BlockContactDialog.show(BlocklistActivity.this, (Blockable) getListItems().get(position));
- return true;
- });
- this.binding.fab.show();
- this.binding.fab.setOnClickListener((v)->showEnterJidDialog());
- }
+ private Account account = null;
- @Override
- public void onBackendConnected() {
- for (final Account account : xmppConnectionService.getAccounts()) {
- if (account.getJid().toEscapedString().equals(getIntent().getStringExtra(EXTRA_ACCOUNT))) {
- this.account = account;
- break;
- }
- }
- filterContacts();
- Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
- if (fragment instanceof OnBackendConnected) {
- ((OnBackendConnected) fragment).onBackendConnected();
- }
- }
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getListView()
+ .setOnItemLongClickListener(
+ (parent, view, position, id) -> {
+ BlockContactDialog.show(
+ BlocklistActivity.this,
+ (Blockable) getListItems().get(position));
+ return true;
+ });
+ this.binding.fab.show();
+ this.binding.fab.setOnClickListener((v) -> showEnterJidDialog());
+ }
- @Override
- protected void filterContacts(final String needle) {
- getListItems().clear();
- if (account != null) {
- for (final Jid jid : account.getBlocklist()) {
- ListItem item;
- if (jid.isFullJid()) {
- item = new RawBlockable(account, jid);
- } else {
- item = account.getRoster().getContact(jid);
- }
- if (item.match(this, needle)) {
- getListItems().add(item);
- }
- }
- Collections.sort(getListItems());
- }
- getListItemAdapter().notifyDataSetChanged();
- }
+ @Override
+ public void onBackendConnected() {
+ for (final Account account : xmppConnectionService.getAccounts()) {
+ if (account.getJid().toString().equals(getIntent().getStringExtra(EXTRA_ACCOUNT))) {
+ this.account = account;
+ break;
+ }
+ }
+ filterContacts();
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
+ if (fragment instanceof OnBackendConnected) {
+ ((OnBackendConnected) fragment).onBackendConnected();
+ }
+ }
- protected void showEnterJidDialog() {
- FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
- Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
- if (prev != null) {
- ft.remove(prev);
- }
- ft.addToBackStack(null);
- EnterJidDialog dialog = EnterJidDialog.newInstance(
- null,
- getString(R.string.block_jabber_id),
- getString(R.string.block),
- null,
- account.getJid().asBareJid().toEscapedString(),
- true,
- false
- );
+ @Override
+ protected void filterContacts(final String needle) {
+ getListItems().clear();
+ if (account != null) {
+ for (final Jid jid : account.getBlocklist()) {
+ ListItem item;
+ if (jid.isFullJid()) {
+ item = new RawBlockable(account, jid);
+ } else {
+ item = account.getRoster().getContact(jid);
+ }
+ if (item.match(this, needle)) {
+ getListItems().add(item);
+ }
+ }
+ Collections.sort(getListItems());
+ }
+ getListItemAdapter().notifyDataSetChanged();
+ }
- dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
- Blockable blockable = new RawBlockable(account, contactJid);
- if (xmppConnectionService.sendBlockRequest(blockable, false, null)) {
- Toast.makeText(BlocklistActivity.this, R.string.corresponding_chats_closed, Toast.LENGTH_SHORT).show();
- }
- return true;
- });
+ protected void showEnterJidDialog() {
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
+ if (prev != null) {
+ ft.remove(prev);
+ }
+ ft.addToBackStack(null);
+ EnterJidDialog dialog =
+ EnterJidDialog.newInstance(
+ null,
+ getString(R.string.block_jabber_id),
+ getString(R.string.block),
+ null,
+ account.getJid().asBareJid().toString(),
+ true,
+ false);
- dialog.show(ft, "dialog");
- }
+ dialog.setOnEnterJidDialogPositiveListener(
+ (accountJid, contactJid) -> {
+ Blockable blockable = new RawBlockable(account, contactJid);
+ if (xmppConnectionService.sendBlockRequest(blockable, false, null)) {
+ Toast.makeText(
+ BlocklistActivity.this,
+ R.string.corresponding_chats_closed,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ return true;
+ });
- protected void refreshUiReal() {
- final Editable editable = getSearchEditText().getText();
- if (editable != null) {
- filterContacts(editable.toString());
- } else {
- filterContacts();
- }
- }
+ dialog.show(ft, "dialog");
+ }
- @Override
- public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) {
- refreshUi();
- }
+ protected void refreshUiReal() {
+ final Editable editable = getSearchEditText().getText();
+ if (editable != null) {
+ filterContacts(editable.toString());
+ } else {
+ filterContacts();
+ }
+ }
+ @Override
+ public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) {
+ refreshUi();
+ }
}
@@ -294,7 +294,7 @@ public class ChannelDiscoveryActivity extends XmppActivity
}
public void joinChannelSearchResult(final String selectedAccount, final Room result) {
- final Jid jid = Jid.ofEscaped(selectedAccount);
+ final Jid jid = Jid.of(selectedAccount);
final Account account = xmppConnectionService.findAccountByJid(jid);
final Conversation conversation =
xmppConnectionService.findOrCreateConversation(
@@ -4,14 +4,11 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
-
import androidx.databinding.DataBindingUtil;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityManageAccountsBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.ui.adapter.AccountAdapter;
-
import java.util.ArrayList;
import java.util.List;
@@ -29,16 +26,18 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActivityManageAccountsBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_manage_accounts);
+ final ActivityManageAccountsBinding binding =
+ DataBindingUtil.setContentView(this, R.layout.activity_manage_accounts);
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
setSupportActionBar(binding.toolbar);
configureActionBar(getSupportActionBar(), false);
this.mAccountAdapter = new AccountAdapter(this, accountList, false);
binding.accountList.setAdapter(this.mAccountAdapter);
- binding.accountList.setOnItemClickListener((arg0, view, position, arg3) -> {
- final Account account = accountList.get(position);
- goToProfilePictureActivity(account);
- });
+ binding.accountList.setOnItemClickListener(
+ (arg0, view, position, arg3) -> {
+ final Account account = accountList.get(position);
+ goToProfilePictureActivity(account);
+ });
}
@Override
@@ -58,7 +57,7 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
private void loadEnabledAccounts() {
accountList.clear();
- for(Account account : xmppConnectionService.getAccounts()) {
+ for (Account account : xmppConnectionService.getAccounts()) {
if (account.isEnabled()) {
accountList.add(account);
}
@@ -70,13 +69,17 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
final Uri uri = startIntent == null ? null : startIntent.getData();
if (uri != null) {
Intent intent = new Intent(this, PublishProfilePictureActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(intent);
} catch (SecurityException e) {
- Toast.makeText(this, R.string.sharing_application_not_grant_permission, Toast.LENGTH_SHORT).show();
+ Toast.makeText(
+ this,
+ R.string.sharing_application_not_grant_permission,
+ Toast.LENGTH_SHORT)
+ .show();
return;
}
}
@@ -16,23 +16,12 @@ import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
-
import com.google.common.base.Strings;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@@ -44,8 +33,15 @@ import eu.siacs.conversations.ui.util.ActivityResult;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
-public class ChooseContactActivity extends AbstractSearchableListItemActivity implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
+public class ChooseContactActivity extends AbstractSearchableListItemActivity
+ implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
public static final String EXTRA_TITLE_RES_ID = "extra_title_res_id";
public static final String EXTRA_GROUP_CHAT_NAME = "extra_group_chat_name";
public static final String EXTRA_SELECT_MULTIPLE = "extra_select_multiple";
@@ -75,11 +71,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
} else {
contacts.add(conversation.getJid().asBareJid().toString());
}
- intent.putExtra(EXTRA_FILTERED_CONTACTS, contacts.toArray(new String[contacts.size()]));
+ intent.putExtra(EXTRA_FILTERED_CONTACTS, contacts.toArray(new String[0]));
intent.putExtra(EXTRA_CONVERSATION, conversation.getUuid());
intent.putExtra(EXTRA_SELECT_MULTIPLE, true);
intent.putExtra(EXTRA_SHOW_ENTER_JID, true);
- intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
return intent;
}
@@ -135,8 +131,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
final SharedPreferences preferences = getPreferences();
- this.startSearching = intent.getBooleanExtra("direct_search", false) && preferences.getBoolean("start_searching", getResources().getBoolean(R.bool.start_searching));
-
+ this.startSearching =
+ intent.getBooleanExtra("direct_search", false)
+ && preferences.getBoolean(
+ "start_searching",
+ getResources().getBoolean(R.bool.start_searching));
}
private void onFabClicked(View v) {
@@ -159,9 +158,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
binding.fab.setImageResource(R.drawable.ic_navigate_next_24dp);
binding.fab.show();
final View view = getSearchEditText();
- final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ final InputMethodManager imm =
+ (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (view != null && imm != null) {
- imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
+ imm.hideSoftInputFromWindow(
+ getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
}
return true;
}
@@ -226,11 +227,14 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
}
- public @StringRes
- int getTitleFromIntent() {
+ public @StringRes int getTitleFromIntent() {
final Intent intent = getIntent();
boolean multiple = intent != null && intent.getBooleanExtra(EXTRA_SELECT_MULTIPLE, false);
- @StringRes int fallback = multiple ? R.string.title_activity_choose_contacts : R.string.title_activity_choose_contact;
+ @StringRes
+ int fallback =
+ multiple
+ ? R.string.title_activity_choose_contacts
+ : R.string.title_activity_choose_contact;
return intent != null ? intent.getIntExtra(EXTRA_TITLE_RES_ID, fallback) : fallback;
}
@@ -239,7 +243,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
super.onCreateOptionsMenu(menu);
final Intent i = getIntent();
boolean showEnterJid = i != null && i.getBooleanExtra(EXTRA_SHOW_ENTER_JID, false);
- menu.findItem(R.id.action_scan_qr_code).setVisible(isCameraFeatureAvailable() && showEnterJid);
+ menu.findItem(R.id.action_scan_qr_code)
+ .setVisible(isCameraFeatureAvailable() && showEnterJid);
MenuItem mMenuSearchView = menu.findItem(R.id.action_search);
if (startSearching) {
mMenuSearchView.expandActionView();
@@ -276,8 +281,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
for (final Account account : xmppConnectionService.getAccounts()) {
if (account.isEnabled()) {
for (final Contact contact : account.getRoster().getContacts()) {
- if (contact.showInContactList() &&
- !filterContacts.contains(contact.getJid().asBareJid().toString())
+ if (contact.showInContactList()
+ && !filterContacts.contains(contact.getJid().asBareJid().toString())
&& contact.match(this, needle)) {
getListItems().add(contact);
}
@@ -293,7 +298,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
public void refreshUiReal() {
- //nothing to do. This Activity doesn't implement any listeners
+ // nothing to do. This Activity doesn't implement any listeners
}
@Override
@@ -314,28 +319,29 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
ft.addToBackStack(null);
Jid jid = uri == null ? null : uri.getJid();
- EnterJidDialog dialog = EnterJidDialog.newInstance(
- mActivatedAccounts,
- getString(R.string.enter_contact),
- getString(R.string.select),
- jid == null ? null : jid.asBareJid().toString(),
- getIntent().getStringExtra(EXTRA_ACCOUNT),
- true,
- false
- );
-
- dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
- final Intent request = getIntent();
- final Intent data = new Intent();
- data.putExtra("contact", contactJid.toString());
- data.putExtra(EXTRA_ACCOUNT, accountJid.toEscapedString());
- data.putExtra(EXTRA_SELECT_MULTIPLE, false);
- copy(request, data);
- setResult(RESULT_OK, data);
- finish();
-
- return true;
- });
+ EnterJidDialog dialog =
+ EnterJidDialog.newInstance(
+ mActivatedAccounts,
+ getString(R.string.enter_contact),
+ getString(R.string.select),
+ jid == null ? null : jid.asBareJid().toString(),
+ getIntent().getStringExtra(EXTRA_ACCOUNT),
+ true,
+ false);
+
+ dialog.setOnEnterJidDialogPositiveListener(
+ (accountJid, contactJid) -> {
+ final Intent request = getIntent();
+ final Intent data = new Intent();
+ data.putExtra("contact", contactJid.toString());
+ data.putExtra(EXTRA_ACCOUNT, accountJid.toString());
+ data.putExtra(EXTRA_SELECT_MULTIPLE, false);
+ copy(request, data);
+ setResult(RESULT_OK, data);
+ finish();
+
+ return true;
+ });
dialog.show(ft, "dialog");
}
@@ -352,7 +358,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
private void handleActivityResult(ActivityResult activityResult) {
- if (activityResult.resultCode == RESULT_OK && activityResult.requestCode == ScanActivity.REQUEST_SCAN_QR_CODE) {
+ if (activityResult.resultCode == RESULT_OK
+ && activityResult.requestCode == ScanActivity.REQUEST_SCAN_QR_CODE) {
String result = activityResult.data.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
XmppUri uri = new XmppUri(Strings.nullToEmpty(result));
if (uri.isValidJid()) {
@@ -367,21 +374,23 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
this.mActivatedAccounts.clear();
for (final Account account : xmppConnectionService.getAccounts()) {
if (account.isEnabled()) {
- this.mActivatedAccounts.add(account.getJid().asBareJid().toEscapedString());
+ this.mActivatedAccounts.add(account.getJid().asBareJid().toString());
}
}
ActivityResult activityResult = this.postponedActivityResult.pop();
if (activityResult != null) {
handleActivityResult(activityResult);
}
- final Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
+ final Fragment fragment =
+ getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
if (fragment instanceof OnBackendConnected) {
((OnBackendConnected) fragment).onBackendConnected();
}
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ public void onRequestPermissionsResult(
+ int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
ScanActivity.onRequestPermissionResult(this, requestCode, grantResults);
}
@@ -393,8 +402,10 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
getListView().setItemChecked(position, true);
return;
}
- 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);
final ListItem mListItem = getListItems().get(position);
onListItemClicked(mListItem);
}
@@ -405,7 +416,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
data.putExtra("contact", item.getJid().toString());
String account = request.getStringExtra(EXTRA_ACCOUNT);
if (account == null && item instanceof Contact) {
- account = ((Contact) item).getAccount().getJid().asBareJid().toEscapedString();
+ account = ((Contact) item).getAccount().getJid().asBareJid().toString();
}
data.putExtra(EXTRA_ACCOUNT, account);
data.putExtra(EXTRA_SELECT_MULTIPLE, false);
@@ -405,8 +405,7 @@ public class ConferenceDetailsActivity extends XmppActivity
if (mConversation != null) {
if (http) {
return "https://conversations.im/j/"
- + XmppUri.lameUrlEncode(
- mConversation.getJid().asBareJid().toEscapedString());
+ + XmppUri.lameUrlEncode(mConversation.getJid().asBareJid().toString());
} else {
return "xmpp:" + mConversation.getJid().asBareJid() + "?join";
}
@@ -522,7 +521,7 @@ public class ConferenceDetailsActivity extends XmppActivity
}
final MucOptions mucOptions = mConversation.getMucOptions();
final User self = mucOptions.getSelf();
- final String account = mConversation.getAccount().getJid().asBareJid().toEscapedString();
+ final String account = mConversation.getAccount().getJid().asBareJid().toString();
setTitle(
mucOptions.isPrivateAndNonAnonymous()
? R.string.action_muc_details
@@ -537,7 +536,7 @@ public class ConferenceDetailsActivity extends XmppActivity
this.binding.jid.setText(
getString(R.string.hosted_on, mConversation.getJid().getDomain()));
} else {
- this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString());
+ this.binding.jid.setText(mConversation.getJid().asBareJid().toString());
}
AvatarWorkerTask.loadAvatar(
mConversation, binding.yourPhoto, R.dimen.avatar_on_details_screen_size);
@@ -682,7 +681,7 @@ public class ConferenceDetailsActivity extends XmppActivity
@Override
public void onAffiliationChangeFailed(Jid jid, int resId) {
- displayToast(getString(resId, jid.asBareJid().toEscapedString()));
+ displayToast(getString(resId, jid.asBareJid().toString()));
}
@Override
@@ -172,7 +172,7 @@ public class ContactDetailsActivity extends OmemoActivity
if (quicksyContact) {
value = PhoneNumberUtilWrapper.toFormattedPhoneNumber(this, jid);
} else {
- value = jid.toEscapedString();
+ value = jid.toString();
}
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(getString(R.string.action_add_phone_book));
@@ -233,9 +233,9 @@ public class ContactDetailsActivity extends OmemoActivity
protected String getShareableUri(boolean http) {
if (http) {
return "https://conversations.im/i/"
- + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toEscapedString());
+ + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toString());
} else {
- return "xmpp:" + contact.getJid().asBareJid().toEscapedString();
+ return "xmpp:" + contact.getJid().asBareJid().toString();
}
}
@@ -247,11 +247,11 @@ public class ContactDetailsActivity extends OmemoActivity
&& savedInstanceState.getBoolean("show_inactive_omemo", false);
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
try {
- this.accountJid = Jid.ofEscaped(getIntent().getExtras().getString(EXTRA_ACCOUNT));
+ this.accountJid = Jid.of(getIntent().getExtras().getString(EXTRA_ACCOUNT));
} catch (final IllegalArgumentException ignored) {
}
try {
- this.contactJid = Jid.ofEscaped(getIntent().getExtras().getString("contact"));
+ this.contactJid = Jid.of(getIntent().getExtras().getString("contact"));
} catch (final IllegalArgumentException ignored) {
}
}
@@ -328,7 +328,7 @@ public class ContactDetailsActivity extends OmemoActivity
JidDialog.style(
this,
R.string.remove_contact_text,
- contact.getJid().toEscapedString()))
+ contact.getJid().toString()))
.setPositiveButton(getString(R.string.delete), removeFromRoster)
.create()
.show();
@@ -506,7 +506,7 @@ public class ContactDetailsActivity extends OmemoActivity
}
binding.detailsContactjid.setText(IrregularUnicodeDetector.style(this, contact.getJid()));
- final String account = contact.getAccount().getJid().asBareJid().toEscapedString();
+ final String account = contact.getAccount().getJid().asBareJid().toString();
binding.detailsAccount.setText(getString(R.string.using_account, account));
AvatarWorkerTask.loadAvatar(
contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size);
@@ -902,8 +902,7 @@ public class ConversationFragment extends XmppFragment
}
intent.putExtra("contacts", contacts);
intent.putExtra(
- EXTRA_ACCOUNT,
- conversation.getAccount().getJid().asBareJid().toEscapedString());
+ EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
intent.putExtra("conversation", conversation.getUuid());
startActivityForResult(intent, requestCode);
return true;
@@ -1562,8 +1561,8 @@ public class ConversationFragment extends XmppFragment
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(
RtpSessionActivity.EXTRA_ACCOUNT,
- id.getAccount().getJid().asBareJid().toEscapedString());
- intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toEscapedString());
+ id.getAccount().getJid().asBareJid().toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toString());
if (id instanceof AbstractJingleConnection) {
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.getSessionId());
startActivity(intent);
@@ -3570,7 +3569,7 @@ public class ConversationFragment extends XmppFragment
+ message.getContact()
.getJid()
.asBareJid()
- .toEscapedString());
+ .toString());
break;
}
return true;
@@ -29,12 +29,13 @@
package eu.siacs.conversations.ui;
+import static androidx.recyclerview.widget.ItemTouchHelper.LEFT;
+import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
+
import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Canvas;
-import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -44,22 +45,14 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.google.common.collect.Collections2;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -77,227 +70,281 @@ import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.ui.util.ScrollState;
import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.EasyOnboardingInvite;
-
-import static androidx.recyclerview.widget.ItemTouchHelper.LEFT;
-import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
public class ConversationsOverviewFragment extends XmppFragment {
- private static final String STATE_SCROLL_POSITION = ConversationsOverviewFragment.class.getName()+".scroll_state";
-
- private final List<Conversation> conversations = new ArrayList<>();
- private final PendingItem<Conversation> swipedConversation = new PendingItem<>();
- private final PendingItem<ScrollState> pendingScrollState = new PendingItem<>();
- private FragmentConversationsOverviewBinding binding;
- private ConversationAdapter conversationsAdapter;
- private XmppActivity activity;
- private final PendingActionHelper pendingActionHelper = new PendingActionHelper();
-
- private final ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0,LEFT|RIGHT) {
- @Override
- public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
- return false;
- }
-
- @Override
- public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder,
- float dX, float dY, int actionState, boolean isCurrentlyActive) {
- if (viewHolder instanceof ConversationAdapter.ConversationViewHolder conversationViewHolder) {
- getDefaultUIUtil().onDraw(c,recyclerView,conversationViewHolder.binding.frame,dX,dY,actionState,isCurrentlyActive);
- }
- }
-
- @Override
- public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
- if (viewHolder instanceof ConversationAdapter.ConversationViewHolder conversationViewHolder) {
- getDefaultUIUtil().clearView(conversationViewHolder.binding.frame);
- }
- }
-
- @Override
- public float getSwipeEscapeVelocity(final float defaultEscapeVelocity) {
- return 32 * defaultEscapeVelocity;
- }
-
- @Override
- public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) {
- pendingActionHelper.execute();
- int position = viewHolder.getLayoutPosition();
- try {
- swipedConversation.push(conversations.get(position));
- } catch (IndexOutOfBoundsException e) {
- return;
- }
- conversationsAdapter.remove(swipedConversation.peek(), position);
- activity.xmppConnectionService.markRead(swipedConversation.peek());
-
- if (position == 0 && conversationsAdapter.getItemCount() == 0) {
- final Conversation c = swipedConversation.pop();
- activity.xmppConnectionService.archiveConversation(c);
- return;
- }
- final boolean formerlySelected = ConversationFragment.getConversation(getActivity()) == swipedConversation.peek();
- if (activity instanceof OnConversationArchived) {
- ((OnConversationArchived) activity).onConversationArchived(swipedConversation.peek());
- }
- final Conversation c = swipedConversation.peek();
- final int title;
- if (c.getMode() == Conversational.MODE_MULTI) {
- if (c.getMucOptions().isPrivateAndNonAnonymous()) {
- title = R.string.title_undo_swipe_out_group_chat;
- } else {
- title = R.string.title_undo_swipe_out_channel;
- }
- } else {
- title = R.string.title_undo_swipe_out_chat;
- }
-
- final Snackbar snackbar = Snackbar.make(binding.list, title, 5000)
- .setAction(R.string.undo, v -> {
- pendingActionHelper.undo();
- Conversation conversation = swipedConversation.pop();
- conversationsAdapter.insert(conversation, position);
- if (formerlySelected) {
- if (activity instanceof OnConversationSelected) {
- ((OnConversationSelected) activity).onConversationSelected(c);
- }
- }
- LinearLayoutManager layoutManager = (LinearLayoutManager) binding.list.getLayoutManager();
- if (position > layoutManager.findLastVisibleItemPosition()) {
- binding.list.smoothScrollToPosition(position);
- }
- })
- .addCallback(new Snackbar.Callback() {
- @Override
- public void onDismissed(Snackbar transientBottomBar, int event) {
- switch (event) {
- case DISMISS_EVENT_SWIPE:
- case DISMISS_EVENT_TIMEOUT:
- pendingActionHelper.execute();
- break;
- }
- }
- });
-
- pendingActionHelper.push(() -> {
- if (snackbar.isShownOrQueued()) {
- snackbar.dismiss();
- }
- final Conversation conversation = swipedConversation.pop();
- if(conversation != null){
- if (!conversation.isRead() && conversation.getMode() == Conversation.MODE_SINGLE) {
- return;
- }
- activity.xmppConnectionService.archiveConversation(c);
- }
- });
- snackbar.show();
- }
- };
-
- private ItemTouchHelper touchHelper;
-
- public static Conversation getSuggestion(Activity activity) {
- final Conversation exception;
- Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
- if (fragment instanceof ConversationsOverviewFragment) {
- exception = ((ConversationsOverviewFragment) fragment).swipedConversation.peek();
- } else {
- exception = null;
- }
- return getSuggestion(activity, exception);
- }
-
- public static Conversation getSuggestion(Activity activity, Conversation exception) {
- Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
- if (fragment instanceof ConversationsOverviewFragment) {
- List<Conversation> conversations = ((ConversationsOverviewFragment) fragment).conversations;
- if (conversations.size() > 0) {
- Conversation suggestion = conversations.get(0);
- if (suggestion == exception) {
- if (conversations.size() > 1) {
- return conversations.get(1);
- }
- } else {
- return suggestion;
- }
- }
- }
- return null;
-
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- if (savedInstanceState == null) {
- return;
- }
- pendingScrollState.push(savedInstanceState.getParcelable(STATE_SCROLL_POSITION));
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (activity instanceof XmppActivity) {
- this.activity = (XmppActivity) activity;
- } else {
- throw new IllegalStateException("Trying to attach fragment to activity that is not an XmppActivity");
- }
- }
- @Override
- public void onDestroyView() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onDestroyView()");
- super.onDestroyView();
- this.binding = null;
- this.conversationsAdapter = null;
- this.touchHelper = null;
- }
- @Override
- public void onDestroy() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onDestroy()");
- super.onDestroy();
-
- }
- @Override
- public void onPause() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onPause()");
- pendingActionHelper.execute();
- super.onPause();
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- this.activity = null;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- this.binding = DataBindingUtil.inflate(inflater, R.layout.fragment_conversations_overview, container, false);
- this.binding.fab.setOnClickListener((view) -> StartConversationActivity.launch(getActivity()));
-
- this.conversationsAdapter = new ConversationAdapter(this.activity, this.conversations);
- this.conversationsAdapter.setConversationClickListener((view, conversation) -> {
- if (activity instanceof OnConversationSelected) {
- ((OnConversationSelected) activity).onConversationSelected(conversation);
- } else {
- Log.w(ConversationsOverviewFragment.class.getCanonicalName(), "Activity does not implement OnConversationSelected");
- }
- });
- this.binding.list.setAdapter(this.conversationsAdapter);
- this.binding.list.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
- this.binding.list.addOnScrollListener(ExtendedFabSizeChanger.of(binding.fab));
- this.touchHelper = new ItemTouchHelper(this.callback);
- this.touchHelper.attachToRecyclerView(this.binding.list);
- return binding.getRoot();
- }
+ private static final String STATE_SCROLL_POSITION =
+ ConversationsOverviewFragment.class.getName() + ".scroll_state";
+
+ private final List<Conversation> conversations = new ArrayList<>();
+ private final PendingItem<Conversation> swipedConversation = new PendingItem<>();
+ private final PendingItem<ScrollState> pendingScrollState = new PendingItem<>();
+ private FragmentConversationsOverviewBinding binding;
+ private ConversationAdapter conversationsAdapter;
+ private XmppActivity activity;
+ private final PendingActionHelper pendingActionHelper = new PendingActionHelper();
+
+ private final ItemTouchHelper.SimpleCallback callback =
+ new ItemTouchHelper.SimpleCallback(0, LEFT | RIGHT) {
+ @Override
+ public boolean onMove(
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ @NonNull RecyclerView.ViewHolder target) {
+ return false;
+ }
+
+ @Override
+ public void onChildDraw(
+ @NonNull Canvas c,
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ float dX,
+ float dY,
+ int actionState,
+ boolean isCurrentlyActive) {
+ if (viewHolder
+ instanceof
+ ConversationAdapter.ConversationViewHolder conversationViewHolder) {
+ getDefaultUIUtil()
+ .onDraw(
+ c,
+ recyclerView,
+ conversationViewHolder.binding.frame,
+ dX,
+ dY,
+ actionState,
+ isCurrentlyActive);
+ }
+ }
+
+ @Override
+ public void clearView(
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder
+ instanceof
+ ConversationAdapter.ConversationViewHolder conversationViewHolder) {
+ getDefaultUIUtil().clearView(conversationViewHolder.binding.frame);
+ }
+ }
+
+ @Override
+ public float getSwipeEscapeVelocity(final float defaultEscapeVelocity) {
+ return 32 * defaultEscapeVelocity;
+ }
+
+ @Override
+ public void onSwiped(
+ final RecyclerView.ViewHolder viewHolder, final int direction) {
+ pendingActionHelper.execute();
+ int position = viewHolder.getLayoutPosition();
+ try {
+ swipedConversation.push(conversations.get(position));
+ } catch (IndexOutOfBoundsException e) {
+ return;
+ }
+ conversationsAdapter.remove(swipedConversation.peek(), position);
+ activity.xmppConnectionService.markRead(swipedConversation.peek());
+
+ if (position == 0 && conversationsAdapter.getItemCount() == 0) {
+ final Conversation c = swipedConversation.pop();
+ activity.xmppConnectionService.archiveConversation(c);
+ return;
+ }
+ final boolean formerlySelected =
+ ConversationFragment.getConversation(getActivity())
+ == swipedConversation.peek();
+ if (activity instanceof OnConversationArchived) {
+ ((OnConversationArchived) activity)
+ .onConversationArchived(swipedConversation.peek());
+ }
+ final Conversation c = swipedConversation.peek();
+ final int title;
+ if (c.getMode() == Conversational.MODE_MULTI) {
+ if (c.getMucOptions().isPrivateAndNonAnonymous()) {
+ title = R.string.title_undo_swipe_out_group_chat;
+ } else {
+ title = R.string.title_undo_swipe_out_channel;
+ }
+ } else {
+ title = R.string.title_undo_swipe_out_chat;
+ }
+
+ final Snackbar snackbar =
+ Snackbar.make(binding.list, title, 5000)
+ .setAction(
+ R.string.undo,
+ v -> {
+ pendingActionHelper.undo();
+ Conversation conversation =
+ swipedConversation.pop();
+ conversationsAdapter.insert(conversation, position);
+ if (formerlySelected) {
+ if (activity
+ instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity)
+ .onConversationSelected(c);
+ }
+ }
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager)
+ binding.list.getLayoutManager();
+ if (position
+ > layoutManager
+ .findLastVisibleItemPosition()) {
+ binding.list.smoothScrollToPosition(position);
+ }
+ })
+ .addCallback(
+ new Snackbar.Callback() {
+ @Override
+ public void onDismissed(
+ Snackbar transientBottomBar, int event) {
+ switch (event) {
+ case DISMISS_EVENT_SWIPE:
+ case DISMISS_EVENT_TIMEOUT:
+ pendingActionHelper.execute();
+ break;
+ }
+ }
+ });
+
+ pendingActionHelper.push(
+ () -> {
+ if (snackbar.isShownOrQueued()) {
+ snackbar.dismiss();
+ }
+ final Conversation conversation = swipedConversation.pop();
+ if (conversation != null) {
+ if (!conversation.isRead()
+ && conversation.getMode() == Conversation.MODE_SINGLE) {
+ return;
+ }
+ activity.xmppConnectionService.archiveConversation(c);
+ }
+ });
+ snackbar.show();
+ }
+ };
+
+ private ItemTouchHelper touchHelper;
+
+ public static Conversation getSuggestion(Activity activity) {
+ final Conversation exception;
+ Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
+ if (fragment instanceof ConversationsOverviewFragment) {
+ exception = ((ConversationsOverviewFragment) fragment).swipedConversation.peek();
+ } else {
+ exception = null;
+ }
+ return getSuggestion(activity, exception);
+ }
+
+ public static Conversation getSuggestion(Activity activity, Conversation exception) {
+ Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
+ if (fragment instanceof ConversationsOverviewFragment) {
+ List<Conversation> conversations =
+ ((ConversationsOverviewFragment) fragment).conversations;
+ if (conversations.size() > 0) {
+ Conversation suggestion = conversations.get(0);
+ if (suggestion == exception) {
+ if (conversations.size() > 1) {
+ return conversations.get(1);
+ }
+ } else {
+ return suggestion;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState == null) {
+ return;
+ }
+ pendingScrollState.push(savedInstanceState.getParcelable(STATE_SCROLL_POSITION));
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (activity instanceof XmppActivity) {
+ this.activity = (XmppActivity) activity;
+ } else {
+ throw new IllegalStateException(
+ "Trying to attach fragment to activity that is not an XmppActivity");
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onDestroyView()");
+ super.onDestroyView();
+ this.binding = null;
+ this.conversationsAdapter = null;
+ this.touchHelper = null;
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onDestroy()");
+ super.onDestroy();
+ }
+
+ @Override
+ public void onPause() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onPause()");
+ pendingActionHelper.execute();
+ super.onPause();
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ this.activity = null;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(
+ final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ this.binding =
+ DataBindingUtil.inflate(
+ inflater, R.layout.fragment_conversations_overview, container, false);
+ this.binding.fab.setOnClickListener(
+ (view) -> StartConversationActivity.launch(getActivity()));
+
+ this.conversationsAdapter = new ConversationAdapter(this.activity, this.conversations);
+ this.conversationsAdapter.setConversationClickListener(
+ (view, conversation) -> {
+ if (activity instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity).onConversationSelected(conversation);
+ } else {
+ Log.w(
+ ConversationsOverviewFragment.class.getCanonicalName(),
+ "Activity does not implement OnConversationSelected");
+ }
+ });
+ this.binding.list.setAdapter(this.conversationsAdapter);
+ this.binding.list.setLayoutManager(
+ new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
+ this.binding.list.addOnScrollListener(ExtendedFabSizeChanger.of(binding.fab));
+ this.touchHelper = new ItemTouchHelper(this.callback);
+ this.touchHelper.attachToRecyclerView(this.binding.list);
+ return binding.getRoot();
+ }
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
@@ -313,114 +360,131 @@ public class ConversationsOverviewFragment extends XmppFragment {
&& QuickConversationsService.isPlayStoreFlavor());
}
- @Override
- public void onBackendConnected() {
- refresh();
- }
-
- @Override
- public void onSaveInstanceState(Bundle bundle) {
- super.onSaveInstanceState(bundle);
- ScrollState scrollState = getScrollState();
- if (scrollState != null) {
- bundle.putParcelable(STATE_SCROLL_POSITION, scrollState);
- }
- }
-
- private ScrollState getScrollState() {
- if (this.binding == null) {
- return null;
- }
- LinearLayoutManager layoutManager = (LinearLayoutManager) this.binding.list.getLayoutManager();
- int position = layoutManager.findFirstVisibleItemPosition();
- final View view = this.binding.list.getChildAt(0);
- if (view != null) {
- return new ScrollState(position,view.getTop());
- } else {
- return new ScrollState(position, 0);
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onStart()");
- if (activity.xmppConnectionService != null) {
- refresh();
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- if (MenuDoubleTabUtil.shouldIgnoreTap()) {
- return false;
- }
- switch (item.getItemId()) {
- case R.id.action_search:
- startActivity(new Intent(getActivity(), SearchActivity.class));
- return true;
- case R.id.action_easy_invite:
- selectAccountToStartEasyInvite();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- private void selectAccountToStartEasyInvite() {
- final List<Account> accounts = EasyOnboardingInvite.getSupportingAccounts(activity.xmppConnectionService);
- if (accounts.isEmpty()) {
- //This can technically happen if opening the menu item races with accounts reconnecting or something
- Toast.makeText(getActivity(),R.string.no_active_accounts_support_this, Toast.LENGTH_LONG).show();
- } else if (accounts.size() == 1) {
- openEasyInviteScreen(accounts.get(0));
- } else {
- final AtomicReference<Account> selectedAccount = new AtomicReference<>(accounts.get(0));
- final MaterialAlertDialogBuilder alertDialogBuilder = new MaterialAlertDialogBuilder(activity);
- alertDialogBuilder.setTitle(R.string.choose_account);
- final String[] asStrings = Collections2.transform(accounts, a -> a.getJid().asBareJid().toEscapedString()).toArray(new String[0]);
- alertDialogBuilder.setSingleChoiceItems(asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
- alertDialogBuilder.setNegativeButton(R.string.cancel, null);
- alertDialogBuilder.setPositiveButton(R.string.ok, (dialog, which) -> openEasyInviteScreen(selectedAccount.get()));
- alertDialogBuilder.create().show();
- }
- }
-
- private void openEasyInviteScreen(final Account account) {
- EasyOnboardingInviteActivity.launch(account, activity);
- }
-
- @Override
- void refresh() {
- if (this.binding == null || this.activity == null) {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.refresh() skipped updated because view binding or activity was null");
- return;
- }
- this.activity.xmppConnectionService.populateWithOrderedConversations(this.conversations);
- Conversation removed = this.swipedConversation.peek();
- if (removed != null) {
- if (removed.isRead()) {
- this.conversations.remove(removed);
- } else {
- pendingActionHelper.execute();
- }
- }
- this.conversationsAdapter.notifyDataSetChanged();
- ScrollState scrollState = pendingScrollState.pop();
- if (scrollState != null) {
- setScrollPosition(scrollState);
- }
- }
-
- private void setScrollPosition(ScrollState scrollPosition) {
- if (scrollPosition != null) {
- LinearLayoutManager layoutManager = (LinearLayoutManager) binding.list.getLayoutManager();
- layoutManager.scrollToPositionWithOffset(scrollPosition.position, scrollPosition.offset);
- }
- }
+ @Override
+ public void onBackendConnected() {
+ refresh();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle bundle) {
+ super.onSaveInstanceState(bundle);
+ ScrollState scrollState = getScrollState();
+ if (scrollState != null) {
+ bundle.putParcelable(STATE_SCROLL_POSITION, scrollState);
+ }
+ }
+
+ private ScrollState getScrollState() {
+ if (this.binding == null) {
+ return null;
+ }
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager) this.binding.list.getLayoutManager();
+ int position = layoutManager.findFirstVisibleItemPosition();
+ final View view = this.binding.list.getChildAt(0);
+ if (view != null) {
+ return new ScrollState(position, view.getTop());
+ } else {
+ return new ScrollState(position, 0);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onStart()");
+ if (activity.xmppConnectionService != null) {
+ refresh();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (MenuDoubleTabUtil.shouldIgnoreTap()) {
+ return false;
+ }
+ switch (item.getItemId()) {
+ case R.id.action_search:
+ startActivity(new Intent(getActivity(), SearchActivity.class));
+ return true;
+ case R.id.action_easy_invite:
+ selectAccountToStartEasyInvite();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void selectAccountToStartEasyInvite() {
+ final List<Account> accounts =
+ EasyOnboardingInvite.getSupportingAccounts(activity.xmppConnectionService);
+ if (accounts.isEmpty()) {
+ // This can technically happen if opening the menu item races with accounts reconnecting
+ // or something
+ Toast.makeText(
+ getActivity(),
+ R.string.no_active_accounts_support_this,
+ Toast.LENGTH_LONG)
+ .show();
+ } else if (accounts.size() == 1) {
+ openEasyInviteScreen(accounts.get(0));
+ } else {
+ final AtomicReference<Account> selectedAccount = new AtomicReference<>(accounts.get(0));
+ final MaterialAlertDialogBuilder alertDialogBuilder =
+ new MaterialAlertDialogBuilder(activity);
+ alertDialogBuilder.setTitle(R.string.choose_account);
+ final String[] asStrings =
+ Collections2.transform(accounts, a -> a.getJid().asBareJid().toString())
+ .toArray(new String[0]);
+ alertDialogBuilder.setSingleChoiceItems(
+ asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
+ alertDialogBuilder.setNegativeButton(R.string.cancel, null);
+ alertDialogBuilder.setPositiveButton(
+ R.string.ok, (dialog, which) -> openEasyInviteScreen(selectedAccount.get()));
+ alertDialogBuilder.create().show();
+ }
+ }
+
+ private void openEasyInviteScreen(final Account account) {
+ EasyOnboardingInviteActivity.launch(account, activity);
+ }
+
+ @Override
+ void refresh() {
+ if (this.binding == null || this.activity == null) {
+ Log.d(
+ Config.LOGTAG,
+ "ConversationsOverviewFragment.refresh() skipped updated because view binding"
+ + " or activity was null");
+ return;
+ }
+ this.activity.xmppConnectionService.populateWithOrderedConversations(this.conversations);
+ Conversation removed = this.swipedConversation.peek();
+ if (removed != null) {
+ if (removed.isRead()) {
+ this.conversations.remove(removed);
+ } else {
+ pendingActionHelper.execute();
+ }
+ }
+ this.conversationsAdapter.notifyDataSetChanged();
+ ScrollState scrollState = pendingScrollState.pop();
+ if (scrollState != null) {
+ setScrollPosition(scrollState);
+ }
+ }
+
+ private void setScrollPosition(ScrollState scrollPosition) {
+ if (scrollPosition != null) {
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager) binding.list.getLayoutManager();
+ layoutManager.scrollToPositionWithOffset(
+ scrollPosition.position, scrollPosition.offset);
+ }
+ }
}
@@ -11,18 +11,11 @@ import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
-
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.Collection;
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogCreatePublicChannelBinding;
import eu.siacs.conversations.entities.Account;
@@ -33,10 +26,14 @@ import eu.siacs.conversations.ui.util.DelayedHintHelper;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
public class CreatePublicChannelDialog extends DialogFragment implements OnBackendConnected {
- private static final char[] FORBIDDEN = new char[]{'\u0022','&','\'','/',':','<','>','@'};
+ private static final char[] FORBIDDEN =
+ new char[] {'\u0022', '&', '\'', '/', ':', '<', '>', '@'};
private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
private CreatePublicChannelDialogListener mListener;
@@ -62,48 +59,56 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- jidWasModified = savedInstanceState != null && savedInstanceState.getBoolean("jid_was_modified_false", false);
- nameEntered = savedInstanceState != null && savedInstanceState.getBoolean("name_entered", false);
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
+ jidWasModified =
+ savedInstanceState != null
+ && savedInstanceState.getBoolean("jid_was_modified_false", false);
+ nameEntered =
+ savedInstanceState != null && savedInstanceState.getBoolean("name_entered", false);
+ final MaterialAlertDialogBuilder builder =
+ new MaterialAlertDialogBuilder(requireActivity());
builder.setTitle(R.string.create_public_channel);
- final DialogCreatePublicChannelBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.dialog_create_public_channel, null, false);
- binding.account.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- updateJidSuggestion(binding);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
-
- }
- });
- binding.jid.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
-
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (skipTetxWatcher) {
- return;
- }
- if (jidWasModified) {
- jidWasModified = !TextUtils.isEmpty(s);
- } else {
- jidWasModified = !s.toString().equals(getJidSuggestion(binding));
- }
- }
- });
- updateInputs(binding,false);
+ final DialogCreatePublicChannelBinding binding =
+ DataBindingUtil.inflate(
+ getActivity().getLayoutInflater(),
+ R.layout.dialog_create_public_channel,
+ null,
+ false);
+ binding.account.setOnItemSelectedListener(
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(
+ AdapterView<?> parent, View view, int position, long id) {
+ updateJidSuggestion(binding);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {}
+ });
+ binding.jid.addTextChangedListener(
+ new TextWatcher() {
+ @Override
+ public void beforeTextChanged(
+ CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (skipTetxWatcher) {
+ return;
+ }
+ if (jidWasModified) {
+ jidWasModified = !TextUtils.isEmpty(s);
+ } else {
+ jidWasModified = !s.toString().equals(getJidSuggestion(binding));
+ }
+ }
+ });
+ updateInputs(binding, 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(nameEntered ? R.string.create : R.string.next, null);
builder.setNegativeButton(nameEntered ? R.string.back : R.string.cancel, null);
@@ -111,14 +116,18 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
binding.jid.setAdapter(knownHostsAdapter);
final AlertDialog dialog = builder.create();
- binding.groupChatName.setOnEditorActionListener((v, actionId, event) -> {
- submit(dialog, binding);
- return true;
- });
- dialog.setOnShowListener(dialogInterface -> {
- dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(v -> goBack(dialog, binding));
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> submit(dialog, binding));
- });
+ binding.groupChatName.setOnEditorActionListener(
+ (v, actionId, event) -> {
+ submit(dialog, binding);
+ return true;
+ });
+ dialog.setOnShowListener(
+ dialogInterface -> {
+ dialog.getButton(DialogInterface.BUTTON_NEGATIVE)
+ .setOnClickListener(v -> goBack(dialog, binding));
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .setOnClickListener(v -> submit(dialog, binding));
+ });
return dialog;
}
@@ -134,13 +143,15 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
@Override
public void onSaveInstanceState(Bundle outState) {
- outState.putBoolean("jid_was_modified",jidWasModified);
+ outState.putBoolean("jid_was_modified", jidWasModified);
outState.putBoolean("name_entered", nameEntered);
super.onSaveInstanceState(outState);
}
private static String getJidSuggestion(final DialogCreatePublicChannelBinding binding) {
- final Account account = StartConversationActivity.getSelectedAccount(binding.getRoot().getContext(), binding.account);
+ final Account account =
+ StartConversationActivity.getSelectedAccount(
+ binding.getRoot().getContext(), binding.account);
final XmppConnection connection = account == null ? null : account.getXmppConnection();
if (connection == null) {
return "";
@@ -156,18 +167,18 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
return "";
} else {
try {
- return Jid.of(localpart, domain, null).toEscapedString();
+ return Jid.of(localpart, domain, null).toString();
} catch (IllegalArgumentException e) {
- return Jid.of(CryptoHelper.pronounceable(), domain, null).toEscapedString();
+ return Jid.of(CryptoHelper.pronounceable(), domain, null).toString();
}
}
}
private static String clean(String name) {
- for(char c : FORBIDDEN) {
- name = name.replace(String.valueOf(c),"");
+ for (char c : FORBIDDEN) {
+ name = name.replace(String.valueOf(c), "");
}
- return name.replaceAll("\\s+","-");
+ return name.replaceAll("\\s+", "-");
}
private void goBack(AlertDialog dialog, DialogCreatePublicChannelBinding binding) {
@@ -189,22 +200,26 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
if (nameEntered) {
binding.nameLayout.setError(null);
if (address.isEmpty()) {
- binding.xmppAddressLayout.setError(context.getText(R.string.please_enter_xmpp_address));
+ binding.xmppAddressLayout.setError(
+ context.getText(R.string.please_enter_xmpp_address));
} else {
final Jid jid;
try {
- jid = Jid.ofEscaped(address);
- } catch (IllegalArgumentException e) {
+ jid = Jid.ofUserInput(address);
+ } catch (final IllegalArgumentException e) {
binding.xmppAddressLayout.setError(context.getText(R.string.invalid_jid));
return;
}
- final Account account = StartConversationActivity.getSelectedAccount(context, binding.account);
+ final Account account =
+ StartConversationActivity.getSelectedAccount(context, binding.account);
if (account == null) {
return;
}
- final XmppConnectionService service = ((XmppActivity )context).xmppConnectionService;
+ final XmppConnectionService service =
+ ((XmppActivity) context).xmppConnectionService;
if (service != null && service.findFirstMuc(jid) != null) {
- binding.xmppAddressLayout.setError(context.getString(R.string.channel_already_exists));
+ binding.xmppAddressLayout.setError(
+ context.getString(R.string.channel_already_exists));
return;
}
mListener.onCreatePublicChannel(account, name, jid);
@@ -214,7 +229,7 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
binding.xmppAddressLayout.setError(null);
if (name.isEmpty()) {
binding.nameLayout.setError(context.getText(R.string.please_enter_name));
- } else if (StartConversationActivity.isValidJid(name)){
+ } else if (StartConversationActivity.isValidJid(name)) {
binding.nameLayout.setError(context.getText(R.string.this_is_an_xmpp_address));
} else {
binding.nameLayout.setError(null);
@@ -227,8 +242,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
}
}
-
- private void updateInputs(final DialogCreatePublicChannelBinding binding, final boolean requestFocus) {
+ private void updateInputs(
+ final DialogCreatePublicChannelBinding binding, final boolean requestFocus) {
binding.xmppAddressLayout.setVisibility(nameEntered ? View.VISIBLE : View.GONE);
binding.nameLayout.setVisibility(nameEntered ? View.GONE : View.VISIBLE);
if (!requestFocus) {
@@ -256,7 +271,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
private void refreshKnownHosts() {
Activity activity = getActivity();
if (activity instanceof XmppActivity) {
- Collection<String> hosts = ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts();
+ Collection<String> hosts =
+ ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts();
this.knownHostsAdapter.refresh(hosts);
}
}
@@ -271,8 +287,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
try {
mListener = (CreatePublicChannelDialogListener) context;
} catch (ClassCastException e) {
- throw new ClassCastException(context.toString()
- + " must implement CreateConferenceDialogListener");
+ throw new ClassCastException(
+ context.toString() + " must implement CreateConferenceDialogListener");
}
}
@@ -280,7 +296,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
public void onStart() {
super.onStart();
final Activity activity = getActivity();
- if (activity instanceof XmppActivity && ((XmppActivity) activity).xmppConnectionService != null) {
+ if (activity instanceof XmppActivity
+ && ((XmppActivity) activity).xmppConnectionService != null) {
refreshKnownHosts();
}
}
@@ -29,19 +29,16 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Lifecycle;
-
import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
-
import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -79,15 +76,12 @@ import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.XmppConnection.Features;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.pep.Avatar;
-
-import okhttp3.HttpUrl;
-
-import org.openintents.openpgp.util.OpenPgpUtils;
-
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import okhttp3.HttpUrl;
+import org.openintents.openpgp.util.OpenPgpUtils;
public class EditAccountActivity extends OmemoActivity
implements OnAccountUpdate,
@@ -144,8 +138,7 @@ public class EditAccountActivity extends OmemoActivity
new Intent(
getApplicationContext(),
PublishProfilePictureActivity.class);
- intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
startActivity(intent);
}
}
@@ -259,12 +252,12 @@ public class EditAccountActivity extends OmemoActivity
try {
if (mUsernameMode) {
jid =
- Jid.ofEscaped(
+ Jid.of(
binding.accountJid.getText().toString(),
getUserModeDomain(),
null);
} else {
- jid = Jid.ofEscaped(binding.accountJid.getText().toString());
+ jid = Jid.ofUserInput(binding.accountJid.getText().toString());
Resolver.checkDomain(jid);
}
} catch (final NullPointerException | IllegalArgumentException e) {
@@ -539,15 +532,13 @@ public class EditAccountActivity extends OmemoActivity
if (wasFirstAccount) {
intent.putExtra("init", true);
}
- intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
} else {
intent =
new Intent(
getApplicationContext(),
PublishProfilePictureActivity.class);
- intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
intent.putExtra("setup", true);
}
if (wasFirstAccount) {
@@ -700,9 +691,9 @@ public class EditAccountActivity extends OmemoActivity
protected boolean jidEdited() {
final String unmodified;
if (mUsernameMode) {
- unmodified = this.mAccount.getJid().getEscapedLocal();
+ unmodified = this.mAccount.getJid().getLocal();
} else {
- unmodified = this.mAccount.getJid().asBareJid().toEscapedString();
+ unmodified = this.mAccount.getJid().asBareJid().toString();
}
return !unmodified.equals(this.binding.accountJid.getText().toString());
}
@@ -824,7 +815,7 @@ public class EditAccountActivity extends OmemoActivity
final Intent intent = getIntent();
if (intent != null) {
try {
- this.jidToEdit = Jid.ofEscaped(intent.getStringExtra("jid"));
+ this.jidToEdit = Jid.of(intent.getStringExtra("jid"));
} catch (final IllegalArgumentException | NullPointerException ignored) {
this.jidToEdit = null;
}
@@ -929,8 +920,7 @@ public class EditAccountActivity extends OmemoActivity
@Override
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
if (mAccount != null) {
- savedInstanceState.putString(
- "account", mAccount.getJid().asBareJid().toEscapedString());
+ savedInstanceState.putString("account", mAccount.getJid().asBareJid().toString());
savedInstanceState.putBoolean("initMode", mInitMode);
savedInstanceState.putBoolean(
"showMoreTable", binding.serverInfoMore.getVisibility() == View.VISIBLE);
@@ -943,8 +933,7 @@ public class EditAccountActivity extends OmemoActivity
if (mSavedInstanceAccount != null) {
try {
this.mAccount =
- xmppConnectionService.findAccountByJid(
- Jid.ofEscaped(mSavedInstanceAccount));
+ xmppConnectionService.findAccountByJid(Jid.of(mSavedInstanceAccount));
this.mInitMode = mSavedInstanceInit;
init = false;
} catch (IllegalArgumentException e) {
@@ -1010,7 +999,7 @@ public class EditAccountActivity extends OmemoActivity
break;
case R.id.action_show_block_list:
final Intent showBlocklistIntent = new Intent(this, BlocklistActivity.class);
- showBlocklistIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toEscapedString());
+ showBlocklistIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
startActivity(showBlocklistIntent);
break;
case R.id.action_server_info_show_more:
@@ -1070,7 +1059,7 @@ public class EditAccountActivity extends OmemoActivity
private void gotoChangePassword() {
final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
- changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toEscapedString());
+ changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
startActivity(changePasswordIntent);
}
@@ -1167,15 +1156,12 @@ public class EditAccountActivity extends OmemoActivity
if (init) {
this.binding.accountJid.getEditableText().clear();
if (mUsernameMode) {
- this.binding
- .accountJid
- .getEditableText()
- .append(this.mAccount.getJid().getEscapedLocal());
+ this.binding.accountJid.getEditableText().append(this.mAccount.getJid().getLocal());
} else {
this.binding
.accountJid
.getEditableText()
- .append(this.mAccount.getJid().asBareJid().toEscapedString());
+ .append(this.mAccount.getJid().asBareJid().toString());
}
this.binding.accountPassword.getEditableText().clear();
this.binding.accountPassword.getEditableText().append(this.mAccount.getPassword());
@@ -7,21 +7,12 @@ import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.ArrayAdapter;
-
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.common.base.Strings;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogEnterJidBinding;
import eu.siacs.conversations.services.XmppConnectionService;
@@ -29,6 +20,11 @@ import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
import eu.siacs.conversations.ui.util.DelayedHintHelper;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
public class EnterJidDialog extends DialogFragment implements OnBackendConnected, TextWatcher {
@@ -95,10 +91,15 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final var arguments = getArguments();
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
+ final MaterialAlertDialogBuilder builder =
+ new MaterialAlertDialogBuilder(requireActivity());
builder.setTitle(arguments.getString(TITLE_KEY));
binding =
- DataBindingUtil.inflate(requireActivity().getLayoutInflater(), R.layout.dialog_enter_jid, null, false);
+ DataBindingUtil.inflate(
+ requireActivity().getLayoutInflater(),
+ R.layout.dialog_enter_jid,
+ null,
+ false);
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
binding.jid.setAdapter(this.knownHostsAdapter);
binding.jid.addTextChangedListener(this);
@@ -124,7 +125,8 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
binding.account);
} else {
final ArrayAdapter<String> adapter =
- new ArrayAdapter<>(requireActivity(), R.layout.item_autocomplete, new String[] {account});
+ new ArrayAdapter<>(
+ requireActivity(), R.layout.item_autocomplete, new String[] {account});
binding.account.setText(account);
binding.account.setEnabled(false);
adapter.setDropDownViewResource(R.layout.item_autocomplete);
@@ -136,8 +138,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
builder.setPositiveButton(getArguments().getString(POSITIVE_BUTTON_KEY), null);
this.dialog = builder.create();
- View.OnClickListener dialogOnClick =
- v -> handleEnter(binding, account);
+ View.OnClickListener dialogOnClick = v -> handleEnter(binding, account);
binding.jid.setOnEditorActionListener(
(v, actionId, event) -> {
@@ -156,13 +157,13 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
return;
}
try {
- accountJid = Jid.ofEscaped((String) binding.account.getEditableText().toString());
+ accountJid = Jid.of(binding.account.getEditableText().toString());
} catch (final IllegalArgumentException e) {
return;
}
final Jid contactJid;
try {
- contactJid = Jid.ofEscaped(binding.jid.getText().toString().trim());
+ contactJid = Jid.ofUserInput(binding.jid.getText().toString().trim());
} catch (final IllegalArgumentException e) {
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
return;
@@ -176,7 +177,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
issuedWarning = true;
return;
}
- if (suspiciousSubDomain(contactJid.getDomain().toEscapedString())) {
+ if (suspiciousSubDomain(contactJid.getDomain().toString())) {
binding.jidLayout.setError(
getActivity().getString(R.string.this_looks_like_channel));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
@@ -3,11 +3,7 @@ package eu.siacs.conversations.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-
import androidx.databinding.DataBindingUtil;
-
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityMediaBrowserBinding;
import eu.siacs.conversations.entities.Account;
@@ -18,6 +14,7 @@ import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.GridManager;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.List;
public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded {
@@ -28,20 +25,17 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- this.binding = DataBindingUtil.setContentView(this,R.layout.activity_media_browser);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_media_browser);
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
setSupportActionBar(binding.toolbar);
configureActionBar(getSupportActionBar());
mMediaAdapter = new MediaAdapter(this, R.dimen.media_size);
this.binding.media.setAdapter(mMediaAdapter);
GridManager.setupLayoutManager(this, this.binding.media, R.dimen.browser_media_size);
-
}
@Override
- protected void refreshUiReal() {
-
- }
+ protected void refreshUiReal() {}
@Override
protected void onBackendConnected() {
@@ -49,29 +43,30 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
String account = intent == null ? null : intent.getStringExtra("account");
String jid = intent == null ? null : intent.getStringExtra("jid");
if (account != null && jid != null) {
- xmppConnectionService.getAttachments(account, Jid.ofEscaped(jid), 0, this);
+ xmppConnectionService.getAttachments(account, Jid.of(jid), 0, this);
}
}
public static void launch(Context context, Contact contact) {
- launch(context, contact.getAccount(), contact.getJid().asBareJid().toEscapedString());
+ launch(context, contact.getAccount(), contact.getJid().asBareJid().toString());
}
public static void launch(Context context, Conversation conversation) {
- launch(context, conversation.getAccount(), conversation.getJid().asBareJid().toEscapedString());
+ launch(context, conversation.getAccount(), conversation.getJid().asBareJid().toString());
}
private static void launch(Context context, Account account, String jid) {
final Intent intent = new Intent(context, MediaBrowserActivity.class);
- intent.putExtra("account",account.getUuid());
- intent.putExtra("jid",jid);
+ intent.putExtra("account", account.getUuid());
+ intent.putExtra("jid", jid);
context.startActivity(intent);
}
@Override
public void onMediaLoaded(List<Attachment> attachments) {
- runOnUiThread(()->{
- mMediaAdapter.setAttachments(attachments);
- });
+ runOnUiThread(
+ () -> {
+ mMediaAdapter.setAttachments(attachments);
+ });
}
}
@@ -60,8 +60,7 @@ public class PublishProfilePictureActivity extends XmppActivity
getApplicationContext(), StartConversationActivity.class);
StartConversationActivity.addInviteUri(intent, getIntent());
intent.putExtra("init", true);
- intent.putExtra(
- EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
startActivity(intent);
}
Toast.makeText(
@@ -118,8 +117,7 @@ public class PublishProfilePictureActivity extends XmppActivity
}
StartConversationActivity.addInviteUri(intent, getIntent());
if (account != null) {
- intent.putExtra(
- EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
}
startActivity(intent);
}
@@ -1,7 +1,6 @@
package eu.siacs.conversations.ui;
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
-
import static java.util.Arrays.asList;
import android.Manifest;
@@ -25,13 +24,11 @@ import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
@@ -41,7 +38,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityRtpSessionBinding;
@@ -65,16 +61,14 @@ import eu.siacs.conversations.xmpp.jingle.Media;
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
-
-import org.webrtc.RendererCommon;
-import org.webrtc.SurfaceViewRenderer;
-import org.webrtc.VideoTrack;
-
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import org.webrtc.RendererCommon;
+import org.webrtc.SurfaceViewRenderer;
+import org.webrtc.VideoTrack;
public class RtpSessionActivity extends XmppActivity
implements XmppConnectionService.OnJingleRtpConnectionUpdate,
@@ -300,7 +294,7 @@ public class RtpSessionActivity extends XmppActivity
final String action = intent.getAction();
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final String state = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
if (!Intent.ACTION_VIEW.equals(action)
|| state == null
@@ -504,7 +498,7 @@ public class RtpSessionActivity extends XmppActivity
Log.d(Config.LOGTAG, "initializeWithIntent(" + event + "," + action + ")");
final Account account = extractAccount(intent);
final var extraWith = intent.getStringExtra(EXTRA_WITH);
- final Jid with = Strings.isNullOrEmpty(extraWith) ? null : Jid.ofEscaped(extraWith);
+ final Jid with = Strings.isNullOrEmpty(extraWith) ? null : Jid.of(extraWith);
if (with == null || account == null) {
Log.e(Config.LOGTAG, "intent is missing extras (account or with)");
return;
@@ -573,7 +567,7 @@ public class RtpSessionActivity extends XmppActivity
binding.with.setText(contact.getDisplayName());
if (Arrays.asList(RtpEndUserState.INCOMING_CALL, RtpEndUserState.ACCEPTING_CALL)
.contains(state)) {
- binding.withJid.setText(contact.getJid().asBareJid().toEscapedString());
+ binding.withJid.setText(contact.getJid().asBareJid().toString());
binding.withJid.setVisibility(View.VISIBLE);
} else {
binding.withJid.setVisibility(View.GONE);
@@ -776,7 +770,8 @@ public class RtpSessionActivity extends XmppActivity
.getTerminalSessionState(with, sessionId);
if (terminatedRtpSession == null) {
throw new IllegalStateException(
- "failed to initialize activity with running rtp session. session not found");
+ "failed to initialize activity with running rtp session. session not"
+ + " found");
}
initializeWithTerminatedSessionState(account, with, terminatedRtpSession);
return true;
@@ -837,8 +832,8 @@ public class RtpSessionActivity extends XmppActivity
private void resetIntent(final Account account, final Jid with, final String sessionId) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
- intent.putExtra(EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().toString());
+ intent.putExtra(EXTRA_WITH, with.toString());
intent.putExtra(EXTRA_SESSION_ID, sessionId);
setIntent(intent);
}
@@ -895,10 +890,12 @@ public class RtpSessionActivity extends XmppActivity
case RETRACTED -> setTitle(R.string.rtp_state_retracted);
case APPLICATION_ERROR -> setTitle(R.string.rtp_state_application_failure);
case SECURITY_ERROR -> setTitle(R.string.rtp_state_security_error);
- case ENDED -> throw new IllegalStateException(
- "Activity should have called finishAndReleaseWakeLock();");
- default -> throw new IllegalStateException(
- String.format("State %s has not been handled in UI", state));
+ case ENDED ->
+ throw new IllegalStateException(
+ "Activity should have called finishAndReleaseWakeLock();");
+ default ->
+ throw new IllegalStateException(
+ String.format("State %s has not been handled in UI", state));
}
}
@@ -932,9 +929,7 @@ public class RtpSessionActivity extends XmppActivity
final Account account = contact == null ? getWith().getAccount() : contact.getAccount();
binding.usingAccount.setVisibility(View.VISIBLE);
binding.usingAccount.setText(
- getString(
- R.string.using_account,
- account.getJid().asBareJid().toEscapedString()));
+ getString(R.string.using_account, account.getJid().asBareJid().toString()));
} else {
binding.usingAccount.setVisibility(View.GONE);
binding.contactPhoto.setVisibility(View.GONE);
@@ -1430,12 +1425,12 @@ public class RtpSessionActivity extends XmppActivity
private void retry(final View view) {
final Intent intent = getIntent();
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
final String action = intent.getAction();
final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
this.rtpConnectionReference = null;
- Log.d(Config.LOGTAG, "attempting retry with " + with.toEscapedString());
+ Log.d(Config.LOGTAG, "attempting retry with " + with.toString());
CallIntegrationConnectionService.placeCall(xmppConnectionService, account, with, media);
}
@@ -1446,7 +1441,7 @@ public class RtpSessionActivity extends XmppActivity
private void recordVoiceMail(final View view) {
final Intent intent = getIntent();
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final Conversation conversation =
xmppConnectionService.findOrCreateConversation(account, with, false, true);
final Intent launchIntent = new Intent(this, ConversationsActivity.class);
@@ -1611,7 +1606,7 @@ public class RtpSessionActivity extends XmppActivity
return;
}
final Set<Media> media = actionToMedia(currentIntent.getStringExtra(EXTRA_LAST_ACTION));
- if (Jid.ofEscaped(withExtra).asBareJid().equals(with)) {
+ if (Jid.of(withExtra).asBareJid().equals(with)) {
runOnUiThread(
() -> {
updateVerifiedShield(false);
@@ -1634,11 +1629,11 @@ public class RtpSessionActivity extends XmppActivity
private void resetIntent(
final Account account, Jid with, final RtpEndUserState state, final Set<Media> media) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().toString());
if (RtpCapability.jmiSupport(account.getRoster().getContact(with))) {
- intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_WITH, with.asBareJid().toString());
} else {
- intent.putExtra(EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(EXTRA_WITH, with.toString());
}
intent.putExtra(EXTRA_LAST_REPORTED_STATE, state.toString());
intent.putExtra(
@@ -216,7 +216,7 @@ public class ShareWithActivity extends XmppActivity
final Conversation conversation;
Account account;
try {
- account = xmppConnectionService.findAccountByJid(Jid.ofEscaped(share.account));
+ account = xmppConnectionService.findAccountByJid(Jid.of(share.account));
} catch (final IllegalArgumentException e) {
account = null;
}
@@ -36,7 +36,6 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
-
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -52,7 +51,6 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
-
import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
@@ -60,7 +58,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.leinardi.android.speeddial.SpeedDialActionItem;
import com.leinardi.android.speeddial.SpeedDialView;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -87,7 +84,6 @@ import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.XmppConnection;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -359,7 +355,7 @@ public class StartConversationActivity extends XmppActivity
mSearchEditText != null ? mSearchEditText.getText().toString() : null;
final String prefilled;
if (isValidJid(searchString)) {
- prefilled = Jid.ofEscaped(searchString).toEscapedString();
+ prefilled = Jid.of(searchString).toString();
} else {
prefilled = null;
}
@@ -418,14 +414,15 @@ public class StartConversationActivity extends XmppActivity
.create();
speedDialView.addActionItem(actionItem);
}
- speedDialView.setContentDescription(getString(R.string.add_contact_or_create_or_join_group_chat));
+ speedDialView.setContentDescription(
+ getString(R.string.add_contact_or_create_or_join_group_chat));
}
- public static boolean isValidJid(String input) {
+ public static boolean isValidJid(final String input) {
try {
- Jid jid = Jid.ofEscaped(input);
+ final Jid jid = Jid.ofUserInput(input);
return !jid.isDomainJid();
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
return false;
}
}
@@ -505,7 +502,7 @@ public class StartConversationActivity extends XmppActivity
protected void shareBookmarkUri(int position) {
Bookmark bookmark = (Bookmark) conferences.get(position);
- shareAsChannel(this, bookmark.getJid().asBareJid().toEscapedString());
+ shareAsChannel(this, bookmark.getJid().asBareJid().toString());
}
public static void shareAsChannel(final Context context, final String address) {
@@ -549,7 +546,7 @@ public class StartConversationActivity extends XmppActivity
protected void showQrForContact() {
int position = contact_context_id;
Contact contact = (Contact) contacts.get(position);
- showQrCode("xmpp:" + contact.getJid().asBareJid().toEscapedString());
+ showQrCode("xmpp:" + contact.getJid().asBareJid().toString());
}
protected void toggleContactBlock() {
@@ -564,8 +561,7 @@ public class StartConversationActivity extends XmppActivity
builder.setNegativeButton(R.string.cancel, null);
builder.setTitle(R.string.action_delete_contact);
builder.setMessage(
- JidDialog.style(
- this, R.string.remove_contact_text, contact.getJid().toEscapedString()));
+ JidDialog.style(this, R.string.remove_contact_text, contact.getJid().toString()));
builder.setPositiveButton(
R.string.delete,
(dialog, which) -> {
@@ -588,11 +584,10 @@ public class StartConversationActivity extends XmppActivity
JidDialog.style(
this,
R.string.remove_bookmark_and_close,
- bookmark.getJid().toEscapedString()));
+ bookmark.getJid().toString()));
} else {
builder.setMessage(
- JidDialog.style(
- this, R.string.remove_bookmark, bookmark.getJid().toEscapedString()));
+ JidDialog.style(this, R.string.remove_bookmark, bookmark.getJid().toString()));
}
builder.setPositiveButton(
hasConversation ? R.string.delete_and_close : R.string.delete,
@@ -710,7 +705,7 @@ public class StartConversationActivity extends XmppActivity
if (context instanceof XmppActivity) {
final Jid jid;
try {
- jid = Jid.ofEscaped(spinner.getText().toString());
+ jid = Jid.of(spinner.getText().toString());
} catch (final IllegalArgumentException e) {
return null;
}
@@ -1078,11 +1073,11 @@ public class StartConversationActivity extends XmppActivity
switchToConversationDoNotAppend(muc, invite.getBody());
return true;
} else {
- showJoinConferenceDialog(invite.getJid().asBareJid().toEscapedString());
+ showJoinConferenceDialog(invite.getJid().asBareJid().toString());
return false;
}
- } else if (contacts.size() == 0) {
- showCreateContactDialog(invite.getJid().toEscapedString(), invite);
+ } else if (contacts.isEmpty()) {
+ showCreateContactDialog(invite.getJid().toString(), invite);
return false;
} else if (contacts.size() == 1) {
Contact contact = contacts.get(0);
@@ -1106,10 +1101,10 @@ public class StartConversationActivity extends XmppActivity
if (mMenuSearchView != null) {
mMenuSearchView.expandActionView();
mSearchEditText.setText("");
- mSearchEditText.append(invite.getJid().toEscapedString());
- filter(invite.getJid().toEscapedString());
+ mSearchEditText.append(invite.getJid().toString());
+ filter(invite.getJid().toString());
} else {
- mInitialSearchValue.push(invite.getJid().toEscapedString());
+ mInitialSearchValue.push(invite.getJid().toString());
}
return true;
}
@@ -1125,7 +1120,7 @@ public class StartConversationActivity extends XmppActivity
JidDialog.style(
this,
R.string.verifying_omemo_keys_trusted_source,
- contact.getJid().asBareJid().toEscapedString(),
+ contact.getJid().asBareJid().toString(),
contact.getDisplayName()));
builder.setView(view);
builder.setPositiveButton(
@@ -1237,8 +1232,7 @@ public class StartConversationActivity extends XmppActivity
intent.putExtra(ChooseContactActivity.EXTRA_SELECT_MULTIPLE, true);
intent.putExtra(ChooseContactActivity.EXTRA_GROUP_CHAT_NAME, name.trim());
intent.putExtra(
- ChooseContactActivity.EXTRA_ACCOUNT,
- account.getJid().asBareJid().toEscapedString());
+ ChooseContactActivity.EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
intent.putExtra(ChooseContactActivity.EXTRA_TITLE_RES_ID, R.string.choose_participants);
startActivityForResult(intent, REQUEST_CREATE_CONFERENCE);
}
@@ -1259,13 +1253,13 @@ public class StartConversationActivity extends XmppActivity
final String input = jid.getText().toString().trim();
Jid conferenceJid;
try {
- conferenceJid = Jid.ofEscaped(input);
+ conferenceJid = Jid.ofUserInput(input);
} catch (final IllegalArgumentException e) {
final XmppUri xmppUri = new XmppUri(input);
if (xmppUri.isValidJid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) {
final Editable editable = jid.getEditableText();
editable.clear();
- editable.append(xmppUri.getJid().toEscapedString());
+ editable.append(xmppUri.getJid().toString());
conferenceJid = xmppUri.getJid();
} else {
layout.setError(getString(R.string.invalid_jid));
@@ -1,6 +1,5 @@
package eu.siacs.conversations.ui;
-import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -10,12 +9,9 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
-
import androidx.appcompat.app.ActionBar;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.OmemoSetting;
@@ -32,429 +28,515 @@ import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
-
-import org.whispersystems.libsignal.IdentityKey;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.whispersystems.libsignal.IdentityKey;
public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated {
- private final Map<String, Boolean> ownKeysToTrust = new HashMap<>();
- private final Map<Jid, Map<String, Boolean>> foreignKeysToTrust = new HashMap<>();
- private final OnClickListener mCancelButtonListener = v -> {
- setResult(RESULT_CANCELED);
- finish();
- };
- private List<Jid> contactJids;
- private Account mAccount;
- private Conversation mConversation;
- private final OnClickListener mSaveButtonListener = v -> {
- commitTrusts();
- finishOk(false);
- };
- private final AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
- private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
- private Toast mUseCameraHintToast = null;
- private ActivityTrustKeysBinding binding;
-
- @Override
- protected void refreshUiReal() {
- invalidateOptionsMenu();
- populateView();
- }
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.binding = DataBindingUtil.setContentView(this, R.layout.activity_trust_keys);
- Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
- this.contactJids = new ArrayList<>();
- final var intent = getIntent();
- final String[] contacts = intent == null ? null : intent.getStringArrayExtra("contacts");
- for (final String jid : (contacts == null ? new String[0] : contacts)) {
- try {
- this.contactJids.add(Jid.of(jid));
- } catch (final IllegalArgumentException ignored) {
- }
- }
-
- binding.cancelButton.setOnClickListener(mCancelButtonListener);
- binding.saveButton.setOnClickListener(mSaveButtonListener);
-
- setSupportActionBar(binding.toolbar);
- configureActionBar(getSupportActionBar());
-
- if (savedInstanceState != null) {
- mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown", false));
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- savedInstanceState.putBoolean("camera_hint_shown", mUseCameraHintShown.get());
- super.onSaveInstanceState(savedInstanceState);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.trust_keys, menu);
- MenuItem scanQrCode = menu.findItem(R.id.action_scan_qr_code);
- scanQrCode.setVisible((!ownKeysToTrust.isEmpty() || foreignActuallyHasKeys()) && isCameraFeatureAvailable());
- return super.onCreateOptionsMenu(menu);
- }
-
- private void showCameraToast() {
- mUseCameraHintToast = Toast.makeText(this, R.string.use_camera_icon_to_scan_barcode, Toast.LENGTH_LONG);
- ActionBar actionBar = getSupportActionBar();
- mUseCameraHintToast.setGravity(Gravity.TOP | Gravity.END, 0, actionBar == null ? 0 : actionBar.getHeight());
- mUseCameraHintToast.show();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_scan_qr_code:
- if (hasPendingKeyFetches()) {
- Toast.makeText(this, R.string.please_wait_for_keys_to_be_fetched, Toast.LENGTH_SHORT).show();
- } else {
- ScanActivity.scan(this);
- //new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE"));
- return true;
- }
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (mUseCameraHintToast != null) {
- mUseCameraHintToast.cancel();
- }
- }
-
- @Override
- protected void processFingerprintVerification(XmppUri uri) {
- if (mConversation != null
- && mAccount != null
- && uri.hasFingerprints()
- && mAccount.getAxolotlService().getCryptoTargets(mConversation).contains(uri.getJid())) {
- boolean performedVerification = xmppConnectionService.verifyFingerprints(mAccount.getRoster().getContact(uri.getJid()), uri.getFingerprints());
- boolean keys = reloadFingerprints();
- if (performedVerification && !keys && !hasNoOtherTrustedKeys() && !hasPendingKeyFetches()) {
- Toast.makeText(this, R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT).show();
- finishOk(false);
- return;
- } else if (performedVerification) {
- Toast.makeText(this, R.string.verified_fingerprints, Toast.LENGTH_SHORT).show();
- }
- } else {
- reloadFingerprints();
- Log.d(Config.LOGTAG, "xmpp uri was: " + uri.getJid() + " has Fingerprints: " + uri.hasFingerprints());
- Toast.makeText(this, R.string.barcode_does_not_contain_fingerprints_for_this_chat, Toast.LENGTH_SHORT).show();
- }
- populateView();
- }
-
- private void populateView() {
- setTitle(getString(R.string.trust_omemo_fingerprints));
- binding.ownKeysDetails.removeAllViews();
- binding.foreignKeys.removeAllViews();
- boolean hasOwnKeys = false;
- boolean hasForeignKeys = false;
- for (final String fingerprint : ownKeysToTrust.keySet()) {
- hasOwnKeys = true;
- addFingerprintRowWithListeners(binding.ownKeysDetails, mAccount, fingerprint, false,
- FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, false,
- (buttonView, isChecked) -> {
- ownKeysToTrust.put(fingerprint, isChecked);
- // own fingerprints have no impact on locked status.
- }
- );
- }
-
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
- hasForeignKeys = true;
- KeysCardBinding keysCardBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.keys_card, binding.foreignKeys, false);
- final Jid jid = entry.getKey();
- keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this, jid));
- keysCardBinding.foreignKeysTitle.setOnClickListener(v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
- final Map<String, Boolean> fingerprints = entry.getValue();
- for (final String fingerprint : fingerprints.keySet()) {
- addFingerprintRowWithListeners(keysCardBinding.foreignKeysDetails, mAccount, fingerprint, false,
- FingerprintStatus.createActive(fingerprints.get(fingerprint)), false, false,
- (buttonView, isChecked) -> {
- fingerprints.put(fingerprint, isChecked);
- lockOrUnlockAsNeeded();
- }
- );
- }
- if (fingerprints.isEmpty()) {
- keysCardBinding.noKeysToAccept.setVisibility(View.VISIBLE);
- if (hasNoOtherTrustedKeys(jid)) {
- if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
- keysCardBinding.noKeysToAccept.setText(R.string.error_no_keys_to_trust_presence);
- } else {
- keysCardBinding.noKeysToAccept.setText(R.string.error_no_keys_to_trust_server_error);
- }
- } else {
- keysCardBinding.noKeysToAccept.setText(getString(R.string.no_keys_just_confirm, mAccount.getRoster().getContact(jid).getDisplayName()));
- }
- } else {
- keysCardBinding.noKeysToAccept.setVisibility(View.GONE);
- }
- binding.foreignKeys.addView(keysCardBinding.foreignKeysCard);
- }
- }
-
- if ((hasOwnKeys || foreignActuallyHasKeys()) && isCameraFeatureAvailable() && mUseCameraHintShown.compareAndSet(false, true)) {
- showCameraToast();
- }
-
- binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toEscapedString());
- binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
- binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
- if (hasPendingKeyFetches()) {
- setFetching();
- lock();
- } else {
- if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
- binding.keyErrorMessageCard.setVisibility(View.VISIBLE);
- boolean lastReportWasError = lastFetchReport == AxolotlService.FetchStatus.ERROR;
- boolean errorFetchingBundle = mAccount.getAxolotlService().fetchMapHasErrors(contactJids);
- boolean errorFetchingDeviceList = mAccount.getAxolotlService().hasErrorFetchingDeviceList(contactJids);
- boolean anyWithoutMutualPresenceSubscription = anyWithoutMutualPresenceSubscription(contactJids);
- if (errorFetchingDeviceList) {
- binding.keyErrorMessage.setVisibility(View.VISIBLE);
- binding.keyErrorMessage.setText(R.string.error_trustkey_device_list);
- } else if (errorFetchingBundle || lastReportWasError) {
- binding.keyErrorMessage.setVisibility(View.VISIBLE);
- binding.keyErrorMessage.setText(R.string.error_trustkey_bundle);
- } else {
- binding.keyErrorMessage.setVisibility(View.GONE);
- }
- this.binding.keyErrorHintMutual.setVisibility(anyWithoutMutualPresenceSubscription ? View.VISIBLE : View.GONE);
- Contact contact = mAccount.getRoster().getContact(contactJids.get(0));
- binding.keyErrorGeneral.setText(getString(R.string.error_trustkey_general, getString(R.string.app_name), contact.getDisplayName()));
- binding.ownKeysDetails.removeAllViews();
- if (OmemoSetting.isAlways()) {
- binding.disableButton.setVisibility(View.GONE);
- } else {
- binding.disableButton.setVisibility(View.VISIBLE);
- binding.disableButton.setOnClickListener(this::disableEncryptionDialog);
- }
- binding.ownKeysCard.setVisibility(View.GONE);
- binding.foreignKeys.removeAllViews();
- binding.foreignKeys.setVisibility(View.GONE);
- }
- lockOrUnlockAsNeeded();
- setDone();
- }
- }
-
- private void disableEncryptionDialog(final View view) {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setTitle(R.string.disable_encryption);
- builder.setMessage(R.string.disable_encryption_message);
- builder.setPositiveButton(R.string.disable_now, (dialog, which) -> {
- mConversation.setNextEncryption(Message.ENCRYPTION_NONE);
- xmppConnectionService.updateConversation(mConversation);
- finishOk(true);
- });
- builder.setNegativeButton(R.string.cancel, null);
- builder.create().show();
- }
-
- private boolean anyWithoutMutualPresenceSubscription(List<Jid> contactJids) {
- for (Jid jid : contactJids) {
- if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
- return true;
- }
- }
- return false;
- }
-
- private boolean foreignActuallyHasKeys() {
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
- if (!entry.getValue().isEmpty()) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean reloadFingerprints() {
- List<Jid> acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
- ownKeysToTrust.clear();
- if (this.mAccount == null) {
- return false;
- }
- AxolotlService service = this.mAccount.getAxolotlService();
- Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
- for (final IdentityKey identityKey : ownKeysSet) {
- final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
- if (!ownKeysToTrust.containsKey(fingerprint)) {
- ownKeysToTrust.put(fingerprint, false);
- }
- }
- synchronized (this.foreignKeysToTrust) {
- foreignKeysToTrust.clear();
- for (Jid jid : contactJids) {
- Set<IdentityKey> foreignKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), jid);
- if (hasNoOtherTrustedKeys(jid) && ownKeysSet.isEmpty()) {
- foreignKeysSet.addAll(service.getKeysWithTrust(FingerprintStatus.createActive(false), jid));
- }
- Map<String, Boolean> foreignFingerprints = new HashMap<>();
- for (final IdentityKey identityKey : foreignKeysSet) {
- final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
- if (!foreignFingerprints.containsKey(fingerprint)) {
- foreignFingerprints.put(fingerprint, false);
- }
- }
- if (!foreignFingerprints.isEmpty() || !acceptedTargets.contains(jid)) {
- foreignKeysToTrust.put(jid, foreignFingerprints);
- }
- }
- }
- return ownKeysSet.size() + foreignKeysToTrust.size() > 0;
- }
-
- public void onBackendConnected() {
- Intent intent = getIntent();
- this.mAccount = extractAccount(intent);
- if (this.mAccount != null && intent != null) {
- String uuid = intent.getStringExtra("conversation");
- this.mConversation = xmppConnectionService.findConversationByUuid(uuid);
- if (this.mPendingFingerprintVerificationUri != null) {
- processFingerprintVerification(this.mPendingFingerprintVerificationUri);
- this.mPendingFingerprintVerificationUri = null;
- } else {
- final boolean keysToTrust = reloadFingerprints();
- if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
- populateView();
- invalidateOptionsMenu();
- } else {
- finishOk(false);
- }
- }
- }
- }
-
- private boolean hasNoOtherTrustedKeys() {
- return mAccount == null || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids);
- }
-
- private boolean hasNoOtherTrustedKeys(Jid contact) {
- return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0;
- }
-
- private boolean hasPendingKeyFetches() {
- return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(contactJids);
- }
-
-
- @Override
- public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) {
- final boolean keysToTrust = reloadFingerprints();
- if (report != null) {
- lastFetchReport = report;
- runOnUiThread(() -> {
- if (mUseCameraHintToast != null && !keysToTrust) {
- mUseCameraHintToast.cancel();
- }
- switch (report) {
- case ERROR:
- Toast.makeText(TrustKeysActivity.this, R.string.error_fetching_omemo_key, Toast.LENGTH_SHORT).show();
- break;
- case SUCCESS_TRUSTED:
- Toast.makeText(TrustKeysActivity.this, R.string.blindly_trusted_omemo_keys, Toast.LENGTH_LONG).show();
- break;
- case SUCCESS_VERIFIED:
- Toast.makeText(TrustKeysActivity.this,
- Config.X509_VERIFICATION ? R.string.verified_omemo_key_with_certificate : R.string.all_omemo_keys_have_been_verified,
- Toast.LENGTH_LONG).show();
- break;
- }
- });
-
- }
- if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
- refreshUi();
- } else {
- runOnUiThread(() -> finishOk(false));
-
- }
- }
-
- private void finishOk(boolean disabled) {
- Intent data = new Intent();
- data.putExtra("choice", getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID));
- data.putExtra("disabled", disabled);
- setResult(RESULT_OK, data);
- finish();
- }
-
- private void commitTrusts() {
- for (final String fingerprint : ownKeysToTrust.keySet()) {
- mAccount.getAxolotlService().setFingerprintTrust(
- fingerprint,
- FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
- }
- List<Jid> acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
- Jid jid = entry.getKey();
- Map<String, Boolean> value = entry.getValue();
- if (!acceptedTargets.contains(jid)) {
- acceptedTargets.add(jid);
- }
- for (final String fingerprint : value.keySet()) {
- mAccount.getAxolotlService().setFingerprintTrust(
- fingerprint,
- FingerprintStatus.createActive(value.get(fingerprint)));
- }
- }
- }
- if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) {
- mConversation.setAcceptedCryptoTargets(acceptedTargets);
- xmppConnectionService.updateConversation(mConversation);
- }
- }
-
- private void unlock() {
- binding.saveButton.setEnabled(true);
- }
-
- private void lock() {
- binding.saveButton.setEnabled(false);
- }
-
- private void lockOrUnlockAsNeeded() {
- synchronized (this.foreignKeysToTrust) {
- for (Jid jid : contactJids) {
- Map<String, Boolean> fingerprints = foreignKeysToTrust.get(jid);
- if (hasNoOtherTrustedKeys(jid) && (fingerprints == null || !fingerprints.containsValue(true))) {
- lock();
- return;
- }
- }
- }
- unlock();
-
- }
-
- private void setDone() {
- binding.saveButton.setText(getString(R.string.done));
- }
-
- private void setFetching() {
- binding.saveButton.setText(getString(R.string.fetching_keys));
- }
+ private final Map<String, Boolean> ownKeysToTrust = new HashMap<>();
+ private final Map<Jid, Map<String, Boolean>> foreignKeysToTrust = new HashMap<>();
+ private final OnClickListener mCancelButtonListener =
+ v -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ };
+ private List<Jid> contactJids;
+ private Account mAccount;
+ private Conversation mConversation;
+ private final OnClickListener mSaveButtonListener =
+ v -> {
+ commitTrusts();
+ finishOk(false);
+ };
+ private final AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
+ private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
+ private Toast mUseCameraHintToast = null;
+ private ActivityTrustKeysBinding binding;
+
+ @Override
+ protected void refreshUiReal() {
+ invalidateOptionsMenu();
+ populateView();
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_trust_keys);
+ Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
+ this.contactJids = new ArrayList<>();
+ final var intent = getIntent();
+ final String[] contacts = intent == null ? null : intent.getStringArrayExtra("contacts");
+ for (final String jid : (contacts == null ? new String[0] : contacts)) {
+ try {
+ this.contactJids.add(Jid.of(jid));
+ } catch (final IllegalArgumentException ignored) {
+ }
+ }
+
+ binding.cancelButton.setOnClickListener(mCancelButtonListener);
+ binding.saveButton.setOnClickListener(mSaveButtonListener);
+
+ setSupportActionBar(binding.toolbar);
+ configureActionBar(getSupportActionBar());
+
+ if (savedInstanceState != null) {
+ mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown", false));
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ savedInstanceState.putBoolean("camera_hint_shown", mUseCameraHintShown.get());
+ super.onSaveInstanceState(savedInstanceState);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.trust_keys, menu);
+ MenuItem scanQrCode = menu.findItem(R.id.action_scan_qr_code);
+ scanQrCode.setVisible(
+ (!ownKeysToTrust.isEmpty() || foreignActuallyHasKeys())
+ && isCameraFeatureAvailable());
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ private void showCameraToast() {
+ mUseCameraHintToast =
+ Toast.makeText(this, R.string.use_camera_icon_to_scan_barcode, Toast.LENGTH_LONG);
+ ActionBar actionBar = getSupportActionBar();
+ mUseCameraHintToast.setGravity(
+ Gravity.TOP | Gravity.END, 0, actionBar == null ? 0 : actionBar.getHeight());
+ mUseCameraHintToast.show();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_scan_qr_code:
+ if (hasPendingKeyFetches()) {
+ Toast.makeText(
+ this,
+ R.string.please_wait_for_keys_to_be_fetched,
+ Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ ScanActivity.scan(this);
+ // new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE"));
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mUseCameraHintToast != null) {
+ mUseCameraHintToast.cancel();
+ }
+ }
+
+ @Override
+ protected void processFingerprintVerification(XmppUri uri) {
+ if (mConversation != null
+ && mAccount != null
+ && uri.hasFingerprints()
+ && mAccount.getAxolotlService()
+ .getCryptoTargets(mConversation)
+ .contains(uri.getJid())) {
+ boolean performedVerification =
+ xmppConnectionService.verifyFingerprints(
+ mAccount.getRoster().getContact(uri.getJid()), uri.getFingerprints());
+ boolean keys = reloadFingerprints();
+ if (performedVerification
+ && !keys
+ && !hasNoOtherTrustedKeys()
+ && !hasPendingKeyFetches()) {
+ Toast.makeText(this, R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT)
+ .show();
+ finishOk(false);
+ return;
+ } else if (performedVerification) {
+ Toast.makeText(this, R.string.verified_fingerprints, Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ reloadFingerprints();
+ Log.d(
+ Config.LOGTAG,
+ "xmpp uri was: "
+ + uri.getJid()
+ + " has Fingerprints: "
+ + uri.hasFingerprints());
+ Toast.makeText(
+ this,
+ R.string.barcode_does_not_contain_fingerprints_for_this_chat,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ populateView();
+ }
+
+ private void populateView() {
+ setTitle(getString(R.string.trust_omemo_fingerprints));
+ binding.ownKeysDetails.removeAllViews();
+ binding.foreignKeys.removeAllViews();
+ boolean hasOwnKeys = false;
+ boolean hasForeignKeys = false;
+ for (final String fingerprint : ownKeysToTrust.keySet()) {
+ hasOwnKeys = true;
+ addFingerprintRowWithListeners(
+ binding.ownKeysDetails,
+ mAccount,
+ fingerprint,
+ false,
+ FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)),
+ false,
+ false,
+ (buttonView, isChecked) -> {
+ ownKeysToTrust.put(fingerprint, isChecked);
+ // own fingerprints have no impact on locked status.
+ });
+ }
+
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
+ hasForeignKeys = true;
+ KeysCardBinding keysCardBinding =
+ DataBindingUtil.inflate(
+ getLayoutInflater(),
+ R.layout.keys_card,
+ binding.foreignKeys,
+ false);
+ final Jid jid = entry.getKey();
+ keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this, jid));
+ keysCardBinding.foreignKeysTitle.setOnClickListener(
+ v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
+ final Map<String, Boolean> fingerprints = entry.getValue();
+ for (final String fingerprint : fingerprints.keySet()) {
+ addFingerprintRowWithListeners(
+ keysCardBinding.foreignKeysDetails,
+ mAccount,
+ fingerprint,
+ false,
+ FingerprintStatus.createActive(fingerprints.get(fingerprint)),
+ false,
+ false,
+ (buttonView, isChecked) -> {
+ fingerprints.put(fingerprint, isChecked);
+ lockOrUnlockAsNeeded();
+ });
+ }
+ if (fingerprints.isEmpty()) {
+ keysCardBinding.noKeysToAccept.setVisibility(View.VISIBLE);
+ if (hasNoOtherTrustedKeys(jid)) {
+ if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
+ keysCardBinding.noKeysToAccept.setText(
+ R.string.error_no_keys_to_trust_presence);
+ } else {
+ keysCardBinding.noKeysToAccept.setText(
+ R.string.error_no_keys_to_trust_server_error);
+ }
+ } else {
+ keysCardBinding.noKeysToAccept.setText(
+ getString(
+ R.string.no_keys_just_confirm,
+ mAccount.getRoster().getContact(jid).getDisplayName()));
+ }
+ } else {
+ keysCardBinding.noKeysToAccept.setVisibility(View.GONE);
+ }
+ binding.foreignKeys.addView(keysCardBinding.foreignKeysCard);
+ }
+ }
+
+ if ((hasOwnKeys || foreignActuallyHasKeys())
+ && isCameraFeatureAvailable()
+ && mUseCameraHintShown.compareAndSet(false, true)) {
+ showCameraToast();
+ }
+
+ binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toString());
+ binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
+ binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
+ if (hasPendingKeyFetches()) {
+ setFetching();
+ lock();
+ } else {
+ if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
+ binding.keyErrorMessageCard.setVisibility(View.VISIBLE);
+ boolean lastReportWasError = lastFetchReport == AxolotlService.FetchStatus.ERROR;
+ boolean errorFetchingBundle =
+ mAccount.getAxolotlService().fetchMapHasErrors(contactJids);
+ boolean errorFetchingDeviceList =
+ mAccount.getAxolotlService().hasErrorFetchingDeviceList(contactJids);
+ boolean anyWithoutMutualPresenceSubscription =
+ anyWithoutMutualPresenceSubscription(contactJids);
+ if (errorFetchingDeviceList) {
+ binding.keyErrorMessage.setVisibility(View.VISIBLE);
+ binding.keyErrorMessage.setText(R.string.error_trustkey_device_list);
+ } else if (errorFetchingBundle || lastReportWasError) {
+ binding.keyErrorMessage.setVisibility(View.VISIBLE);
+ binding.keyErrorMessage.setText(R.string.error_trustkey_bundle);
+ } else {
+ binding.keyErrorMessage.setVisibility(View.GONE);
+ }
+ this.binding.keyErrorHintMutual.setVisibility(
+ anyWithoutMutualPresenceSubscription ? View.VISIBLE : View.GONE);
+ Contact contact = mAccount.getRoster().getContact(contactJids.get(0));
+ binding.keyErrorGeneral.setText(
+ getString(
+ R.string.error_trustkey_general,
+ getString(R.string.app_name),
+ contact.getDisplayName()));
+ binding.ownKeysDetails.removeAllViews();
+ if (OmemoSetting.isAlways()) {
+ binding.disableButton.setVisibility(View.GONE);
+ } else {
+ binding.disableButton.setVisibility(View.VISIBLE);
+ binding.disableButton.setOnClickListener(this::disableEncryptionDialog);
+ }
+ binding.ownKeysCard.setVisibility(View.GONE);
+ binding.foreignKeys.removeAllViews();
+ binding.foreignKeys.setVisibility(View.GONE);
+ }
+ lockOrUnlockAsNeeded();
+ setDone();
+ }
+ }
+
+ private void disableEncryptionDialog(final View view) {
+ final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
+ builder.setTitle(R.string.disable_encryption);
+ builder.setMessage(R.string.disable_encryption_message);
+ builder.setPositiveButton(
+ R.string.disable_now,
+ (dialog, which) -> {
+ mConversation.setNextEncryption(Message.ENCRYPTION_NONE);
+ xmppConnectionService.updateConversation(mConversation);
+ finishOk(true);
+ });
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.create().show();
+ }
+
+ private boolean anyWithoutMutualPresenceSubscription(List<Jid> contactJids) {
+ for (Jid jid : contactJids) {
+ if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean foreignActuallyHasKeys() {
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
+ if (!entry.getValue().isEmpty()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean reloadFingerprints() {
+ List<Jid> acceptedTargets =
+ mConversation == null
+ ? new ArrayList<>()
+ : mConversation.getAcceptedCryptoTargets();
+ ownKeysToTrust.clear();
+ if (this.mAccount == null) {
+ return false;
+ }
+ AxolotlService service = this.mAccount.getAxolotlService();
+ Set<IdentityKey> ownKeysSet =
+ service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
+ for (final IdentityKey identityKey : ownKeysSet) {
+ final String fingerprint =
+ CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
+ if (!ownKeysToTrust.containsKey(fingerprint)) {
+ ownKeysToTrust.put(fingerprint, false);
+ }
+ }
+ synchronized (this.foreignKeysToTrust) {
+ foreignKeysToTrust.clear();
+ for (Jid jid : contactJids) {
+ Set<IdentityKey> foreignKeysSet =
+ service.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), jid);
+ if (hasNoOtherTrustedKeys(jid) && ownKeysSet.isEmpty()) {
+ foreignKeysSet.addAll(
+ service.getKeysWithTrust(FingerprintStatus.createActive(false), jid));
+ }
+ Map<String, Boolean> foreignFingerprints = new HashMap<>();
+ for (final IdentityKey identityKey : foreignKeysSet) {
+ final String fingerprint =
+ CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
+ if (!foreignFingerprints.containsKey(fingerprint)) {
+ foreignFingerprints.put(fingerprint, false);
+ }
+ }
+ if (!foreignFingerprints.isEmpty() || !acceptedTargets.contains(jid)) {
+ foreignKeysToTrust.put(jid, foreignFingerprints);
+ }
+ }
+ }
+ return ownKeysSet.size() + foreignKeysToTrust.size() > 0;
+ }
+
+ public void onBackendConnected() {
+ Intent intent = getIntent();
+ this.mAccount = extractAccount(intent);
+ if (this.mAccount != null && intent != null) {
+ String uuid = intent.getStringExtra("conversation");
+ this.mConversation = xmppConnectionService.findConversationByUuid(uuid);
+ if (this.mPendingFingerprintVerificationUri != null) {
+ processFingerprintVerification(this.mPendingFingerprintVerificationUri);
+ this.mPendingFingerprintVerificationUri = null;
+ } else {
+ final boolean keysToTrust = reloadFingerprints();
+ if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
+ populateView();
+ invalidateOptionsMenu();
+ } else {
+ finishOk(false);
+ }
+ }
+ }
+ }
+
+ private boolean hasNoOtherTrustedKeys() {
+ return mAccount == null
+ || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids);
+ }
+
+ private boolean hasNoOtherTrustedKeys(Jid contact) {
+ return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0;
+ }
+
+ private boolean hasPendingKeyFetches() {
+ return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(contactJids);
+ }
+
+ @Override
+ public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) {
+ final boolean keysToTrust = reloadFingerprints();
+ if (report != null) {
+ lastFetchReport = report;
+ runOnUiThread(
+ () -> {
+ if (mUseCameraHintToast != null && !keysToTrust) {
+ mUseCameraHintToast.cancel();
+ }
+ switch (report) {
+ case ERROR:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ R.string.error_fetching_omemo_key,
+ Toast.LENGTH_SHORT)
+ .show();
+ break;
+ case SUCCESS_TRUSTED:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ R.string.blindly_trusted_omemo_keys,
+ Toast.LENGTH_LONG)
+ .show();
+ break;
+ case SUCCESS_VERIFIED:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ Config.X509_VERIFICATION
+ ? R.string
+ .verified_omemo_key_with_certificate
+ : R.string
+ .all_omemo_keys_have_been_verified,
+ Toast.LENGTH_LONG)
+ .show();
+ break;
+ }
+ });
+ }
+ if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
+ refreshUi();
+ } else {
+ runOnUiThread(() -> finishOk(false));
+ }
+ }
+
+ private void finishOk(boolean disabled) {
+ Intent data = new Intent();
+ data.putExtra(
+ "choice",
+ getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID));
+ data.putExtra("disabled", disabled);
+ setResult(RESULT_OK, data);
+ finish();
+ }
+
+ private void commitTrusts() {
+ for (final String fingerprint : ownKeysToTrust.keySet()) {
+ mAccount.getAxolotlService()
+ .setFingerprintTrust(
+ fingerprint,
+ FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
+ }
+ List<Jid> acceptedTargets =
+ mConversation == null
+ ? new ArrayList<>()
+ : mConversation.getAcceptedCryptoTargets();
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
+ Jid jid = entry.getKey();
+ Map<String, Boolean> value = entry.getValue();
+ if (!acceptedTargets.contains(jid)) {
+ acceptedTargets.add(jid);
+ }
+ for (final String fingerprint : value.keySet()) {
+ mAccount.getAxolotlService()
+ .setFingerprintTrust(
+ fingerprint,
+ FingerprintStatus.createActive(value.get(fingerprint)));
+ }
+ }
+ }
+ if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) {
+ mConversation.setAcceptedCryptoTargets(acceptedTargets);
+ xmppConnectionService.updateConversation(mConversation);
+ }
+ }
+
+ private void unlock() {
+ binding.saveButton.setEnabled(true);
+ }
+
+ private void lock() {
+ binding.saveButton.setEnabled(false);
+ }
+
+ private void lockOrUnlockAsNeeded() {
+ synchronized (this.foreignKeysToTrust) {
+ for (Jid jid : contactJids) {
+ Map<String, Boolean> fingerprints = foreignKeysToTrust.get(jid);
+ if (hasNoOtherTrustedKeys(jid)
+ && (fingerprints == null || !fingerprints.containsValue(true))) {
+ lock();
+ return;
+ }
+ }
+ }
+ unlock();
+ }
+
+ private void setDone() {
+ binding.saveButton.setText(getString(R.string.done));
+ }
+
+ private void setFetching() {
+ binding.saveButton.setText(getString(R.string.fetching_keys));
+ }
}
@@ -9,14 +9,11 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
-
import com.google.common.base.Strings;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityUriHandlerBinding;
@@ -27,18 +24,16 @@ import eu.siacs.conversations.utils.ProvisioningUtils;
import eu.siacs.conversations.utils.SignupUtils;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
-
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
-import java.io.IOException;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
public class UriHandlerActivity extends BaseActivity {
public static final String ACTION_SCAN_QR_CODE = "scan_qr_code";
@@ -56,7 +51,8 @@ public class UriHandlerActivity extends BaseActivity {
}
public static void scan(final Activity activity, final boolean provisioning) {
- if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
+ if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED) {
final Intent intent = new Intent(activity, UriHandlerActivity.class);
intent.setAction(UriHandlerActivity.ACTION_SCAN_QR_CODE);
if (provisioning) {
@@ -128,7 +124,7 @@ public class UriHandlerActivity extends BaseActivity {
final String preAuth = xmppUri.getParameter(XmppUri.PARAMETER_PRE_AUTH);
final Jid jid = xmppUri.getJid();
if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
- if (jid.getEscapedLocal() != null && accounts.contains(jid.asBareJid())) {
+ if (jid.getLocal() != null && accounts.contains(jid.asBareJid())) {
showError(R.string.account_already_exists);
return false;
}
@@ -172,13 +168,13 @@ public class UriHandlerActivity extends BaseActivity {
final Class<?> clazz = findShareViaAccountClass();
if (clazz != null) {
intent = new Intent(this, clazz);
- intent.putExtra("contact", jid.toEscapedString());
+ intent.putExtra("contact", jid.toString());
intent.putExtra("body", body);
} else {
intent = new Intent(this, StartConversationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
- intent.putExtra("account", accounts.get(0).toEscapedString());
+ intent.putExtra("account", accounts.get(0).toString());
}
} else {
intent = new Intent(this, ShareWithActivity.class);
@@ -209,8 +205,8 @@ public class UriHandlerActivity extends BaseActivity {
private void checkForLinkHeader(final HttpUrl url) {
Log.d(Config.LOGTAG, "checking for link header on " + url);
this.call =
- HttpConnectionManager.okHttpClient(this).newCall(
- new Request.Builder().url(url).head().build());
+ HttpConnectionManager.okHttpClient(this)
+ .newCall(new Request.Builder().url(url).head().build());
this.call.enqueue(
new Callback() {
@Override
@@ -252,7 +248,7 @@ public class UriHandlerActivity extends BaseActivity {
}
private void showErrorOnUiThread(@StringRes int error) {
- runOnUiThread(()-> showError(error));
+ runOnUiThread(() -> showError(error));
}
private static Class<?> findShareViaAccountClass() {
@@ -350,4 +346,4 @@ public class UriHandlerActivity extends BaseActivity {
final String trimmed = Strings.nullToEmpty(input).trim();
return trimmed.charAt(0) == '{' && trimmed.charAt(trimmed.length() - 1) == '}';
}
-}
+}
@@ -733,8 +733,8 @@ public abstract class XmppActivity extends ActionBarActivity {
public void switchToContactDetails(Contact contact, String messageFingerprint) {
Intent intent = new Intent(this, ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
- intent.putExtra(EXTRA_ACCOUNT, contact.getAccount().getJid().asBareJid().toEscapedString());
- intent.putExtra("contact", contact.getJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, contact.getAccount().getJid().asBareJid().toString());
+ intent.putExtra("contact", contact.getJid().toString());
intent.putExtra("fingerprint", messageFingerprint);
startActivity(intent);
}
@@ -749,7 +749,7 @@ public abstract class XmppActivity extends ActionBarActivity {
public void switchToAccount(Account account, boolean init, String fingerprint) {
Intent intent = new Intent(this, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", account.getJid().asBareJid().toString());
intent.putExtra("init", init);
if (init) {
intent.setFlags(
@@ -1141,7 +1141,7 @@ public abstract class XmppActivity extends ActionBarActivity {
protected Account extractAccount(Intent intent) {
final String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null;
try {
- return jid != null ? xmppConnectionService.findAccountByJid(Jid.ofEscaped(jid)) : null;
+ return jid != null ? xmppConnectionService.findAccountByJid(Jid.of(jid)) : null;
} catch (IllegalArgumentException e) {
return null;
}
@@ -4,19 +4,14 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
-
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.color.MaterialColors;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ItemAccountBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
-
import java.util.List;
public class AccountAdapter extends ArrayAdapter<Account> {
@@ -42,27 +37,42 @@ public class AccountAdapter extends ArrayAdapter<Account> {
final Account account = getItem(position);
final ViewHolder viewHolder;
if (view == null) {
- ItemAccountBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_account, parent, false);
+ ItemAccountBinding binding =
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_account,
+ parent,
+ false);
view = binding.getRoot();
viewHolder = new ViewHolder(binding);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
- viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toEscapedString());
+ viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toString());
AvatarWorkerTask.loadAvatar(account, viewHolder.binding.accountImage, R.dimen.avatar);
- viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId()));
+ viewHolder.binding.accountStatus.setText(
+ getContext().getString(account.getStatus().getReadableId()));
switch (account.getStatus()) {
case ONLINE:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorPrimary));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorPrimary));
break;
case DISABLED:
case LOGGED_OUT:
case CONNECTING:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorOnSurfaceVariant));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorOnSurfaceVariant));
break;
default:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorError));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorError));
break;
}
final boolean isDisabled = (account.getStatus() == Account.State.DISABLED);
@@ -73,11 +83,12 @@ public class AccountAdapter extends ArrayAdapter<Account> {
} else {
viewHolder.binding.tglAccountStatus.setVisibility(View.GONE);
}
- viewHolder.binding.tglAccountStatus.setOnCheckedChangeListener((compoundButton, b) -> {
- if (b == isDisabled && activity instanceof OnTglAccountState) {
- ((OnTglAccountState) activity).onClickTglAccountState(account, b);
- }
- });
+ viewHolder.binding.tglAccountStatus.setOnCheckedChangeListener(
+ (compoundButton, b) -> {
+ if (b == isDisabled && activity instanceof OnTglAccountState) {
+ ((OnTglAccountState) activity).onClickTglAccountState(account, b);
+ }
+ });
return view;
}
@@ -89,10 +100,7 @@ public class AccountAdapter extends ArrayAdapter<Account> {
}
}
-
-
public interface OnTglAccountState {
void onClickTglAccountState(Account account, boolean state);
}
-
}
@@ -3,14 +3,10 @@ package eu.siacs.conversations.ui.adapter;
import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
-
import androidx.annotation.NonNull;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
-
import eu.siacs.conversations.Config;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -22,61 +18,66 @@ public class KnownHostsAdapter extends ArrayAdapter<String> {
private static final Pattern E164_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$");
private List<String> domains;
- private final Filter domainFilter = new Filter() {
+ private final Filter domainFilter =
+ new Filter() {
- @Override
- protected FilterResults performFiltering(final CharSequence constraint) {
- final ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
- final String[] split = constraint == null ? new String[0] : constraint.toString().split("@");
- if (split.length == 1) {
- final String local = split[0].toLowerCase(Locale.ENGLISH);
- if (Config.QUICKSY_DOMAIN != null && E164_PATTERN.matcher(local).matches()) {
- builder.add(local + '@' + Config.QUICKSY_DOMAIN.toEscapedString());
- } else {
- for (String domain : domains) {
- builder.add(local + '@' + domain);
- }
- }
- } else if (split.length == 2) {
- final String localPart = split[0].toLowerCase(Locale.ENGLISH);
- final String domainPart = split[1].toLowerCase(Locale.ENGLISH);
- if (domains.contains(domainPart)) {
- return new FilterResults();
- }
- for (final String domain : domains) {
- if (domain.contains(domainPart)) {
- builder.add(localPart + "@" + domain);
+ @Override
+ protected FilterResults performFiltering(final CharSequence constraint) {
+ final ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
+ final String[] split =
+ constraint == null ? new String[0] : constraint.toString().split("@");
+ if (split.length == 1) {
+ 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());
+ } else {
+ for (String domain : domains) {
+ builder.add(local + '@' + domain);
+ }
+ }
+ } else if (split.length == 2) {
+ final String localPart = split[0].toLowerCase(Locale.ENGLISH);
+ final String domainPart = split[1].toLowerCase(Locale.ENGLISH);
+ if (domains.contains(domainPart)) {
+ return new FilterResults();
+ }
+ for (final String domain : domains) {
+ if (domain.contains(domainPart)) {
+ builder.add(localPart + "@" + domain);
+ }
+ }
+ } else {
+ return new FilterResults();
}
+ final var suggestions = builder.build();
+ final FilterResults filterResults = new FilterResults();
+ filterResults.values = suggestions;
+ filterResults.count = suggestions.size();
+ return filterResults;
}
- } else {
- return new FilterResults();
- }
- final var suggestions = builder.build();
- final FilterResults filterResults = new FilterResults();
- filterResults.values = suggestions;
- filterResults.count = suggestions.size();
- return filterResults;
- }
- @Override
- protected void publishResults(final CharSequence constraint, final FilterResults results) {
- final ImmutableList.Builder<String> suggestions = new ImmutableList.Builder<>();
- if (results.values instanceof Collection<?> collection) {
- for(final Object item : collection) {
- if (item instanceof String string) {
- suggestions.add(string);
+ @Override
+ protected void publishResults(
+ final CharSequence constraint, final FilterResults results) {
+ final ImmutableList.Builder<String> suggestions = new ImmutableList.Builder<>();
+ if (results.values instanceof Collection<?> collection) {
+ for (final Object item : collection) {
+ if (item instanceof String string) {
+ suggestions.add(string);
+ }
+ }
}
+ clear();
+ addAll(suggestions.build());
+ notifyDataSetChanged();
}
- }
- clear();
- addAll(suggestions.build());
- notifyDataSetChanged();
- }
- };
+ };
- public KnownHostsAdapter(final Context context, final int viewResourceId, final Collection<String> knownHosts) {
+ public KnownHostsAdapter(
+ final Context context, final int viewResourceId, final Collection<String> knownHosts) {
super(context, viewResourceId, new ArrayList<>());
- domains = Ordering.natural().sortedCopy(knownHosts);
+ domains = Ordering.natural().sortedCopy(knownHosts);
}
public KnownHostsAdapter(final Context context, final int viewResourceId) {
@@ -2,20 +2,16 @@ package eu.siacs.conversations.ui.fragment.settings;
import android.os.Bundle;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.receiver.UnifiedPushDistributor;
import eu.siacs.conversations.xmpp.Jid;
-
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@@ -31,29 +27,38 @@ public class UpSettingsFragment extends XmppPreferenceFragment {
@Override
public void onBackendConnected() {
final ListPreference upAccounts = findPreference(UnifiedPushDistributor.PREFERENCE_ACCOUNT);
- final EditTextPreference pushServer = findPreference(UnifiedPushDistributor.PREFERENCE_PUSH_SERVER);
+ final EditTextPreference pushServer =
+ findPreference(UnifiedPushDistributor.PREFERENCE_PUSH_SERVER);
if (upAccounts == null || pushServer == null) {
throw new IllegalStateException();
}
- pushServer.setOnPreferenceChangeListener((preference, newValue) -> {
- if (newValue instanceof String string) {
- if (Strings.isNullOrEmpty(string) || isJidInvalid(string) || isHttpUri(string)) {
- Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
- return false;
- } else {
- return true;
- }
- } else {
- Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
- return false;
- }
- });
+ pushServer.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof String string) {
+ if (Strings.isNullOrEmpty(string)
+ || isJidInvalid(string)
+ || isHttpUri(string)) {
+ Toast.makeText(
+ requireActivity(),
+ R.string.invalid_jid,
+ Toast.LENGTH_LONG)
+ .show();
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ Toast.makeText(requireActivity(), R.string.invalid_jid, Toast.LENGTH_LONG)
+ .show();
+ return false;
+ }
+ });
reconfigureUpAccountPreference(upAccounts);
}
private static boolean isJidInvalid(final String input) {
try {
- final var jid = Jid.ofEscaped(input);
+ final var jid = Jid.ofUserInput(input);
return !jid.isBareJid();
} catch (final IllegalArgumentException e) {
return true;
@@ -67,16 +72,15 @@ public class UpSettingsFragment extends XmppPreferenceFragment {
} catch (final URISyntaxException e) {
return false;
}
- return Arrays.asList("http","https").contains(uri.getScheme());
+ return Arrays.asList("http", "https").contains(uri.getScheme());
}
-
private void reconfigureUpAccountPreference(final ListPreference listPreference) {
final List<CharSequence> accounts =
ImmutableList.copyOf(
Lists.transform(
requireService().getAccounts(),
- a -> a.getJid().asBareJid().toEscapedString()));
+ a -> a.getJid().asBareJid().toString()));
final ImmutableList.Builder<CharSequence> entries = new ImmutableList.Builder<>();
final ImmutableList.Builder<CharSequence> entryValues = new ImmutableList.Builder<>();
entries.add(getString(R.string.no_account_deactivated));
@@ -5,20 +5,16 @@ import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
-
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Longs;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.XmppActivity;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
public class AccountUtils {
@@ -50,9 +46,7 @@ public class AccountUtils {
public static UUID createUuid4(long mostSigBits, long leastSigBits) {
final byte[] bytes =
- Bytes.concat(
- Longs.toByteArray(mostSigBits),
- Longs.toByteArray(leastSigBits));
+ Bytes.concat(Longs.toByteArray(mostSigBits), Longs.toByteArray(leastSigBits));
bytes[6] &= 0x0f; /* clear version */
bytes[6] |= 0x40; /* set to version 4 */
bytes[8] &= 0x3f; /* clear variant */
@@ -65,7 +59,7 @@ public class AccountUtils {
final ArrayList<String> accounts = new ArrayList<>();
for (final Account account : service.getAccounts()) {
if (account.isEnabled()) {
- accounts.add(account.getJid().asBareJid().toEscapedString());
+ accounts.add(account.getJid().asBareJid().toString());
}
}
return accounts;
@@ -1,13 +1,11 @@
package eu.siacs.conversations.utils;
import androidx.annotation.NonNull;
-
+import eu.siacs.conversations.xmpp.Jid;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import eu.siacs.conversations.xmpp.Jid;
-
public class BackupFileHeader {
private static final int VERSION = 2;
@@ -18,17 +16,22 @@ public class BackupFileHeader {
private final byte[] iv;
private final byte[] salt;
-
@NonNull
@Override
public String toString() {
- return "BackupFileHeader{" +
- "app='" + app + '\'' +
- ", jid=" + jid +
- ", timestamp=" + timestamp +
- ", iv=" + CryptoHelper.bytesToHex(iv) +
- ", salt=" + CryptoHelper.bytesToHex(salt) +
- '}';
+ return "BackupFileHeader{"
+ + "app='"
+ + app
+ + '\''
+ + ", jid="
+ + jid
+ + ", timestamp="
+ + timestamp
+ + ", iv="
+ + CryptoHelper.bytesToHex(iv)
+ + ", salt="
+ + CryptoHelper.bytesToHex(salt)
+ + '}';
}
public BackupFileHeader(String app, Jid jid, long timestamp, byte[] iv, byte[] salt) {
@@ -42,7 +45,7 @@ public class BackupFileHeader {
public void write(DataOutputStream dataOutputStream) throws IOException {
dataOutputStream.writeInt(VERSION);
dataOutputStream.writeUTF(app);
- dataOutputStream.writeUTF(jid.asBareJid().toEscapedString());
+ dataOutputStream.writeUTF(jid.asBareJid().toString());
dataOutputStream.writeLong(timestamp);
dataOutputStream.write(iv);
dataOutputStream.write(salt);
@@ -61,10 +64,13 @@ public class BackupFileHeader {
throw new OutdatedBackupFileVersion();
}
if (version != VERSION) {
- throw new IllegalArgumentException("Backup File version was " + version + " but app only supports version " + VERSION);
+ throw new IllegalArgumentException(
+ "Backup File version was "
+ + version
+ + " but app only supports version "
+ + VERSION);
}
return new BackupFileHeader(app, Jid.of(jid), timestamp, iv, salt);
-
}
public byte[] getSalt() {
@@ -87,7 +93,5 @@ public class BackupFileHeader {
return timestamp;
}
- public static class OutdatedBackupFileVersion extends RuntimeException {
-
- }
+ public static class OutdatedBackupFileVersion extends RuntimeException {}
}
@@ -5,14 +5,12 @@ import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
import android.os.Bundle;
import android.util.Base64;
import android.util.Pair;
-
import androidx.annotation.StringRes;
-
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.bouncycastle.asn1.x500.style.IETFUtils;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
-
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.xmpp.Jid;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -28,22 +26,22 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.regex.Pattern;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.xmpp.Jid;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.bouncycastle.asn1.x500.style.IETFUtils;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
public final class CryptoHelper {
- public static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
- final public static byte[] ONE = new byte[]{0, 0, 0, 1};
- private static final char[] CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789+-/#$!?".toCharArray();
+ public static final Pattern UUID_PATTERN =
+ Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
+ public static final byte[] ONE = new byte[] {0, 0, 0, 1};
+ private static final char[] CHARS =
+ "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789+-/#$!?".toCharArray();
private static final int PW_LENGTH = 12;
private static final char[] VOWELS = "aeiou".toCharArray();
private static final char[] CONSONANTS = "bcfghjklmnpqrstvwxyz".toCharArray();
- private final static char[] hexArray = "0123456789abcdef".toCharArray();
+ private static final char[] hexArray = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
@@ -68,7 +66,10 @@ public final class CryptoHelper {
char[] output = new char[rand * 2 + (5 - rand)];
boolean vowel = SECURE_RANDOM.nextBoolean();
for (int i = 0; i < output.length; ++i) {
- output[i] = vowel ? VOWELS[SECURE_RANDOM.nextInt(VOWELS.length)] : CONSONANTS[SECURE_RANDOM.nextInt(CONSONANTS.length)];
+ output[i] =
+ vowel
+ ? VOWELS[SECURE_RANDOM.nextInt(VOWELS.length)]
+ : CONSONANTS[SECURE_RANDOM.nextInt(CONSONANTS.length)];
vowel = !vowel;
}
return String.valueOf(output);
@@ -78,8 +79,10 @@ public final class CryptoHelper {
int len = hexString.length();
byte[] array = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
- array[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
- .digit(hexString.charAt(i + 1), 16));
+ array[i / 2] =
+ (byte)
+ ((Character.digit(hexString.charAt(i), 16) << 4)
+ + Character.digit(hexString.charAt(i + 1), 16));
}
return array;
}
@@ -95,9 +98,7 @@ public final class CryptoHelper {
return result;
}
- /**
- * Escapes usernames or passwords for SASL.
- */
+ /** Escapes usernames or passwords for SASL. */
public static String saslEscape(final String s) {
final StringBuilder sb = new StringBuilder((int) (s.length() * 1.1));
for (int i = 0; i < s.length(); i++) {
@@ -149,7 +150,8 @@ public final class CryptoHelper {
}
public static String[] getOrderedCipherSuites(final String[] platformSupportedCipherSuites) {
- final Collection<String> cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS));
+ final Collection<String> cipherSuites =
+ new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS));
final List<String> platformCiphers = Arrays.asList(platformSupportedCipherSuites);
cipherSuites.retainAll(platformCiphers);
cipherSuites.addAll(platformCiphers);
@@ -172,7 +174,10 @@ public final class CryptoHelper {
}
}
- public static Pair<Jid, String> extractJidAndName(X509Certificate certificate) throws CertificateEncodingException, IllegalArgumentException, CertificateParsingException {
+ public static Pair<Jid, String> extractJidAndName(X509Certificate certificate)
+ throws CertificateEncodingException,
+ IllegalArgumentException,
+ CertificateParsingException {
Collection<List<?>> alternativeNames = certificate.getSubjectAlternativeNames();
List<String> emails = new ArrayList<>();
if (alternativeNames != null) {
@@ -185,9 +190,15 @@ public final class CryptoHelper {
}
X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject();
if (emails.size() == 0 && x500name.getRDNs(BCStyle.EmailAddress).length > 0) {
- emails.add(IETFUtils.valueToString(x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue()));
+ emails.add(
+ IETFUtils.valueToString(
+ x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue()));
}
- String name = x500name.getRDNs(BCStyle.CN).length > 0 ? IETFUtils.valueToString(x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue()) : null;
+ String name =
+ x500name.getRDNs(BCStyle.CN).length > 0
+ ? IETFUtils.valueToString(
+ x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue())
+ : null;
if (emails.size() >= 1) {
return new Pair<>(Jid.of(emails.get(0)), name);
} else if (name != null) {
@@ -209,26 +220,33 @@ public final class CryptoHelper {
JcaX509CertificateHolder holder = new JcaX509CertificateHolder(certificate);
X500Name subject = holder.getSubject();
try {
- information.putString("subject_cn", subject.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
+ information.putString(
+ "subject_cn",
+ subject.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
- information.putString("subject_o", subject.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
+ information.putString(
+ "subject_o",
+ subject.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
X500Name issuer = holder.getIssuer();
try {
- information.putString("issuer_cn", issuer.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
+ information.putString(
+ "issuer_cn",
+ issuer.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
- information.putString("issuer_o", issuer.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
+ information.putString(
+ "issuer_o", issuer.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
information.putString("sha1", getFingerprintCert(certificate.getEncoded()));
@@ -248,7 +266,7 @@ public final class CryptoHelper {
}
public static String getFingerprint(Jid jid, String androidId) {
- return getFingerprint(jid.toEscapedString() + "\00" + androidId);
+ return getFingerprint(jid.toString() + "\00" + androidId);
}
public static String getAccountFingerprint(Account account, String androidId) {
@@ -268,8 +286,9 @@ public final class CryptoHelper {
return switch (encryption) {
case Message.ENCRYPTION_OTR -> R.string.encryption_choice_otr;
case Message.ENCRYPTION_AXOLOTL,
- Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE,
- Message.ENCRYPTION_AXOLOTL_FAILED -> R.string.encryption_choice_omemo;
+ Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE,
+ Message.ENCRYPTION_AXOLOTL_FAILED ->
+ R.string.encryption_choice_omemo;
case Message.ENCRYPTION_PGP -> R.string.encryption_choice_pgp;
default -> R.string.encryption_choice_unencrypted;
};
@@ -280,6 +299,8 @@ public final class CryptoHelper {
return false;
}
final String u = url.toLowerCase();
- return !u.contains(" ") && (u.startsWith("https://") || u.startsWith("http://") || u.startsWith("p1s3://")) && u.endsWith(".pgp");
+ return !u.contains(" ")
+ && (u.startsWith("https://") || u.startsWith("http://") || u.startsWith("p1s3://"))
+ && u.endsWith(".pgp");
}
}
@@ -37,11 +37,9 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.LruCache;
-
import androidx.annotation.ColorInt;
-
import com.google.android.material.color.MaterialColors;
-
+import eu.siacs.conversations.xmpp.Jid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -54,224 +52,234 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.xmpp.Jid;
-
public class IrregularUnicodeDetector {
- private static final Map<Character.UnicodeBlock, Character.UnicodeBlock> NORMALIZATION_MAP;
- private static final LruCache<Jid, PatternTuple> CACHE = new LruCache<>(4096);
- private static final List<String> AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ј","ķ","ԛ","о","р","с","у","х");
-
- static {
- Map<Character.UnicodeBlock, Character.UnicodeBlock> temp = new HashMap<>();
- temp.put(Character.UnicodeBlock.LATIN_1_SUPPLEMENT, Character.UnicodeBlock.BASIC_LATIN);
- NORMALIZATION_MAP = Collections.unmodifiableMap(temp);
- }
+ private static final Map<Character.UnicodeBlock, Character.UnicodeBlock> NORMALIZATION_MAP;
+ private static final LruCache<Jid, PatternTuple> CACHE = new LruCache<>(4096);
+ private static final List<String> AMBIGUOUS_CYRILLIC =
+ Arrays.asList("а", "г", "е", "ѕ", "і", "ј", "ķ", "ԛ", "о", "р", "с", "у", "х");
- private static Character.UnicodeBlock normalize(Character.UnicodeBlock in) {
- if (NORMALIZATION_MAP.containsKey(in)) {
- return NORMALIZATION_MAP.get(in);
- } else {
- return in;
- }
- }
+ static {
+ Map<Character.UnicodeBlock, Character.UnicodeBlock> temp = new HashMap<>();
+ temp.put(Character.UnicodeBlock.LATIN_1_SUPPLEMENT, Character.UnicodeBlock.BASIC_LATIN);
+ NORMALIZATION_MAP = Collections.unmodifiableMap(temp);
+ }
- public static Spannable style(final Context context, Jid jid) {
- return style(jid, MaterialColors.getColor(context, com.google.android.material.R.attr.colorError,"colorError not found"));
- }
+ private static Character.UnicodeBlock normalize(Character.UnicodeBlock in) {
+ if (NORMALIZATION_MAP.containsKey(in)) {
+ return NORMALIZATION_MAP.get(in);
+ } else {
+ return in;
+ }
+ }
- private static Spannable style(Jid jid, @ColorInt int color) {
- PatternTuple patternTuple = find(jid);
- SpannableStringBuilder builder = new SpannableStringBuilder();
- if (jid.getEscapedLocal() != null && patternTuple.local != null) {
- SpannableString local = new SpannableString(jid.getEscapedLocal());
- colorize(local, patternTuple.local, color);
- builder.append(local);
- builder.append('@');
- }
- if (jid.getDomain() != null) {
- String[] labels = jid.getDomain().toEscapedString().split("\\.");
- for (int i = 0; i < labels.length; ++i) {
- SpannableString spannableString = new SpannableString(labels[i]);
- colorize(spannableString, patternTuple.domain.get(i), color);
- if (i != 0) {
- builder.append('.');
- }
- builder.append(spannableString);
- }
- }
- if (builder.length() != 0 && jid.getResource() != null) {
- builder.append('/');
- builder.append(jid.getResource());
- }
- return builder;
- }
+ public static Spannable style(final Context context, Jid jid) {
+ return style(
+ jid,
+ MaterialColors.getColor(
+ context,
+ com.google.android.material.R.attr.colorError,
+ "colorError not found"));
+ }
- private static void colorize(SpannableString spannableString, Pattern pattern, @ColorInt int color) {
- Matcher matcher = pattern.matcher(spannableString);
- while (matcher.find()) {
- if (matcher.start() < matcher.end()) {
- spannableString.setSpan(new ForegroundColorSpan(color), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
+ private static Spannable style(Jid jid, @ColorInt int color) {
+ PatternTuple patternTuple = find(jid);
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ if (jid.getLocal() != null && patternTuple.local != null) {
+ SpannableString local = new SpannableString(jid.getLocal());
+ colorize(local, patternTuple.local, color);
+ builder.append(local);
+ builder.append('@');
+ }
+ if (jid.getDomain() != null) {
+ String[] labels = jid.getDomain().toString().split("\\.");
+ for (int i = 0; i < labels.length; ++i) {
+ SpannableString spannableString = new SpannableString(labels[i]);
+ colorize(spannableString, patternTuple.domain.get(i), color);
+ if (i != 0) {
+ builder.append('.');
+ }
+ builder.append(spannableString);
+ }
+ }
+ if (builder.length() != 0 && jid.getResource() != null) {
+ builder.append('/');
+ builder.append(jid.getResource());
+ }
+ return builder;
+ }
- private static Map<Character.UnicodeBlock, List<String>> mapCompat(String word) {
- Map<Character.UnicodeBlock, List<String>> map = new HashMap<>();
- final int length = word.length();
- for (int offset = 0; offset < length; ) {
- final int codePoint = word.codePointAt(offset);
- offset += Character.charCount(codePoint);
- if (!Character.isLetter(codePoint)) {
- continue;
- }
- Character.UnicodeBlock block = normalize(Character.UnicodeBlock.of(codePoint));
- List<String> codePoints;
- if (map.containsKey(block)) {
- codePoints = map.get(block);
- } else {
- codePoints = new ArrayList<>();
- map.put(block, codePoints);
- }
- codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
- }
- return map;
- }
+ private static void colorize(
+ SpannableString spannableString, Pattern pattern, @ColorInt int color) {
+ Matcher matcher = pattern.matcher(spannableString);
+ while (matcher.find()) {
+ if (matcher.start() < matcher.end()) {
+ spannableString.setSpan(
+ new ForegroundColorSpan(color),
+ matcher.start(),
+ matcher.end(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ }
- @TargetApi(Build.VERSION_CODES.N)
- private static Map<Character.UnicodeScript, List<String>> map(String word) {
- Map<Character.UnicodeScript, List<String>> map = new HashMap<>();
- final int length = word.length();
- for (int offset = 0; offset < length; ) {
- final int codePoint = word.codePointAt(offset);
- Character.UnicodeScript script = Character.UnicodeScript.of(codePoint);
- if (script != Character.UnicodeScript.COMMON) {
- List<String> codePoints;
- if (map.containsKey(script)) {
- codePoints = map.get(script);
- } else {
- codePoints = new ArrayList<>();
- map.put(script, codePoints);
- }
- codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
- }
- offset += Character.charCount(codePoint);
- }
- return map;
- }
+ private static Map<Character.UnicodeBlock, List<String>> mapCompat(String word) {
+ Map<Character.UnicodeBlock, List<String>> map = new HashMap<>();
+ final int length = word.length();
+ for (int offset = 0; offset < length; ) {
+ final int codePoint = word.codePointAt(offset);
+ offset += Character.charCount(codePoint);
+ if (!Character.isLetter(codePoint)) {
+ continue;
+ }
+ Character.UnicodeBlock block = normalize(Character.UnicodeBlock.of(codePoint));
+ List<String> codePoints;
+ if (map.containsKey(block)) {
+ codePoints = map.get(block);
+ } else {
+ codePoints = new ArrayList<>();
+ map.put(block, codePoints);
+ }
+ codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
+ }
+ return map;
+ }
- private static Set<String> eliminateFirstAndGetCodePointsCompat(Map<Character.UnicodeBlock, List<String>> map) {
- return eliminateFirstAndGetCodePoints(map, Character.UnicodeBlock.BASIC_LATIN);
- }
+ @TargetApi(Build.VERSION_CODES.N)
+ private static Map<Character.UnicodeScript, List<String>> map(String word) {
+ Map<Character.UnicodeScript, List<String>> map = new HashMap<>();
+ final int length = word.length();
+ for (int offset = 0; offset < length; ) {
+ final int codePoint = word.codePointAt(offset);
+ Character.UnicodeScript script = Character.UnicodeScript.of(codePoint);
+ if (script != Character.UnicodeScript.COMMON) {
+ List<String> codePoints;
+ if (map.containsKey(script)) {
+ codePoints = map.get(script);
+ } else {
+ codePoints = new ArrayList<>();
+ map.put(script, codePoints);
+ }
+ codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
+ }
+ offset += Character.charCount(codePoint);
+ }
+ return map;
+ }
- @TargetApi(Build.VERSION_CODES.N)
- private static Set<String> eliminateFirstAndGetCodePoints(Map<Character.UnicodeScript, List<String>> map) {
- return eliminateFirstAndGetCodePoints(map, Character.UnicodeScript.COMMON);
- }
+ private static Set<String> eliminateFirstAndGetCodePointsCompat(
+ Map<Character.UnicodeBlock, List<String>> map) {
+ return eliminateFirstAndGetCodePoints(map, Character.UnicodeBlock.BASIC_LATIN);
+ }
- private static <T> Set<String> eliminateFirstAndGetCodePoints(Map<T, List<String>> map, T defaultPick) {
- T pick = defaultPick;
- int size = 0;
- for (Map.Entry<T, List<String>> entry : map.entrySet()) {
- if (entry.getValue().size() > size) {
- size = entry.getValue().size();
- pick = entry.getKey();
- }
- }
- map.remove(pick);
- Set<String> all = new HashSet<>();
- for (List<String> codePoints : map.values()) {
- all.addAll(codePoints);
- }
- return all;
- }
+ @TargetApi(Build.VERSION_CODES.N)
+ private static Set<String> eliminateFirstAndGetCodePoints(
+ Map<Character.UnicodeScript, List<String>> map) {
+ return eliminateFirstAndGetCodePoints(map, Character.UnicodeScript.COMMON);
+ }
- private static Set<String> findIrregularCodePoints(String word) {
- Set<String> codePoints;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
- final Map<Character.UnicodeBlock, List<String>> map = mapCompat(word);
- final Set<String> set = asSet(map);
- if (containsOnlyAmbiguousCyrillic(set)) {
- return set;
- }
- codePoints = eliminateFirstAndGetCodePointsCompat(map);
- } else {
- final Map<Character.UnicodeScript, List<String>> map = map(word);
- final Set<String> set = asSet(map);
- if (containsOnlyAmbiguousCyrillic(set)) {
- return set;
- }
- codePoints = eliminateFirstAndGetCodePoints(map);
- }
- return codePoints;
- }
+ private static <T> Set<String> eliminateFirstAndGetCodePoints(
+ Map<T, List<String>> map, T defaultPick) {
+ T pick = defaultPick;
+ int size = 0;
+ for (Map.Entry<T, List<String>> entry : map.entrySet()) {
+ if (entry.getValue().size() > size) {
+ size = entry.getValue().size();
+ pick = entry.getKey();
+ }
+ }
+ map.remove(pick);
+ Set<String> all = new HashSet<>();
+ for (List<String> codePoints : map.values()) {
+ all.addAll(codePoints);
+ }
+ return all;
+ }
- private static Set<String> asSet(Map<?, List<String>> map) {
- final Set<String> flat = new HashSet<>();
- for(List<String> value : map.values()) {
- flat.addAll(value);
- }
- return flat;
- }
+ private static Set<String> findIrregularCodePoints(String word) {
+ Set<String> codePoints;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ final Map<Character.UnicodeBlock, List<String>> map = mapCompat(word);
+ final Set<String> set = asSet(map);
+ if (containsOnlyAmbiguousCyrillic(set)) {
+ return set;
+ }
+ codePoints = eliminateFirstAndGetCodePointsCompat(map);
+ } else {
+ final Map<Character.UnicodeScript, List<String>> map = map(word);
+ final Set<String> set = asSet(map);
+ if (containsOnlyAmbiguousCyrillic(set)) {
+ return set;
+ }
+ codePoints = eliminateFirstAndGetCodePoints(map);
+ }
+ return codePoints;
+ }
+ private static Set<String> asSet(Map<?, List<String>> map) {
+ final Set<String> flat = new HashSet<>();
+ for (List<String> value : map.values()) {
+ flat.addAll(value);
+ }
+ return flat;
+ }
- private static boolean containsOnlyAmbiguousCyrillic(Collection<String> codePoints) {
- for (String codePoint : codePoints) {
- if (!AMBIGUOUS_CYRILLIC.contains(codePoint)) {
- return false;
- }
- }
- return true;
- }
+ private static boolean containsOnlyAmbiguousCyrillic(Collection<String> codePoints) {
+ for (String codePoint : codePoints) {
+ if (!AMBIGUOUS_CYRILLIC.contains(codePoint)) {
+ return false;
+ }
+ }
+ return true;
+ }
- private static PatternTuple find(Jid jid) {
- synchronized (CACHE) {
- PatternTuple pattern = CACHE.get(jid);
- if (pattern != null) {
- return pattern;
- }
+ private static PatternTuple find(Jid jid) {
+ synchronized (CACHE) {
+ PatternTuple pattern = CACHE.get(jid);
+ if (pattern != null) {
+ return pattern;
+ }
pattern = PatternTuple.of(jid);
- CACHE.put(jid, pattern);
- return pattern;
- }
- }
+ CACHE.put(jid, pattern);
+ return pattern;
+ }
+ }
- private static Pattern create(Set<String> codePoints) {
- final StringBuilder pattern = new StringBuilder();
- for (String codePoint : codePoints) {
- if (pattern.length() != 0) {
- pattern.append('|');
- }
- pattern.append(Pattern.quote(codePoint));
- }
- return Pattern.compile(pattern.toString());
- }
+ private static Pattern create(Set<String> codePoints) {
+ final StringBuilder pattern = new StringBuilder();
+ for (String codePoint : codePoints) {
+ if (pattern.length() != 0) {
+ pattern.append('|');
+ }
+ pattern.append(Pattern.quote(codePoint));
+ }
+ return Pattern.compile(pattern.toString());
+ }
- private static class PatternTuple {
- private final Pattern local;
- private final List<Pattern> domain;
+ private static class PatternTuple {
+ private final Pattern local;
+ private final List<Pattern> domain;
- private PatternTuple(Pattern local, List<Pattern> domain) {
- this.local = local;
- this.domain = domain;
- }
+ private PatternTuple(Pattern local, List<Pattern> domain) {
+ this.local = local;
+ this.domain = domain;
+ }
- private static PatternTuple of(Jid jid) {
- final Pattern localPattern;
- if (jid.getEscapedLocal() != null) {
- localPattern = create(findIrregularCodePoints(jid.getEscapedLocal()));
- } else {
- localPattern = null;
- }
- String domain = jid.getDomain().toEscapedString();
- final List<Pattern> domainPatterns = new ArrayList<>();
- if (domain != null) {
- for (String label : domain.split("\\.")) {
- domainPatterns.add(create(findIrregularCodePoints(label)));
- }
- }
- return new PatternTuple(localPattern, domainPatterns);
- }
- }
+ private static PatternTuple of(Jid jid) {
+ final Pattern localPattern;
+ if (jid.getLocal() != null) {
+ localPattern = create(findIrregularCodePoints(jid.getLocal()));
+ } else {
+ localPattern = null;
+ }
+ String domain = jid.getDomain().toString();
+ final List<Pattern> domainPatterns = new ArrayList<>();
+ if (domain != null) {
+ for (String label : domain.split("\\.")) {
+ domainPatterns.add(create(findIrregularCodePoints(label)));
+ }
+ }
+ return new PatternTuple(localPattern, domainPatterns);
+ }
+ }
}
@@ -29,22 +29,19 @@
package eu.siacs.conversations.utils;
-
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.xmpp.Jid;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.xmpp.InvalidJid;
-import eu.siacs.conversations.xmpp.Jid;
-
public class JidHelper {
private static final List<String> LOCAL_PART_BLACKLIST = Arrays.asList("xmpp", "jabber", "me");
public static String localPartOrFallback(Jid jid) {
if (LOCAL_PART_BLACKLIST.contains(jid.getLocal().toLowerCase(Locale.ENGLISH))) {
- final String domain = jid.getDomain().toEscapedString();
+ final String domain = jid.getDomain().toString();
final int index = domain.indexOf('.');
return index > 1 ? domain.substring(0, index) : domain;
} else {
@@ -52,16 +49,7 @@ public class JidHelper {
}
}
- public static Jid parseOrFallbackToInvalid(String jid) {
- try {
- return Jid.of(jid);
- } catch (IllegalArgumentException e) {
- return InvalidJid.of(jid, true);
- }
- }
-
public static boolean isQuicksyDomain(final Jid jid) {
return Config.QUICKSY_DOMAIN != null && Config.QUICKSY_DOMAIN.equals(jid.getDomain());
}
-
}
@@ -1,14 +1,12 @@
package eu.siacs.conversations.utils;
import android.net.Uri;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.CharMatcher;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-
+import eu.siacs.conversations.xmpp.Jid;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
@@ -18,8 +16,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-import eu.siacs.conversations.xmpp.Jid;
-
public class XmppUri {
public static final String ACTION_JOIN = "join";
@@ -42,8 +38,8 @@ public class XmppUri {
parse(Uri.parse(uri));
} catch (IllegalArgumentException e) {
try {
- jid = Jid.ofEscaped(uri).asBareJid().toEscapedString();
- } catch (IllegalArgumentException e2) {
+ jid = Jid.of(uri).asBareJid().toString();
+ } catch (final IllegalArgumentException e2) {
jid = null;
}
}
@@ -60,7 +56,8 @@ public class XmppUri {
private static Map<String, String> parseParameters(final String query, final char seperator) {
final ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
- final String[] pairs = query == null ? new String[0] : query.split(String.valueOf(seperator));
+ final String[] pairs =
+ query == null ? new String[0] : query.split(String.valueOf(seperator));
for (String pair : pairs) {
final String[] parts = pair.split("=", 2);
if (parts.length == 0) {
@@ -94,7 +91,7 @@ public class XmppUri {
final int id = Integer.parseInt(key.substring(OMEMO_URI_PARAM.length()));
builder.add(new Fingerprint(FingerprintType.OMEMO, value, id));
} catch (Exception e) {
- //ignoring invalid device id
+ // ignoring invalid device id
}
} else if ("omemo".equals(key)) {
builder.add(new Fingerprint(FingerprintType.OMEMO, value, 0));
@@ -103,7 +100,8 @@ public class XmppUri {
return builder.build();
}
- public static String getFingerprintUri(final String base, final List<XmppUri.Fingerprint> fingerprints, char separator) {
+ public static String getFingerprintUri(
+ final String base, final List<XmppUri.Fingerprint> fingerprints, char separator) {
final StringBuilder builder = new StringBuilder(base);
builder.append('?');
for (int i = 0; i < fingerprints.size(); ++i) {
@@ -145,8 +143,8 @@ public class XmppUri {
if (segments.size() >= 2 && segments.get(1).contains("@")) {
// sample : https://conversations.im/i/foo@bar.com
try {
- jid = Jid.ofEscaped(lameUrlDecode(segments.get(1))).toEscapedString();
- } catch (Exception e) {
+ jid = Jid.of(lameUrlDecode(segments.get(1))).toString();
+ } catch (final Exception e) {
jid = null;
}
} else if (segments.size() >= 3) {
@@ -172,7 +170,8 @@ public class XmppUri {
}
}
this.fingerprints = parseFingerprints(parameters);
- } else if ("imto".equalsIgnoreCase(scheme) && Arrays.asList("xmpp", "jabber").contains(uri.getHost())) {
+ } else if ("imto".equalsIgnoreCase(scheme)
+ && Arrays.asList("xmpp", "jabber").contains(uri.getHost())) {
// sample: imto://xmpp/foo@bar.com
try {
jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1].trim();
@@ -195,15 +194,18 @@ public class XmppUri {
public boolean isAction(final String action) {
return Collections2.transform(
- parameters.keySet(),
- s -> CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(s)
- ).contains(action);
+ parameters.keySet(),
+ s ->
+ CharMatcher.inRange('a', 'z')
+ .or(CharMatcher.inRange('A', 'Z'))
+ .retainFrom(s))
+ .contains(action);
}
public Jid getJid() {
try {
- return this.jid == null ? null : Jid.ofEscaped(this.jid);
- } catch (IllegalArgumentException e) {
+ return this.jid == null ? null : Jid.ofUserInput(this.jid);
+ } catch (final IllegalArgumentException e) {
return null;
}
}
@@ -213,9 +215,9 @@ public class XmppUri {
return false;
}
try {
- Jid.ofEscaped(jid);
+ Jid.ofUserInput(jid);
return true;
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
return false;
}
}
@@ -237,7 +239,7 @@ public class XmppUri {
}
public boolean hasFingerprints() {
- return fingerprints.size() > 0;
+ return !fingerprints.isEmpty();
}
public enum FingerprintType {
@@ -13,19 +13,16 @@ import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.SystemClock;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.work.ForegroundInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
-
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gson.stream.JsonWriter;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
@@ -36,7 +33,6 @@ import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.BackupFileHeader;
import eu.siacs.conversations.utils.Compatibility;
-
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -56,7 +52,6 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.zip.GZIPOutputStream;
-
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
@@ -162,7 +157,8 @@ public class ExportBackupWorker extends Worker {
Log.d(
Config.LOGTAG,
String.format(
- "skipping backup for %s because password is empty. unable to encrypt",
+ "skipping backup for %s because password is empty. unable to"
+ + " encrypt",
account.getJid().asBareJid()));
count++;
continue;
@@ -170,7 +166,7 @@ public class ExportBackupWorker extends Worker {
final String filename =
String.format(
"%s.%s.ceb",
- account.getJid().asBareJid().toEscapedString(),
+ account.getJid().asBareJid().toString(),
DATE_FORMAT.format(new Date()));
final File file = new File(FileBackend.getBackupDirectory(context), filename);
try {
@@ -379,7 +375,9 @@ public class ExportBackupWorker extends Worker {
getApplicationContext().getSystemService(NotificationManager.class);
try (final Cursor cursor =
db.rawQuery(
- "select messages.* from messages join conversations on conversations.uuid=messages.conversationUuid where conversations.accountUuid=?",
+ "select messages.* from messages join conversations on"
+ + " conversations.uuid=messages.conversationUuid where"
+ + " conversations.accountUuid=?",
new String[] {uuid})) {
final int size = cursor != null ? cursor.getCount() : 0;
Log.d(Config.LOGTAG, "exporting " + size + " messages for account " + uuid);
@@ -1,20 +1,16 @@
package eu.siacs.conversations.xml;
import androidx.annotation.NonNull;
-
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
-
import eu.siacs.conversations.utils.XmlHelper;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Message;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
public class Element {
private final String name;
@@ -133,7 +129,7 @@ public class Element {
public Element setAttribute(String name, Jid value) {
if (name != null && value != null) {
- this.attributes.put(name, value.toEscapedString());
+ this.attributes.put(name, value.toString());
}
return this;
}
@@ -172,16 +168,12 @@ public class Element {
return Optional.fromNullable(Ints.tryParse(value));
}
- public Jid getAttributeAsJid(String name) {
+ public Jid getAttributeAsJid(final String name) {
final String jid = this.getAttribute(name);
- if (jid != null && !jid.isEmpty()) {
- try {
- return Jid.ofEscaped(jid);
- } catch (final IllegalArgumentException e) {
- return InvalidJid.of(jid, this instanceof Message);
- }
+ if (Strings.isNullOrEmpty(jid)) {
+ return null;
}
- return null;
+ return Jid.ofOrInvalid(jid, this instanceof Message);
}
public Hashtable<String, String> getAttributes() {
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2018, Daniel Gultsch All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package eu.siacs.conversations.xmpp;
-
-import androidx.annotation.NonNull;
-
-import im.conversations.android.xmpp.model.stanza.Stanza;
-
-public class InvalidJid implements Jid {
-
- private final String value;
-
- private InvalidJid(String jid) {
- this.value = jid;
- }
-
- public static Jid of(String jid, boolean fallback) {
- final int pos = jid.indexOf('/');
- if (fallback && pos >= 0 && jid.length() >= pos + 1) {
- if (jid.substring(pos+1).trim().isEmpty()) {
- return Jid.ofEscaped(jid.substring(0,pos));
- }
- }
- return new InvalidJid(jid);
- }
-
- @Override
- @NonNull
- public String toString() {
- return value;
- }
-
- @Override
- public boolean isFullJid() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public boolean isBareJid() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public boolean isDomainJid() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public Jid asBareJid() {
- throw new AssertionError("Not implemented");
- }
-
-
- @Override
- public Jid withResource(CharSequence charSequence) {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public String getLocal() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public String getEscapedLocal() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public Jid getDomain() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public String getResource() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public String toEscapedString() {
- throw new AssertionError("Not implemented");
- }
-
- @Override
- public int length() {
- return value.length();
- }
-
- @Override
- public char charAt(int index) {
- return value.charAt(index);
- }
-
- @Override
- public CharSequence subSequence(int start, int end) {
- return value.subSequence(start, end);
- }
-
- @Override
- public int compareTo(@NonNull Jid o) {
- throw new AssertionError("Not implemented");
- }
-
- public static Jid getNullForInvalid(Jid jid) {
- if (jid instanceof InvalidJid) {
- return null;
- } else {
- return jid;
- }
- }
-
- public static boolean isValid(Jid jid) {
- return !(jid instanceof InvalidJid);
- }
-
- public static boolean hasValidFrom(Stanza stanza) {
- final String from = stanza.getAttribute("from");
- if (from == null) {
- return false;
- }
- try {
- Jid.ofEscaped(from);
- return true;
- } catch (IllegalArgumentException e) {
- return false;
- }
- }
-}
@@ -1,20 +1,19 @@
package eu.siacs.conversations.xmpp;
+import androidx.annotation.NonNull;
+import com.google.common.base.CharMatcher;
+import im.conversations.android.xmpp.model.stanza.Stanza;
+import java.io.Serializable;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
-import java.io.Serializable;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
-
- Pattern JID = Pattern.compile("^((.*?)@)?([^/@]+)(/(.*))?$");
+public abstract class Jid implements Comparable<Jid>, Serializable, CharSequence {
- static Jid of(CharSequence local, CharSequence domain, CharSequence resource) {
+ public static Jid of(
+ final CharSequence local, final CharSequence domain, final CharSequence resource) {
if (local == null) {
if (resource == null) {
return ofDomain(domain);
@@ -26,120 +25,312 @@ public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
return ofLocalAndDomain(local, domain);
}
try {
- return new WrappedJid(JidCreate.entityFullFrom(
- Localpart.fromUnescaped(local.toString()),
- Domainpart.from(domain.toString()),
- Resourcepart.from(resource.toString())
- ));
- } catch (XmppStringprepException e) {
+ return new InternalRepresentation(
+ JidCreate.entityFullFrom(
+ Localpart.from(local.toString()),
+ Domainpart.from(domain.toString()),
+ Resourcepart.from(resource.toString())));
+ } catch (final XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
- static Jid ofEscaped(CharSequence local, CharSequence domain, CharSequence resource) {
+ public static Jid ofDomain(final CharSequence domain) {
try {
- if (resource == null) {
- return new WrappedJid(
- JidCreate.bareFrom(
- Localpart.from(local.toString()),
- Domainpart.from(domain.toString())
- )
- );
- }
- return new WrappedJid(JidCreate.entityFullFrom(
- Localpart.from(local.toString()),
- Domainpart.from(domain.toString()),
- Resourcepart.from(resource.toString())
- ));
- } catch (XmppStringprepException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
-
- static Jid ofDomain(CharSequence domain) {
- try {
- return new WrappedJid(JidCreate.domainBareFrom(domain));
- } catch (XmppStringprepException e) {
+ return new InternalRepresentation(JidCreate.domainBareFrom(domain));
+ } catch (final XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
- static Jid ofLocalAndDomain(CharSequence local, CharSequence domain) {
+ public static Jid ofLocalAndDomain(final CharSequence local, final CharSequence domain) {
try {
- return new WrappedJid(
+ return new InternalRepresentation(
JidCreate.bareFrom(
- Localpart.fromUnescaped(local.toString()),
- Domainpart.from(domain.toString())
- )
- );
- } catch (XmppStringprepException e) {
+ Localpart.from(local.toString()), Domainpart.from(domain.toString())));
+ } catch (final XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
- static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
+ public static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
try {
- return new WrappedJid(
+ return new InternalRepresentation(
JidCreate.domainFullFrom(
Domainpart.from(domain.toString()),
- Resourcepart.from(resource.toString())
- ));
- } catch (XmppStringprepException e) {
+ Resourcepart.from(resource.toString())));
+ } catch (final XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
- static Jid ofLocalAndDomainEscaped(CharSequence local, CharSequence domain) {
+ public static Jid of(final CharSequence input) {
+ if (input instanceof Jid jid) {
+ return jid;
+ }
try {
- return new WrappedJid(
- JidCreate.bareFrom(
- Localpart.from(local.toString()),
- Domainpart.from(domain.toString())
- )
- );
- } catch (XmppStringprepException e) {
+ return new InternalRepresentation(JidCreate.from(input));
+ } catch (final XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
- static Jid of(CharSequence jid) {
- if (jid instanceof Jid) {
- return (Jid) jid;
- }
- Matcher matcher = JID.matcher(jid);
- if (matcher.matches()) {
- return of(matcher.group(2), matcher.group(3), matcher.group(5));
- } else {
- throw new IllegalArgumentException("Could not parse JID: " + jid);
+ public static Jid ofUserInput(final CharSequence input) {
+ final var jid = of(input);
+ if (CharMatcher.is('@').matchesAnyOf(jid.getDomain())) {
+ throw new IllegalArgumentException("Domain should not contain @");
}
+ return jid;
+ }
+
+ public static Jid ofOrInvalid(final String input) {
+ return ofOrInvalid(input, false);
}
- static Jid ofEscaped(CharSequence jid) {
+ /**
+ *
+ * @param jid a string representation of the jid to parse
+ * @param fallback indicates whether an attempt should be made to parse a bare version of the jid
+ * @return an instance of Jid; may be Jid.Invalid
+ */
+ public static Jid ofOrInvalid(final String jid, final boolean fallback) {
try {
- return new WrappedJid(JidCreate.from(jid));
- } catch (final XmppStringprepException e) {
- throw new IllegalArgumentException(e);
+ return Jid.of(jid);
+ } catch (final IllegalArgumentException e) {
+ return Jid.invalidOf(jid, fallback);
}
}
- boolean isFullJid();
+ private static Jid invalidOf(final String jid, boolean fallback) {
+ final int pos = jid.indexOf('/');
+ if (fallback && pos >= 0 && jid.length() >= pos + 1) {
+ if (jid.substring(pos + 1).trim().isEmpty()) {
+ return Jid.of(jid.substring(0, pos));
+ }
+ }
+ return new Invalid(jid);
+ }
+
+ public abstract boolean isFullJid();
+
+ public abstract boolean isBareJid();
+
+ public abstract boolean isDomainJid();
+
+ public abstract Jid asBareJid();
- boolean isBareJid();
+ public abstract Jid withResource(CharSequence resource);
- boolean isDomainJid();
+ public abstract String getLocal();
- Jid asBareJid();
+ public abstract Jid getDomain();
- Jid withResource(CharSequence resource);
+ public abstract String getResource();
- String getLocal();
+ private static class InternalRepresentation extends Jid {
+ private final org.jxmpp.jid.Jid inner;
- String getEscapedLocal();
+ private InternalRepresentation(final org.jxmpp.jid.Jid inner) {
+ this.inner = inner;
+ }
+
+ @Override
+ public boolean isFullJid() {
+ return inner.isEntityFullJid() || inner.isDomainFullJid();
+ }
- Jid getDomain();
+ @Override
+ public boolean isBareJid() {
+ return inner.isDomainBareJid() || inner.isEntityBareJid();
+ }
- String getResource();
+ @Override
+ public boolean isDomainJid() {
+ return inner.isDomainBareJid() || inner.isDomainFullJid();
+ }
+
+ @Override
+ public Jid asBareJid() {
+ return new InternalRepresentation(inner.asBareJid());
+ }
+
+ @Override
+ public Jid withResource(CharSequence resource) {
+ final Localpart localpart = inner.getLocalpartOrNull();
+ try {
+ final Resourcepart resourcepart = Resourcepart.from(resource.toString());
+ if (localpart == null) {
+ return new InternalRepresentation(
+ JidCreate.domainFullFrom(inner.getDomain(), resourcepart));
+ } else {
+ return new InternalRepresentation(
+ JidCreate.fullFrom(localpart, inner.getDomain(), resourcepart));
+ }
+ } catch (XmppStringprepException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public String getLocal() {
+ final Localpart localpart = inner.getLocalpartOrNull();
+ return localpart == null ? null : localpart.toString();
+ }
+
+ @Override
+ public Jid getDomain() {
+ return new InternalRepresentation(inner.asDomainBareJid());
+ }
+
+ @Override
+ public String getResource() {
+ final Resourcepart resourcepart = inner.getResourceOrNull();
+ return resourcepart == null ? null : resourcepart.toString();
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return inner.toString();
+ }
+
+ @Override
+ public int length() {
+ return inner.length();
+ }
- String toEscapedString();
+ @Override
+ public char charAt(int i) {
+ return inner.charAt(i);
+ }
+
+ @NonNull
+ @Override
+ public CharSequence subSequence(int i, int i1) {
+ return inner.subSequence(i, i1);
+ }
+
+ @Override
+ public int compareTo(Jid jid) {
+ if (jid instanceof InternalRepresentation) {
+ return inner.compareTo(((InternalRepresentation) jid).inner);
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ InternalRepresentation that = (InternalRepresentation) o;
+ return inner.equals(that.inner);
+ }
+
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+ }
+
+ public static class Invalid extends Jid {
+
+ private final String value;
+
+ private Invalid(final String jid) {
+ this.value = jid;
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean isFullJid() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public boolean isBareJid() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public boolean isDomainJid() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public Jid asBareJid() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public Jid withResource(CharSequence charSequence) {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public String getLocal() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public Jid getDomain() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public String getResource() {
+ throw new AssertionError("Not implemented");
+ }
+
+ @Override
+ public int length() {
+ return value.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return value.charAt(index);
+ }
+
+ @NonNull
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return value.subSequence(start, end);
+ }
+
+ @Override
+ public int compareTo(@NonNull Jid o) {
+ throw new AssertionError("Not implemented");
+ }
+
+ public static Jid getNullForInvalid(final Jid jid) {
+ if (jid instanceof Invalid) {
+ return null;
+ } else {
+ return jid;
+ }
+ }
+
+ public static boolean isValid(Jid jid) {
+ return !(jid instanceof Invalid);
+ }
+
+ public static boolean hasValidFrom(final Stanza stanza) {
+ final String from = stanza.getAttribute("from");
+ if (from == null) {
+ return false;
+ }
+ try {
+ Jid.of(from);
+ return true;
+ } catch (final IllegalArgumentException e) {
+ return false;
+ }
+ }
+ }
}
@@ -1,130 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-
-import androidx.annotation.NonNull;
-
-import org.jxmpp.jid.Jid;
-import org.jxmpp.jid.impl.JidCreate;
-import org.jxmpp.jid.parts.Localpart;
-import org.jxmpp.jid.parts.Resourcepart;
-import org.jxmpp.stringprep.XmppStringprepException;
-
-
-public class WrappedJid implements eu.siacs.conversations.xmpp.Jid {
- private final Jid inner;
-
- WrappedJid(Jid inner) {
- this.inner = inner;
- }
-
- @Override
- public boolean isFullJid() {
- return inner.isEntityFullJid() || inner.isDomainFullJid();
- }
-
- @Override
- public boolean isBareJid() {
- return inner.isDomainBareJid() || inner.isEntityBareJid();
- }
-
- @Override
- public boolean isDomainJid() {
- return inner.isDomainBareJid() || inner.isDomainFullJid();
- }
-
- @Override
- public eu.siacs.conversations.xmpp.Jid asBareJid() {
- return new WrappedJid(inner.asBareJid());
- }
-
- @Override
- public eu.siacs.conversations.xmpp.Jid withResource(CharSequence resource) {
- final Localpart localpart = inner.getLocalpartOrNull();
- try {
- final Resourcepart resourcepart = Resourcepart.from(resource.toString());
- if (localpart == null) {
- return new WrappedJid(JidCreate.domainFullFrom(inner.getDomain(),resourcepart));
- } else {
- return new WrappedJid(
- JidCreate.fullFrom(
- localpart,
- inner.getDomain(),
- resourcepart
- ));
- }
- } catch (XmppStringprepException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- @Override
- public String getLocal() {
- final Localpart localpart = inner.getLocalpartOrNull();
- return localpart == null ? null : localpart.asUnescapedString();
- }
-
- @Override
- public String getEscapedLocal() {
- final Localpart localpart = inner.getLocalpartOrNull();
- return localpart == null ? null : localpart.toString();
- }
-
- @Override
- public eu.siacs.conversations.xmpp.Jid getDomain() {
- return new WrappedJid(inner.asDomainBareJid());
- }
-
- @Override
- public String getResource() {
- final Resourcepart resourcepart = inner.getResourceOrNull();
- return resourcepart == null ? null : resourcepart.toString();
- }
-
- @Override
- public String toEscapedString() {
- return inner.toString();
- }
-
- @NonNull
- @Override
- public String toString() {
- return inner.asUnescapedString();
- }
-
- @Override
- public int length() {
- return inner.length();
- }
-
- @Override
- public char charAt(int i) {
- return inner.charAt(i);
- }
-
- @Override
- public CharSequence subSequence(int i, int i1) {
- return inner.subSequence(i,i1);
- }
-
- @Override
- public int compareTo(eu.siacs.conversations.xmpp.Jid jid) {
- if (jid instanceof WrappedJid) {
- return inner.compareTo(((WrappedJid) jid).inner);
- } else {
- return 0;
- }
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- WrappedJid that = (WrappedJid) o;
- return inner.equals(that.inner);
- }
-
- @Override
- public int hashCode() {
- return inner.hashCode();
- }
-}
@@ -2319,7 +2319,7 @@ public class XmppConnection implements Runnable {
for (final Element element : elements) {
if (element.getName().equals("item")) {
final Jid jid =
- InvalidJid.getNullForInvalid(
+ Jid.Invalid.getNullForInvalid(
element.getAttributeAsJid("jid"));
if (jid != null && !jid.equals(account.getDomain())) {
items.add(jid);
@@ -2484,7 +2484,7 @@ public class XmppConnection implements Runnable {
final Tag stream = Tag.start("stream:stream");
stream.setAttribute("to", account.getServer());
if (from) {
- stream.setAttribute("from", account.getJid().asBareJid().toEscapedString());
+ stream.setAttribute("from", account.getJid().asBareJid().toString());
}
stream.setAttribute("version", "1.0");
stream.setAttribute("xml:lang", LocalizedContent.STREAM_LANGUAGE);
@@ -2703,7 +2703,7 @@ public class XmppConnection implements Runnable {
public List<String> getMucServersWithholdAccount() {
final List<String> servers = getMucServers();
- servers.remove(account.getDomain().toEscapedString());
+ servers.remove(account.getDomain().toString());
return servers;
}
@@ -4,9 +4,7 @@ import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Base64;
import android.util.Log;
-
import androidx.annotation.Nullable;
-
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
@@ -15,7 +13,6 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Collections2;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSet;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@@ -39,10 +36,8 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
import eu.siacs.conversations.xmpp.jingle.transports.InbandBytestreamsTransport;
import eu.siacs.conversations.xmpp.jingle.transports.Transport;
-
import im.conversations.android.xmpp.model.jingle.Jingle;
import im.conversations.android.xmpp.model.stanza.Iq;
-
import java.lang.ref.WeakReference;
import java.security.SecureRandom;
import java.util.Arrays;
@@ -353,7 +348,8 @@ public class JingleConnectionManager extends AbstractConnectionManager {
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": updated previous busy because call got picked up by another device");
+ + ": updated previous busy because call got picked up by"
+ + " another device");
mXmppConnectionService.getNotificationService().clearMissedCall(previousBusy);
return;
}
@@ -393,15 +389,14 @@ public class JingleConnectionManager extends AbstractConnectionManager {
final String theirSessionId = id.sessionId;
if (ComparisonChain.start()
.compare(ourSessionId, theirSessionId)
- .compare(
- account.getJid().toEscapedString(),
- id.with.toEscapedString())
+ .compare(account.getJid().toString(), id.with.toString())
.result()
> 0) {
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
- + ": our session lost tie break. automatically accepting their session. winning Session="
+ + ": our session lost tie break. automatically accepting"
+ + " their session. winning Session="
+ theirSessionId);
// TODO a retract for this reason should probably include some indication of
// tie break
@@ -417,7 +412,8 @@ public class JingleConnectionManager extends AbstractConnectionManager {
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
- + ": our session won tie break. waiting for other party to accept. winningSession="
+ + ": our session won tie break. waiting for other party to"
+ + " accept. winningSession="
+ ourSessionId);
// TODO reject their session with <tie-break/>?
}
@@ -453,7 +449,8 @@ public class JingleConnectionManager extends AbstractConnectionManager {
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": ignoring proposal because busy on this device but there are other devices");
+ + ": ignoring proposal because busy on this device but"
+ + " there are other devices");
}
} else {
final JingleRtpConnection rtpConnection =
@@ -772,12 +769,14 @@ public class JingleConnectionManager extends AbstractConnectionManager {
if (hasMatchingRtpSession(account, with, media)) {
Log.d(
Config.LOGTAG,
- "ignoring request to propose jingle session because the other party already created one for us");
+ "ignoring request to propose jingle session because the other party"
+ + " already created one for us");
// TODO return something that we can parse the connection of of
return null;
}
throw new IllegalStateException(
- "There is already a running RTP session. This should have been caught by the UI");
+ "There is already a running RTP session. This should have been caught by"
+ + " the UI");
}
final CallIntegration callIntegration =
new CallIntegration(mXmppConnectionService.getApplicationContext());
@@ -4,10 +4,8 @@ import android.content.Intent;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
@@ -24,7 +22,6 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@@ -47,15 +44,8 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Proceed;
import eu.siacs.conversations.xmpp.jingle.stanzas.Propose;
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
-
import im.conversations.android.xmpp.model.jingle.Jingle;
import im.conversations.android.xmpp.model.stanza.Iq;
-
-import org.webrtc.EglBase;
-import org.webrtc.IceCandidate;
-import org.webrtc.PeerConnection;
-import org.webrtc.VideoTrack;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -67,6 +57,10 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import org.webrtc.EglBase;
+import org.webrtc.IceCandidate;
+import org.webrtc.PeerConnection;
+import org.webrtc.VideoTrack;
public class JingleRtpConnection extends AbstractJingleConnection
implements WebRTCWrapper.EventCallback, CallIntegration.Callback, OngoingRtpSession {
@@ -278,7 +272,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": PeerConnection was not initialized when processing transport info. this usually indicates a race condition that can be ignored");
+ + ": PeerConnection was not initialized when processing transport info."
+ + " this usually indicates a race condition that can be ignored");
}
}
@@ -625,7 +620,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.getAccount().getJid().asBareJid()
- + ": unable to rollback local description after receiving content-reject",
+ + ": unable to rollback local description after receiving"
+ + " content-reject",
cause);
webRTCWrapper.close();
sendSessionTerminate(Reason.FAILED_APPLICATION, cause.getMessage());
@@ -694,7 +690,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.getAccount().getJid().asBareJid()
- + ": unable to rollback local description after trying to retract content-add",
+ + ": unable to rollback local description after trying to retract"
+ + " content-add",
cause);
webRTCWrapper.close();
sendSessionTerminate(Reason.FAILED_APPLICATION, cause.getMessage());
@@ -773,14 +770,16 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": remote has accepted our upgrade to senders=both");
+ + ": remote has accepted our upgrade to"
+ + " senders=both");
acceptContentAdd(
ContentAddition.summary(modifiedSenders), modifiedSenders);
} else {
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": remote has rejected our upgrade to senders=both");
+ + ": remote has rejected our upgrade to"
+ + " senders=both");
acceptContentAdd(contentAddition, incomingContentAdd);
}
});
@@ -1072,7 +1071,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": no identification tags found in initial offer. we won't be able to calculate mLineIndices");
+ + ": no identification tags found in initial offer. we won't be able to"
+ + " calculate mLineIndices");
}
return identificationTags;
}
@@ -1169,7 +1169,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
sendSessionTerminate(
Reason.SECURITY_ERROR,
String.format(
- "Your session proposal (Jingle Message Initiation) included media %s but your session-initiate was %s",
+ "Your session proposal (Jingle Message Initiation) included media"
+ + " %s but your session-initiate was %s",
this.proposedMedia, contentMap.getMedia()));
return;
}
@@ -1254,7 +1255,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
sendSessionTerminate(
Reason.SECURITY_ERROR,
String.format(
- "Your session-included included media %s but our session-initiate was %s",
+ "Your session-included included media %s but our session-initiate was"
+ + " %s",
this.proposedMedia, contentMap.getMedia()));
return;
}
@@ -1342,7 +1344,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": ICE servers got discovered when session was already terminated. nothing to do.");
+ + ": ICE servers got discovered when session was already terminated."
+ + " nothing to do.");
return;
}
final boolean includeCandidates = remoteHasSdpOfferAnswer();
@@ -1445,7 +1448,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": preparing session accept was too slow. already terminated. nothing to do.");
+ + ": preparing session accept was too slow. already terminated. nothing"
+ + " to do.");
return;
}
transitionOrThrow(State.SESSION_ACCEPTED);
@@ -1488,10 +1492,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
+ ": delivered message to JingleRtpConnection "
+ message);
switch (message.getName()) {
- case "propose" -> receivePropose(
- from, Propose.upgrade(message), serverMessageId, timestamp);
- case "proceed" -> receiveProceed(
- from, Proceed.upgrade(message), serverMessageId, timestamp);
+ case "propose" ->
+ receivePropose(from, Propose.upgrade(message), serverMessageId, timestamp);
+ case "proceed" ->
+ receiveProceed(from, Proceed.upgrade(message), serverMessageId, timestamp);
case "retract" -> receiveRetract(from, serverMessageId, timestamp);
case "reject" -> receiveReject(from, serverMessageId, timestamp);
case "accept" -> receiveAccept(from, serverMessageId, timestamp);
@@ -1605,7 +1609,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.account.getJid()
- + ": received reject while in SESSION_INITIATED_PRE_APPROVED. callee reconsidered before receiving session-init");
+ + ": received reject while in SESSION_INITIATED_PRE_APPROVED. callee"
+ + " reconsidered before receiving session-init");
closeTransitionLogFinish(State.TERMINATED_DECLINED_OR_BUSY);
return;
}
@@ -1727,7 +1732,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": remote party signaled support for OMEMO verification but we have OMEMO disabled");
+ + ": remote party signaled support for OMEMO"
+ + " verification but we have OMEMO disabled");
}
this.omemoVerification.setDeviceId(null);
}
@@ -1822,7 +1828,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": ICE servers got discovered when session was already terminated. nothing to do.");
+ + ": ICE servers got discovered when session was already terminated."
+ + " nothing to do.");
return;
}
final boolean includeCandidates = remoteHasSdpOfferAnswer();
@@ -1917,7 +1924,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": preparing session was too slow. already terminated. nothing to do.");
+ + ": preparing session was too slow. already terminated. nothing to"
+ + " do.");
return;
}
this.transitionOrThrow(targetState);
@@ -1956,7 +1964,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": unable to use OMEMO DTLS verification on outgoing session initiate. falling back",
+ + ": unable to use OMEMO DTLS verification on outgoing"
+ + " session initiate. falling back",
e);
return rtpContentMap;
},
@@ -2070,9 +2079,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
case CONNECTED -> RtpEndUserState.CONNECTED;
case NEW, CONNECTING -> RtpEndUserState.CONNECTING;
case CLOSED -> RtpEndUserState.ENDING_CALL;
- default -> zeroDuration()
- ? RtpEndUserState.CONNECTIVITY_ERROR
- : RtpEndUserState.RECONNECTING;
+ default ->
+ zeroDuration()
+ ? RtpEndUserState.CONNECTIVITY_ERROR
+ : RtpEndUserState.RECONNECTING;
};
}
@@ -2116,13 +2126,14 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
case TERMINATED_SUCCESS -> this.callIntegration.success();
case ACCEPTED -> this.callIntegration.accepted();
- case RETRACTED, RETRACTED_RACED, TERMINATED_CANCEL_OR_TIMEOUT -> this.callIntegration
- .retracted();
+ case RETRACTED, RETRACTED_RACED, TERMINATED_CANCEL_OR_TIMEOUT ->
+ this.callIntegration.retracted();
case TERMINATED_CONNECTIVITY_ERROR,
- TERMINATED_APPLICATION_FAILURE,
- TERMINATED_SECURITY_ERROR -> this.callIntegration.error();
- default -> throw new IllegalStateException(
- String.format("%s is not handled", this.state));
+ TERMINATED_APPLICATION_FAILURE,
+ TERMINATED_SECURITY_ERROR ->
+ this.callIntegration.error();
+ default ->
+ throw new IllegalStateException(String.format("%s is not handled", this.state));
}
}
@@ -2195,14 +2206,18 @@ public class JingleRtpConnection extends AbstractJingleConnection
cancelRingingTimeout();
acceptCallFromSessionInitialized();
}
- case ACCEPTED -> Log.w(
- Config.LOGTAG,
- id.account.getJid().asBareJid()
- + ": the call has already been accepted with another client. UI was just lagging behind");
- case PROCEED, SESSION_ACCEPTED -> Log.w(
- Config.LOGTAG,
- id.account.getJid().asBareJid()
- + ": the call has already been accepted. user probably double tapped the UI");
+ case ACCEPTED ->
+ Log.w(
+ Config.LOGTAG,
+ id.account.getJid().asBareJid()
+ + ": the call has already been accepted with another client."
+ + " UI was just lagging behind");
+ case PROCEED, SESSION_ACCEPTED ->
+ Log.w(
+ Config.LOGTAG,
+ id.account.getJid().asBareJid()
+ + ": the call has already been accepted. user probably double"
+ + " tapped the UI");
default -> throw new IllegalStateException("Can not accept call from " + this.state);
}
}
@@ -2212,7 +2227,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": received rejectCall() when session has already been terminated. nothing to do");
+ + ": received rejectCall() when session has already been terminated."
+ + " nothing to do");
return;
}
switch (this.state) {
@@ -2245,7 +2261,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": received endCall() when session has already been terminated. nothing to do");
+ + ": received endCall() when session has already been terminated."
+ + " nothing to do");
return;
}
if (isInState(State.PROPOSED) && isResponder()) {
@@ -2447,7 +2464,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": not sending session-terminate after connectivity error because session is already in state "
+ + ": not sending session-terminate after connectivity error"
+ + " because session is already in state "
+ this.state);
return;
}
@@ -2649,7 +2667,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.d(
Config.LOGTAG,
id.account.getJid().asBareJid()
- + ": no need to send session-terminate after failed connection. Other party already did");
+ + ": no need to send session-terminate after failed connection."
+ + " Other party already did");
return;
}
sendSessionTerminate(Reason.CONNECTIVITY_ERROR);
@@ -2704,7 +2723,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
// callback when the rtp session has already ended.
Log.w(
Config.LOGTAG,
- "CallIntegration requested incoming call UI but session was already terminated");
+ "CallIntegration requested incoming call UI but session was already"
+ + " terminated");
return;
}
// TODO apparently this can be called too early as well?
@@ -2736,8 +2756,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
// we need to start the UI to a) show it and b) be able to ask for permissions
final Intent intent = new Intent(xmppConnectionService, RtpSessionActivity.class);
intent.setAction(RtpSessionActivity.ACTION_ACCEPT_CALL);
- intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().toEscapedString());
- intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
+ intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
@@ -1,10 +1,8 @@
package eu.siacs.conversations.xmpp.jingle.transports;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
@@ -22,7 +20,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.SocksSocketFactory;
import eu.siacs.conversations.xml.Element;
@@ -33,7 +30,6 @@ import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
import eu.siacs.conversations.xmpp.jingle.DirectConnectionUtils;
import eu.siacs.conversations.xmpp.jingle.stanzas.SocksByteStreamsTransportInfo;
import im.conversations.android.xmpp.model.stanza.Iq;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -104,8 +100,8 @@ public class SocksByteStreamsTransport implements Transport {
.join(
Arrays.asList(
streamId,
- id.with.toEscapedString(),
- id.account.getJid().toEscapedString())),
+ id.with.toString(),
+ id.account.getJid().toString())),
StandardCharsets.UTF_8)
.toString();
final var ourDestination =
@@ -115,8 +111,8 @@ public class SocksByteStreamsTransport implements Transport {
.join(
Arrays.asList(
streamId,
- id.account.getJid().toEscapedString(),
- id.with.toEscapedString())),
+ id.account.getJid().toString(),
+ id.with.toString())),
StandardCharsets.UTF_8)
.toString();
@@ -255,7 +251,7 @@ public class SocksByteStreamsTransport implements Transport {
final Element query = proxyActivation.addChild("query", Namespace.BYTE_STREAMS);
query.setAttribute("sid", this.streamId);
final Element activate = query.addChild("activate");
- activate.setContent(id.with.toEscapedString());
+ activate.setContent(id.with.toString());
xmppConnection.sendIqPacket(
proxyActivation,
(response) -> {
@@ -731,10 +727,12 @@ public class SocksByteStreamsTransport implements Transport {
&& selectedByThemCandidatePriority > candidate.priority) {
Log.d(
Config.LOGTAG,
- "The candidate selected by peer had a higher priority then anything we could try");
+ "The candidate selected by peer had a higher priority then anything we"
+ + " could try");
connectionFuture.setException(
new CandidateErrorException(
- "The candidate selected by peer had a higher priority then anything we could try"));
+ "The candidate selected by peer had a higher priority then"
+ + " anything we could try"));
return;
}
try {
@@ -864,7 +862,7 @@ public class SocksByteStreamsTransport implements Transport {
return new Candidate(
cid,
host,
- Jid.ofEscaped(jid),
+ Jid.of(jid),
Integer.parseInt(port),
Integer.parseInt(priority),
CandidateType.valueOf(type.toUpperCase(Locale.ROOT)));
@@ -1,7 +1,6 @@
package im.conversations.android.xmpp.model.bind;
import com.google.common.base.Strings;
-
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension;
@@ -26,7 +25,7 @@ public class Bind extends Extension {
return null;
}
try {
- return eu.siacs.conversations.xmpp.Jid.ofEscaped(content);
+ return eu.siacs.conversations.xmpp.Jid.of(content);
} catch (final IllegalArgumentException e) {
return null;
}
@@ -1,7 +1,6 @@
package im.conversations.android.xmpp.model.sasl2;
import com.google.common.base.Strings;
-
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension;
@@ -9,18 +8,17 @@ import im.conversations.android.xmpp.model.Extension;
@XmlElement
public class AuthorizationIdentifier extends Extension {
-
public AuthorizationIdentifier() {
super(AuthorizationIdentifier.class);
}
public Jid get() {
final var content = getContent();
- if ( Strings.isNullOrEmpty(content)) {
+ if (Strings.isNullOrEmpty(content)) {
return null;
}
try {
- return Jid.ofEscaped(content);
+ return Jid.of(content);
} catch (final IllegalArgumentException e) {
return null;
}
@@ -1,10 +1,7 @@
package im.conversations.android.xmpp.model.stanza;
import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
-
-import im.conversations.android.xmpp.model.Extension;
import im.conversations.android.xmpp.model.StreamElement;
import im.conversations.android.xmpp.model.error.Error;
@@ -45,7 +42,7 @@ public abstract class Stanza extends StreamElement {
public boolean isInvalid() {
final var to = getTo();
final var from = getFrom();
- if (to instanceof InvalidJid || from instanceof InvalidJid) {
+ if (to instanceof Jid.Invalid || from instanceof Jid.Invalid) {
return true;
}
return false;