diff --git a/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java b/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java index f824f7399..021ebf0ef 100644 --- a/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java +++ b/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java @@ -5,7 +5,6 @@ import androidx.room.Room; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.Iterables; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.IDs; import im.conversations.android.database.ConversationsDatabase; import im.conversations.android.database.entity.AccountEntity; @@ -28,12 +27,16 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; @RunWith(AndroidJUnit4.class) public class TransformationTest { - private static final Jid ACCOUNT = Jid.of("user@example.com"); - private static final Jid REMOTE = Jid.of("juliet@example.com"); + private static final BareJid ACCOUNT = JidCreate.bareFromOrThrowUnchecked("user@example.com"); + private static final BareJid REMOTE = JidCreate.bareFromOrThrowUnchecked("juliet@example.com"); private static final String GREETING = "Hi Juliet. How are you?"; @@ -55,11 +58,11 @@ public class TransformationTest { } @Test - public void reactionBeforeOriginal() { + public void reactionBeforeOriginal() throws XmppStringprepException { final var reactionMessage = new Message(); reactionMessage.setId("2"); reactionMessage.setTo(ACCOUNT); - reactionMessage.setFrom(REMOTE.withResource("junit")); + reactionMessage.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); final var reactions = reactionMessage.addExtension(new Reactions()); reactions.setId("1"); final var reaction = reactions.addExtension(new Reaction()); @@ -69,7 +72,7 @@ public class TransformationTest { final var originalMessage = new Message(); originalMessage.setId("1"); originalMessage.setTo(REMOTE); - originalMessage.setFrom(ACCOUNT.withResource("junit")); + originalMessage.setFrom(JidCreate.fullFrom(ACCOUNT, Resourcepart.from(("junit")))); final var body = originalMessage.addExtension(new Body()); body.setContent(GREETING); this.transformer.transform( @@ -86,28 +89,28 @@ public class TransformationTest { } @Test - public void multipleReactions() { - final var group = Jid.ofEscaped("a@group.example.com"); + public void multipleReactions() throws XmppStringprepException { + final var group = JidCreate.bareFrom("a@group.example.com"); final var message = new Message(Message.Type.GROUPCHAT); message.addExtension(new Body("Please give me a thumbs up")); - message.setFrom(group.withResource("user-a")); + message.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a")); final var reactionA = new Message(Message.Type.GROUPCHAT); - reactionA.setFrom(group.withResource("user-b")); + reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionA.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of(reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b")); final var reactionB = new Message(Message.Type.GROUPCHAT); - reactionB.setFrom(group.withResource("user-c")); + reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c"))); reactionB.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of(reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-c")); final var reactionC = new Message(Message.Type.GROUPCHAT); - reactionC.setFrom(group.withResource("user-d")); + reactionC.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-d"))); final var reactions = reactionC.addExtension(Reactions.to("stanza-a")); reactions.addExtension(new Reaction("Y")); reactions.addExtension(new Reaction("Z")); @@ -128,12 +131,12 @@ public class TransformationTest { } @Test - public void correctionBeforeOriginal() { + public void correctionBeforeOriginal() throws XmppStringprepException { final var messageCorrection = new Message(); messageCorrection.setId("2"); messageCorrection.setTo(ACCOUNT); - messageCorrection.setFrom(REMOTE.withResource("junit")); + messageCorrection.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); messageCorrection.addExtension(new Body()).setContent("Hi example!"); messageCorrection.addExtension(new Replace()).setId("1"); @@ -146,7 +149,7 @@ public class TransformationTest { final var messageWithTypo = new Message(); messageWithTypo.setId("1"); messageWithTypo.setTo(ACCOUNT); - messageWithTypo.setFrom(REMOTE.withResource("junit")); + messageWithTypo.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); messageWithTypo.addExtension(new Body()).setContent("Hii example!"); this.transformer.transform( @@ -163,12 +166,12 @@ public class TransformationTest { } @Test - public void correctionAfterOriginal() { + public void correctionAfterOriginal() throws XmppStringprepException { final var messageWithTypo = new Message(); messageWithTypo.setId("1"); messageWithTypo.setTo(ACCOUNT); - messageWithTypo.setFrom(REMOTE.withResource("junit")); + messageWithTypo.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); messageWithTypo.addExtension(new Body()).setContent("Hii example!"); this.transformer.transform( @@ -179,7 +182,7 @@ public class TransformationTest { final var messageCorrection = new Message(); messageCorrection.setId("2"); messageCorrection.setTo(ACCOUNT); - messageCorrection.setFrom(REMOTE.withResource("junit")); + messageCorrection.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); messageCorrection.addExtension(new Body()).setContent("Hi example!"); messageCorrection.addExtension(new Replace()).setId("1"); @@ -197,22 +200,22 @@ public class TransformationTest { } @Test - public void replacingReactions() { - final var group = Jid.ofEscaped("a@group.example.com"); + public void replacingReactions() throws XmppStringprepException { + final var group = JidCreate.bareFrom("a@group.example.com"); final var message = new Message(Message.Type.GROUPCHAT); message.addExtension(new Body("Please give me a thumbs up")); - message.setFrom(group.withResource("user-a")); + message.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a")); final var reactionA = new Message(Message.Type.GROUPCHAT); - reactionA.setFrom(group.withResource("user-b")); + reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionA.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("N")); this.transformer.transform( Transformation.of(reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b")); final var reactionB = new Message(Message.Type.GROUPCHAT); - reactionB.setFrom(group.withResource("user-b")); + reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionB.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of(reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-b")); @@ -224,8 +227,9 @@ public class TransformationTest { } @Test - public void twoCorrectionsOneReactionBeforeOriginalInGroupChat() { - final var group = Jid.ofEscaped("a@group.example.com"); + public void twoCorrectionsOneReactionBeforeOriginalInGroupChat() + throws XmppStringprepException { + final var group = JidCreate.bareFrom("a@group.example.com"); final var ogStanzaId = "og-stanza-id"; final var ogMessageId = "og-message-id"; @@ -234,7 +238,7 @@ public class TransformationTest { // m1.setId(ogMessageId); m1.addExtension(new Body("Please give me an thumbs up")); m1.addExtension(new Replace()).setId(ogMessageId); - m1.setFrom(group.withResource("user-a")); + m1.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of( m1, @@ -248,7 +252,7 @@ public class TransformationTest { // m2.setId(ogMessageId); m2.addExtension(new Body("Please give me a thumbs up")); m2.addExtension(new Replace()).setId(ogMessageId); - m2.setFrom(group.withResource("user-a")); + m2.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of( m2, @@ -259,7 +263,7 @@ public class TransformationTest { // a reaction final var reactionB = new Message(Message.Type.GROUPCHAT); - reactionB.setFrom(group.withResource("user-b")); + reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of( @@ -269,7 +273,7 @@ public class TransformationTest { final var m4 = new Message(Message.Type.GROUPCHAT); m4.setId(ogMessageId); m4.addExtension(new Body("Please give me thumbs up")); - m4.setFrom(group.withResource("user-a")); + m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a")); @@ -283,14 +287,15 @@ public class TransformationTest { } @Test - public void twoReactionsOneCorrectionBeforeOriginalInGroupChat() { - final var group = Jid.ofEscaped("a@group.example.com"); + public void twoReactionsOneCorrectionBeforeOriginalInGroupChat() + throws XmppStringprepException { + final var group = JidCreate.bareFrom("a@group.example.com"); final var ogStanzaId = "og-stanza-id"; final var ogMessageId = "og-message-id"; // first reaction final var reactionA = new Message(Message.Type.GROUPCHAT); - reactionA.setFrom(group.withResource("user-b")); + reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionA.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of( @@ -298,7 +303,7 @@ public class TransformationTest { // second reaction final var reactionB = new Message(Message.Type.GROUPCHAT); - reactionB.setFrom(group.withResource("user-c")); + reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c"))); reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of( @@ -308,7 +313,7 @@ public class TransformationTest { final var m1 = new Message(Message.Type.GROUPCHAT); m1.addExtension(new Body("Please give me a thumbs up")); m1.addExtension(new Replace()).setId(ogMessageId); - m1.setFrom(group.withResource("user-a")); + m1.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of( m1, @@ -321,7 +326,7 @@ public class TransformationTest { final var m4 = new Message(Message.Type.GROUPCHAT); m4.setId(ogMessageId); m4.addExtension(new Body("Please give me thumbs up (Typo)")); - m4.setFrom(group.withResource("user-a")); + m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a")); @@ -337,8 +342,8 @@ public class TransformationTest { } @Test - public void twoReactionsInGroupChat() { - final var group = Jid.ofEscaped("a@group.example.com"); + public void twoReactionsInGroupChat() throws XmppStringprepException { + final var group = JidCreate.bareFrom("a@group.example.com"); final var ogStanzaId = "og-stanza-id"; final var ogMessageId = "og-message-id"; @@ -346,13 +351,13 @@ public class TransformationTest { final var m4 = new Message(Message.Type.GROUPCHAT); m4.setId(ogMessageId); m4.addExtension(new Body("Please give me a thumbs up")); - m4.setFrom(group.withResource("user-a")); + m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a"))); this.transformer.transform( Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a")); // first reaction final var reactionA = new Message(Message.Type.GROUPCHAT); - reactionA.setFrom(group.withResource("user-b")); + reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b"))); reactionA.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of( @@ -360,7 +365,7 @@ public class TransformationTest { // second reaction final var reactionB = new Message(Message.Type.GROUPCHAT); - reactionB.setFrom(group.withResource("user-c")); + reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c"))); reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y")); this.transformer.transform( Transformation.of( @@ -378,11 +383,11 @@ public class TransformationTest { } @Test - public void inReplyTo() { + public void inReplyTo() throws XmppStringprepException { final var m1 = new Message(); m1.setId("1"); m1.setTo(ACCOUNT); - m1.setFrom(REMOTE.withResource("junit")); + m1.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); m1.addExtension(new Body("Hi. How are you?")); this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, "stanza-a", null)); @@ -411,18 +416,18 @@ public class TransformationTest { } @Test - public void messageWithReceipt() { + public void messageWithReceipt() throws XmppStringprepException { final var m1 = new Message(); m1.setId("1"); m1.setTo(REMOTE); - m1.setFrom(ACCOUNT.withResource("junit")); + m1.setFrom(JidCreate.fullFrom(ACCOUNT, Resourcepart.from("junit"))); m1.addExtension(new Body("Hi. How are you?")); this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, null, null)); final var m2 = new Message(); - m2.setTo(ACCOUNT.withResource("junit")); - m2.setFrom(REMOTE.withResource("junit")); + m2.setTo(JidCreate.fullFrom(ACCOUNT, Resourcepart.from("junit"))); + m2.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); m2.addExtension(new Received()).setId("1"); this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, null, null)); @@ -434,10 +439,10 @@ public class TransformationTest { } @Test - public void messageAndRetraction() { + public void messageAndRetraction() throws XmppStringprepException { final var m1 = new Message(); m1.setTo(ACCOUNT); - m1.setFrom(REMOTE.withResource("junit")); + m1.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); m1.setId("m1"); m1.addExtension(new Body("It is raining outside")); @@ -445,7 +450,7 @@ public class TransformationTest { final var m2 = new Message(); m2.setTo(ACCOUNT); - m2.setFrom(REMOTE.withResource("junit")); + m2.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit"))); m2.addExtension(new Retract()).setId("m1"); this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, null, null)); diff --git a/src/main/java/im/conversations/android/IDs.java b/src/main/java/im/conversations/android/IDs.java index 7f50d8040..a0945288f 100644 --- a/src/main/java/im/conversations/android/IDs.java +++ b/src/main/java/im/conversations/android/IDs.java @@ -10,6 +10,12 @@ public class IDs { private static final long UUID_VERSION_MASK = 4 << 12; + public static String huge() { + final var random = new byte[96]; + Conversations.SECURE_RANDOM.nextBytes(random); + return BaseEncoding.base64Url().encode(random); + } + public static String medium() { final var random = new byte[9]; Conversations.SECURE_RANDOM.nextBytes(random); diff --git a/src/main/java/im/conversations/android/database/Converters.java b/src/main/java/im/conversations/android/database/Converters.java index 3c6f51a1a..9c6aee271 100644 --- a/src/main/java/im/conversations/android/database/Converters.java +++ b/src/main/java/im/conversations/android/database/Converters.java @@ -1,9 +1,13 @@ package im.conversations.android.database; import androidx.room.TypeConverter; -import eu.siacs.conversations.xmpp.Jid; +import com.google.common.base.Strings; import java.io.IOException; import java.time.Instant; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -26,13 +30,35 @@ public final class Converters { } @TypeConverter - public static Jid toJid(final String input) { - return input == null ? null : Jid.ofEscaped(input); + public static BareJid toBareJid(final String input) { + return input == null ? null : JidCreate.bareFromOrThrowUnchecked(input); + } + + @TypeConverter + public static String fromBareJid(final BareJid jid) { + return jid == null ? null : jid.toString(); } @TypeConverter public static String fromJid(final Jid jid) { - return jid == null ? null : jid.toEscapedString(); + return jid == null ? null : jid.toString(); + } + + @TypeConverter + public static Jid toJid(final String input) { + return input == null ? null : JidCreate.fromOrThrowUnchecked(input); + } + + @TypeConverter + public static Resourcepart toResourcePart(final String input) { + return Strings.isNullOrEmpty(input) + ? Resourcepart.EMPTY + : Resourcepart.fromOrThrowUnchecked(input); + } + + @TypeConverter + public static String fromResourcePart(final Resourcepart resourcepart) { + return resourcepart == null ? null : resourcepart.toString(); } @TypeConverter diff --git a/src/main/java/im/conversations/android/database/CredentialStore.java b/src/main/java/im/conversations/android/database/CredentialStore.java index e5b8b22f0..432de986b 100644 --- a/src/main/java/im/conversations/android/database/CredentialStore.java +++ b/src/main/java/im/conversations/android/database/CredentialStore.java @@ -159,14 +159,14 @@ public class CredentialStore { private Credential getOrEmpty(final Account account) { final Map store = loadOrEmpty(); - final Credential credential = store.get(account.address.toEscapedString()); + final Credential credential = store.get(account.address.toString()); return credential == null ? Credential.empty() : credential; } private void set(@NonNull final Account account, @NonNull final Credential credential) throws GeneralSecurityException, IOException { final HashMap credentialStore = new HashMap<>(loadOrEmpty()); - credentialStore.put(account.address.toEscapedString(), credential); + credentialStore.put(account.address.toString(), credential); store(credentialStore); } diff --git a/src/main/java/im/conversations/android/database/dao/AccountDao.java b/src/main/java/im/conversations/android/database/dao/AccountDao.java index b1da1cc26..9ca569824 100644 --- a/src/main/java/im/conversations/android/database/dao/AccountDao.java +++ b/src/main/java/im/conversations/android/database/dao/AccountDao.java @@ -5,11 +5,11 @@ import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; import com.google.common.util.concurrent.ListenableFuture; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.AccountEntity; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.Connection; import java.util.List; +import org.jxmpp.jid.BareJid; @Dao public interface AccountDao { @@ -21,7 +21,7 @@ public interface AccountDao { ListenableFuture> getEnabledAccounts(); @Query("SELECT id,address,randomSeed FROM account WHERE address=:address AND enabled=1") - ListenableFuture getEnabledAccount(Jid address); + ListenableFuture getEnabledAccount(BareJid address); @Query("SELECT id,address,randomSeed FROM account WHERE id=:id AND enabled=1") ListenableFuture getEnabledAccount(long id); diff --git a/src/main/java/im/conversations/android/database/dao/AvatarDao.java b/src/main/java/im/conversations/android/database/dao/AvatarDao.java index fc337683e..16e972db5 100644 --- a/src/main/java/im/conversations/android/database/dao/AvatarDao.java +++ b/src/main/java/im/conversations/android/database/dao/AvatarDao.java @@ -4,12 +4,12 @@ import androidx.room.Dao; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.AvatarAdditionalEntity; import im.conversations.android.database.entity.AvatarEntity; import im.conversations.android.database.model.Account; import im.conversations.android.xmpp.model.avatar.Info; import java.util.Collection; +import org.jxmpp.jid.BareJid; @Dao public abstract class AvatarDao { @@ -22,7 +22,7 @@ public abstract class AvatarDao { public void set( final Account account, - final Jid address, + final BareJid address, final Info thumbnail, final Collection additional) { final long id = insert(AvatarEntity.of(account, address, thumbnail)); diff --git a/src/main/java/im/conversations/android/database/dao/AxolotlDao.java b/src/main/java/im/conversations/android/database/dao/AxolotlDao.java index d841eeefc..7a490eb65 100644 --- a/src/main/java/im/conversations/android/database/dao/AxolotlDao.java +++ b/src/main/java/im/conversations/android/database/dao/AxolotlDao.java @@ -6,7 +6,6 @@ import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Transaction; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.AxolotlDeviceListEntity; import im.conversations.android.database.entity.AxolotlDeviceListItemEntity; import im.conversations.android.database.entity.AxolotlIdentityEntity; @@ -19,6 +18,7 @@ import im.conversations.android.xmpp.model.error.Condition; import java.util.Collection; import java.util.List; import java.util.Set; +import org.jxmpp.jid.BareJid; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.ecc.Curve; @@ -36,7 +36,7 @@ public abstract class AxolotlDao { protected abstract void insert(Collection entities); @Transaction - public void setDeviceList(Account account, Jid from, Set deviceIds) { + public void setDeviceList(Account account, BareJid from, Set deviceIds) { final var listId = insert(AxolotlDeviceListEntity.of(account.id, from)); insert( Collections2.transform( @@ -47,15 +47,17 @@ public abstract class AxolotlDao { "SELECT EXISTS(SELECT deviceId FROM axolotl_device_list JOIN axolotl_device_list_item" + " ON axolotl_device_list.id=axolotl_device_list_item.deviceListId WHERE" + " accountId=:account AND address=:address AND deviceId=:deviceId)") - public abstract boolean hasDeviceId(final long account, final Jid address, final int deviceId); + public abstract boolean hasDeviceId( + final long account, final BareJid address, final int deviceId); @Transaction - public void setDeviceListError(final Account account, final Jid address, Condition condition) { + public void setDeviceListError( + final Account account, final BareJid address, Condition condition) { insert(AxolotlDeviceListEntity.of(account.id, address, condition.getName())); } @Transaction - public void setDeviceListParsingError(final Account account, final Jid address) { + public void setDeviceListParsingError(final Account account, final BareJid address) { insert(AxolotlDeviceListEntity.ofParsingIssue(account.id, address)); } @@ -96,7 +98,7 @@ public abstract class AxolotlDao { @Transaction public boolean setIdentity( - Account account, Jid address, int deviceId, IdentityKey identityKey) { + Account account, BareJid address, int deviceId, IdentityKey identityKey) { final var existing = getIdentityKey(account.id, address, deviceId); if (existing == null || !existing.equals(identityKey)) { insert(AxolotlIdentityEntity.of(account, address, deviceId, identityKey)); @@ -112,7 +114,7 @@ public abstract class AxolotlDao { @Query( "SELECT identityKey FROM AXOLOTL_IDENTITY WHERE accountId=:account AND" + " address=:address AND deviceId=:deviceId") - protected abstract IdentityKey getIdentityKey(long account, Jid address, int deviceId); + protected abstract IdentityKey getIdentityKey(long account, BareJid address, int deviceId); @Query( "SELECT preKeyRecord FROM axolotl_pre_key WHERE accountId=:account AND" @@ -165,24 +167,25 @@ public abstract class AxolotlDao { @Query( "SELECT sessionRecord FROM axolotl_session WHERE accountId=:account AND" + " address=:address AND deviceId=:deviceId") - public abstract SessionRecord getSessionRecord(long account, Jid address, int deviceId); + public abstract SessionRecord getSessionRecord(long account, BareJid address, int deviceId); @Query("SELECT deviceId FROM axolotl_session WHERE accountId=:account AND address=:address") public abstract List getSessionDeviceIds(long account, String address); - public void setSessionRecord(Account account, Jid address, int deviceId, SessionRecord record) { + public void setSessionRecord( + Account account, BareJid address, int deviceId, SessionRecord record) { insert(AxolotlSessionEntity.of(account, address, deviceId, record)); } @Query( "SELECT EXISTS(SELECT id FROM axolotl_session WHERE accountId=:account AND" + " address=:address AND deviceId=:deviceId)") - public abstract boolean hasSession(long account, Jid address, int deviceId); + public abstract boolean hasSession(long account, BareJid address, int deviceId); @Query( "DELETE FROM axolotl_session WHERE accountId=:account AND address=:address AND" + " deviceId=:deviceId") - public abstract void deleteSession(long account, Jid address, int deviceId); + public abstract void deleteSession(long account, BareJid address, int deviceId); @Query("DELETE FROM axolotl_session WHERE accountId=:account AND address=:address") public abstract void deleteSessions(long account, String address); diff --git a/src/main/java/im/conversations/android/database/dao/BlockingDao.java b/src/main/java/im/conversations/android/database/dao/BlockingDao.java index 997259791..47cfd4e04 100644 --- a/src/main/java/im/conversations/android/database/dao/BlockingDao.java +++ b/src/main/java/im/conversations/android/database/dao/BlockingDao.java @@ -6,11 +6,11 @@ import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Transaction; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.BlockedItemEntity; import im.conversations.android.database.model.Account; import im.conversations.android.xmpp.model.blocking.Item; import java.util.Collection; +import org.jxmpp.jid.Jid; @Dao public abstract class BlockingDao { diff --git a/src/main/java/im/conversations/android/database/dao/BookmarkDao.java b/src/main/java/im/conversations/android/database/dao/BookmarkDao.java index c1ff277ea..a52ede216 100644 --- a/src/main/java/im/conversations/android/database/dao/BookmarkDao.java +++ b/src/main/java/im/conversations/android/database/dao/BookmarkDao.java @@ -5,13 +5,14 @@ import androidx.room.Insert; import androidx.room.Query; import androidx.room.Transaction; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.BookmarkEntity; import im.conversations.android.database.model.Account; import im.conversations.android.xmpp.model.bookmark.Conference; import java.util.Collection; import java.util.Map; import java.util.Objects; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; @Dao public abstract class BookmarkDao { @@ -28,7 +29,7 @@ public abstract class BookmarkDao { @Transaction public void updateItems(final Account account, Map items) { final Collection addresses = - Collections2.transform(items.keySet(), BookmarkEntity::jidOrNull); + Collections2.transform(items.keySet(), JidCreate::fromOrNull); delete(account.id, addresses); final var entities = Collections2.transform( diff --git a/src/main/java/im/conversations/android/database/dao/ChatDao.java b/src/main/java/im/conversations/android/database/dao/ChatDao.java index 4eeccd0a3..acd7206d5 100644 --- a/src/main/java/im/conversations/android/database/dao/ChatDao.java +++ b/src/main/java/im/conversations/android/database/dao/ChatDao.java @@ -4,13 +4,13 @@ import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Transaction; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.ChatEntity; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.ChatIdentifier; import im.conversations.android.database.model.ChatType; import im.conversations.android.xmpp.model.stanza.Message; import java.util.Arrays; +import org.jxmpp.jid.Jid; @Dao public abstract class ChatDao { @@ -38,7 +38,7 @@ public abstract class ChatDao { // TODO do not create entity for 'error' final var entity = new ChatEntity(); entity.accountId = account.id; - entity.address = address.toEscapedString(); + entity.address = address.toString(); entity.type = chatType; entity.archived = true; final long id = insert(entity); diff --git a/src/main/java/im/conversations/android/database/dao/DiscoDao.java b/src/main/java/im/conversations/android/database/dao/DiscoDao.java index 1499d9b31..1ed9dc575 100644 --- a/src/main/java/im/conversations/android/database/dao/DiscoDao.java +++ b/src/main/java/im/conversations/android/database/dao/DiscoDao.java @@ -8,7 +8,6 @@ import androidx.room.Query; import androidx.room.Transaction; import com.google.common.base.Strings; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.DiscoEntity; import im.conversations.android.database.entity.DiscoExtensionEntity; import im.conversations.android.database.entity.DiscoExtensionFieldEntity; @@ -27,6 +26,8 @@ import im.conversations.android.xmpp.model.disco.info.Identity; import im.conversations.android.xmpp.model.disco.info.InfoQuery; import im.conversations.android.xmpp.model.disco.items.Item; import java.util.Collection; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Resourcepart; @Dao public abstract class DiscoDao { @@ -56,7 +57,7 @@ public abstract class DiscoDao { "UPDATE presence SET discoId=:discoId WHERE accountId=:account AND address=:address" + " AND resource=:resource") protected abstract void updateDiscoIdInPresence( - long account, Jid address, String resource, long discoId); + long account, Jid address, Resourcepart resource, long discoId); @Query( "UPDATE disco_item SET discoId=:discoId WHERE accountId=:account AND address=:address" @@ -131,7 +132,7 @@ public abstract class DiscoDao { updateDiscoIdInPresence( account, entity.address.asBareJid(), - Strings.nullToEmpty(entity.address.getResource()), + entity.address.getResourceOrEmpty(), discoId); } } diff --git a/src/main/java/im/conversations/android/database/dao/MessageDao.java b/src/main/java/im/conversations/android/database/dao/MessageDao.java index 7c3f6e85f..a3c31019d 100644 --- a/src/main/java/im/conversations/android/database/dao/MessageDao.java +++ b/src/main/java/im/conversations/android/database/dao/MessageDao.java @@ -9,7 +9,6 @@ import androidx.room.Update; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.MessageContentEntity; import im.conversations.android.database.entity.MessageEntity; import im.conversations.android.database.entity.MessageReactionEntity; @@ -27,6 +26,9 @@ import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.stanza.Message; import java.util.Collection; import java.util.List; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Resourcepart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,14 +40,17 @@ public abstract class MessageDao { @Query( "UPDATE message SET acknowledged=1 WHERE messageId=:messageId AND toBare=:toBare AND" + " toResource=NULL AND chatId IN (SELECT id FROM chat WHERE accountId=:account)") - abstract int acknowledge(long account, String messageId, final String toBare); + abstract int acknowledge(long account, String messageId, final BareJid toBare); @Query( "UPDATE message SET acknowledged=1 WHERE messageId=:messageId AND toBare=:toBare AND" + " toResource=:toResource AND chatId IN (SELECT id FROM chat WHERE" + " accountId=:account)") abstract int acknowledge( - long account, final String messageId, final String toBare, final String toResource); + long account, + final String messageId, + final BareJid toBare, + final Resourcepart toResource); public boolean acknowledge( final Account account, @NonNull final String messageId, @NonNull final Jid to) { @@ -54,12 +59,10 @@ public abstract class MessageDao { public boolean acknowledge( final long account, @NonNull final String messageId, @NonNull final Jid to) { - if (to.isBareJid()) { - return acknowledge(account, messageId, to.toEscapedString()) > 0; + if (to.hasResource()) { + return acknowledge(account, messageId, to.asBareJid(), to.getResourceOrThrow()) > 0; } else { - return acknowledge( - account, messageId, to.asBareJid().toEscapedString(), to.getResource()) - > 0; + return acknowledge(account, messageId, to.asBareJid()) > 0; } } @@ -192,7 +195,7 @@ public abstract class MessageDao { + " stanzaId=:stanzaId AND (stanzaIdVerified=1 OR latestVersion IS NULL)) OR" + " (stanzaId IS NULL AND messageId=:messageId AND latestVersion IS NULL))") abstract MessageIdentifier get( - long chatId, Jid fromBare, String occupantId, String stanzaId, String messageId); + long chatId, BareJid fromBare, String occupantId, String stanzaId, String messageId); public MessageIdentifier getOrCreateVersion( ChatIdentifier chat, @@ -257,13 +260,13 @@ public abstract class MessageDao { + " chatId=:chatId AND (fromBare=:fromBare OR fromBare IS NULL) AND" + " (occupantId=:occupantId OR occupantId IS NULL) AND messageId=:messageId") abstract MessageIdentifier getByOccupantIdAndMessageId( - long chatId, Jid fromBare, String occupantId, String messageId); + long chatId, BareJid fromBare, String occupantId, String messageId); @Query( "SELECT id,stanzaId,messageId,fromBare,latestVersion as version FROM message WHERE" + " chatId=:chatId AND (fromBare=:fromBare OR fromBare IS NULL) AND" + " messageId=:messageId") - abstract MessageIdentifier getByMessageId(long chatId, Jid fromBare, String messageId); + abstract MessageIdentifier getByMessageId(long chatId, BareJid fromBare, String messageId); @Query( "SELECT id FROM message_version WHERE messageEntityId=:messageEntityId ORDER BY (CASE" @@ -393,7 +396,7 @@ public abstract class MessageDao { @Query( "DELETE FROM message_reaction WHERE messageEntityId=:messageEntityId AND" + " reactionBy=:fromBare") - protected abstract void deleteReactionsByFromBare(long messageEntityId, Jid fromBare); + protected abstract void deleteReactionsByFromBare(long messageEntityId, BareJid fromBare); @Transaction @Query( @@ -436,7 +439,7 @@ public abstract class MessageDao { @Query( "SELECT id FROM message WHERE chatId=:chatId AND fromBare=:fromBare AND" + " messageId=:messageId") - protected abstract Long getMessageByMessageId(long chatId, Jid fromBare, String messageId); + protected abstract Long getMessageByMessageId(long chatId, BareJid fromBare, String messageId); @Query("SELECT id FROM message WHERE chatId=:chatId AND stanzaId=:stanzaId") protected abstract Long getMessageByStanzaId(long chatId, String stanzaId); diff --git a/src/main/java/im/conversations/android/database/dao/NickDao.java b/src/main/java/im/conversations/android/database/dao/NickDao.java index e0997bd2c..91ddfa4a5 100644 --- a/src/main/java/im/conversations/android/database/dao/NickDao.java +++ b/src/main/java/im/conversations/android/database/dao/NickDao.java @@ -3,9 +3,9 @@ package im.conversations.android.database.dao; import androidx.room.Dao; import androidx.room.Insert; import androidx.room.OnConflictStrategy; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.NickEntity; import im.conversations.android.database.model.Account; +import org.jxmpp.jid.Jid; @Dao public abstract class NickDao { diff --git a/src/main/java/im/conversations/android/database/dao/PresenceDao.java b/src/main/java/im/conversations/android/database/dao/PresenceDao.java index 9e406792c..4ba615147 100644 --- a/src/main/java/im/conversations/android/database/dao/PresenceDao.java +++ b/src/main/java/im/conversations/android/database/dao/PresenceDao.java @@ -6,12 +6,13 @@ import androidx.room.Dao; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.PresenceEntity; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.PresenceShow; import im.conversations.android.database.model.PresenceType; import java.util.Arrays; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Dao public abstract class PresenceDao { @@ -20,29 +21,29 @@ public abstract class PresenceDao { public abstract void deletePresences(long account); @Query("DELETE FROM presence WHERE accountId=:account AND address=:address") - abstract void deletePresences(long account, Jid address); + abstract void deletePresences(long account, BareJid address); @Query( "DELETE FROM presence WHERE accountId=:account AND address=:address AND" + " resource=:resource") - abstract void deletePresence(long account, Jid address, String resource); + abstract void deletePresence(long account, BareJid address, Resourcepart resource); @Insert(onConflict = OnConflictStrategy.REPLACE) abstract void insert(PresenceEntity entity); public void set( @NonNull final Account account, - @NonNull final Jid address, - @Nullable final String resource, + @NonNull final BareJid address, + @NonNull final Resourcepart resource, @Nullable final PresenceType type, @Nullable final PresenceShow show, @Nullable final String status) { - if (resource == null + if (resource.equals(Resourcepart.EMPTY) && Arrays.asList(PresenceType.ERROR, PresenceType.UNAVAILABLE).contains(type)) { deletePresences(account.id, address); } if (type == PresenceType.UNAVAILABLE) { - if (resource != null) { + if (!resource.equals(Resourcepart.EMPTY)) { deletePresence(account.id, address, resource); } // unavailable presence only delete previous nothing left to do diff --git a/src/main/java/im/conversations/android/database/dao/RosterDao.java b/src/main/java/im/conversations/android/database/dao/RosterDao.java index 0f05a5db4..7648afb0b 100644 --- a/src/main/java/im/conversations/android/database/dao/RosterDao.java +++ b/src/main/java/im/conversations/android/database/dao/RosterDao.java @@ -7,12 +7,12 @@ import androidx.room.Insert; import androidx.room.Query; import androidx.room.Transaction; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.RosterItemEntity; import im.conversations.android.database.entity.RosterItemGroupEntity; import im.conversations.android.database.model.Account; import im.conversations.android.xmpp.model.roster.Item; import java.util.Collection; +import org.jxmpp.jid.Jid; @Dao public abstract class RosterDao { diff --git a/src/main/java/im/conversations/android/database/entity/AccountEntity.java b/src/main/java/im/conversations/android/database/entity/AccountEntity.java index e4d197510..1e90ff14f 100644 --- a/src/main/java/im/conversations/android/database/entity/AccountEntity.java +++ b/src/main/java/im/conversations/android/database/entity/AccountEntity.java @@ -5,9 +5,10 @@ import androidx.room.Embedded; import androidx.room.Entity; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.Connection; import im.conversations.android.database.model.Proxy; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "account", @@ -21,8 +22,8 @@ public class AccountEntity { @PrimaryKey(autoGenerate = true) public Long id; - @NonNull public Jid address; - public String resource; + @NonNull public BareJid address; + public Resourcepart resource; public byte[] randomSeed; public boolean enabled; diff --git a/src/main/java/im/conversations/android/database/entity/AvatarEntity.java b/src/main/java/im/conversations/android/database/entity/AvatarEntity.java index 4d28b3a7a..1bea4cf2a 100644 --- a/src/main/java/im/conversations/android/database/entity/AvatarEntity.java +++ b/src/main/java/im/conversations/android/database/entity/AvatarEntity.java @@ -6,10 +6,10 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.AvatarThumbnail; import im.conversations.android.xmpp.model.avatar.Info; +import org.jxmpp.jid.BareJid; @Entity( tableName = "avatar", @@ -31,13 +31,13 @@ public class AvatarEntity { @NonNull public Long accountId; - @NonNull public Jid address; + @NonNull public BareJid address; @Embedded(prefix = "thumb_") @NonNull public AvatarThumbnail thumbnail; - public static AvatarEntity of(final Account account, final Jid address, final Info info) { + public static AvatarEntity of(final Account account, final BareJid address, final Info info) { final var entity = new AvatarEntity(); entity.accountId = account.id; entity.address = address; diff --git a/src/main/java/im/conversations/android/database/entity/AxolotlDeviceListEntity.java b/src/main/java/im/conversations/android/database/entity/AxolotlDeviceListEntity.java index ea0b245a0..95f5a3911 100644 --- a/src/main/java/im/conversations/android/database/entity/AxolotlDeviceListEntity.java +++ b/src/main/java/im/conversations/android/database/entity/AxolotlDeviceListEntity.java @@ -5,8 +5,8 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import java.time.Instant; +import org.jxmpp.jid.BareJid; @Entity( tableName = "axolotl_device_list", @@ -28,7 +28,7 @@ public class AxolotlDeviceListEntity { @NonNull public Long accountId; - @NonNull public Jid address; + @NonNull public BareJid address; @NonNull public Instant receivedAt; @@ -36,7 +36,7 @@ public class AxolotlDeviceListEntity { public boolean isParsingIssue; - public static AxolotlDeviceListEntity of(long accountId, final Jid address) { + public static AxolotlDeviceListEntity of(long accountId, final BareJid address) { final var entity = new AxolotlDeviceListEntity(); entity.accountId = accountId; entity.address = address; @@ -46,7 +46,7 @@ public class AxolotlDeviceListEntity { } public static AxolotlDeviceListEntity of( - final long accountId, final Jid address, final String errorCondition) { + final long accountId, final BareJid address, final String errorCondition) { final var entity = new AxolotlDeviceListEntity(); entity.accountId = accountId; entity.address = address; @@ -55,7 +55,7 @@ public class AxolotlDeviceListEntity { return entity; } - public static AxolotlDeviceListEntity ofParsingIssue(final long account, Jid address) { + public static AxolotlDeviceListEntity ofParsingIssue(final long account, BareJid address) { final var entity = new AxolotlDeviceListEntity(); entity.accountId = account; entity.address = address; diff --git a/src/main/java/im/conversations/android/database/entity/AxolotlIdentityEntity.java b/src/main/java/im/conversations/android/database/entity/AxolotlIdentityEntity.java index ae88326e7..c47e924c3 100644 --- a/src/main/java/im/conversations/android/database/entity/AxolotlIdentityEntity.java +++ b/src/main/java/im/conversations/android/database/entity/AxolotlIdentityEntity.java @@ -5,8 +5,8 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.Account; +import org.jxmpp.jid.BareJid; import org.whispersystems.libsignal.IdentityKey; @Entity( @@ -29,14 +29,14 @@ public class AxolotlIdentityEntity { @NonNull public Long accountId; - @NonNull public Jid address; + @NonNull public BareJid address; @NonNull public Integer deviceId; @NonNull public IdentityKey identityKey; public static AxolotlIdentityEntity of( - Account account, Jid address, int deviceId, IdentityKey identityKey) { + Account account, BareJid address, int deviceId, IdentityKey identityKey) { final var entity = new AxolotlIdentityEntity(); entity.accountId = account.id; entity.address = address; diff --git a/src/main/java/im/conversations/android/database/entity/AxolotlSessionEntity.java b/src/main/java/im/conversations/android/database/entity/AxolotlSessionEntity.java index 94b1f1b22..4980b8394 100644 --- a/src/main/java/im/conversations/android/database/entity/AxolotlSessionEntity.java +++ b/src/main/java/im/conversations/android/database/entity/AxolotlSessionEntity.java @@ -5,8 +5,8 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.Account; +import org.jxmpp.jid.BareJid; import org.whispersystems.libsignal.state.SessionRecord; @Entity( @@ -29,14 +29,14 @@ public class AxolotlSessionEntity { @NonNull public Long accountId; - @NonNull public Jid address; + @NonNull public BareJid address; @NonNull public Integer deviceId; @NonNull public SessionRecord sessionRecord; public static AxolotlSessionEntity of( - Account account, Jid address, int deviceId, SessionRecord record) { + Account account, BareJid address, int deviceId, SessionRecord record) { final var entity = new AxolotlSessionEntity(); entity.accountId = account.id; entity.address = address; diff --git a/src/main/java/im/conversations/android/database/entity/BlockedItemEntity.java b/src/main/java/im/conversations/android/database/entity/BlockedItemEntity.java index 51a71a150..9d3eae2a5 100644 --- a/src/main/java/im/conversations/android/database/entity/BlockedItemEntity.java +++ b/src/main/java/im/conversations/android/database/entity/BlockedItemEntity.java @@ -5,7 +5,7 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.Jid; @Entity( tableName = "blocked", diff --git a/src/main/java/im/conversations/android/database/entity/BookmarkEntity.java b/src/main/java/im/conversations/android/database/entity/BookmarkEntity.java index 792a2b744..758c62a2e 100644 --- a/src/main/java/im/conversations/android/database/entity/BookmarkEntity.java +++ b/src/main/java/im/conversations/android/database/entity/BookmarkEntity.java @@ -5,9 +5,10 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.model.bookmark.Conference; import java.util.Map; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; @Entity( tableName = "bookmark", @@ -41,7 +42,7 @@ public class BookmarkEntity { public static BookmarkEntity of( final long accountId, final Map.Entry entry) { - final var address = jidOrNull(entry.getKey()); + final var address = JidCreate.fromOrNull(entry.getKey()); final var conference = entry.getValue(); if (address == null) { return null; @@ -53,12 +54,4 @@ public class BookmarkEntity { entity.name = conference.getConferenceName(); return entity; } - - public static Jid jidOrNull(final String address) { - try { - return address == null ? null : Jid.ofEscaped(address); - } catch (final IllegalArgumentException e) { - return null; - } - } } diff --git a/src/main/java/im/conversations/android/database/entity/DiscoItemEntity.java b/src/main/java/im/conversations/android/database/entity/DiscoItemEntity.java index b0a88496b..229192ba6 100644 --- a/src/main/java/im/conversations/android/database/entity/DiscoItemEntity.java +++ b/src/main/java/im/conversations/android/database/entity/DiscoItemEntity.java @@ -6,8 +6,8 @@ import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; import com.google.common.base.Strings; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.model.disco.items.Item; +import org.jxmpp.jid.Jid; @Entity( tableName = "disco_item", @@ -57,7 +57,7 @@ public class DiscoItemEntity { entity.accountId = accountId; entity.address = item.getJid(); entity.node = Strings.nullToEmpty(item.getNode()); - entity.parentAddress = parent.toEscapedString(); + entity.parentAddress = parent.toString(); entity.parentNode = Strings.nullToEmpty(parentNode); return entity; } diff --git a/src/main/java/im/conversations/android/database/entity/MessageEntity.java b/src/main/java/im/conversations/android/database/entity/MessageEntity.java index 58c5e64a4..a3b7f7134 100644 --- a/src/main/java/im/conversations/android/database/entity/MessageEntity.java +++ b/src/main/java/im/conversations/android/database/entity/MessageEntity.java @@ -6,10 +6,11 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.transformer.Transformation; import java.time.Instant; import java.util.Objects; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "message", @@ -47,10 +48,10 @@ public class MessageEntity { public boolean outgoing; - public Jid toBare; - public String toResource; - public Jid fromBare; - public String fromResource; + public BareJid toBare; + public Resourcepart toResource; + public BareJid fromBare; + public Resourcepart fromResource; public String occupantId; diff --git a/src/main/java/im/conversations/android/database/entity/MessageReactionEntity.java b/src/main/java/im/conversations/android/database/entity/MessageReactionEntity.java index 7fbbbf0ec..f0a93a773 100644 --- a/src/main/java/im/conversations/android/database/entity/MessageReactionEntity.java +++ b/src/main/java/im/conversations/android/database/entity/MessageReactionEntity.java @@ -5,9 +5,10 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.transformer.Transformation; import java.time.Instant; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "message_reaction", @@ -27,8 +28,8 @@ public class MessageReactionEntity { public String stanzaId; public String messageId; - public Jid reactionBy; - public String reactionByResource; + public BareJid reactionBy; + public Resourcepart reactionByResource; public String occupantId; public Instant receivedAt; diff --git a/src/main/java/im/conversations/android/database/entity/MessageStateEntity.java b/src/main/java/im/conversations/android/database/entity/MessageStateEntity.java index 116a755a7..83c8af924 100644 --- a/src/main/java/im/conversations/android/database/entity/MessageStateEntity.java +++ b/src/main/java/im/conversations/android/database/entity/MessageStateEntity.java @@ -6,9 +6,10 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.MessageState; import im.conversations.android.database.model.StateType; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "message_state", @@ -26,9 +27,9 @@ public class MessageStateEntity { @NonNull public Long messageVersionId; - @NonNull public Jid fromBare; + @NonNull public BareJid fromBare; - @Nullable public String fromResource; + @Nullable public Resourcepart fromResource; @NonNull public StateType type; diff --git a/src/main/java/im/conversations/android/database/entity/MessageVersionEntity.java b/src/main/java/im/conversations/android/database/entity/MessageVersionEntity.java index c88685879..98834b431 100644 --- a/src/main/java/im/conversations/android/database/entity/MessageVersionEntity.java +++ b/src/main/java/im/conversations/android/database/entity/MessageVersionEntity.java @@ -6,11 +6,12 @@ import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; import com.google.common.base.Preconditions; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.Modification; import im.conversations.android.transformer.Transformation; import im.conversations.android.xmpp.model.stanza.Message; import java.time.Instant; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "message_version", @@ -31,8 +32,8 @@ public class MessageVersionEntity { public String messageId; public String stanzaId; public Modification modification; - public Jid modifiedBy; - public String modifiedByResource; + public BareJid modifiedBy; + public Resourcepart modifiedByResource; public String occupantId; public Instant receivedAt; diff --git a/src/main/java/im/conversations/android/database/entity/NickEntity.java b/src/main/java/im/conversations/android/database/entity/NickEntity.java index 88388eaf5..3e568b4ef 100644 --- a/src/main/java/im/conversations/android/database/entity/NickEntity.java +++ b/src/main/java/im/conversations/android/database/entity/NickEntity.java @@ -5,7 +5,7 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.Jid; @Entity( tableName = "nick", diff --git a/src/main/java/im/conversations/android/database/entity/PresenceEntity.java b/src/main/java/im/conversations/android/database/entity/PresenceEntity.java index 6092829ab..760d9667f 100644 --- a/src/main/java/im/conversations/android/database/entity/PresenceEntity.java +++ b/src/main/java/im/conversations/android/database/entity/PresenceEntity.java @@ -6,11 +6,12 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import com.google.common.base.Strings; import eu.siacs.conversations.entities.MucOptions; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.model.PresenceShow; import im.conversations.android.database.model.PresenceType; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Resourcepart; @Entity( tableName = "presence", @@ -39,9 +40,9 @@ public class PresenceEntity { @NonNull public Long accountId; - @NonNull public Jid address; + @NonNull public BareJid address; - @NonNull public String resource; + @NonNull public Resourcepart resource; @Nullable public PresenceType type; @@ -66,15 +67,15 @@ public class PresenceEntity { public static PresenceEntity of( long account, - Jid address, - @Nullable String resource, + @NonNull BareJid address, + @NonNull Resourcepart resource, PresenceType type, PresenceShow show, String status) { final var entity = new PresenceEntity(); entity.accountId = account; entity.address = address; - entity.resource = Strings.nullToEmpty(resource); + entity.resource = resource; entity.type = type; entity.show = show; entity.status = status; diff --git a/src/main/java/im/conversations/android/database/entity/RosterItemEntity.java b/src/main/java/im/conversations/android/database/entity/RosterItemEntity.java index a5c9dacd6..2f9b68545 100644 --- a/src/main/java/im/conversations/android/database/entity/RosterItemEntity.java +++ b/src/main/java/im/conversations/android/database/entity/RosterItemEntity.java @@ -5,8 +5,8 @@ import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; import androidx.room.PrimaryKey; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.model.roster.Item; +import org.jxmpp.jid.Jid; @Entity( tableName = "roster", diff --git a/src/main/java/im/conversations/android/database/model/Account.java b/src/main/java/im/conversations/android/database/model/Account.java index 43a6d3797..5b1cc61d3 100644 --- a/src/main/java/im/conversations/android/database/model/Account.java +++ b/src/main/java/im/conversations/android/database/model/Account.java @@ -6,20 +6,19 @@ import com.google.common.base.Preconditions; import com.google.common.hash.Hashing; import com.google.common.io.ByteSource; import com.google.common.primitives.Ints; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.IDs; import java.io.IOException; import java.util.UUID; +import org.jxmpp.jid.BareJid; public class Account { public final long id; - @NonNull public final Jid address; + @NonNull public final BareJid address; @NonNull public final byte[] randomSeed; - public Account(final long id, @NonNull final Jid address, @NonNull byte[] randomSeed) { + public Account(final long id, @NonNull final BareJid address, @NonNull byte[] randomSeed) { Preconditions.checkNotNull(address, "Account can not be instantiated without an address"); - Preconditions.checkArgument(address.isBareJid(), "Account address must be bare"); Preconditions.checkArgument( randomSeed.length == 32, "RandomSeed must have exactly 32 bytes"); this.id = id; @@ -43,7 +42,7 @@ public class Account { } public boolean isOnion() { - final String domain = address.getDomain().toEscapedString(); + final String domain = address.getDomain().toString(); return domain.endsWith(".onion"); } diff --git a/src/main/java/im/conversations/android/database/model/ChatIdentifier.java b/src/main/java/im/conversations/android/database/model/ChatIdentifier.java index db1e6f6f0..7d15f6b22 100644 --- a/src/main/java/im/conversations/android/database/model/ChatIdentifier.java +++ b/src/main/java/im/conversations/android/database/model/ChatIdentifier.java @@ -1,6 +1,6 @@ package im.conversations.android.database.model; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.Jid; public class ChatIdentifier { diff --git a/src/main/java/im/conversations/android/database/model/MessageEmbedded.java b/src/main/java/im/conversations/android/database/model/MessageEmbedded.java index 5583d5fe3..45f11a9db 100644 --- a/src/main/java/im/conversations/android/database/model/MessageEmbedded.java +++ b/src/main/java/im/conversations/android/database/model/MessageEmbedded.java @@ -1,10 +1,10 @@ package im.conversations.android.database.model; import androidx.room.Relation; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.MessageContentEntity; import java.time.Instant; import java.util.List; +import org.jxmpp.jid.Jid; public class MessageEmbedded { diff --git a/src/main/java/im/conversations/android/database/model/MessageIdentifier.java b/src/main/java/im/conversations/android/database/model/MessageIdentifier.java index c9b6fb214..90d26b658 100644 --- a/src/main/java/im/conversations/android/database/model/MessageIdentifier.java +++ b/src/main/java/im/conversations/android/database/model/MessageIdentifier.java @@ -1,17 +1,17 @@ package im.conversations.android.database.model; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.BareJid; public class MessageIdentifier { public final long id; public final String stanzaId; public final String messageId; - public final Jid fromBare; + public final BareJid fromBare; public final Long version; public MessageIdentifier( - long id, String stanzaId, String messageId, Jid fromBare, Long version) { + long id, String stanzaId, String messageId, BareJid fromBare, Long version) { this.id = id; this.stanzaId = stanzaId; this.messageId = messageId; diff --git a/src/main/java/im/conversations/android/database/model/MessageReaction.java b/src/main/java/im/conversations/android/database/model/MessageReaction.java index c7b677831..00f31eca7 100644 --- a/src/main/java/im/conversations/android/database/model/MessageReaction.java +++ b/src/main/java/im/conversations/android/database/model/MessageReaction.java @@ -1,6 +1,6 @@ package im.conversations.android.database.model; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.Jid; public class MessageReaction { diff --git a/src/main/java/im/conversations/android/database/model/MessageState.java b/src/main/java/im/conversations/android/database/model/MessageState.java index 6fafd58b8..d9cfe3bb8 100644 --- a/src/main/java/im/conversations/android/database/model/MessageState.java +++ b/src/main/java/im/conversations/android/database/model/MessageState.java @@ -1,18 +1,19 @@ package im.conversations.android.database.model; import com.google.common.base.Preconditions; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.transformer.Transformation; import im.conversations.android.xmpp.model.error.Condition; import im.conversations.android.xmpp.model.error.Error; import im.conversations.android.xmpp.model.error.Text; import im.conversations.android.xmpp.model.stanza.Message; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.parts.Resourcepart; public class MessageState { - public final Jid fromBare; + public final BareJid fromBare; - public final String fromResource; + public final Resourcepart fromResource; public final StateType type; @@ -21,8 +22,8 @@ public class MessageState { public final String errorText; public MessageState( - Jid fromBare, - String fromResource, + BareJid fromBare, + Resourcepart fromResource, StateType type, String errorCondition, String errorText) { diff --git a/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java b/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java index 0463c5754..cc74e0976 100644 --- a/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java +++ b/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java @@ -4,7 +4,6 @@ import androidx.room.Relation; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Maps; import com.google.common.collect.Multimaps; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.database.entity.MessageContentEntity; import im.conversations.android.database.entity.MessageEntity; import im.conversations.android.database.entity.MessageReactionEntity; @@ -14,6 +13,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import org.jxmpp.jid.Jid; public class MessageWithContentReactions { diff --git a/src/main/java/im/conversations/android/repository/AccountRepository.java b/src/main/java/im/conversations/android/repository/AccountRepository.java index eb03b97f8..dc90b2760 100644 --- a/src/main/java/im/conversations/android/repository/AccountRepository.java +++ b/src/main/java/im/conversations/android/repository/AccountRepository.java @@ -6,7 +6,6 @@ import com.google.common.base.Preconditions; 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.xmpp.Jid; import im.conversations.android.IDs; import im.conversations.android.database.CredentialStore; import im.conversations.android.database.entity.AccountEntity; @@ -14,6 +13,7 @@ import im.conversations.android.database.model.Account; import im.conversations.android.xmpp.ConnectionPool; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.manager.RegistrationManager; +import org.jxmpp.jid.BareJid; public class AccountRepository extends AbstractRepository { @@ -22,9 +22,7 @@ public class AccountRepository extends AbstractRepository { } private Account createAccount( - @NonNull final Jid address, final String password, final boolean loginAndBind) { - Preconditions.checkArgument( - address.isBareJid(), "Account should be specified without resource"); + @NonNull final BareJid address, final String password, final boolean loginAndBind) { Preconditions.checkArgument(password != null, "Missing password"); final byte[] randomSeed = IDs.seed(); final var entity = new AccountEntity(); @@ -44,12 +42,12 @@ public class AccountRepository extends AbstractRepository { } public ListenableFuture createAccountAsync( - final @NonNull Jid address, final String password, final boolean loginAndBind) { + final @NonNull BareJid address, final String password, final boolean loginAndBind) { return Futures.submit(() -> createAccount(address, password, loginAndBind), IO_EXECUTOR); } public ListenableFuture createAccountAsync( - final @NonNull Jid address, final String password) { + final @NonNull BareJid address, final String password) { return createAccountAsync(address, password, true); } diff --git a/src/main/java/im/conversations/android/transformer/Transformation.java b/src/main/java/im/conversations/android/transformer/Transformation.java index f99184cdf..b83aad847 100644 --- a/src/main/java/im/conversations/android/transformer/Transformation.java +++ b/src/main/java/im/conversations/android/transformer/Transformation.java @@ -4,7 +4,6 @@ import androidx.annotation.NonNull; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.model.DeliveryReceipt; import im.conversations.android.xmpp.model.DeliveryReceiptRequest; import im.conversations.android.xmpp.model.Extension; @@ -25,6 +24,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Resourcepart; public class Transformation { @@ -83,20 +85,20 @@ public class Transformation { return this.extensions.size() > 0; } - public Jid fromBare() { + public BareJid fromBare() { return from == null ? null : from.asBareJid(); } - public String fromResource() { - return from == null ? null : from.getResource(); + public Resourcepart fromResource() { + return from == null ? null : from.getResourceOrNull(); } - public Jid toBare() { + public BareJid toBare() { return to == null ? null : to.asBareJid(); } - public String toResource() { - return to == null ? null : to.getResource(); + public Resourcepart toResource() { + return to == null ? null : to.getResourceOrNull(); } public Instant sentAt() { diff --git a/src/main/java/im/conversations/android/transformer/TransformationFactory.java b/src/main/java/im/conversations/android/transformer/TransformationFactory.java index 39556cc89..aa17fe2cf 100644 --- a/src/main/java/im/conversations/android/transformer/TransformationFactory.java +++ b/src/main/java/im/conversations/android/transformer/TransformationFactory.java @@ -1,13 +1,13 @@ package im.conversations.android.transformer; import android.content.Context; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.manager.DiscoManager; import im.conversations.android.xmpp.model.occupant.OccupantId; import im.conversations.android.xmpp.model.stanza.Message; import java.time.Instant; +import org.jxmpp.jid.Jid; public class TransformationFactory extends XmppConnection.Delegate { diff --git a/src/main/java/im/conversations/android/transformer/Transformer.java b/src/main/java/im/conversations/android/transformer/Transformer.java index 3660195e2..b8e6d8e3d 100644 --- a/src/main/java/im/conversations/android/transformer/Transformer.java +++ b/src/main/java/im/conversations/android/transformer/Transformer.java @@ -4,7 +4,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import eu.siacs.conversations.xmpp.InvalidJid; import im.conversations.android.database.ConversationsDatabase; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.ChatIdentifier; @@ -132,7 +131,7 @@ public class Transformer { final var reply = transformation.getExtension(Reply.class); if (Objects.nonNull(reply) && Objects.nonNull(reply.getId()) - && InvalidJid.isValid(reply.getTo())) { + && Objects.nonNull(reply.getTo())) { database.messageDao() .setInReplyTo( chat, messageIdentifier, messageType, reply.getTo(), reply.getId()); diff --git a/src/main/java/im/conversations/android/xml/Element.java b/src/main/java/im/conversations/android/xml/Element.java index 2f4d1b31f..9dd608f8d 100644 --- a/src/main/java/im/conversations/android/xml/Element.java +++ b/src/main/java/im/conversations/android/xml/Element.java @@ -1,7 +1,6 @@ package im.conversations.android.xml; import androidx.annotation.NonNull; - import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -9,15 +8,14 @@ import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; -import eu.siacs.conversations.xmpp.InvalidJid; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.ExtensionFactory; import im.conversations.android.xmpp.model.Extension; -import im.conversations.android.xmpp.model.stanza.Message; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.List; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; public class Element { private final String name; @@ -154,7 +152,7 @@ public class Element { } public Element setAttribute(final String name, final Jid value) { - return this.setAttribute(name, value == null ? null : value.toEscapedString()); + return this.setAttribute(name, value == null ? null : value.toString()); } public void removeAttribute(final String name) { @@ -187,16 +185,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 (Strings.isNullOrEmpty(jid)) { return null; } - try { - return Jid.ofEscaped(jid); - } catch (final IllegalArgumentException e) { - return InvalidJid.of(jid, this instanceof Message); - } + return JidCreate.fromOrThrowUnchecked(jid); } public Hashtable getAttributes() { diff --git a/src/main/java/im/conversations/android/xml/Tag.java b/src/main/java/im/conversations/android/xml/Tag.java index eed482225..41cb27c07 100644 --- a/src/main/java/im/conversations/android/xml/Tag.java +++ b/src/main/java/im/conversations/android/xml/Tag.java @@ -1,10 +1,10 @@ package im.conversations.android.xml; -import eu.siacs.conversations.xmpp.Jid; import java.util.Hashtable; import java.util.Map.Entry; import java.util.Set; import org.jetbrains.annotations.NotNull; +import org.jxmpp.jid.Jid; public class Tag { public static final int NO = -1; @@ -52,7 +52,7 @@ public class Tag { public Tag setAttribute(final String attrName, final Jid attrValue) { if (attrValue != null) { - this.attributes.put(attrName, attrValue.toEscapedString()); + this.attributes.put(attrName, attrValue.toString()); } return this; } diff --git a/src/main/java/im/conversations/android/xmpp/ConnectionPool.java b/src/main/java/im/conversations/android/xmpp/ConnectionPool.java index e4cf2634c..fdb6342aa 100644 --- a/src/main/java/im/conversations/android/xmpp/ConnectionPool.java +++ b/src/main/java/im/conversations/android/xmpp/ConnectionPool.java @@ -12,9 +12,7 @@ import com.google.common.primitives.Ints; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import eu.siacs.conversations.Config; -import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.PhoneHelper; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.Conversations; import im.conversations.android.database.ConversationsDatabase; import im.conversations.android.database.model.Account; @@ -26,6 +24,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +66,7 @@ public class ConnectionPool { return setupXmppConnection(context, account); } - public synchronized ListenableFuture get(final Jid address) { + public synchronized ListenableFuture get(final BareJid address) { final var configured = Iterables.tryFind(this.connections, c -> address.equals(c.getAccount().address)); if (configured.isPresent()) { @@ -78,8 +78,7 @@ public class ConnectionPool { if (account == null) { throw new IllegalStateException( String.format( - "No enabled account with address %s", - address.toEscapedString())); + "No enabled account with address %s", address.toString())); } return reconfigure(account); }, @@ -231,9 +230,8 @@ public class ConnectionPool { final String androidId = PhoneHelper.getAndroidId(context); for (final XmppConnection xmppConnection : this.connections) { final Account account = xmppConnection.getAccount(); - final boolean pushWasMeantForThisAccount = - CryptoHelper.getFingerprint(account.address, androidId) - .equals(pushedAccountHash); + // TODO fix me if we bring back FCM push support + final boolean pushWasMeantForThisAccount = false; if (processAccountState(xmppConnection, pushWasMeantForThisAccount, pingCandidates)) { pingNow++; } diff --git a/src/main/java/im/conversations/android/xmpp/Entity.java b/src/main/java/im/conversations/android/xmpp/Entity.java index 799d7a5ea..a578d2507 100644 --- a/src/main/java/im/conversations/android/xmpp/Entity.java +++ b/src/main/java/im/conversations/android/xmpp/Entity.java @@ -1,6 +1,6 @@ package im.conversations.android.xmpp; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.Jid; public abstract class Entity { diff --git a/src/main/java/im/conversations/android/xmpp/XmppConnection.java b/src/main/java/im/conversations/android/xmpp/XmppConnection.java index 6d7c430eb..eabb1c58b 100644 --- a/src/main/java/im/conversations/android/xmpp/XmppConnection.java +++ b/src/main/java/im/conversations/android/xmpp/XmppConnection.java @@ -30,9 +30,6 @@ import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.utils.Resolver; import eu.siacs.conversations.utils.SSLSockets; import eu.siacs.conversations.utils.SocksSocketFactory; -import eu.siacs.conversations.xml.LocalizedContent; -import eu.siacs.conversations.xmpp.InvalidJid; -import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.bind.Bind2; import im.conversations.android.Conversations; import im.conversations.android.IDs; @@ -91,6 +88,7 @@ import java.util.Collections; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -107,6 +105,9 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; import okhttp3.HttpUrl; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xmlpull.v1.XmlPullParserException; @@ -293,7 +294,7 @@ public class XmppConnection implements Runnable { final int port; final boolean directTls; if (connection == null || account.isOnion()) { - destination = account.address.getDomain().toEscapedString(); + destination = account.address.getDomain().toString(); port = 5222; directTls = false; } else { @@ -328,7 +329,7 @@ public class XmppConnection implements Runnable { throw new IOException("Could not start stream", e); } } else { - final String domain = account.address.getDomain().toEscapedString(); + final String domain = account.address.getDomain().toString(); final List results; if (connection != null) { results = Resolver.fromHardCoded(connection.hostname, connection.port); @@ -497,7 +498,7 @@ public class XmppConnection implements Runnable { final boolean quickStart; if (socket instanceof SSLSocket) { final SSLSocket sslSocket = (SSLSocket) socket; - SSLSockets.log(account.address, sslSocket); + logTlsCipher(sslSocket); quickStart = establishStream(SSLSockets.version(sslSocket)); } else { quickStart = establishStream(SSLSockets.Version.NONE); @@ -524,7 +525,7 @@ public class XmppConnection implements Runnable { } else { keyManager = new KeyManager[] {new MyKeyManager(context, credential)}; } - final String domain = account.address.getDomain().toEscapedString(); + final String domain = account.address.getDomain().toString(); // TODO we used to use two different trust managers; interactive and non interactive (to // trigger SSL cert prompts) // we need a better solution for this using live data or similar @@ -719,8 +720,8 @@ public class XmppConnection implements Runnable { authorizationJid = Strings.isNullOrEmpty(authorizationIdentifier) ? null - : Jid.ofEscaped(authorizationIdentifier); - } catch (final IllegalArgumentException e) { + : JidCreate.from(authorizationIdentifier); + } catch (final XmppStringprepException e) { Log.d( Config.LOGTAG, account.address @@ -993,7 +994,9 @@ public class XmppConnection implements Runnable { private void changeStatusToOnline() { Log.d( Config.LOGTAG, - account.address + ": online with resource " + connectionAddress.getResource()); + account.address + + ": online with resource " + + connectionAddress.getResourceOrNull()); changeStatus(ConnectionState.ONLINE); } @@ -1058,7 +1061,7 @@ public class XmppConnection implements Runnable { final S stanza = tagReader.readElement(currentTag, clazz); if (stanzasReceived == Integer.MAX_VALUE) { resetStreamId(); - throw new IOException("time to restart the session. cant handle >2 billion pcks"); + throw new IOException("time to restart the session. cant handle >2 billion stanzas"); } if (inSmacksSession) { ++stanzasReceived; @@ -1071,25 +1074,12 @@ public class XmppConnection implements Runnable { + "). Not in smacks session."); } lastPacketReceived = SystemClock.elapsedRealtime(); - if (InvalidJid.invalid(stanza.getTo()) || InvalidJid.invalid(stanza.getFrom())) { - Log.e( - Config.LOGTAG, - "encountered invalid stanza from " - + stanza.getFrom() - + " to " - + stanza.getTo()); - } + // TODO validate to and from return stanza; } private void processIq(final Tag currentTag) throws IOException { final Iq packet = processStanza(currentTag, Iq.class); - if (InvalidJid.invalid(packet.getTo()) || InvalidJid.invalid(packet.getFrom())) { - Log.e( - Config.LOGTAG, - "encountered invalid IQ from " + packet.getFrom() + " to " + packet.getTo()); - return; - } final Consumer callback; synchronized (this.packetCallbacks) { final Pair> packetCallbackDuple = packetCallbacks.get(packet.getId()); @@ -1130,29 +1120,11 @@ public class XmppConnection implements Runnable { private void processMessage(final Tag currentTag) throws IOException { final var message = processStanza(currentTag, Message.class); - if (InvalidJid.invalid(message.getTo()) || InvalidJid.invalid(message.getFrom())) { - Log.e( - Config.LOGTAG, - "encountered invalid Message from " - + message.getFrom() - + " to " - + message.getTo()); - return; - } this.messagePacketConsumer.accept(message); } private void processPresence(final Tag currentTag) throws IOException { final var presence = processStanza(currentTag, Presence.class); - if (InvalidJid.invalid(presence.getTo()) || InvalidJid.invalid(presence.getFrom())) { - Log.e( - Config.LOGTAG, - "encountered invalid Presence from " - + presence.getFrom() - + " to " - + presence.getTo()); - return; - } this.presencePacketConsumer.accept(presence); } @@ -1181,7 +1153,7 @@ public class XmppConnection implements Runnable { this.encryptionEnabled = true; final Tag tag = tagReader.readTag(); if (tag != null && tag.isStart("stream", Namespace.STREAMS)) { - SSLSockets.log(account.address, sslSocket); + logTlsCipher(sslSocket); processStream(); } else { throw new StateChangingException(ConnectionState.STREAM_OPENING_ERROR); @@ -1189,6 +1161,14 @@ public class XmppConnection implements Runnable { sslSocket.close(); } + private void logTlsCipher(final SSLSocket sslSocket) { + final var session = sslSocket.getSession(); + LOGGER.info( + "TLS session protocol {} cipher {}", + session.getProtocol(), + session.getCipherSuite()); + } + private SSLSocket upgradeSocketToTls(final Socket socket) throws IOException { final SSLSocketFactory sslSocketFactory; try { @@ -1202,13 +1182,12 @@ public class XmppConnection implements Runnable { sslSocketFactory.createSocket( socket, address.getHostAddress(), socket.getPort(), true); SSLSockets.setSecurity(sslSocket); - SSLSockets.setHostname( - sslSocket, IDN.toASCII(account.address.getDomain().toEscapedString())); + SSLSockets.setHostname(sslSocket, IDN.toASCII(account.address.getDomain().toString())); SSLSockets.setApplicationProtocol(sslSocket, "xmpp-client"); final XmppDomainVerifier xmppDomainVerifier = new XmppDomainVerifier(); try { if (!xmppDomainVerifier.verify( - account.address.getDomain().toEscapedString(), + account.address.getDomain().toString(), this.verifiedHostname, sslSocket.getSession())) { Log.d( @@ -1536,8 +1515,8 @@ public class XmppConnection implements Runnable { } final Jid assignedJid; try { - assignedJid = Jid.ofEscaped(jid); - } catch (final IllegalArgumentException e) { + assignedJid = JidCreate.from(jid); + } catch (final XmppStringprepException e) { Log.d( Config.LOGTAG, account.address @@ -1675,7 +1654,7 @@ public class XmppConnection implements Runnable { final var discoManager = getManager(DiscoManager.class); final var nodeHash = this.streamFeatures.getCapabilities(); - final var domainDiscoItem = Entity.discoItem(account.address.getDomain()); + final var domainDiscoItem = Entity.discoItem(account.address.asDomainBareJid()); if (nodeHash != null) { discoFutures.add( discoManager.infoOrCache(domainDiscoItem, nodeHash.node, nodeHash.hash)); @@ -1819,12 +1798,13 @@ public class XmppConnection implements Runnable { private void sendStartStream(final boolean from, final boolean flush) throws IOException { final Tag stream = Tag.start("stream:stream"); - stream.setAttribute("to", account.address.getDomain()); + stream.setAttribute("to", account.address.asDomainBareJid()); if (from) { stream.setAttribute("from", account.address); } stream.setAttribute("version", "1.0"); - stream.setAttribute("xml:lang", LocalizedContent.STREAM_LANGUAGE); + // TODO use 'en' when privacy mode is enabled + stream.setAttribute("xml:lang", Locale.getDefault().getLanguage()); stream.setAttribute("xmlns", "jabber:client"); stream.setAttribute("xmlns:stream", Namespace.STREAMS); tagWriter.writeTag(stream, flush); diff --git a/src/main/java/im/conversations/android/xmpp/axolotl/AxolotlAddress.java b/src/main/java/im/conversations/android/xmpp/axolotl/AxolotlAddress.java index c4fccf396..3bc246253 100644 --- a/src/main/java/im/conversations/android/xmpp/axolotl/AxolotlAddress.java +++ b/src/main/java/im/conversations/android/xmpp/axolotl/AxolotlAddress.java @@ -1,20 +1,18 @@ package im.conversations.android.xmpp.axolotl; -import com.google.common.base.Preconditions; -import eu.siacs.conversations.xmpp.Jid; +import org.jxmpp.jid.BareJid; import org.whispersystems.libsignal.SignalProtocolAddress; public class AxolotlAddress extends SignalProtocolAddress { - private final Jid jid; + private final BareJid jid; - public AxolotlAddress(final Jid jid, int deviceId) { - super(jid.toEscapedString(), deviceId); - Preconditions.checkArgument(jid.isBareJid(), "AxolotlAddresses must use bare JIDs"); + public AxolotlAddress(final BareJid jid, int deviceId) { + super(jid.toString(), deviceId); this.jid = jid; } - public Jid getJid() { + public BareJid getJid() { return this.jid; } diff --git a/src/main/java/im/conversations/android/xmpp/manager/AvatarManager.java b/src/main/java/im/conversations/android/xmpp/manager/AvatarManager.java index c18f64fbf..68a4a2a85 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/AvatarManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/AvatarManager.java @@ -9,7 +9,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.xmpp.Jid; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.avatar.Data; import im.conversations.android.xmpp.model.avatar.Info; @@ -21,6 +20,8 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +35,7 @@ public class AvatarManager extends AbstractManager { super(context, connection); } - public void handleItems(final Jid from, final Items items) { + public void handleItems(final BareJid from, final Items items) { final var itemsMap = items.getItemMap(Metadata.class); final var firstEntry = Iterables.getFirst(itemsMap.entrySet(), null); if (firstEntry == null) { @@ -142,7 +143,7 @@ public class AvatarManager extends AbstractManager { new File( accountCacheDirectory, Hashing.sha256() - .hashString(address.toEscapedString(), StandardCharsets.UTF_8) + .hashString(address.toString(), StandardCharsets.UTF_8) .toString()); if (userCacheDirectory.mkdirs()) { LOGGER.debug("Created directory {}", userCacheDirectory.getAbsolutePath()); diff --git a/src/main/java/im/conversations/android/xmpp/manager/AxolotlManager.java b/src/main/java/im/conversations/android/xmpp/manager/AxolotlManager.java index 21aa923cc..38f90869d 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/AxolotlManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/AxolotlManager.java @@ -7,7 +7,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.xmpp.Jid; import im.conversations.android.database.AxolotlDatabaseStore; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.IqErrorException; @@ -22,6 +21,8 @@ import java.util.Collections; import java.util.Locale; import java.util.Set; import java.util.concurrent.TimeoutException; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.IdentityKey; @@ -47,7 +48,7 @@ public class AxolotlManager extends AbstractManager { this.signalProtocolStore = new AxolotlDatabaseStore(context, connection.getAccount()); } - public void handleItems(final Jid from, final Items items) { + public void handleItems(final BareJid from, final Items items) { final var deviceList = items.getFirstItem(DeviceList.class); if (from == null || deviceList == null) { return; @@ -57,7 +58,7 @@ public class AxolotlManager extends AbstractManager { getDatabase().axolotlDao().setDeviceList(getAccount(), from, deviceIds); } - public ListenableFuture> fetchDeviceIds(final Jid address) { + public ListenableFuture> fetchDeviceIds(final BareJid address) { final var deviceIdsFuture = Futures.transform( getManager(PubSubManager.class) diff --git a/src/main/java/im/conversations/android/xmpp/manager/BookmarkManager.java b/src/main/java/im/conversations/android/xmpp/manager/BookmarkManager.java index a135d9ce8..c49dec249 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/BookmarkManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/BookmarkManager.java @@ -7,8 +7,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.xmpp.Jid; -import im.conversations.android.database.entity.BookmarkEntity; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.NodeConfiguration; import im.conversations.android.xmpp.XmppConnection; @@ -18,6 +16,8 @@ import im.conversations.android.xmpp.model.pubsub.event.Retract; import java.util.Collection; import java.util.Map; import java.util.Objects; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +53,7 @@ public class BookmarkManager extends AbstractManager { private void deleteItems(Collection retractions) { final Collection addresses = - Collections2.transform(retractions, r -> BookmarkEntity.jidOrNull(r.getId())); + Collections2.transform(retractions, r -> JidCreate.fromOrNull(r.getId())); getDatabase() .bookmarkDao() .delete(getAccount().id, Collections2.filter(addresses, Objects::nonNull)); @@ -75,7 +75,7 @@ public class BookmarkManager extends AbstractManager { } public ListenableFuture publishBookmark(final Jid address) { - final var itemId = address.toEscapedString(); + final var itemId = address.toString(); final var conference = new Conference(); return Futures.transform( getManager(PepManager.class) @@ -85,7 +85,7 @@ public class BookmarkManager extends AbstractManager { } public ListenableFuture retractBookmark(final Jid address) { - final var itemId = address.toEscapedString(); + final var itemId = address.toString(); return Futures.transform( getManager(PepManager.class).retract(itemId, Namespace.BOOKMARKS2), result -> null, diff --git a/src/main/java/im/conversations/android/xmpp/manager/ChatStateManager.java b/src/main/java/im/conversations/android/xmpp/manager/ChatStateManager.java index d3837b57e..efb2afdd3 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/ChatStateManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/ChatStateManager.java @@ -1,9 +1,9 @@ package im.conversations.android.xmpp.manager; import android.content.Context; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.state.ChatStateNotification; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java b/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java index 24dcae674..50a910e9d 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java @@ -13,7 +13,6 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import eu.siacs.conversations.BuildConfig; import eu.siacs.conversations.R; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.Entity; import im.conversations.android.xmpp.EntityCapabilities; @@ -32,6 +31,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -249,7 +249,7 @@ public class DiscoManager extends AbstractManager { } public boolean hasServerFeature(final String feature) { - return hasFeature(getAccount().address.getDomain(), feature); + return hasFeature(getAccount().address.asDomainBareJid(), feature); } public ServiceDescription getServiceDescription() { diff --git a/src/main/java/im/conversations/android/xmpp/manager/NickManager.java b/src/main/java/im/conversations/android/xmpp/manager/NickManager.java index 64a640f3b..74c97fe19 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/NickManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/NickManager.java @@ -2,10 +2,10 @@ package im.conversations.android.xmpp.manager; import android.content.Context; import com.google.common.base.Strings; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.nick.Nick; import im.conversations.android.xmpp.model.pubsub.Items; +import org.jxmpp.jid.BareJid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,7 +17,7 @@ public class NickManager extends AbstractManager { super(context, connection); } - public void handleItems(final Jid from, Items items) { + public void handleItems(final BareJid from, Items items) { final var item = items.getFirstItem(Nick.class); final var nick = item == null ? null : item.getContent(); if (from == null || Strings.isNullOrEmpty(nick)) { diff --git a/src/main/java/im/conversations/android/xmpp/manager/PepManager.java b/src/main/java/im/conversations/android/xmpp/manager/PepManager.java index 9116178b6..1b5618f23 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/PepManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/PepManager.java @@ -2,12 +2,12 @@ package im.conversations.android.xmpp.manager; import android.content.Context; import com.google.common.util.concurrent.ListenableFuture; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.NodeConfiguration; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.Extension; import im.conversations.android.xmpp.model.stanza.Iq; import java.util.Map; +import org.jxmpp.jid.Jid; public class PepManager extends AbstractManager { diff --git a/src/main/java/im/conversations/android/xmpp/manager/PubSubManager.java b/src/main/java/im/conversations/android/xmpp/manager/PubSubManager.java index a7d411fc4..717bde02a 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/PubSubManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/PubSubManager.java @@ -6,7 +6,6 @@ import com.google.common.util.concurrent.AsyncFunction; 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.xmpp.Jid; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.ExtensionFactory; import im.conversations.android.xmpp.IqErrorException; @@ -29,6 +28,7 @@ import im.conversations.android.xmpp.model.pubsub.owner.PubSubOwner; import im.conversations.android.xmpp.model.stanza.Iq; import im.conversations.android.xmpp.model.stanza.Message; import java.util.Map; +import org.jxmpp.jid.Jid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,6 +147,7 @@ public class PubSubManager extends AbstractManager { private void handleItems(final Message message) { final var from = message.getFrom(); + final var bareFrom = from == null ? null : from.asBareJid(); final var event = message.getExtension(Event.class); final Items items = event.getItems(); final var node = items.getNode(); @@ -155,15 +156,15 @@ public class PubSubManager extends AbstractManager { return; } if (Namespace.AVATAR_METADATA.equals(node)) { - getManager(AvatarManager.class).handleItems(from, items); + getManager(AvatarManager.class).handleItems(bareFrom, items); return; } if (Namespace.NICK.equals(node)) { - getManager(NickManager.class).handleItems(from, items); + getManager(NickManager.class).handleItems(bareFrom, items); return; } if (Namespace.AXOLOTL_DEVICE_LIST.equals(node)) { - getManager(AxolotlManager.class).handleItems(from, items); + getManager(AxolotlManager.class).handleItems(bareFrom, items); } } diff --git a/src/main/java/im/conversations/android/xmpp/manager/ReceiptManager.java b/src/main/java/im/conversations/android/xmpp/manager/ReceiptManager.java index 78ce5845f..32a03bd32 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/ReceiptManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/ReceiptManager.java @@ -2,7 +2,6 @@ package im.conversations.android.xmpp.manager; import android.content.Context; import com.google.common.base.Strings; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.DeliveryReceiptRequest; import im.conversations.android.xmpp.model.markers.Markable; @@ -10,6 +9,7 @@ import im.conversations.android.xmpp.model.receipts.Received; import im.conversations.android.xmpp.model.receipts.Request; import im.conversations.android.xmpp.model.stanza.Message; import java.util.Collection; +import org.jxmpp.jid.Jid; public class ReceiptManager extends AbstractManager { diff --git a/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java b/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java index aa1714a21..31ca0845c 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java @@ -34,9 +34,9 @@ public class RegistrationManager extends AbstractManager { public ListenableFuture setPassword(final String password) { final var account = getAccount(); final var iq = new Iq(Iq.Type.SET); - iq.setTo(account.address.getDomain()); + iq.setTo(account.address.asDomainBareJid()); final var register = iq.addExtension(new Register()); - register.addUsername(account.address.getEscapedLocal()); + register.addUsername(account.address.getLocalpartOrThrow()); register.addPassword(password); return Futures.transform( connection.sendIqPacket(iq), r -> null, MoreExecutors.directExecutor()); @@ -44,7 +44,7 @@ public class RegistrationManager extends AbstractManager { public ListenableFuture unregister() { final var iq = new Iq(Iq.Type.SET); - iq.setTo(getAccount().address.getDomain()); + iq.setTo(getAccount().address.asDomainBareJid()); final var register = iq.addExtension(new Register()); register.addExtension(new Remove()); return Futures.transform( @@ -53,7 +53,7 @@ public class RegistrationManager extends AbstractManager { public ListenableFuture getRegistration() { final var iq = new Iq(Iq.Type.GET); - iq.setTo(getAccount().address.getDomain()); + iq.setTo(getAccount().address.asDomainBareJid()); iq.addExtension(new Register()); return Futures.transform( connection.sendIqPacketUnbound(iq), @@ -98,7 +98,7 @@ public class RegistrationManager extends AbstractManager { public ListenableFuture sendPreAuthentication(final String token) { final var iq = new Iq(Iq.Type.GET); - iq.setTo(getAccount().address.getDomain()); + iq.setTo(getAccount().address.asDomainBareJid()); final var preAuthentication = iq.addExtension(new PreAuth()); preAuthentication.setToken(token); return Futures.transform( diff --git a/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java b/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java index b9811a7fb..586ffb721 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java @@ -1,11 +1,11 @@ package im.conversations.android.xmpp.manager; import android.content.Context; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.unique.StanzaId; +import org.jxmpp.jid.Jid; public class StanzaIdManager extends AbstractManager { diff --git a/src/main/java/im/conversations/android/xmpp/model/blocking/Item.java b/src/main/java/im/conversations/android/xmpp/model/blocking/Item.java index 647b0ae99..f74b622ce 100644 --- a/src/main/java/im/conversations/android/xmpp/model/blocking/Item.java +++ b/src/main/java/im/conversations/android/xmpp/model/blocking/Item.java @@ -1,8 +1,8 @@ package im.conversations.android.xmpp.model.blocking; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.Extension; +import org.jxmpp.jid.Jid; @XmlElement public class Item extends Extension { diff --git a/src/main/java/im/conversations/android/xmpp/model/disco/items/Item.java b/src/main/java/im/conversations/android/xmpp/model/disco/items/Item.java index 9412616f5..4aa89610d 100644 --- a/src/main/java/im/conversations/android/xmpp/model/disco/items/Item.java +++ b/src/main/java/im/conversations/android/xmpp/model/disco/items/Item.java @@ -1,9 +1,9 @@ package im.conversations.android.xmpp.model.disco.items; import androidx.annotation.Nullable; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.Extension; +import org.jxmpp.jid.Jid; @XmlElement public class Item extends Extension { diff --git a/src/main/java/im/conversations/android/xmpp/model/register/Register.java b/src/main/java/im/conversations/android/xmpp/model/register/Register.java index caab0c353..4a48bd8d1 100644 --- a/src/main/java/im/conversations/android/xmpp/model/register/Register.java +++ b/src/main/java/im/conversations/android/xmpp/model/register/Register.java @@ -2,6 +2,7 @@ package im.conversations.android.xmpp.model.register; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.Extension; +import org.jxmpp.jid.parts.Localpart; @XmlElement(name = "query") public class Register extends Extension { @@ -10,8 +11,8 @@ public class Register extends Extension { super(Register.class); } - public void addUsername(final String username) { - this.addExtension(new Username()).setContent(username); + public void addUsername(final Localpart username) { + this.addExtension(new Username()).setContent(username.toString()); } public void addPassword(final String password) { diff --git a/src/main/java/im/conversations/android/xmpp/model/reply/Reply.java b/src/main/java/im/conversations/android/xmpp/model/reply/Reply.java index a944f70eb..1b0b1cb17 100644 --- a/src/main/java/im/conversations/android/xmpp/model/reply/Reply.java +++ b/src/main/java/im/conversations/android/xmpp/model/reply/Reply.java @@ -1,9 +1,9 @@ package im.conversations.android.xmpp.model.reply; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.model.Extension; +import org.jxmpp.jid.Jid; @XmlElement(namespace = Namespace.REPLY) public class Reply extends Extension { diff --git a/src/main/java/im/conversations/android/xmpp/model/roster/Item.java b/src/main/java/im/conversations/android/xmpp/model/roster/Item.java index fbb7d007c..75c8f4095 100644 --- a/src/main/java/im/conversations/android/xmpp/model/roster/Item.java +++ b/src/main/java/im/conversations/android/xmpp/model/roster/Item.java @@ -1,7 +1,6 @@ package im.conversations.android.xmpp.model.roster; import com.google.common.collect.Collections2; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xml.Element; import im.conversations.android.xmpp.model.Extension; @@ -10,6 +9,7 @@ import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Objects; +import org.jxmpp.jid.Jid; @XmlElement public class Item extends Extension { diff --git a/src/main/java/im/conversations/android/xmpp/model/stanza/Stanza.java b/src/main/java/im/conversations/android/xmpp/model/stanza/Stanza.java index 0c91ad699..2bd1c6d08 100644 --- a/src/main/java/im/conversations/android/xmpp/model/stanza/Stanza.java +++ b/src/main/java/im/conversations/android/xmpp/model/stanza/Stanza.java @@ -1,9 +1,9 @@ package im.conversations.android.xmpp.model.stanza; -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; +import org.jxmpp.jid.Jid; public abstract class Stanza extends StreamElement { diff --git a/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java b/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java index 23b0fdcac..a4cc81730 100644 --- a/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java +++ b/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java @@ -1,8 +1,8 @@ package im.conversations.android.xmpp.model.unique; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.Extension; +import org.jxmpp.jid.Jid; @XmlElement public class StanzaId extends Extension { diff --git a/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java b/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java index 11f14525c..800f7be33 100644 --- a/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java +++ b/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java @@ -1,7 +1,6 @@ package im.conversations.android.xmpp.processor; import android.content.Context; -import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xml.Namespace; import im.conversations.android.xmpp.Entity; import im.conversations.android.xmpp.XmppConnection; @@ -12,6 +11,7 @@ import im.conversations.android.xmpp.manager.DiscoManager; import im.conversations.android.xmpp.manager.PresenceManager; import im.conversations.android.xmpp.manager.RosterManager; import java.util.function.Consumer; +import org.jxmpp.jid.Jid; public class BindProcessor extends XmppConnection.Delegate implements Consumer { @@ -35,7 +35,8 @@ public class BindProcessor extends XmppConnection.Delegate implements Consumer { diff --git a/src/main/java/im/conversations/android/xmpp/processor/PresenceProcessor.java b/src/main/java/im/conversations/android/xmpp/processor/PresenceProcessor.java index 62a5961b0..31f4c710e 100644 --- a/src/main/java/im/conversations/android/xmpp/processor/PresenceProcessor.java +++ b/src/main/java/im/conversations/android/xmpp/processor/PresenceProcessor.java @@ -19,7 +19,7 @@ public class PresenceProcessor extends XmppConnection.Delegate implements Consum public void accept(final Presence presencePacket) { final var from = presencePacket.getFrom(); final var address = from == null ? null : from.asBareJid(); - final var resource = from == null ? null : from.getResource(); + final var resource = from == null ? null : from.getResourceOrEmpty(); final var typeAttribute = presencePacket.getAttribute("type"); final PresenceType type; try { diff --git a/src/main/java/im/conversations/android/xmpp/sasl/DigestMd5.java b/src/main/java/im/conversations/android/xmpp/sasl/DigestMd5.java index dc4135d1d..d794a1eb3 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/DigestMd5.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/DigestMd5.java @@ -51,7 +51,7 @@ public class DigestMd5 extends SaslMechanism { final String digestUri = "xmpp/" + account.address.getDomain(); final String nonceCount = "00000001"; final String x = - account.address.getEscapedLocal() + account.address.getLocalpartOrNull().toString() + ":" + account.address.getDomain() + ":" @@ -60,7 +60,7 @@ public class DigestMd5 extends SaslMechanism { final byte[] y = md.digest(x.getBytes(Charset.defaultCharset())); final String cNonce = CryptoHelper.random(100); final byte[] a1 = - CryptoHelper.concatenateByteArrays( + concatenate( y, (":" + nonce + ":" + cNonce) .getBytes(Charset.defaultCharset())); @@ -76,7 +76,7 @@ public class DigestMd5 extends SaslMechanism { md.digest(kd.getBytes(Charset.defaultCharset()))); final String saslString = "username=\"" - + account.address.getEscapedLocal() + + account.address.getLocalpartOrThrow().toString() + "\",realm=\"" + account.address.getDomain() + "\",nonce=\"" diff --git a/src/main/java/im/conversations/android/xmpp/sasl/External.java b/src/main/java/im/conversations/android/xmpp/sasl/External.java index 8ef0f060c..395c52253 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/External.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/External.java @@ -25,6 +25,6 @@ public class External extends SaslMechanism { @Override public String getClientFirstMessage(final SSLSocket sslSocket) { - return Base64.encodeToString(account.address.toEscapedString().getBytes(), Base64.NO_WRAP); + return Base64.encodeToString(account.address.toString().getBytes(), Base64.NO_WRAP); } } diff --git a/src/main/java/im/conversations/android/xmpp/sasl/HashedToken.java b/src/main/java/im/conversations/android/xmpp/sasl/HashedToken.java index 46046683d..7915874a1 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/HashedToken.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/HashedToken.java @@ -49,9 +49,10 @@ public abstract class HashedToken extends SaslMechanism implements ChannelBindin final byte[] cbData = getChannelBindingData(sslSocket); final byte[] initiatorHashedToken = hashing.hashBytes(Bytes.concat(INITIATOR, cbData)).asBytes(); + final String username = account.address.getLocalpartOrThrow().toString(); final byte[] firstMessage = Bytes.concat( - account.address.getEscapedLocal().getBytes(StandardCharsets.UTF_8), + username.getBytes(StandardCharsets.UTF_8), new byte[] {0x00}, initiatorHashedToken); return Base64.encodeToString(firstMessage, Base64.NO_WRAP); diff --git a/src/main/java/im/conversations/android/xmpp/sasl/Plain.java b/src/main/java/im/conversations/android/xmpp/sasl/Plain.java index 3da877e1e..31d6a252a 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/Plain.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/Plain.java @@ -33,6 +33,7 @@ public class Plain extends SaslMechanism { @Override public String getClientFirstMessage(final SSLSocket sslSocket) { return getMessage( - account.address.getEscapedLocal(), Strings.nullToEmpty(credential.password)); + account.address.getLocalpartOrThrow().toString(), + Strings.nullToEmpty(credential.password)); } } diff --git a/src/main/java/im/conversations/android/xmpp/sasl/SaslMechanism.java b/src/main/java/im/conversations/android/xmpp/sasl/SaslMechanism.java index 38156aaca..567b06891 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/SaslMechanism.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/SaslMechanism.java @@ -233,4 +233,11 @@ public abstract class SaslMechanism { public static boolean pin(final SaslMechanism saslMechanism) { return !hashedToken(saslMechanism); } + + protected static byte[] concatenate(byte[] a, byte[] b) { + byte[] result = new byte[a.length + b.length]; + System.arraycopy(a, 0, result, 0, a.length); + System.arraycopy(b, 0, result, a.length, b.length); + return result; + } } diff --git a/src/main/java/im/conversations/android/xmpp/sasl/ScramMechanism.java b/src/main/java/im/conversations/android/xmpp/sasl/ScramMechanism.java index a1790cc28..3402af50b 100644 --- a/src/main/java/im/conversations/android/xmpp/sasl/ScramMechanism.java +++ b/src/main/java/im/conversations/android/xmpp/sasl/ScramMechanism.java @@ -7,11 +7,12 @@ import com.google.common.base.Strings; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.hash.HashFunction; -import eu.siacs.conversations.utils.CryptoHelper; +import im.conversations.android.IDs; import im.conversations.android.database.model.Account; import im.conversations.android.database.model.Credential; import java.nio.charset.Charset; import java.security.InvalidKeyException; +import java.text.Normalizer; import java.util.concurrent.ExecutionException; import javax.crypto.SecretKey; import javax.net.ssl.SSLSocket; @@ -36,6 +37,8 @@ abstract class ScramMechanism extends SaslMechanism { } }; + private static final byte[] ONE = new byte[] {0, 0, 0, 1}; + private static final byte[] CLIENT_KEY_BYTES = "Client Key".getBytes(); private static final byte[] SERVER_KEY_BYTES = "Server Key".getBytes(); private static final Cache CACHE = @@ -67,7 +70,7 @@ abstract class ScramMechanism extends SaslMechanism { .convert(channelBinding.toString())); } // This nonce should be different for each authentication attempt. - this.clientNonce = CryptoHelper.random(100); + this.clientNonce = IDs.huge(); clientFirstMessageBare = ""; } @@ -107,7 +110,7 @@ abstract class ScramMechanism extends SaslMechanism { */ private byte[] hi(final byte[] key, final byte[] salt, final int iterations) throws InvalidKeyException { - byte[] u = hmac(key, CryptoHelper.concatenateByteArrays(salt, CryptoHelper.ONE)); + byte[] u = hmac(key, concatenate(salt, ONE)); byte[] out = u.clone(); for (int i = 1; i < iterations; i++) { u = hmac(key, u); @@ -123,8 +126,7 @@ abstract class ScramMechanism extends SaslMechanism { if (clientFirstMessageBare.isEmpty() && state == State.INITIAL) { clientFirstMessageBare = "n=" - + CryptoHelper.saslEscape( - CryptoHelper.saslPrep(account.address.getEscapedLocal())) + + escape(prep(account.address.getLocalpartOrThrow().toString())) + ",r=" + this.clientNonce; state = State.AUTH_TEXT_SENT; @@ -216,7 +218,7 @@ abstract class ScramMechanism extends SaslMechanism { try { keys = getKeyPair( - CryptoHelper.saslPrep(Strings.nullToEmpty(credential.password)), + prep(Strings.nullToEmpty(credential.password)), salt, iterationCount); } catch (ExecutionException e) { @@ -269,6 +271,29 @@ abstract class ScramMechanism extends SaslMechanism { } } + public static String escape(final String s) { + final StringBuilder sb = new StringBuilder((int) (s.length() * 1.1)); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case ',': + sb.append("=2C"); + break; + case '=': + sb.append("=3D"); + break; + default: + sb.append(c); + break; + } + } + return sb.toString(); + } + + public static String prep(final String s) { + return Normalizer.normalize(s, Normalizer.Form.NFKC); + } + protected byte[] getChannelBindingData(final SSLSocket sslSocket) throws AuthenticationException { if (this.channelBinding == ChannelBinding.NONE) {