From b88d2ede67f0ac9b55da407a1f331ea1fcda4ab9 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 5 Nov 2014 08:35:01 -0500 Subject: [PATCH 01/22] Add jxmpp-stringprep-libidn dependency --- build.gradle | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0e6396da..b95ae8b8 100644 --- a/build.gradle +++ b/build.gradle @@ -20,11 +20,14 @@ allprojects { apply plugin: 'com.android.application' repositories { - jcenter() - mavenCentral() maven { url "http://jitsi.github.com/otr4j/repository/" } + maven { + url "https://oss.sonatype.org/content/repositories/releases/" + } + jcenter() + mavenCentral() } dependencies { @@ -34,6 +37,7 @@ dependencies { compile 'com.android.support:support-v13:19.1.0' compile 'org.bouncycastle:bcprov-jdk15on:1.50' compile 'net.java:otr4j:0.21' + compile 'org.jxmpp:jxmpp-stringprep-libidn:0.4.0' compile 'com.google.zxing:core:3.1.0' compile 'com.google.zxing:android-integration:3.1.0' } From 8e23b6c272d72c645e2102bc8359b75cc9a31620 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 5 Nov 2014 09:00:31 -0500 Subject: [PATCH 02/22] Add first attempt at JID class --- .../eu/siacs/conversations/xmpp/jid/Jid.java | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java new file mode 100644 index 00000000..abb2eef3 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -0,0 +1,151 @@ +package eu.siacs.conversations.xmpp.jid; + +import java.net.IDN; + +import gnu.inet.encoding.Stringprep; +import gnu.inet.encoding.StringprepException; + +/** + * The `Jid' class provides an immutable representation of a JID. + */ +public final class Jid { + + public final static class InvalidJidException extends Exception { } + + private final String localpart; + private final String domainpart; + private final String resourcepart; + + // It's much more efficient to store the ful JID as well as the parts instead of figuring them + // all out every time (since some characters are displayed but aren't used for comparisons). + private final String displayjid; + + public String getLocalpart() { + return IDN.toUnicode(localpart); + } + + public String getDomainpart() { + return IDN.toUnicode(domainpart); + } + + public String getResourcepart() { + return IDN.toUnicode(resourcepart); + } + + // Special private constructor that doesn't do any checking... + private Jid(final String localpart, final String domainpart) { + this.localpart = localpart; + this.domainpart = domainpart; + this.resourcepart = ""; + if (localpart.isEmpty()) { + this.displayjid = domainpart; + } else { + this.displayjid = localpart + "@" + domainpart; + } + } + + // Note: If introducing a mutable instance variable for some reason, make the constructor + // private and add a factory method to ensure thread safety and hash-cach-ability (tm). + public Jid(final String jid) throws InvalidJidException { + + // Hackish Android way to count the number of chars in a string... should work everywhere. + final int atCount = jid.length() - jid.replace("@", "").length(); + final int slashCount = jid.length() - jid.replace("/", "").length(); + + // Throw an error if there's anything obvious wrong with the JID... + if (atCount > 1 || slashCount > 1 || + jid.length() == 0 || jid.length() > 3071 || + jid.startsWith("@") || jid.endsWith("@") || + jid.startsWith("/") || jid.endsWith("/")) { + throw new InvalidJidException(); + } + + String finaljid; + + final int domainpartStart; + if (atCount == 1) { + final int atLoc = jid.indexOf("@"); + final String lp = jid.substring(0, atLoc); + try { + localpart = Stringprep.nodeprep(lp); + } catch (final StringprepException e) { + throw new InvalidJidException(); + } + if (localpart.isEmpty() || localpart.length() > 1023) { + throw new InvalidJidException(); + } + domainpartStart = atLoc; + finaljid = lp + "@"; + } else { + localpart = ""; + finaljid = ""; + domainpartStart = 0; + } + + final String dp; + if (slashCount == 1) { + final int slashLoc = jid.indexOf("/"); + final String rp = jid.substring(slashLoc + 1, jid.length()); + try { + resourcepart = Stringprep.resourceprep(rp); + } catch (final StringprepException e) { + throw new InvalidJidException(); + } + if (resourcepart.isEmpty() || resourcepart.length() > 1023) { + throw new InvalidJidException(); + } + dp = jid.substring(domainpartStart, slashLoc); + finaljid = finaljid + dp + "/" + rp; + } else { + resourcepart = ""; + dp = jid.substring(domainpartStart, jid.length()); + finaljid = finaljid + dp; + } + + // Remove trailling "." before storing the domain part. + if (dp.endsWith(".")) { + domainpart = IDN.toASCII(dp.substring(0, dp.length() - 1), IDN.USE_STD3_ASCII_RULES); + } else { + domainpart = IDN.toASCII(dp, IDN.USE_STD3_ASCII_RULES); + } + + // TODO: Find a proper domain validation library; validate individual parts, separators, etc. + if (domainpart.isEmpty() || domainpart.length() > 1023) { + throw new InvalidJidException(); + } + + this.displayjid = finaljid; + } + + public Jid getBareJid() { + return displayjid.contains("/") ? new Jid(localpart, domainpart) : this; + } + + @Override + public String toString() { + return displayjid; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Jid jid = (Jid) o; + + // Since we're immutable, the JVM will cache hashcodes, making this very fast. + // I'm assuming Dalvik does the same sorts of optimizations... + // Since the hashcode does not include the displayJID it can be used for IDN comparison as + // well. + return jid.hashCode() == this.hashCode(); + + } + + @Override + public int hashCode() { + int result = localpart.hashCode(); + result = 31 * result + domainpart.hashCode(); + result = 31 * result + resourcepart.hashCode(); + return result; + } +} From a11878b139cbc3fd22e5543279cc76225ba8e57a Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 5 Nov 2014 09:21:29 -0500 Subject: [PATCH 03/22] Improve JID error handling --- .../xmpp/jid/InvalidJidException.java | 48 +++++++++++++++++++ .../eu/siacs/conversations/xmpp/jid/Jid.java | 18 +++---- 2 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java new file mode 100644 index 00000000..f1855263 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java @@ -0,0 +1,48 @@ +package eu.siacs.conversations.xmpp.jid; + +public class InvalidJidException extends Exception { + + // This is probably not the "Java way", but the "Java way" means we'd have a ton of extra tiny, + // annoying classes floating around. I like this. + public final static String INVALID_LENGTH = "JID must be between 0 and 3071 characters"; + public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters"; + public final static String INVALID_CHARACTER = "JID contains an invalid character"; + public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID"; + + /** + * Constructs a new {@code Exception} that includes the current stack trace. + */ + public InvalidJidException() { + } + + /** + * Constructs a new {@code Exception} with the current stack trace and the + * specified detail message. + * + * @param detailMessage the detail message for this exception. + */ + public InvalidJidException(final String detailMessage) { + super(detailMessage); + } + + /** + * Constructs a new {@code Exception} with the current stack trace, the + * specified detail message and the specified cause. + * + * @param detailMessage the detail message for this exception. + * @param throwable the cause of this exception. + */ + public InvalidJidException(final String detailMessage, final Throwable throwable) { + super(detailMessage, throwable); + } + + /** + * Constructs a new {@code Exception} with the current stack trace and the + * specified cause. + * + * @param throwable the cause of this exception. + */ + public InvalidJidException(final Throwable throwable) { + super(throwable); + } +} diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index abb2eef3..67105d89 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -10,8 +10,6 @@ import gnu.inet.encoding.StringprepException; */ public final class Jid { - public final static class InvalidJidException extends Exception { } - private final String localpart; private final String domainpart; private final String resourcepart; @@ -53,11 +51,13 @@ public final class Jid { final int slashCount = jid.length() - jid.replace("/", "").length(); // Throw an error if there's anything obvious wrong with the JID... + if (jid.isEmpty() || jid.length() > 3071) { + throw new InvalidJidException(InvalidJidException.INVALID_LENGTH); + } if (atCount > 1 || slashCount > 1 || - jid.length() == 0 || jid.length() > 3071 || jid.startsWith("@") || jid.endsWith("@") || jid.startsWith("/") || jid.endsWith("/")) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.INVALID_CHARACTER); } String finaljid; @@ -69,10 +69,10 @@ public final class Jid { try { localpart = Stringprep.nodeprep(lp); } catch (final StringprepException e) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } if (localpart.isEmpty() || localpart.length() > 1023) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } domainpartStart = atLoc; finaljid = lp + "@"; @@ -89,10 +89,10 @@ public final class Jid { try { resourcepart = Stringprep.resourceprep(rp); } catch (final StringprepException e) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } if (resourcepart.isEmpty() || resourcepart.length() > 1023) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } dp = jid.substring(domainpartStart, slashLoc); finaljid = finaljid + dp + "/" + rp; @@ -111,7 +111,7 @@ public final class Jid { // TODO: Find a proper domain validation library; validate individual parts, separators, etc. if (domainpart.isEmpty() || domainpart.length() > 1023) { - throw new InvalidJidException(); + throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } this.displayjid = finaljid; From a9908613162f753ad71ac25890fb7cc067925764 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 5 Nov 2014 09:40:16 -0500 Subject: [PATCH 04/22] Use factories to generate JIDs --- .../eu/siacs/conversations/xmpp/jid/Jid.java | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 67105d89..7d8f702f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -30,22 +30,26 @@ public final class Jid { return IDN.toUnicode(resourcepart); } - // Special private constructor that doesn't do any checking... - private Jid(final String localpart, final String domainpart) { - this.localpart = localpart; - this.domainpart = domainpart; - this.resourcepart = ""; - if (localpart.isEmpty()) { - this.displayjid = domainpart; - } else { - this.displayjid = localpart + "@" + domainpart; - } + public Jid fromString(final String jid) throws InvalidJidException { + return new Jid(jid); } - // Note: If introducing a mutable instance variable for some reason, make the constructor - // private and add a factory method to ensure thread safety and hash-cach-ability (tm). - public Jid(final String jid) throws InvalidJidException { + public static Jid fromParts(final String localpart, + final String domainpart, + final String resourcepart) throws InvalidJidException { + String out; + if (localpart == null || localpart.isEmpty()) { + out = domainpart; + } else { + out = localpart + "@" + domainpart; + } + if (resourcepart != null && !resourcepart.isEmpty()) { + out = out + "/" + resourcepart; + } + return new Jid(out); + } + private Jid(final String jid) throws InvalidJidException { // Hackish Android way to count the number of chars in a string... should work everywhere. final int atCount = jid.length() - jid.replace("@", "").length(); final int slashCount = jid.length() - jid.replace("/", "").length(); @@ -118,7 +122,12 @@ public final class Jid { } public Jid getBareJid() { - return displayjid.contains("/") ? new Jid(localpart, domainpart) : this; + try { + return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, ""); + } catch (final InvalidJidException e) { + // This should never happen due to the contracts we have in place. + return null; + } } @Override @@ -133,12 +142,7 @@ public final class Jid { final Jid jid = (Jid) o; - // Since we're immutable, the JVM will cache hashcodes, making this very fast. - // I'm assuming Dalvik does the same sorts of optimizations... - // Since the hashcode does not include the displayJID it can be used for IDN comparison as - // well. return jid.hashCode() == this.hashCode(); - } @Override From 9053f4aca0c232db77dbd0a1e5b9b09bf41bec22 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 5 Nov 2014 15:55:47 -0500 Subject: [PATCH 05/22] Move a chunk of classes over to using JID objects --- .../siacs/conversations/crypto/OtrEngine.java | 10 +- .../siacs/conversations/crypto/PgpEngine.java | 40 ++-- .../siacs/conversations/entities/Account.java | 96 +++++---- .../conversations/entities/Bookmark.java | 30 +-- .../siacs/conversations/entities/Contact.java | 99 +++++---- .../conversations/entities/Conversation.java | 74 ++++--- .../conversations/entities/ListItem.java | 4 +- .../siacs/conversations/entities/Message.java | 60 +++--- .../conversations/entities/MucOptions.java | 46 ++-- .../siacs/conversations/entities/Roster.java | 23 +- .../conversations/generator/IqGenerator.java | 7 +- .../generator/MessageGenerator.java | 17 +- .../generator/PresenceGenerator.java | 6 +- .../conversations/parser/AbstractParser.java | 26 +-- .../siacs/conversations/parser/IqParser.java | 21 +- .../persistance/DatabaseBackend.java | 22 +- .../services/XmppConnectionService.java | 173 +++++++-------- .../siacs/conversations/utils/DNSHelper.java | 14 +- .../conversations/xmpp/XmppConnection.java | 199 +++++++++--------- .../eu/siacs/conversations/xmpp/jid/Jid.java | 19 +- .../siacs/conversations/xmpp/pep/Avatar.java | 4 +- .../xmpp/stanzas/AbstractStanza.java | 11 +- 22 files changed, 526 insertions(+), 475 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java index e0bd0e79..82d7145e 100644 --- a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java @@ -85,13 +85,11 @@ public class OtrEngine implements OtrEngineHost { this.account.setKey("otr_p", privateKeySpec.getP().toString(16)); this.account.setKey("otr_q", privateKeySpec.getQ().toString(16)); this.account.setKey("otr_y", publicKeySpec.getY().toString(16)); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeySpecException e) { + } catch (final NoSuchAlgorithmException | InvalidKeySpecException e) { e.printStackTrace(); } - } + } @Override public void askForSecret(SessionID arg0, InstanceTag arg1, String arg2) { @@ -157,9 +155,9 @@ public class OtrEngine implements OtrEngineHost { MessagePacket packet = new MessagePacket(); packet.setFrom(account.getFullJid()); if (session.getUserID().isEmpty()) { - packet.setTo(session.getAccountID()); + packet.setAttribute("to", session.getAccountID()); } else { - packet.setTo(session.getAccountID() + "/" + session.getUserID()); + packet.setAttribute("to", session.getAccountID() + "/" + session.getUserID()); } packet.setBody(body); packet.addChild("private", "urn:xmpp:carbons:2"); diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java index 9a2b4a11..ae4a54a1 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java @@ -41,7 +41,7 @@ public class PgpEngine { Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message - .getConversation().getAccount().getJid()); + .getConversation().getAccount().getJid().toString()); if (message.getType() == Message.TYPE_TEXT) { InputStream is = new ByteArrayInputStream(message.getBody() .getBytes()); @@ -77,10 +77,7 @@ public class PgpEngine { return; case OpenPgpApi.RESULT_CODE_ERROR: callback.error(R.string.openpgp_error, message); - return; - default: - return; - } + } } }); } else if (message.getType() == Message.TYPE_IMAGE) { @@ -135,15 +132,10 @@ public class PgpEngine { return; case OpenPgpApi.RESULT_CODE_ERROR: callback.error(R.string.openpgp_error, message); - return; - default: - return; } } }); - } catch (FileNotFoundException e) { - callback.error(R.string.error_decrypting_file, message); - } catch (IOException e) { + } catch (final IOException e) { callback.error(R.string.error_decrypting_file, message); } @@ -164,7 +156,7 @@ public class PgpEngine { .getMucOptions().getPgpKeyIds()); } params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message - .getConversation().getAccount().getJid()); + .getConversation().getAccount().getJid().toString()); if (message.getType() == Message.TYPE_TEXT) { params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); @@ -237,12 +229,8 @@ public class PgpEngine { } } }); - } catch (FileNotFoundException e) { + } catch (final IOException e) { callback.error(R.string.openpgp_error, message); - return; - } catch (IOException e) { - callback.error(R.string.openpgp_error, message); - return; } } } @@ -254,7 +242,7 @@ public class PgpEngine { if (status == null) { status = ""; } - StringBuilder pgpSig = new StringBuilder(); + final StringBuilder pgpSig = new StringBuilder(); pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----"); pgpSig.append('\n'); pgpSig.append('\n'); @@ -269,7 +257,7 @@ public class PgpEngine { Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid()); + params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid().toString()); InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes()); ByteArrayOutputStream os = new ByteArrayOutputStream(); Intent result = api.executeApi(params, is, os); @@ -296,7 +284,7 @@ public class PgpEngine { Intent params = new Intent(); params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); params.setAction(OpenPgpApi.ACTION_SIGN); - params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid()); + params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid().toString()); InputStream is = new ByteArrayInputStream(status.getBytes()); final OutputStream os = new ByteArrayOutputStream(); api.executeApiAsync(params, is, os, new IOpenPgpCallback() { @@ -338,8 +326,7 @@ public class PgpEngine { return; case OpenPgpApi.RESULT_CODE_ERROR: callback.error(R.string.openpgp_error, account); - return; - } + } } }); } @@ -349,7 +336,7 @@ public class PgpEngine { params.setAction(OpenPgpApi.ACTION_GET_KEY); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId()); params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount() - .getJid()); + .getJid().toString()); api.executeApiAsync(params, null, null, new IOpenPgpCallback() { @Override @@ -365,8 +352,7 @@ public class PgpEngine { return; case OpenPgpApi.RESULT_CODE_ERROR: callback.error(R.string.openpgp_error, contact); - return; - } + } } }); } @@ -376,7 +362,7 @@ public class PgpEngine { params.setAction(OpenPgpApi.ACTION_GET_KEY); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId()); params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount() - .getJid()); + .getJid().toString()); Intent result = api.executeApi(params, null, null); return (PendingIntent) result .getParcelableExtra(OpenPgpApi.RESULT_INTENT); @@ -386,7 +372,7 @@ public class PgpEngine { Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_GET_KEY); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpKeyId); - params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid()); + params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid().toString()); Intent result = api.executeApi(params, null, null); return (PendingIntent) result .getParcelableExtra(OpenPgpApi.RESULT_INTENT); diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 80a9d62f..e600f37b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -2,7 +2,6 @@ package eu.siacs.conversations.entities; import java.security.interfaces.DSAPublicKey; import java.util.List; -import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; import net.java.otr4j.crypto.OtrCryptoEngineImpl; @@ -16,6 +15,9 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrEngine; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.XmppConnection; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.content.ContentValues; import android.database.Cursor; import android.os.SystemClock; @@ -50,12 +52,10 @@ public class Account extends AbstractEntity { public static final int STATUS_REGISTRATION_SUCCESSFULL = 9; public static final int STATUS_REGISTRATION_NOT_SUPPORTED = 10; - protected String username; - protected String server; + protected Jid jid; protected String password; protected int options = 0; protected String rosterVersion; - protected String resource = "mobile"; protected int status = -1; protected JSONObject keys = new JSONObject(); protected String avatar; @@ -69,31 +69,36 @@ public class Account extends AbstractEntity { private String otrFingerprint; private Roster roster = null; - private List bookmarks = new CopyOnWriteArrayList(); - public List pendingConferenceJoins = new CopyOnWriteArrayList(); - public List pendingConferenceLeaves = new CopyOnWriteArrayList(); + private List bookmarks = new CopyOnWriteArrayList<>(); + public List pendingConferenceJoins = new CopyOnWriteArrayList<>(); + public List pendingConferenceLeaves = new CopyOnWriteArrayList<>(); public Account() { this.uuid = "0"; } - public Account(String username, String server, String password) { - this(java.util.UUID.randomUUID().toString(), username, server, + public Account(final Jid jid, final String password) { + this(java.util.UUID.randomUUID().toString(), jid, password, 0, null, "", null); } - public Account(String uuid, String username, String server, - String password, int options, String rosterVersion, String keys, - String avatar) { + public Account(final String uuid, final Jid jid, + final String password, final int options, final String rosterVersion, final String keys, + final String avatar) { this.uuid = uuid; - this.username = username; - this.server = server; + this.jid = jid; + if (jid.getResourcepart().isEmpty()) { + try { + this.setResource("mobile"); + } catch (final InvalidJidException ignored) { + } + } this.password = password; this.options = options; this.rosterVersion = rosterVersion; try { this.keys = new JSONObject(keys); - } catch (JSONException e) { + } catch (final JSONException ignored) { } this.avatar = avatar; @@ -112,30 +117,30 @@ public class Account extends AbstractEntity { } public String getUsername() { - return username; + return jid.getLocalpart(); } - public void setUsername(String username) { - this.username = username; + public void setUsername(final String username) throws InvalidJidException { + jid = Jid.fromParts(username, jid.getDomainpart(), jid.getResourcepart()); + } + + public Jid getServer() { + return jid.toDomainJid(); } - public String getServer() { - return server; - } - - public void setServer(String server) { - this.server = server; + public void setServer(final String server) throws InvalidJidException { + jid = Jid.fromParts(jid.getLocalpart(), server, jid.getResourcepart()); } public String getPassword() { return password; } - public void setPassword(String password) { + public void setPassword(final String password) { this.password = password; } - public void setStatus(int status) { + public void setStatus(final int status) { this.status = status; } @@ -156,25 +161,19 @@ public class Account extends AbstractEntity { } public boolean hasErrorStatus() { - if (getXmppConnection() == null) { - return false; - } else { - return getStatus() > STATUS_NO_INTERNET - && (getXmppConnection().getAttempt() >= 2); - } + return getXmppConnection() != null && getStatus() > STATUS_NO_INTERNET && (getXmppConnection().getAttempt() >= 2); } - public void setResource(String resource) { - this.resource = resource; + public void setResource(final String resource) throws InvalidJidException { + jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); } public String getResource() { - return this.resource; + return jid.getResourcepart(); } - public String getJid() { - return username.toLowerCase(Locale.getDefault()) + "@" - + server.toLowerCase(Locale.getDefault()); + public Jid getJid() { + return jid.toBareJid(); } public JSONObject getKeys() { @@ -210,8 +209,8 @@ public class Account extends AbstractEntity { public ContentValues getContentValues() { ContentValues values = new ContentValues(); values.put(UUID, uuid); - values.put(USERNAME, username); - values.put(SERVER, server); + values.put(USERNAME, jid.getLocalpart()); + values.put(SERVER, jid.getDomainpart()); values.put(PASSWORD, password); values.put(OPTIONS, options); values.put(KEYS, this.keys.toString()); @@ -221,9 +220,14 @@ public class Account extends AbstractEntity { } public static Account fromCursor(Cursor cursor) { - return new Account(cursor.getString(cursor.getColumnIndex(UUID)), - cursor.getString(cursor.getColumnIndex(USERNAME)), - cursor.getString(cursor.getColumnIndex(SERVER)), + Jid jid = null; + try { + jid = Jid.fromParts(cursor.getString(cursor.getColumnIndex(USERNAME)), + cursor.getString(cursor.getColumnIndex(SERVER)), "mobile"); + } catch (final InvalidJidException ignored) { + } + return new Account(cursor.getString(cursor.getColumnIndex(UUID)), + jid, cursor.getString(cursor.getColumnIndex(PASSWORD)), cursor.getInt(cursor.getColumnIndex(OPTIONS)), cursor.getString(cursor.getColumnIndex(ROSTERVERSION)), @@ -246,8 +250,8 @@ public class Account extends AbstractEntity { this.xmppConnection = connection; } - public String getFullJid() { - return this.getJid() + "/" + this.resource; + public Jid getFullJid() { + return this.getJid(); } public String getOtrFingerprint() { @@ -265,7 +269,7 @@ public class Account extends AbstractEntity { builder.insert(26, " "); builder.insert(35, " "); this.otrFingerprint = builder.toString(); - } catch (OtrCryptoException e) { + } catch (final OtrCryptoException ignored) { } } diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index dd9e805c..54dcfea1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -3,15 +3,17 @@ package eu.siacs.conversations.entities; import java.util.Locale; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Bookmark extends Element implements ListItem { private Account account; private Conversation mJoinedConversation; - public Bookmark(Account account, String jid) { + public Bookmark(final Account account, final Jid jid) { super("conference"); - this.setAttribute("jid", jid); + this.setAttribute("jid", jid.toString()); this.account = account; } @@ -55,10 +57,10 @@ public class Bookmark extends Element implements ListItem { } @Override - public int compareTo(ListItem another) { - return this.getDisplayName().compareToIgnoreCase( - another.getDisplayName()); - } + public int compareTo(final ListItem another) { + return this.getDisplayName().compareToIgnoreCase( + another.getDisplayName()); + } @Override public String getDisplayName() { @@ -68,16 +70,20 @@ public class Bookmark extends Element implements ListItem { } else if (getName() != null) { return getName(); } else { - return this.getJid().split("@")[0]; + return this.getJid().getLocalpart(); } } @Override - public String getJid() { - String jid = this.getAttribute("jid"); + public Jid getJid() { + final String jid = this.getAttribute("jid"); if (jid != null) { - return jid.toLowerCase(Locale.US); - } else { + try { + return Jid.fromString(jid); + } catch (final InvalidJidException e) { + return null; + } + } else { return null; } } @@ -108,7 +114,7 @@ public class Bookmark extends Element implements ListItem { public boolean match(String needle) { return needle == null - || getJid().contains(needle.toLowerCase(Locale.US)) + || getJid().toString().toLowerCase(Locale.US).contains(needle.toLowerCase(Locale.US)) || getDisplayName().toLowerCase(Locale.US).contains( needle.toLowerCase(Locale.US)); } diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index af5172d3..8fa91b02 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -1,16 +1,18 @@ package eu.siacs.conversations.entities; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; +import android.content.ContentValues; +import android.database.Cursor; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.util.HashSet; +import java.util.Set; + import eu.siacs.conversations.xml.Element; -import android.content.ContentValues; -import android.database.Cursor; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Contact implements ListItem { public static final String TABLENAME = "contacts"; @@ -31,7 +33,7 @@ public class Contact implements ListItem { protected String systemName; protected String serverName; protected String presenceName; - protected String jid; + protected Jid jid; protected int subscription = 0; protected String systemAccount; protected String photoUri; @@ -41,12 +43,10 @@ public class Contact implements ListItem { protected Account account; - protected boolean inRoster = true; - public Lastseen lastseen = new Lastseen(); public Contact(final String account, final String systemName, final String serverName, - final String jid, final int subscription, final String photoUri, + final Jid jid, final int subscription, final String photoUri, final String systemAccount, final String keys, final String avatar, final Lastseen lastseen) { this(account, systemName, serverName, jid, subscription, photoUri, systemAccount, keys, @@ -55,7 +55,7 @@ public class Contact implements ListItem { } public Contact(final String account, final String systemName, final String serverName, - final String jid, final int subscription, final String photoUri, + final Jid jid, final int subscription, final String photoUri, final String systemAccount, final String keys, final String avatar) { this.accountUuid = account; this.systemName = systemName; @@ -72,7 +72,7 @@ public class Contact implements ListItem { this.avatar = avatar; } - public Contact(final String jid) { + public Contact(final Jid jid) { this.jid = jid; } @@ -84,7 +84,7 @@ public class Contact implements ListItem { } else if (this.presenceName != null) { return this.presenceName; } else { - return this.jid.split("@")[0]; + return jid.getLocalpart(); } } @@ -92,13 +92,13 @@ public class Contact implements ListItem { return this.photoUri; } - public String getJid() { - return this.jid.toLowerCase(Locale.getDefault()); + public Jid getJid() { + return jid; } public boolean match(String needle) { return needle == null - || jid.contains(needle.toLowerCase()) + || jid.toString().contains(needle.toLowerCase()) || getDisplayName().toLowerCase() .contains(needle.toLowerCase()); } @@ -108,7 +108,7 @@ public class Contact implements ListItem { values.put(ACCOUNT, accountUuid); values.put(SYSTEMNAME, systemName); values.put(SERVERNAME, serverName); - values.put(JID, jid); + values.put(JID, jid.toString()); values.put(OPTIONS, subscription); values.put(SYSTEMACCOUNT, systemAccount); values.put(PHOTOURI, photoUri); @@ -123,10 +123,17 @@ public class Contact implements ListItem { final Lastseen lastseen = new Lastseen( cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)), cursor.getLong(cursor.getColumnIndex(LAST_TIME))); - return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)), + final Jid jid; + try { + jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(JID))); + } catch (final InvalidJidException e) { + // TODO: Borked DB... handle this somehow? + return null; + } + return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)), cursor.getString(cursor.getColumnIndex(SYSTEMNAME)), cursor.getString(cursor.getColumnIndex(SERVERNAME)), - cursor.getString(cursor.getColumnIndex(JID)), + jid, cursor.getInt(cursor.getColumnIndex(OPTIONS)), cursor.getString(cursor.getColumnIndex(PHOTOURI)), cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)), @@ -198,7 +205,7 @@ public class Contact implements ListItem { } public Set getOtrFingerprints() { - Set set = new HashSet(); + Set set = new HashSet<>(); try { if (this.keys.has("otr_fingerprints")) { JSONArray fingerprints = this.keys @@ -225,7 +232,7 @@ public class Contact implements ListItem { } fingerprints.put(print); this.keys.put("otr_fingerprints", fingerprints); - } catch (JSONException e) { + } catch (final JSONException ignored) { } } @@ -233,7 +240,7 @@ public class Contact implements ListItem { public void setPgpKeyId(long keyId) { try { this.keys.put("pgp_keyid", keyId); - } catch (JSONException e) { + } catch (final JSONException ignored) { } } @@ -273,21 +280,26 @@ public class Contact implements ListItem { String subscription = item.getAttribute("subscription"); if (subscription != null) { - if (subscription.equals("to")) { - this.resetOption(Contact.Options.FROM); - this.setOption(Contact.Options.TO); - } else if (subscription.equals("from")) { - this.resetOption(Contact.Options.TO); - this.setOption(Contact.Options.FROM); - this.resetOption(Contact.Options.PREEMPTIVE_GRANT); - } else if (subscription.equals("both")) { - this.setOption(Contact.Options.TO); - this.setOption(Contact.Options.FROM); - this.resetOption(Contact.Options.PREEMPTIVE_GRANT); - } else if (subscription.equals("none")) { - this.resetOption(Contact.Options.FROM); - this.resetOption(Contact.Options.TO); - } + switch (subscription) { + case "to": + this.resetOption(Options.FROM); + this.setOption(Options.TO); + break; + case "from": + this.resetOption(Options.TO); + this.setOption(Options.FROM); + this.resetOption(Options.PREEMPTIVE_GRANT); + break; + case "both": + this.setOption(Options.TO); + this.setOption(Options.FROM); + this.resetOption(Options.PREEMPTIVE_GRANT); + break; + case "none": + this.resetOption(Options.FROM); + this.resetOption(Options.TO); + break; + } } // do NOT override asking if pending push request @@ -301,8 +313,8 @@ public class Contact implements ListItem { } public Element asElement() { - Element item = new Element("item"); - item.setAttribute("jid", this.jid); + final Element item = new Element("item"); + item.setAttribute("jid", this.jid.toString()); if (this.serverName != null) { item.setAttribute("name", this.serverName); } @@ -335,18 +347,13 @@ public class Contact implements ListItem { } @Override - public int compareTo(ListItem another) { + public int compareTo(final ListItem another) { return this.getDisplayName().compareToIgnoreCase( another.getDisplayName()); } - public String getServer() { - String[] split = getJid().split("@"); - if (split.length >= 2) { - return split[1]; - } else { - return null; - } + public Jid getServer() { + return getJid().toDomainJid(); } public boolean setAvatar(String filename) { diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 9d4c36db..fdffeccb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -1,13 +1,8 @@ package eu.siacs.conversations.entities; -import java.security.interfaces.DSAPublicKey; -import java.util.ArrayList; -import java.util.List; - -import org.json.JSONException; -import org.json.JSONObject; - -import eu.siacs.conversations.services.XmppConnectionService; +import android.content.ContentValues; +import android.database.Cursor; +import android.os.SystemClock; import net.java.otr4j.OtrException; import net.java.otr4j.crypto.OtrCryptoEngineImpl; @@ -15,9 +10,17 @@ import net.java.otr4j.crypto.OtrCryptoException; import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionStatus; -import android.content.ContentValues; -import android.database.Cursor; -import android.os.SystemClock; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.security.interfaces.DSAPublicKey; +import java.util.ArrayList; +import java.util.List; + +import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Conversation extends AbstractEntity { public static final String TABLENAME = "conversations"; @@ -45,7 +48,7 @@ public class Conversation extends AbstractEntity { private String name; private String contactUuid; private String accountUuid; - private String contactJid; + private Jid contactJid; private int status; private long created; private int mode; @@ -54,7 +57,7 @@ public class Conversation extends AbstractEntity { private String nextPresence; - protected ArrayList messages = new ArrayList(); + protected ArrayList messages = new ArrayList<>(); protected Account account = null; private transient SessionImpl otrSession; @@ -71,17 +74,17 @@ public class Conversation extends AbstractEntity { private Bookmark bookmark; - public Conversation(String name, Account account, String contactJid, - int mode) { + public Conversation(final String name, final Account account, final Jid contactJid, + final int mode) { this(java.util.UUID.randomUUID().toString(), name, null, account .getUuid(), contactJid, System.currentTimeMillis(), STATUS_AVAILABLE, mode, ""); this.account = account; } - public Conversation(String uuid, String name, String contactUuid, - String accountUuid, String contactJid, long created, int status, - int mode, String attributes) { + public Conversation(final String uuid, final String name, final String contactUuid, + final String accountUuid, final Jid contactJid, final long created, final int status, + final int mode, final String attributes) { this.uuid = uuid; this.name = name; this.contactUuid = contactUuid; @@ -91,10 +94,7 @@ public class Conversation extends AbstractEntity { this.status = status; this.mode = mode; try { - if (attributes == null) { - attributes = new String(); - } - this.attributes = new JSONObject(attributes); + this.attributes = new JSONObject(attributes == null ? "" : attributes); } catch (JSONException e) { this.attributes = new JSONObject(); } @@ -105,10 +105,8 @@ public class Conversation extends AbstractEntity { } public boolean isRead() { - if ((this.messages == null) || (this.messages.size() == 0)) - return true; - return this.messages.get(this.messages.size() - 1).isRead(); - } + return (this.messages == null) || (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead(); + } public void markRead() { if (this.messages == null) { @@ -186,7 +184,7 @@ public class Conversation extends AbstractEntity { this.account = account; } - public String getContactJid() { + public Jid getContactJid() { return this.contactJid; } @@ -204,7 +202,7 @@ public class Conversation extends AbstractEntity { values.put(NAME, name); values.put(CONTACT, contactUuid); values.put(ACCOUNT, accountUuid); - values.put(CONTACTJID, contactJid); + values.put(CONTACTJID, contactJid.toString()); values.put(CREATED, created); values.put(STATUS, status); values.put(MODE, mode); @@ -213,11 +211,18 @@ public class Conversation extends AbstractEntity { } public static Conversation fromCursor(Cursor cursor) { - return new Conversation(cursor.getString(cursor.getColumnIndex(UUID)), + Jid jid; + try { + jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(CONTACTJID))); + } catch (final InvalidJidException e) { + // Borked DB.. + jid = null; + } + return new Conversation(cursor.getString(cursor.getColumnIndex(UUID)), cursor.getString(cursor.getColumnIndex(NAME)), cursor.getString(cursor.getColumnIndex(CONTACT)), cursor.getString(cursor.getColumnIndex(ACCOUNT)), - cursor.getString(cursor.getColumnIndex(CONTACTJID)), + jid, cursor.getLong(cursor.getColumnIndex(CREATED)), cursor.getInt(cursor.getColumnIndex(STATUS)), cursor.getInt(cursor.getColumnIndex(MODE)), @@ -241,8 +246,9 @@ public class Conversation extends AbstractEntity { if (this.otrSession != null) { return this.otrSession; } else { - SessionID sessionId = new SessionID(this.getContactJid().split("/", - 2)[0], presence, "xmpp"); + final SessionID sessionId = new SessionID(this.getContactJid().toBareJid().toString(), + presence, + "xmpp"); this.otrSession = new SessionImpl(sessionId, getAccount() .getOtrEngine(service)); try { @@ -317,7 +323,7 @@ public class Conversation extends AbstractEntity { builder.insert(26, " "); builder.insert(35, " "); this.otrFingerprint = builder.toString(); - } catch (OtrCryptoException e) { + } catch (final OtrCryptoException ignored) { } } @@ -335,7 +341,7 @@ public class Conversation extends AbstractEntity { this.mucOptions = null; } - public void setContactJid(String jid) { + public void setContactJid(final Jid jid) { this.contactJid = jid; } diff --git a/src/main/java/eu/siacs/conversations/entities/ListItem.java b/src/main/java/eu/siacs/conversations/entities/ListItem.java index a1872d2f..fa650f1c 100644 --- a/src/main/java/eu/siacs/conversations/entities/ListItem.java +++ b/src/main/java/eu/siacs/conversations/entities/ListItem.java @@ -1,7 +1,9 @@ package eu.siacs.conversations.entities; +import eu.siacs.conversations.xmpp.jid.Jid; + public interface ListItem extends Comparable { public String getDisplayName(); - public String getJid(); + public Jid getJid(); } diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index b33d5f37..ce21addc 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -5,6 +5,9 @@ import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.content.ContentValues; import android.database.Cursor; @@ -44,7 +47,7 @@ public class Message extends AbstractEntity { public static String REMOTE_MSG_ID = "remoteMsgId"; protected String conversationUuid; - protected String counterpart; + protected Jid counterpart; protected String trueCounterpart; protected String body; protected String encryptedBody; @@ -74,17 +77,17 @@ public class Message extends AbstractEntity { this.conversation = conversation; } - public Message(Conversation conversation, String counterpart, String body, - int encryption, int status) { + public Message(final Conversation conversation, final Jid counterpart, final String body, + final int encryption, final int status) { this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), counterpart, null, body, System.currentTimeMillis(), encryption, status, TYPE_TEXT, null); this.conversation = conversation; } - public Message(String uuid, String conversationUUid, String counterpart, - String trueCounterpart, String body, long timeSent, int encryption, - int status, int type, String remoteMsgId) { + public Message(final String uuid, final String conversationUUid, final Jid counterpart, + final String trueCounterpart, final String body, final long timeSent, + final int encryption, final int status, final int type, final String remoteMsgId) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -102,7 +105,7 @@ public class Message extends AbstractEntity { ContentValues values = new ContentValues(); values.put(UUID, uuid); values.put(CONVERSATION, conversationUuid); - values.put(COUNTERPART, counterpart); + values.put(COUNTERPART, counterpart.toString()); values.put(TRUE_COUNTERPART, trueCounterpart); values.put(BODY, body); values.put(TIME_SENT, timeSent); @@ -121,7 +124,7 @@ public class Message extends AbstractEntity { return this.conversation; } - public String getCounterpart() { + public Jid getCounterpart() { return counterpart; } @@ -163,9 +166,15 @@ public class Message extends AbstractEntity { } public static Message fromCursor(Cursor cursor) { - return new Message(cursor.getString(cursor.getColumnIndex(UUID)), + Jid jid; + try { + jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(COUNTERPART))); + } catch (InvalidJidException e) { + jid = null; + } + return new Message(cursor.getString(cursor.getColumnIndex(UUID)), cursor.getString(cursor.getColumnIndex(CONVERSATION)), - cursor.getString(cursor.getColumnIndex(COUNTERPART)), + jid, cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)), cursor.getString(cursor.getColumnIndex(BODY)), cursor.getLong(cursor.getColumnIndex(TIME_SENT)), @@ -225,11 +234,14 @@ public class Message extends AbstractEntity { public void setPresence(String presence) { if (presence == null) { - this.counterpart = this.counterpart.split("/", 2)[0]; + this.counterpart = this.counterpart.toBareJid(); } else { - this.counterpart = this.counterpart.split("/", 2)[0] + "/" - + presence; - } + try { + this.counterpart = Jid.fromString(this.counterpart.toBareJid() + "/" + presence); + } catch (final InvalidJidException ignored) { + // TODO: Handle this? + } + } } public void setTrueCounterpart(String trueCounterpart) { @@ -237,15 +249,11 @@ public class Message extends AbstractEntity { } public String getPresence() { - String[] counterparts = this.counterpart.split("/", 2); - if (counterparts.length == 2) { - return counterparts[1]; + if (!counterpart.getResourcepart().isEmpty()) { + return counterpart.getResourcepart(); } else { - if (this.counterpart.contains("/")) { - return ""; - } else { - return null; - } + // TODO: Return empty string or null? + return null; } } @@ -264,7 +272,7 @@ public class Message extends AbstractEntity { return message; } - public void setCounterpart(String counterpart) { + public void setCounterpart(final Jid counterpart) { this.counterpart = counterpart; } @@ -359,11 +367,7 @@ public class Message extends AbstractEntity { public boolean wasMergedIntoPrevious() { Message prev = this.prev(); - if (prev == null) { - return false; - } else { - return prev.mergeable(this); - } + return prev != null && prev.mergeable(this); } public boolean trusted() { diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index d7407cd5..f83387fc 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -6,6 +6,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; import android.annotation.SuppressLint; @@ -66,15 +68,20 @@ public class MucOptions { public void setRole(String role) { role = role.toLowerCase(); - if (role.equals("moderator")) { - this.role = ROLE_MODERATOR; - } else if (role.equals("participant")) { - this.role = ROLE_PARTICIPANT; - } else if (role.equals("visitor")) { - this.role = ROLE_VISITOR; - } else { - this.role = ROLE_NONE; - } + switch (role) { + case "moderator": + this.role = ROLE_MODERATOR; + break; + case "participant": + this.role = ROLE_PARTICIPANT; + break; + case "visitor": + this.role = ROLE_VISITOR; + break; + default: + this.role = ROLE_NONE; + break; + } } public int getAffiliation() { @@ -109,7 +116,7 @@ public class MucOptions { } private Account account; - private List users = new CopyOnWriteArrayList(); + private List users = new CopyOnWriteArrayList<>(); private Conversation conversation; private boolean isOnline = false; private int error = ERROR_ROOM_NOT_FOUND; @@ -233,13 +240,12 @@ public class MucOptions { } public String getProposedNick() { - String[] mucParts = conversation.getContactJid().split("/", 2); if (conversation.getBookmark() != null && conversation.getBookmark().getNick() != null) { return conversation.getBookmark().getNick(); } else { - if (mucParts.length == 2) { - return mucParts[1]; + if (!conversation.getContactJid().getResourcepart().isEmpty()) { + return conversation.getContactJid().getResourcepart(); } else { return account.getUsername(); } @@ -297,7 +303,7 @@ public class MucOptions { } public long[] getPgpKeyIds() { - List ids = new ArrayList(); + List ids = new ArrayList<>(); for (User user : getUsers()) { if (user.getPgpKeyId() != 0) { ids.add(user.getPgpKeyId()); @@ -328,10 +334,14 @@ public class MucOptions { return true; } - public String getJoinJid() { - return this.conversation.getContactJid().split("/", 2)[0] + "/" - + this.joinnick; - } + public Jid getJoinJid() { + try { + return Jid.fromString(this.conversation.getContactJid().toBareJid().toString() + "/" ++ this.joinnick); + } catch (final InvalidJidException e) { + return null; + } + } public String getTrueCounterpart(String counterpart) { for (User user : this.getUsers()) { diff --git a/src/main/java/eu/siacs/conversations/entities/Roster.java b/src/main/java/eu/siacs/conversations/entities/Roster.java index 3267b15a..27d4deb0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Roster.java +++ b/src/main/java/eu/siacs/conversations/entities/Roster.java @@ -2,12 +2,13 @@ package eu.siacs.conversations.entities; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; +import eu.siacs.conversations.xmpp.jid.Jid; + public class Roster { Account account; - ConcurrentHashMap contacts = new ConcurrentHashMap(); + final ConcurrentHashMap contacts = new ConcurrentHashMap<>(); private String version = null; public Roster(Account account) { @@ -27,14 +28,14 @@ public class Roster { } } - public Contact getContact(String jid) { - String cleanJid = jid.split("/", 2)[0].toLowerCase(Locale.getDefault()); - if (contacts.containsKey(cleanJid)) { - return contacts.get(cleanJid); + public Contact getContact(final Jid jid) { + final Jid bareJid = jid.toBareJid(); + if (contacts.containsKey(bareJid.toString())) { + return contacts.get(bareJid.toString()); } else { - Contact contact = new Contact(cleanJid); + Contact contact = new Contact(bareJid); contact.setAccount(account); - contacts.put(cleanJid, contact); + contacts.put(bareJid.toString(), contact); return contact; } } @@ -60,13 +61,13 @@ public class Roster { } public List getContacts() { - return new ArrayList(this.contacts.values()); + return new ArrayList<>(this.contacts.values()); } - public void initContact(Contact contact) { + public void initContact(final Contact contact) { contact.setAccount(account); contact.setOption(Contact.Options.IN_ROSTER); - contacts.put(contact.getJid(), contact); + contacts.put(contact.getJid().toBareJid().toString(), contact); } public void setVersion(String version) { diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index d44bf0ca..2f6df523 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -6,6 +6,7 @@ import java.util.List; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.stanzas.IqPacket; @@ -18,7 +19,7 @@ public class IqGenerator extends AbstractGenerator { public IqPacket discoResponse(IqPacket request) { IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT); packet.setId(request.getId()); - packet.setTo(request.getFrom()); + packet.setAttribute("to", request.getFrom()); Element query = packet.addChild("query", "http://jabber.org/protocol/disco#info"); query.setAttribute("node", request.query().getAttribute("node")); @@ -86,8 +87,8 @@ public class IqGenerator extends AbstractGenerator { return packet; } - public IqPacket retrieveAvatarMetaData(String to) { - IqPacket packet = retrieve("urn:xmpp:avatar:metadata", null); + public IqPacket retrieveAvatarMetaData(final Jid to) { + final IqPacket packet = retrieve("urn:xmpp:avatar:metadata", null); if (to != null) { packet.setTo(to); } diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index dd833e56..d53346b0 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -12,6 +12,7 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; public class MessageGenerator extends AbstractGenerator { @@ -34,7 +35,7 @@ public class MessageGenerator extends AbstractGenerator { packet.setTo(message.getCounterpart()); packet.setType(MessagePacket.TYPE_CHAT); } else { - packet.setTo(message.getCounterpart().split("/", 2)[0]); + packet.setTo(message.getCounterpart().toBareJid()); packet.setType(MessagePacket.TYPE_GROUPCHAT); } packet.setFrom(account.getFullJid()); @@ -113,13 +114,13 @@ public class MessageGenerator extends AbstractGenerator { private MessagePacket generateError(MessagePacket origin) { MessagePacket packet = new MessagePacket(); packet.setId(origin.getId()); - packet.setTo(origin.getFrom()); + packet.setAttribute("to", origin.getFrom()); packet.setBody(origin.getBody()); packet.setType(MessagePacket.TYPE_ERROR); return packet; } - public MessagePacket confirm(Account account, String to, String id) { + public MessagePacket confirm(final Account account, final Jid to, final String id) { MessagePacket packet = new MessagePacket(); packet.setType(MessagePacket.TYPE_NORMAL); packet.setTo(to); @@ -134,7 +135,7 @@ public class MessageGenerator extends AbstractGenerator { String subject) { MessagePacket packet = new MessagePacket(); packet.setType(MessagePacket.TYPE_GROUPCHAT); - packet.setTo(conversation.getContactJid().split("/", 2)[0]); + packet.setTo(conversation.getContactJid().toBareJid()); Element subjectChild = new Element("subject"); subjectChild.setContent(subject); packet.addChild(subjectChild); @@ -142,19 +143,19 @@ public class MessageGenerator extends AbstractGenerator { return packet; } - public MessagePacket directInvite(Conversation conversation, String contact) { + public MessagePacket directInvite(final Conversation conversation, final Jid contact) { MessagePacket packet = new MessagePacket(); packet.setType(MessagePacket.TYPE_NORMAL); packet.setTo(contact); packet.setFrom(conversation.getAccount().getFullJid()); Element x = packet.addChild("x", "jabber:x:conference"); - x.setAttribute("jid", conversation.getContactJid().split("/", 2)[0]); + x.setAttribute("jid", conversation.getContactJid().toBareJid().toString()); return packet; } public MessagePacket invite(Conversation conversation, String contact) { MessagePacket packet = new MessagePacket(); - packet.setTo(conversation.getContactJid().split("/", 2)[0]); + packet.setTo(conversation.getContactJid().toBareJid()); packet.setFrom(conversation.getAccount().getFullJid()); Element x = new Element("x"); x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user"); @@ -169,7 +170,7 @@ public class MessageGenerator extends AbstractGenerator { MessagePacket originalMessage, String namespace) { MessagePacket receivedPacket = new MessagePacket(); receivedPacket.setType(MessagePacket.TYPE_NORMAL); - receivedPacket.setTo(originalMessage.getFrom()); + receivedPacket.setAttribute("to", originalMessage.getFrom()); receivedPacket.setFrom(account.getFullJid()); Element received = receivedPacket.addChild("received", namespace); received.setAttribute("id", originalMessage.getId()); diff --git a/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java b/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java index d896dd00..6036c802 100644 --- a/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java @@ -15,8 +15,8 @@ public class PresenceGenerator extends AbstractGenerator { private PresencePacket subscription(String type, Contact contact) { PresencePacket packet = new PresencePacket(); packet.setAttribute("type", type); - packet.setAttribute("to", contact.getJid()); - packet.setAttribute("from", contact.getAccount().getJid()); + packet.setTo(contact.getJid()); + packet.setFrom(contact.getAccount().getJid()); return packet; } @@ -38,7 +38,7 @@ public class PresenceGenerator extends AbstractGenerator { public PresencePacket sendPresence(Account account) { PresencePacket packet = new PresencePacket(); - packet.setAttribute("from", account.getFullJid()); + packet.setFrom(account.getFullJid()); String sig = account.getPgpSignature(); if (sig != null) { packet.addChild("status").setContent("online"); diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 5541c1c6..9e413052 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -11,6 +11,8 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public abstract class AbstractParser { @@ -22,7 +24,7 @@ public abstract class AbstractParser { protected long getTimestamp(Element packet) { long now = System.currentTimeMillis(); - ArrayList stamps = new ArrayList(); + ArrayList stamps = new ArrayList<>(); for (Element child : packet.getChildren()) { if (child.getName().equals("delay")) { stamps.add(child.getAttribute("stamp").replace("Z", "+0000")); @@ -58,21 +60,21 @@ public abstract class AbstractParser { } } - protected void updateLastseen(Element packet, Account account, - boolean presenceOverwrite) { - String[] fromParts = packet.getAttribute("from").split("/", 2); - String from = fromParts[0]; - String presence = null; - if (fromParts.length >= 2) { - presence = fromParts[1]; - } else { - presence = ""; - } + protected void updateLastseen(final Element packet, final Account account, + final boolean presenceOverwrite) { + Jid from; + try { + from = Jid.fromString(packet.getAttribute("from")).toBareJid(); + } catch (final InvalidJidException e) { + // TODO: Handle this? + from = null; + } + String presence = from == null || from.getResourcepart().isEmpty() ? "" : from.getResourcepart(); Contact contact = account.getRoster().getContact(from); long timestamp = getTimestamp(packet); if (timestamp >= contact.lastseen.time) { contact.lastseen.time = timestamp; - if ((presence != null) && (presenceOverwrite)) { + if (!presence.isEmpty() && presenceOverwrite) { contact.lastseen.presence = presence; } } diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index df6754f2..1c66da26 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -5,6 +5,8 @@ import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class IqParser extends AbstractParser implements OnIqPacketReceived { @@ -20,8 +22,14 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { } for (Element item : query.getChildren()) { if (item.getName().equals("item")) { - String jid = item.getAttribute("jid"); - String name = item.getAttribute("name"); + Jid jid; + try { + jid = Jid.fromString(item.getAttribute("jid")); + } catch (final InvalidJidException e) { + // TODO: Handle this? + jid = null; + } + String name = item.getAttribute("name"); String subscription = item.getAttribute("subscription"); Contact contact = account.getRoster().getContact(jid); if (!contact.getOption(Contact.Options.DIRTY_PUSH)) { @@ -59,8 +67,13 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.hasChild("query", "jabber:iq:roster")) { - String from = packet.getFrom(); - if ((from == null) || (from.equals(account.getJid()))) { + Jid from = null; + try { + from = Jid.fromString(packet.getFrom()); + } catch (final InvalidJidException e) { + // TODO: Handle this? + } + if ((from == null) || (from.equals(account.getJid()))) { Element query = packet.findChild("query"); this.rosterItems(account, query); } diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index ef045546..310c8f42 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -9,6 +9,8 @@ import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Roster; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteCantOpenDatabaseException; @@ -147,7 +149,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public CopyOnWriteArrayList getConversations(int status) { - CopyOnWriteArrayList list = new CopyOnWriteArrayList(); + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); String[] selectionArgs = { Integer.toString(status) }; Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME @@ -165,7 +167,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { public ArrayList getMessages(Conversation conversation, int limit, long timestamp) { - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; if (timestamp == -1) { @@ -192,9 +194,9 @@ public class DatabaseBackend extends SQLiteOpenHelper { return list; } - public Conversation findConversation(Account account, String contactJid) { + public Conversation findConversation(final Account account, final Jid contactJid) { SQLiteDatabase db = this.getReadableDatabase(); - String[] selectionArgs = { account.getUuid(), contactJid + "%" }; + String[] selectionArgs = { account.getUuid(), contactJid.toBareJid().toString() + "%" }; Cursor cursor = db.query(Conversation.TABLENAME, null, Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID + " like ?", selectionArgs, null, null, null); @@ -212,7 +214,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public List getAccounts() { - List list = new ArrayList(); + List list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(Account.TABLENAME, null, null, null, null, null, null); @@ -276,15 +278,15 @@ public class DatabaseBackend extends SQLiteOpenHelper { cursor.close(); } - public void writeRoster(Roster roster) { - Account account = roster.getAccount(); - SQLiteDatabase db = this.getWritableDatabase(); + public void writeRoster(final Roster roster) { + final Account account = roster.getAccount(); + final SQLiteDatabase db = this.getWritableDatabase(); for (Contact contact : roster.getContacts()) { if (contact.getOption(Contact.Options.IN_ROSTER)) { db.insert(Contact.TABLENAME, null, contact.getContentValues()); } else { String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?"; - String[] whereArgs = { account.getUuid(), contact.getJid() }; + String[] whereArgs = { account.getUuid(), contact.getJid().toString() }; db.delete(Contact.TABLENAME, where, whereArgs); } } @@ -341,7 +343,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public List getImageMessages(Conversation conversation) { - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; String[] selectionArgs = { conversation.getUuid(), String.valueOf(Message.TYPE_IMAGE) }; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ea6f509f..27268898 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -55,6 +55,8 @@ import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnMessageAcknowledged; import eu.siacs.conversations.xmpp.OnStatusChanged; import eu.siacs.conversations.xmpp.XmppConnection; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; @@ -91,8 +93,6 @@ public class XmppConnectionService extends Service { public DatabaseBackend databaseBackend; private FileBackend fileBackend = new FileBackend(this); - public long startDate; - private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; public static String ACTION_CLEAR_NOTIFICATION = "clear_notification"; @@ -171,7 +171,6 @@ public class XmppConnectionService extends Service { XmppConnection connection = account.getXmppConnection(); if (mOnAccountUpdate != null) { mOnAccountUpdate.onAccountUpdate(); - ; } if (account.getStatus() == Account.STATUS_ONLINE) { for (Conversation conversation : account.pendingConferenceLeaves) { @@ -182,12 +181,12 @@ public class XmppConnectionService extends Service { } mJingleConnectionManager.cancelInTransmission(); List conversations = getConversations(); - for (int i = 0; i < conversations.size(); ++i) { - if (conversations.get(i).getAccount() == account) { - conversations.get(i).startOtrIfNeeded(); - sendUnsendMessages(conversations.get(i)); - } - } + for (Conversation conversation : conversations) { + if (conversation.getAccount() == account) { + conversation.startOtrIfNeeded(); + sendUnsendMessages(conversation); + } + } if (connection != null && connection.getFeatures().csi()) { if (checkListeners()) { Log.d(Config.LOGTAG, account.getJid() @@ -335,7 +334,7 @@ public class XmppConnectionService extends Service { return find(bookmark.getAccount(), bookmark.getJid()); } - public Conversation find(Account account, String jid) { + public Conversation find(final Account account, final Jid jid) { return find(getConversations(), account, jid); } @@ -415,7 +414,7 @@ public class XmppConnectionService extends Service { if (wakeLock.isHeld()) { try { wakeLock.release(); - } catch (RuntimeException re) { + } catch (final RuntimeException ignored) { } } return START_STICKY; @@ -536,9 +535,12 @@ public class XmppConnectionService extends Service { public XmppConnection createConnection(Account account) { SharedPreferences sharedPref = getPreferences(); - account.setResource(sharedPref.getString("resource", "mobile") - .toLowerCase(Locale.getDefault())); - XmppConnection connection = new XmppConnection(account, this); + try { + account.setResource(sharedPref.getString("resource", "mobile") + .toLowerCase(Locale.getDefault())); + } catch (final InvalidJidException ignored) { + } + XmppConnection connection = new XmppConnection(account, this); connection.setOnMessagePacketReceivedListener(this.mMessageParser); connection.setOnStatusChangedListener(this.statusListener); connection.setOnPresencePacketReceivedListener(this.mPresenceParser); @@ -757,7 +759,7 @@ public class XmppConnectionService extends Service { @Override public void onIqPacketReceived(Account account, IqPacket packet) { Element query = packet.query(); - List bookmarks = new CopyOnWriteArrayList(); + List bookmarks = new CopyOnWriteArrayList<>(); Element storage = query.findChild("storage", "storage:bookmarks"); if (storage != null) { @@ -806,8 +808,14 @@ public class XmppConnectionService extends Service { } for (Bundle phoneContact : phoneContacts) { for (Account account : accounts) { - String jid = phoneContact.getString("jid"); - Contact contact = account.getRoster() + Jid jid; + try { + jid = Jid.fromString(phoneContact.getString("jid")); + } catch (final InvalidJidException e) { + // TODO: Warn if contact import fails here? + break; + } + final Contact contact = account.getRoster() .getContact(jid); String systemAccount = phoneContact .getInt("phoneid") @@ -827,7 +835,7 @@ public class XmppConnectionService extends Service { public List getConversations() { if (this.conversations == null) { - Hashtable accountLookupTable = new Hashtable(); + Hashtable accountLookupTable = new Hashtable<>(); for (Account account : this.accounts) { accountLookupTable.put(account.getUuid(), account); } @@ -925,20 +933,20 @@ public class XmppConnectionService extends Service { return null; } - public Conversation find(List haystack, Account account, - String jid) { + public Conversation find(final List haystack, + final Account account, + final Jid jid) { for (Conversation conversation : haystack) { if ((account == null || conversation.getAccount() == account) - && (conversation.getContactJid().split("/", 2)[0] - .equalsIgnoreCase(jid))) { + && (conversation.getContactJid().toBareJid().equals(jid.toBareJid()))) { return conversation; } } return null; } - public Conversation findOrCreateConversation(Account account, String jid, - boolean muc) { + public Conversation findOrCreateConversation(final Account account, final Jid jid, + final boolean muc) { Conversation conversation = find(account, jid); if (conversation != null) { return conversation; @@ -961,7 +969,7 @@ public class XmppConnectionService extends Service { if (contact != null) { conversationName = contact.getDisplayName(); } else { - conversationName = jid.split("@")[0]; + conversationName = jid.getLocalpart(); } if (muc) { conversation = new Conversation(conversationName, account, jid, @@ -1163,13 +1171,12 @@ public class XmppConnectionService extends Service { public void connectMultiModeConversations(Account account) { List conversations = getConversations(); - for (int i = 0; i < conversations.size(); i++) { - Conversation conversation = conversations.get(i); - if ((conversation.getMode() == Conversation.MODE_MULTI) - && (conversation.getAccount() == account)) { - joinMuc(conversation); - } - } + for (Conversation conversation : conversations) { + if ((conversation.getMode() == Conversation.MODE_MULTI) + && (conversation.getAccount() == account)) { + joinMuc(conversation); + } + } } public void joinMuc(Conversation conversation) { @@ -1182,8 +1189,8 @@ public class XmppConnectionService extends Service { String nick = conversation.getMucOptions().getProposedNick(); conversation.getMucOptions().setJoinNick(nick); PresencePacket packet = new PresencePacket(); - String joinJid = conversation.getMucOptions().getJoinJid(); - packet.setAttribute("to", conversation.getMucOptions().getJoinJid()); + final Jid joinJid = conversation.getMucOptions().getJoinJid(); + packet.setTo(conversation.getMucOptions().getJoinJid()); Element x = new Element("x"); x.setAttribute("xmlns", "http://jabber.org/protocol/muc"); if (conversation.getMucOptions().getPassword() != null) { @@ -1260,8 +1267,8 @@ public class XmppConnectionService extends Service { }); options.flagAboutToRename(); PresencePacket packet = new PresencePacket(); - packet.setAttribute("to", options.getJoinJid()); - packet.setAttribute("from", conversation.getAccount().getFullJid()); + packet.setTo(options.getJoinJid()); + packet.setFrom(conversation.getAccount().getFullJid()); String sig = account.getPgpSignature(); if (sig != null) { @@ -1289,8 +1296,8 @@ public class XmppConnectionService extends Service { account.pendingConferenceLeaves.remove(conversation); if (account.getStatus() == Account.STATUS_ONLINE) { PresencePacket packet = new PresencePacket(); - packet.setAttribute("to", conversation.getMucOptions().getJoinJid()); - packet.setAttribute("from", conversation.getAccount().getFullJid()); + packet.setTo(conversation.getMucOptions().getJoinJid()); + packet.setFrom(conversation.getAccount().getFullJid()); packet.setAttribute("type", "unavailable"); sendPresencePacket(conversation.getAccount(), packet); conversation.getMucOptions().setOffline(); @@ -1307,20 +1314,19 @@ public class XmppConnectionService extends Service { || (account.getStatus() == Account.STATUS_DISABLED)) { if (!force) { List conversations = getConversations(); - for (int i = 0; i < conversations.size(); i++) { - Conversation conversation = conversations.get(i); - if (conversation.getAccount() == account) { - if (conversation.getMode() == Conversation.MODE_MULTI) { - leaveMuc(conversation); - } else { - if (conversation.endOtrIfNeeded()) { - Log.d(Config.LOGTAG, account.getJid() - + ": ended otr session with " - + conversation.getContactJid()); - } - } - } - } + for (Conversation conversation : conversations) { + if (conversation.getAccount() == account) { + if (conversation.getMode() == Conversation.MODE_MULTI) { + leaveMuc(conversation); + } else { + if (conversation.endOtrIfNeeded()) { + Log.d(Config.LOGTAG, account.getJid() + + ": ended otr session with " + + conversation.getContactJid()); + } + } + } + } } account.getXmppConnection().disconnect(force); } @@ -1365,24 +1371,23 @@ public class XmppConnectionService extends Service { account.getJid() + " otr session established with " + conversation.getContactJid() + "/" + otrSession.getSessionID().getUserID()); - for (int i = 0; i < messages.size(); ++i) { - Message msg = messages.get(i); - if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING) - && (msg.getEncryption() == Message.ENCRYPTION_OTR)) { - msg.setPresence(otrSession.getSessionID().getUserID()); - if (msg.getType() == Message.TYPE_TEXT) { - MessagePacket outPacket = mMessageGenerator - .generateOtrChat(msg, true); - if (outPacket != null) { - msg.setStatus(Message.STATUS_SEND); - databaseBackend.updateMessage(msg); - sendMessagePacket(account, outPacket); - } - } else if (msg.getType() == Message.TYPE_IMAGE) { - mJingleConnectionManager.createNewConnection(msg); - } - } - } + for (Message msg : messages) { + if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING) + && (msg.getEncryption() == Message.ENCRYPTION_OTR)) { + msg.setPresence(otrSession.getSessionID().getUserID()); + if (msg.getType() == Message.TYPE_TEXT) { + MessagePacket outPacket = mMessageGenerator + .generateOtrChat(msg, true); + if (outPacket != null) { + msg.setStatus(Message.STATUS_SEND); + databaseBackend.updateMessage(msg); + sendMessagePacket(account, outPacket); + } + } else if (msg.getType() == Message.TYPE_IMAGE) { + mJingleConnectionManager.createNewConnection(msg); + } + } + } updateConversationUi(); } @@ -1397,8 +1402,8 @@ public class XmppConnectionService extends Service { packet.setFrom(account.getFullJid()); packet.addChild("private", "urn:xmpp:carbons:2"); packet.addChild("no-copy", "urn:xmpp:hints"); - packet.setTo(otrSession.getSessionID().getAccountID() + "/" - + otrSession.getSessionID().getUserID()); + packet.setAttribute("to", otrSession.getSessionID().getAccountID() + "/" + + otrSession.getSessionID().getUserID()); try { packet.setBody(otrSession .transformSending(CryptoHelper.FILETRANSFER @@ -1596,7 +1601,7 @@ public class XmppConnectionService extends Service { if (account.getStatus() == Account.STATUS_ONLINE) { IqPacket iq = new IqPacket(IqPacket.TYPE_SET); Element item = iq.query("jabber:iq:roster").addChild("item"); - item.setAttribute("jid", contact.getJid()); + item.setAttribute("jid", contact.getJid().toString()); item.setAttribute("subscription", "remove"); account.getXmppConnection().sendIqPacket(iq, null); } @@ -1648,8 +1653,8 @@ public class XmppConnectionService extends Service { } } - public boolean markMessage(Account account, String recipient, String uuid, - int status) { + public boolean markMessage(final Account account, final Jid recipient, final String uuid, + final int status) { if (uuid == null) { return false; } else { @@ -1730,7 +1735,7 @@ public class XmppConnectionService extends Service { } } - public Account findAccountByJid(String accountJid) { + public Account findAccountByJid(final Jid accountJid) { for (Account account : this.accounts) { if (account.getJid().equals(accountJid)) { return account; @@ -1756,7 +1761,7 @@ public class XmppConnectionService extends Service { Log.d(Config.LOGTAG, conversation.getAccount().getJid() + ": sending read marker for " + conversation.getName()); Account account = conversation.getAccount(); - String to = conversation.getContactJid(); + final Jid to = conversation.getContactJid(); this.sendMessagePacket(conversation.getAccount(), mMessageGenerator.confirm(account, to, id)); } @@ -1810,14 +1815,14 @@ public class XmppConnectionService extends Service { } public List getKnownHosts() { - List hosts = new ArrayList(); + List hosts = new ArrayList<>(); for (Account account : getAccounts()) { - if (!hosts.contains(account.getServer())) { - hosts.add(account.getServer()); + if (!hosts.contains(account.getServer().toString())) { + hosts.add(account.getServer().toString()); } for (Contact contact : account.getRoster().getContacts()) { if (contact.showInRoster()) { - String server = contact.getServer(); + final String server = contact.getServer().toString(); if (server != null && !hosts.contains(server)) { hosts.add(server); } @@ -1828,7 +1833,7 @@ public class XmppConnectionService extends Service { } public List getKnownConferenceHosts() { - ArrayList mucServers = new ArrayList(); + ArrayList mucServers = new ArrayList<>(); for (Account account : accounts) { if (account.getXmppConnection() != null) { String server = account.getXmppConnection().getMucServer(); @@ -1891,7 +1896,7 @@ public class XmppConnectionService extends Service { } public List findContacts(String jid) { - ArrayList contacts = new ArrayList(); + ArrayList contacts = new ArrayList<>(); for (Account account : getAccounts()) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { Contact contact = account.getRoster().getContactFromRoster(jid); @@ -1931,7 +1936,7 @@ public class XmppConnectionService extends Service { } public void resendFailedMessages(Message message) { - List messages = new ArrayList(); + List messages = new ArrayList<>(); Message current = message; while(current.getStatus() == Message.STATUS_SEND_FAILED) { messages.add(current); diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index f101e883..8c1a8dea 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -11,6 +11,7 @@ import de.measite.minidns.record.AAAA; import de.measite.minidns.record.Data; import de.measite.minidns.util.NameUtil; import eu.siacs.conversations.Config; +import eu.siacs.conversations.xmpp.jid.Jid; import java.io.IOException; import java.net.InetAddress; @@ -26,7 +27,8 @@ import android.util.Log; public class DNSHelper { protected static Client client = new Client(); - public static Bundle getSRVRecord(String host) throws IOException { + public static Bundle getSRVRecord(final Jid jid) throws IOException { + final String host = jid.getDomainpart(); String dns[] = client.findDNS(); if (dns != null) { @@ -62,9 +64,9 @@ public class DNSHelper { // a random order respecting the weight, and dump that priority by // priority - TreeMap> priorities = new TreeMap>(); - TreeMap> ips4 = new TreeMap>(); - TreeMap> ips6 = new TreeMap>(); + TreeMap> priorities = new TreeMap<>(); + TreeMap> ips4 = new TreeMap<>(); + TreeMap> ips6 = new TreeMap<>(); for (Record[] rrset : new Record[][] { message.getAnswers(), message.getAdditionalResourceRecords() }) { @@ -97,7 +99,7 @@ public class DNSHelper { } Random rnd = new Random(); - ArrayList result = new ArrayList( + ArrayList result = new ArrayList<>( priorities.size() * 2 + 1); for (ArrayList s : priorities.values()) { @@ -136,7 +138,7 @@ public class DNSHelper { bundle.putString("error", "nosrv"); return bundle; } - ArrayList values = new ArrayList(); + ArrayList values = new ArrayList<>(); for (SRV srv : result) { Bundle namePort = new Bundle(); namePort.putString("name", srv.getName()); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 2b9d6632..9c160384 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -48,6 +48,8 @@ import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Tag; import eu.siacs.conversations.xml.TagWriter; import eu.siacs.conversations.xml.XmlReader; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; @@ -76,10 +78,12 @@ public class XmppConnection implements Runnable { private boolean shouldBind = true; private boolean shouldAuthenticate = true; private Element streamFeatures; - private HashMap> disco = new HashMap>(); + private HashMap> disco = new HashMap<>(); + private String streamId = null; private int smVersion = 3; - private SparseArray messageReceipts = new SparseArray(); + private SparseArray messageReceipts = new SparseArray<>(); + private boolean usingCompression = false; private boolean usingEncryption = false; private int stanzasReceived = 0; @@ -89,7 +93,7 @@ public class XmppConnection implements Runnable { private long lastConnect = 0; private long lastSessionStarted = 0; private int attempt = 0; - private Hashtable packetCallbacks = new Hashtable(); + private Hashtable packetCallbacks = new Hashtable<>(); private OnPresencePacketReceived presenceListener = null; private OnJinglePacketReceived jingleListener = null; private OnIqPacketReceived unregisteredIqListener = null; @@ -102,7 +106,7 @@ public class XmppConnection implements Runnable { public XmppConnection(Account account, XmppConnectionService service) { this.account = account; this.wakeLock = service.getPowerManager().newWakeLock( - PowerManager.PARTIAL_WAKE_LOCK, account.getJid()); + PowerManager.PARTIAL_WAKE_LOCK, account.getJid().toString()); tagWriter = new TagWriter(); mXmppConnectionService = service; applicationContext = service.getApplicationContext(); @@ -127,7 +131,7 @@ public class XmppConnection implements Runnable { } protected void connect() { - Log.d(Config.LOGTAG, account.getJid() + ": connecting"); + Log.d(Config.LOGTAG, account.getJid().toString() + ": connecting"); usingCompression = false; usingEncryption = false; lastConnect = SystemClock.elapsedRealtime(); @@ -143,7 +147,7 @@ public class XmppConnection implements Runnable { Bundle result = DNSHelper.getSRVRecord(account.getServer()); ArrayList values = result.getParcelableArrayList("values"); if ("timeout".equals(result.getString("error"))) { - Log.d(Config.LOGTAG, account.getJid() + ": dns timeout"); + Log.d(Config.LOGTAG, account.getJid().toString() + ": dns timeout"); this.changeStatus(Account.STATUS_OFFLINE); return; } else if (values != null) { @@ -158,12 +162,12 @@ public class XmppConnection implements Runnable { InetSocketAddress addr; if (srvIpServer != null) { addr = new InetSocketAddress(srvIpServer, srvRecordPort); - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": using values from dns " + srvRecordServer + "[" + srvIpServer + "]:" + srvRecordPort); } else { addr = new InetSocketAddress(srvRecordServer, srvRecordPort); - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": using values from dns " + srvRecordServer + ":" + srvRecordPort); } @@ -171,10 +175,10 @@ public class XmppConnection implements Runnable { socket.connect(addr, 20000); socketError = false; } catch (UnknownHostException e) { - Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); + Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage()); i++; } catch (IOException e) { - Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); + Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage()); i++; } } @@ -183,16 +187,16 @@ public class XmppConnection implements Runnable { if (wakeLock.isHeld()) { try { wakeLock.release(); - } catch (RuntimeException re) { + } catch (final RuntimeException ignored) { } } return; } } else if (result.containsKey("error") && "nosrv".equals(result.getString("error", null))) { - socket = new Socket(account.getServer(), 5222); + socket = new Socket(account.getServer().getDomainpart(), 5222); } else { - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": timeout in DNS resolution"); changeStatus(Account.STATUS_OFFLINE); return; @@ -222,51 +226,38 @@ public class XmppConnection implements Runnable { if (wakeLock.isHeld()) { try { wakeLock.release(); - } catch (RuntimeException re) { + } catch (final RuntimeException ignored) { } } - return; - } catch (IOException e) { - Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); + } catch (final IOException | XmlPullParserException e) { + Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage()); this.changeStatus(Account.STATUS_OFFLINE); if (wakeLock.isHeld()) { try { wakeLock.release(); - } catch (RuntimeException re) { + } catch (final RuntimeException ignored) { } } - return; - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); + } catch (NoSuchAlgorithmException e) { + Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage()); this.changeStatus(Account.STATUS_OFFLINE); Log.d(Config.LOGTAG, "compression exception " + e.getMessage()); if (wakeLock.isHeld()) { try { wakeLock.release(); - } catch (RuntimeException re) { + } catch (final RuntimeException ignored) { } } - return; - } catch (XmlPullParserException e) { - Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); - this.changeStatus(Account.STATUS_OFFLINE); - if (wakeLock.isHeld()) { - try { - wakeLock.release(); - } catch (RuntimeException re) { - } - } - return; - } + } - } + } @Override public void run() { connect(); } - private void processStream(Tag currentTag) throws XmlPullParserException, + private void processStream(final Tag currentTag) throws XmlPullParserException, IOException, NoSuchAlgorithmException { Tag nextTag = tagReader.readTag(); while ((nextTag != null) && (!nextTag.isEnd("stream"))) { @@ -279,7 +270,7 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("compressed")) { switchOverToZLib(nextTag); } else if (nextTag.isStart("success")) { - Log.d(Config.LOGTAG, account.getJid() + ": logged in"); + Log.d(Config.LOGTAG, account.getJid().toString() + ": logged in"); tagReader.readTag(); tagReader.reset(); sendStartStream(); @@ -300,11 +291,11 @@ public class XmppConnection implements Runnable { Element enabled = tagReader.readElement(nextTag); if ("true".equals(enabled.getAttribute("resume"))) { this.streamId = enabled.getAttribute("id"); - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": stream managment(" + smVersion + ") enabled (resumable)"); } else { - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": stream managment(" + smVersion + ") enabled"); } this.lastSessionStarted = SystemClock.elapsedRealtime(); @@ -318,11 +309,11 @@ public class XmppConnection implements Runnable { try { int serverCount = Integer.parseInt(h); if (serverCount != stanzasSent) { - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": session resumed with lost packages"); stanzasSent = serverCount; } else { - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": session resumed"); } if (acknowledgedListener != null) { @@ -334,7 +325,7 @@ public class XmppConnection implements Runnable { } } messageReceipts.clear(); - } catch (NumberFormatException e) { + } catch (final NumberFormatException ignored) { } sendInitialPing(); @@ -357,7 +348,7 @@ public class XmppConnection implements Runnable { } } else if (nextTag.isStart("failed")) { tagReader.readElement(nextTag); - Log.d(Config.LOGTAG, account.getJid() + ": resumption failed"); + Log.d(Config.LOGTAG, account.getJid().toString() + ": resumption failed"); streamId = null; if (account.getStatus() != Account.STATUS_ONLINE) { sendBindRequest(); @@ -380,7 +371,7 @@ public class XmppConnection implements Runnable { } private void sendInitialPing() { - Log.d(Config.LOGTAG, account.getJid() + ": sending intial ping"); + Log.d(Config.LOGTAG, account.getJid().toString() + ": sending intial ping"); IqPacket iq = new IqPacket(IqPacket.TYPE_GET); iq.setFrom(account.getFullJid()); iq.addChild("ping", "urn:xmpp:ping"); @@ -388,7 +379,7 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid().toString() + ": online with resource " + account.getResource()); changeStatus(Account.STATUS_ONLINE); } @@ -507,7 +498,7 @@ public class XmppConnection implements Runnable { tagWriter.writeElement(compress); } - private void switchOverToZLib(Tag currentTag) + private void switchOverToZLib(final Tag currentTag) throws XmlPullParserException, IOException, NoSuchAlgorithmException { tagReader.readTag(); // read tag close @@ -537,7 +528,7 @@ public class XmppConnection implements Runnable { return getPreferences().getBoolean("enable_legacy_ssl", false); } - private void switchOverToTls(Tag currentTag) throws XmlPullParserException, + private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException { tagReader.readTag(); try { @@ -551,24 +542,23 @@ public class XmppConnection implements Runnable { throw new IOException("SSLSocketFactory was null"); } - HostnameVerifier verifier = this.mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier()); + final HostnameVerifier verifier = this.mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier()); if (socket == null) { throw new IOException("socket was null"); } - SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, + final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); // Support all protocols except legacy SSL. // The min SDK version prevents us having to worry about SSLv2. In - // future, this may be - // true of SSLv3 as well. + // future, this may be true of SSLv3 as well. final String[] supportProtocols; if (enableLegacySSL()) { supportProtocols = sslSocket.getSupportedProtocols(); } else { - final List supportedProtocols = new LinkedList( + final List supportedProtocols = new LinkedList<>( Arrays.asList(sslSocket.getSupportedProtocols())); supportedProtocols.remove("SSLv3"); supportProtocols = new String[supportedProtocols.size()]; @@ -577,7 +567,7 @@ public class XmppConnection implements Runnable { sslSocket.setEnabledProtocols(supportProtocols); if (verifier != null - && !verifier.verify(account.getServer(), + && !verifier.verify(account.getServer().getDomainpart(), sslSocket.getSession())) { sslSocket.close(); throw new IOException("host mismatch in TLS connection"); @@ -590,12 +580,10 @@ public class XmppConnection implements Runnable { usingEncryption = true; processStream(tagReader.readTag()); sslSocket.close(); - } catch (NoSuchAlgorithmException e1) { + } catch (final NoSuchAlgorithmException | KeyManagementException e1) { e1.printStackTrace(); - } catch (KeyManagementException e) { - e.printStackTrace(); } - } + } private void sendSaslAuthPlain() throws IOException { String saslString = CryptoHelper.saslPlain(account.getUsername(), @@ -676,7 +664,7 @@ public class XmppConnection implements Runnable { } private List extractMechanisms(Element stream) { - ArrayList mechanisms = new ArrayList(stream + ArrayList mechanisms = new ArrayList<>(stream .getChildren().size()); for (Element child : stream.getChildren()) { mechanisms.add(child.getContent()); @@ -742,10 +730,14 @@ public class XmppConnection implements Runnable { public void onIqPacketReceived(Account account, IqPacket packet) { Element bind = packet.findChild("bind"); if (bind != null) { - Element jid = bind.findChild("jid"); + final Element jid = bind.findChild("jid"); if (jid != null && jid.getContent() != null) { - account.setResource(jid.getContent().split("/", 2)[1]); - if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { + try { + account.setResource(Jid.fromString(jid.getContent()).getResourcepart()); + } catch (final InvalidJidException e) { + // TODO: Handle the case where an external JID is technically invalid? + } + if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { smVersion = 3; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); @@ -783,24 +775,24 @@ public class XmppConnection implements Runnable { } } - private void sendServiceDiscoveryInfo(final String server) { - IqPacket iq = new IqPacket(IqPacket.TYPE_GET); - iq.setTo(server); + private void sendServiceDiscoveryInfo(final Jid server) { + final IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#info"); this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - List elements = packet.query().getChildren(); - List features = new ArrayList(); - for (int i = 0; i < elements.size(); ++i) { - if (elements.get(i).getName().equals("feature")) { - features.add(elements.get(i).getAttribute("var")); - } - } - disco.put(server, features); + final List elements = packet.query().getChildren(); + final List features = new ArrayList<>(); + for (Element element : elements) { + if (element.getName().equals("feature")) { + features.add(element.getAttribute("var")); + } + } + disco.put(server.toDomainJid().toString(), features); - if (account.getServer().equals(server)) { + if (account.getServer().equals(server.toDomainJid())) { enableAdvancedStreamFeatures(); } } @@ -813,21 +805,25 @@ public class XmppConnection implements Runnable { } } - private void sendServiceDiscoveryItems(final String server) { - IqPacket iq = new IqPacket(IqPacket.TYPE_GET); - iq.setTo(server); + private void sendServiceDiscoveryItems(final Jid server) { + final IqPacket iq = new IqPacket(IqPacket.TYPE_GET); + iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#items"); this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { List elements = packet.query().getChildren(); - for (int i = 0; i < elements.size(); ++i) { - if (elements.get(i).getName().equals("item")) { - String jid = elements.get(i).getAttribute("jid"); - sendServiceDiscoveryInfo(jid); - } - } + for (Element element : elements) { + if (element.getName().equals("item")) { + final String jid = element.getAttribute("jid"); + try { + sendServiceDiscoveryInfo(Jid.fromString(jid).toDomainJid()); + } catch (final InvalidJidException ignored) { + // TODO: Handle the case where an external JID is technically invalid? + } + } + } } }); } @@ -854,9 +850,13 @@ public class XmppConnection implements Runnable { throws XmlPullParserException, IOException { Element streamError = tagReader.readElement(currentTag); if (streamError != null && streamError.hasChild("conflict")) { - String resource = account.getResource().split("\\.")[0]; - account.setResource(resource + "." + nextRandomId()); - Log.d(Config.LOGTAG, + final String resource = account.getResource().split("\\.")[0]; + try { + account.setResource(resource + "." + nextRandomId()); + } catch (final InvalidJidException ignored) { + // Should never reach here. + } + Log.d(Config.LOGTAG, account.getJid() + ": switching resource due to conflict (" + account.getResource() + ")"); } @@ -864,8 +864,8 @@ public class XmppConnection implements Runnable { private void sendStartStream() throws IOException { Tag stream = Tag.start("stream:stream"); - stream.setAttribute("from", account.getJid()); - stream.setAttribute("to", account.getServer()); + stream.setAttribute("from", account.getJid().toString()); + stream.setAttribute("to", account.getServer().toString()); stream.setAttribute("version", "1.0"); stream.setAttribute("xml:lang", "en"); stream.setAttribute("xmlns", "jabber:client"); @@ -1003,7 +1003,7 @@ public class XmppConnection implements Runnable { } public List findDiscoItemsByFeature(String feature) { - List items = new ArrayList(); + final List items = new ArrayList<>(); for (Entry> cursor : disco.entrySet()) { if (cursor.getValue().contains(feature)) { items.add(cursor.getKey()); @@ -1079,12 +1079,10 @@ public class XmppConnection implements Runnable { this.connection = connection; } - private boolean hasDiscoFeature(String server, String feature) { - if (!connection.disco.containsKey(server)) { - return false; - } - return connection.disco.get(server).contains(feature); - } + private boolean hasDiscoFeature(final Jid server, final String feature) { + return connection.disco.containsKey(server.toDomainJid().toString()) && + connection.disco.get(server.toDomainJid().toString()).contains(feature); + } public boolean carbons() { return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2"); @@ -1095,12 +1093,7 @@ public class XmppConnection implements Runnable { } public boolean csi() { - if (connection.streamFeatures == null) { - return false; - } else { - return connection.streamFeatures.hasChild("csi", - "urn:xmpp:csi:0"); - } + return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0"); } public boolean pubsub() { @@ -1113,11 +1106,7 @@ public class XmppConnection implements Runnable { } public boolean rosterVersioning() { - if (connection.streamFeatures == null) { - return false; - } else { - return connection.streamFeatures.hasChild("ver"); - } + return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver"); } public boolean streamhost() { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 7d8f702f..2bbde7ab 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -19,7 +19,7 @@ public final class Jid { private final String displayjid; public String getLocalpart() { - return IDN.toUnicode(localpart); + return localpart; } public String getDomainpart() { @@ -27,10 +27,10 @@ public final class Jid { } public String getResourcepart() { - return IDN.toUnicode(resourcepart); + return resourcepart; } - public Jid fromString(final String jid) throws InvalidJidException { + public static Jid fromString(final String jid) throws InvalidJidException { return new Jid(jid); } @@ -121,11 +121,20 @@ public final class Jid { this.displayjid = finaljid; } - public Jid getBareJid() { + public Jid toBareJid() { try { return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, ""); } catch (final InvalidJidException e) { - // This should never happen due to the contracts we have in place. + // This should never happen. + return null; + } + } + + public Jid toDomainJid() { + try { + return resourcepart.isEmpty() && localpart.isEmpty() ? this : fromString(getDomainpart()); + } catch (final InvalidJidException e) { + // This should never happen. return null; } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java b/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java index 154fadf6..9f5ac988 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java +++ b/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java @@ -1,6 +1,8 @@ package eu.siacs.conversations.xmpp.pep; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.util.Base64; public class Avatar { @@ -10,7 +12,7 @@ public class Avatar { public int height; public int width; public long size; - public String owner; + public Jid owner; public byte[] getImageAsBytes() { return Base64.decode(image, Base64.DEFAULT); diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java index eef41c79..ea8f64a9 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp.stanzas; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; public class AbstractStanza extends Element { @@ -20,15 +21,15 @@ public class AbstractStanza extends Element { return this.getAttribute("id"); } - public void setTo(String to) { - setAttribute("to", to); + public void setTo(final Jid to) { + setAttribute("to", to.toString()); } - public void setFrom(String from) { - setAttribute("from", from); + public void setFrom(final Jid from) { + setAttribute("from", from.toString()); } - public void setId(String id) { + public void setId(final String id) { setAttribute("id", id); } } From f15900426d4713b48eb96e0ad0b1cdda5a86becf Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:10:03 -0500 Subject: [PATCH 06/22] Update more files to use JID objects --- .../conversations/entities/MucOptions.java | 6 +- .../siacs/conversations/parser/IqParser.java | 7 +- .../conversations/parser/MessageParser.java | 93 ++++++++++--------- .../conversations/parser/PresenceParser.java | 27 +++--- .../eu/siacs/conversations/xml/Element.java | 42 ++++++++- .../eu/siacs/conversations/xmpp/jid/Jid.java | 4 + .../xmpp/jingle/JingleCandidate.java | 31 ++++--- .../xmpp/jingle/JingleConnection.java | 25 ++--- .../xmpp/jingle/JingleConnectionManager.java | 18 ++-- .../xmpp/jingle/JingleInbandTransport.java | 13 ++- .../xmpp/jingle/stanzas/JinglePacket.java | 5 +- .../xmpp/stanzas/AbstractStanza.java | 21 +++-- 12 files changed, 178 insertions(+), 114 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index f83387fc..166b6b68 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -152,9 +152,9 @@ public class MucOptions { } public void processPacket(PresencePacket packet, PgpEngine pgp) { - String[] fromParts = packet.getFrom().split("/", 2); - if (fromParts.length >= 2) { - String name = fromParts[1]; + final Jid from = packet.getFrom(); + if (!from.isBareJid()) { + final String name = from.getResourcepart(); String type = packet.getAttribute("type"); if (type == null) { User user = new User(); diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 1c66da26..b864329e 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -67,12 +67,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.hasChild("query", "jabber:iq:roster")) { - Jid from = null; - try { - from = Jid.fromString(packet.getFrom()); - } catch (final InvalidJidException e) { - // TODO: Handle this? - } + final Jid from = packet.getFrom(); if ((from == null) || (from.equals(account.getJid()))) { Element query = packet.findChild("query"); this.rosterItems(account, query); diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 7fab1b1b..9796814b 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -11,6 +11,8 @@ import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnMessagePacketReceived; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; @@ -21,9 +23,9 @@ public class MessageParser extends AbstractParser implements } private Message parseChat(MessagePacket packet, Account account) { - String[] fromParts = packet.getFrom().split("/", 2); + final Jid jid = packet.getFrom().toBareJid(); Conversation conversation = mXmppConnectionService - .findOrCreateConversation(account, fromParts[0], false); + .findOrCreateConversation(account, jid.toBareJid(), false); updateLastseen(packet, account, true); String pgpBody = getPgpBody(packet); Message finishedMessage; @@ -38,11 +40,11 @@ public class MessageParser extends AbstractParser implements finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.markable = isMarkable(packet); if (conversation.getMode() == Conversation.MODE_MULTI - && fromParts.length >= 2) { + && !jid.getResourcepart().isEmpty()) { finishedMessage.setType(Message.TYPE_PRIVATE); - finishedMessage.setPresence(fromParts[1]); + finishedMessage.setPresence(jid.getResourcepart()); finishedMessage.setTrueCounterpart(conversation.getMucOptions() - .getTrueCounterpart(fromParts[1])); + .getTrueCounterpart(jid.getResourcepart())); if (conversation.hasDuplicateMessage(finishedMessage)) { return null; } @@ -53,16 +55,16 @@ public class MessageParser extends AbstractParser implements } private Message parseOtrChat(MessagePacket packet, Account account) { - boolean properlyAddressed = (packet.getTo().split("/", 2).length == 2) + boolean properlyAddressed = (!packet.getTo().isBareJid()) || (account.countPresences() == 1); - String[] fromParts = packet.getFrom().split("/", 2); + final Jid from = packet.getFrom(); Conversation conversation = mXmppConnectionService - .findOrCreateConversation(account, fromParts[0], false); + .findOrCreateConversation(account, from.toBareJid(), false); String presence; - if (fromParts.length >= 2) { - presence = fromParts[1]; + if (from.isBareJid()) { + presence = ""; } else { - presence = ""; + presence = from.getResourcepart(); } updateLastseen(packet, account, true); String body = packet.getBody(); @@ -127,24 +129,23 @@ public class MessageParser extends AbstractParser implements private Message parseGroupchat(MessagePacket packet, Account account) { int status; - String[] fromParts = packet.getFrom().split("/", 2); + final Jid from = packet.getFrom(); if (mXmppConnectionService.find(account.pendingConferenceLeaves, - account, fromParts[0]) != null) { + account, from.toBareJid()) != null) { return null; } Conversation conversation = mXmppConnectionService - .findOrCreateConversation(account, fromParts[0], true); + .findOrCreateConversation(account, from.toBareJid(), true); if (packet.hasChild("subject")) { conversation.getMucOptions().setSubject( packet.findChild("subject").getContent()); mXmppConnectionService.updateConversationUi(); return null; } - if ((fromParts.length == 1)) { + if (from.isBareJid()) { return null; } - String counterPart = fromParts[1]; - if (counterPart.equals(conversation.getMucOptions().getActualNick())) { + if (from.getResourcepart().equals(conversation.getMucOptions().getActualNick())) { if (mXmppConnectionService.markMessage(conversation, packet.getId(), Message.STATUS_SEND)) { return null; @@ -157,17 +158,17 @@ public class MessageParser extends AbstractParser implements String pgpBody = getPgpBody(packet); Message finishedMessage; if (pgpBody == null) { - finishedMessage = new Message(conversation, counterPart, + finishedMessage = new Message(conversation, from, packet.getBody(), Message.ENCRYPTION_NONE, status); } else { - finishedMessage = new Message(conversation, counterPart, pgpBody, + finishedMessage = new Message(conversation, from, pgpBody, Message.ENCRYPTION_PGP, status); } finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.markable = isMarkable(packet); if (status == Message.STATUS_RECEIVED) { finishedMessage.setTrueCounterpart(conversation.getMucOptions() - .getTrueCounterpart(counterPart)); + .getTrueCounterpart(from.getResourcepart())); } if (packet.hasChild("delay") && conversation.hasDuplicateMessage(finishedMessage)) { @@ -177,9 +178,9 @@ public class MessageParser extends AbstractParser implements return finishedMessage; } - private Message parseCarbonMessage(MessagePacket packet, Account account) { + private Message parseCarbonMessage(final MessagePacket packet, final Account account) { int status; - String fullJid; + final Jid fullJid; Element forwarded; if (packet.hasChild("received", "urn:xmpp:carbons:2")) { forwarded = packet.findChild("received", "urn:xmpp:carbons:2") @@ -205,11 +206,11 @@ public class MessageParser extends AbstractParser implements parseNonMessage(message, account); } else if (status == Message.STATUS_SEND && message.hasChild("displayed", "urn:xmpp:chat-markers:0")) { - String to = message.getAttribute("to"); + final Jid to = message.getTo(); if (to != null) { - Conversation conversation = mXmppConnectionService.find( + final Conversation conversation = mXmppConnectionService.find( mXmppConnectionService.getConversations(), account, - to.split("/")[0]); + to.toBareJid()); if (conversation != null) { mXmppConnectionService.markRead(conversation, false); } @@ -218,21 +219,20 @@ public class MessageParser extends AbstractParser implements return null; } if (status == Message.STATUS_RECEIVED) { - fullJid = message.getAttribute("from"); + fullJid = message.getFrom(); if (fullJid == null) { return null; } else { updateLastseen(message, account, true); } } else { - fullJid = message.getAttribute("to"); + fullJid = message.getTo(); if (fullJid == null) { return null; } } - String[] parts = fullJid.split("/", 2); Conversation conversation = mXmppConnectionService - .findOrCreateConversation(account, parts[0], false); + .findOrCreateConversation(account, fullJid.toBareJid(), false); String pgpBody = getPgpBody(message); Message finishedMessage; if (pgpBody != null) { @@ -247,11 +247,11 @@ public class MessageParser extends AbstractParser implements finishedMessage.setRemoteMsgId(message.getAttribute("id")); finishedMessage.markable = isMarkable(message); if (conversation.getMode() == Conversation.MODE_MULTI - && parts.length >= 2) { + && !fullJid.isBareJid()) { finishedMessage.setType(Message.TYPE_PRIVATE); - finishedMessage.setPresence(parts[1]); + finishedMessage.setPresence(fullJid.getResourcepart()); finishedMessage.setTrueCounterpart(conversation.getMucOptions() - .getTrueCounterpart(parts[1])); + .getTrueCounterpart(fullJid.getResourcepart())); if (conversation.hasDuplicateMessage(finishedMessage)) { return null; } @@ -259,39 +259,39 @@ public class MessageParser extends AbstractParser implements return finishedMessage; } - private void parseError(MessagePacket packet, Account account) { - String[] fromParts = packet.getFrom().split("/", 2); - mXmppConnectionService.markMessage(account, fromParts[0], + private void parseError(final MessagePacket packet, final Account account) { + final Jid from = packet.getFrom(); + mXmppConnectionService.markMessage(account, from.toBareJid(), packet.getId(), Message.STATUS_SEND_FAILED); } private void parseNonMessage(Element packet, Account account) { - String from = packet.getAttribute("from"); + final Jid from = packet.getFrom(); if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) { Element event = packet.findChild("event", "http://jabber.org/protocol/pubsub#event"); - parseEvent(event, packet.getAttribute("from"), account); + parseEvent(event, from, account); } else if (from != null && packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) { String id = packet .findChild("displayed", "urn:xmpp:chat-markers:0") .getAttribute("id"); updateLastseen(packet, account, true); - mXmppConnectionService.markMessage(account, from.split("/", 2)[0], + mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_DISPLAYED); } else if (from != null && packet.hasChild("received", "urn:xmpp:chat-markers:0")) { String id = packet.findChild("received", "urn:xmpp:chat-markers:0") .getAttribute("id"); updateLastseen(packet, account, false); - mXmppConnectionService.markMessage(account, from.split("/", 2)[0], + mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_RECEIVED); } else if (from != null && packet.hasChild("received", "urn:xmpp:receipts")) { String id = packet.findChild("received", "urn:xmpp:receipts") .getAttribute("id"); updateLastseen(packet, account, false); - mXmppConnectionService.markMessage(account, from.split("/", 2)[0], + mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_RECEIVED); } else if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { Element x = packet.findChild("x", @@ -299,7 +299,7 @@ public class MessageParser extends AbstractParser implements if (x.hasChild("invite")) { Conversation conversation = mXmppConnectionService .findOrCreateConversation(account, - packet.getAttribute("from"), true); + packet.getFrom(), true); if (!conversation.getMucOptions().online()) { if (x.hasChild("password")) { Element password = x.findChild("password"); @@ -314,8 +314,13 @@ public class MessageParser extends AbstractParser implements } } else if (packet.hasChild("x", "jabber:x:conference")) { Element x = packet.findChild("x", "jabber:x:conference"); - String jid = x.getAttribute("jid"); - String password = x.getAttribute("password"); + Jid jid; + try { + jid = Jid.fromString(x.getAttribute("jid")); + } catch (InvalidJidException e) { + jid = null; + } + String password = x.getAttribute("password"); if (jid != null) { Conversation conversation = mXmppConnectionService .findOrCreateConversation(account, jid, true); @@ -332,7 +337,7 @@ public class MessageParser extends AbstractParser implements } } - private void parseEvent(Element event, String from, Account account) { + private void parseEvent(final Element event, final Jid from, final Account account) { Element items = event.findChild("items"); String node = items.getAttribute("node"); if (node != null) { diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 4e90cda8..8393585e 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -9,6 +9,7 @@ import eu.siacs.conversations.generator.PresenceGenerator; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnPresencePacketReceived; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; public class PresenceParser extends AbstractParser implements @@ -21,8 +22,8 @@ public class PresenceParser extends AbstractParser implements public void parseConferencePresence(PresencePacket packet, Account account) { PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine(); if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { - Conversation muc = mXmppConnectionService.find(account, packet - .getAttribute("from").split("/", 2)[0]); + final Conversation muc = mXmppConnectionService.find(account, + packet.getFrom().toBareJid()); if (muc != null) { boolean before = muc.getMucOptions().online(); muc.getMucOptions().processPacket(packet, mPgpEngine); @@ -32,8 +33,8 @@ public class PresenceParser extends AbstractParser implements mXmppConnectionService.getAvatarService().clear(muc); } } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { - Conversation muc = mXmppConnectionService.find(account, packet - .getAttribute("from").split("/", 2)[0]); + final Conversation muc = mXmppConnectionService.find(account, + packet.getFrom().toBareJid()); if (muc != null) { boolean before = muc.getMucOptions().online(); muc.getMucOptions().processPacket(packet, mPgpEngine); @@ -51,15 +52,15 @@ public class PresenceParser extends AbstractParser implements if (packet.getFrom() == null) { return; } - String[] fromParts = packet.getFrom().split("/", 2); + final Jid from = packet.getFrom(); String type = packet.getAttribute("type"); - if (fromParts[0].equals(account.getJid())) { - if (fromParts.length == 2) { + if (from.toBareJid().equals(account.getJid())) { + if (!from.getResourcepart().isEmpty()) { if (type == null) { - account.updatePresence(fromParts[1], + account.updatePresence(from.getResourcepart(), Presences.parseShow(packet.findChild("show"))); } else if (type.equals("unavailable")) { - account.removePresence(fromParts[1]); + account.removePresence(from.getResourcepart()); account.deactivateGracePeriod(); } } @@ -67,8 +68,8 @@ public class PresenceParser extends AbstractParser implements Contact contact = account.getRoster().getContact(packet.getFrom()); if (type == null) { String presence; - if (fromParts.length >= 2) { - presence = fromParts[1]; + if (!from.getResourcepart().isEmpty()) { + presence = from.getResourcepart(); } else { presence = ""; } @@ -95,10 +96,10 @@ public class PresenceParser extends AbstractParser implements mXmppConnectionService.onContactStatusChanged .onContactStatusChanged(contact, online); } else if (type.equals("unavailable")) { - if (fromParts.length != 2) { + if (from.isBareJid()) { contact.clearPresences(); } else { - contact.removePresence(fromParts[1]); + contact.removePresence(from.getResourcepart()); } mXmppConnectionService.onContactStatusChanged .onContactStatusChanged(contact, false); diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index 4e11ee2c..31edec52 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -5,12 +5,14 @@ import java.util.Hashtable; import java.util.List; import eu.siacs.conversations.utils.XmlHelper; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Element { protected String name; - protected Hashtable attributes = new Hashtable(); + protected Hashtable attributes = new Hashtable<>(); protected String content; - protected List children = new ArrayList(); + protected List children = new ArrayList<>(); public Element(String name) { this.name = name; @@ -103,6 +105,42 @@ public class Element { } } + public Jid getJid() { + final String jid = this.getAttribute("jid"); + if (jid != null && !jid.isEmpty()) { + try { + return Jid.fromString(jid); + } catch (final InvalidJidException e) { + return null; + } + } + return null; + } + + public Jid getTo() { + final String to = this.getAttribute("to"); + if (to != null && !to.isEmpty()) { + try { + return Jid.fromString(to); + } catch (final InvalidJidException e) { + return null; + } + } + return null; + } + + public Jid getFrom() { + final String from = this.getAttribute("from"); + if (from != null && !from.isEmpty()) { + try { + return Jid.fromString(from); + } catch (final InvalidJidException e) { + return null; + } + } + return null; + } + public Hashtable getAttributes() { return this.attributes; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 2bbde7ab..7a1e1f1b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -161,4 +161,8 @@ public final class Jid { result = 31 * result + resourcepart.hashCode(); return result; } + + public boolean isBareJid() { + return this.resourcepart.isEmpty(); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java index 3e7c7b68..9a0306fc 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; public class JingleCandidate { @@ -17,7 +18,7 @@ public class JingleCandidate { private String host; private int port; private int type; - private String jid; + private Jid jid; private int priority; public JingleCandidate(String cid, boolean ours) { @@ -37,11 +38,11 @@ public class JingleCandidate { return this.host; } - public void setJid(String jid) { + public void setJid(final Jid jid) { this.jid = jid; } - public String getJid() { + public Jid getJid() { return this.jid; } @@ -58,13 +59,17 @@ public class JingleCandidate { } public void setType(String type) { - if ("proxy".equals(type)) { - this.type = TYPE_PROXY; - } else if ("direct".equals(type)) { - this.type = TYPE_DIRECT; - } else { - this.type = TYPE_UNKNOWN; - } + switch (type) { + case "proxy": + this.type = TYPE_PROXY; + break; + case "direct": + this.type = TYPE_DIRECT; + break; + default: + this.type = TYPE_UNKNOWN; + break; + } } public void setPriority(int i) { @@ -93,7 +98,7 @@ public class JingleCandidate { } public static List parse(List canditates) { - List parsedCandidates = new ArrayList(); + List parsedCandidates = new ArrayList<>(); for (Element c : canditates) { parsedCandidates.add(JingleCandidate.parse(c)); } @@ -104,7 +109,7 @@ public class JingleCandidate { JingleCandidate parsedCandidate = new JingleCandidate( candidate.getAttribute("cid"), false); parsedCandidate.setHost(candidate.getAttribute("host")); - parsedCandidate.setJid(candidate.getAttribute("jid")); + parsedCandidate.setJid(candidate.getJid()); parsedCandidate.setType(candidate.getAttribute("type")); parsedCandidate.setPriority(Integer.parseInt(candidate .getAttribute("priority"))); @@ -118,7 +123,7 @@ public class JingleCandidate { element.setAttribute("cid", this.getCid()); element.setAttribute("host", this.getHost()); element.setAttribute("port", Integer.toString(this.getPort())); - element.setAttribute("jid", this.getJid()); + element.setAttribute("jid", this.getJid().toString()); element.setAttribute("priority", Integer.toString(this.getPriority())); if (this.getType() == TYPE_DIRECT) { element.setAttribute("type", "direct"); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 6b9ca9aa..a863775d 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -21,6 +21,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jingle.stanzas.Content; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.Reason; @@ -49,10 +50,10 @@ public class JingleConnection implements Downloadable { private Message message; private String sessionId; private Account account; - private String initiator; - private String responder; - private List candidates = new ArrayList(); - private ConcurrentHashMap connections = new ConcurrentHashMap(); + private Jid initiator; + private Jid responder; + private List candidates = new ArrayList<>(); + private ConcurrentHashMap connections = new ConcurrentHashMap<>(); private String transportId; private Element fileOffer; @@ -150,7 +151,7 @@ public class JingleConnection implements Downloadable { return this.account; } - public String getCounterPart() { + public Jid getCounterPart() { return this.message.getCounterpart(); } @@ -254,14 +255,14 @@ public class JingleConnection implements Downloadable { this.mJingleStatus = JINGLE_STATUS_INITIATED; Conversation conversation = this.mXmppConnectionService .findOrCreateConversation(account, - packet.getFrom().split("/", 2)[0], false); + packet.getFrom().toBareJid(), false); this.message = new Message(conversation, "", Message.ENCRYPTION_NONE); this.message.setStatus(Message.STATUS_RECEIVED); this.message.setType(Message.TYPE_IMAGE); this.mStatus = Downloadable.STATUS_OFFER; this.message.setDownloadable(this); - String[] fromParts = packet.getFrom().split("/", 2); - this.message.setPresence(fromParts[1]); + final Jid from = packet.getFrom(); + this.message.setPresence(from.isBareJid() ? "" : from.getResourcepart()); this.account = account; this.initiator = packet.getFrom(); this.responder = this.account.getFullJid(); @@ -375,7 +376,7 @@ public class JingleConnection implements Downloadable { } private List getCandidatesAsElements() { - List elements = new ArrayList(); + List elements = new ArrayList<>(); for (JingleCandidate c : this.candidates) { elements.add(c.toElement()); } @@ -547,7 +548,7 @@ public class JingleConnection implements Downloadable { activation.query("http://jabber.org/protocol/bytestreams") .setAttribute("sid", this.getSessionId()); activation.query().addChild("activate") - .setContent(this.getCounterPart()); + .setContent(this.getCounterPart().toString()); this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() { @@ -810,11 +811,11 @@ public class JingleConnection implements Downloadable { this.sendJinglePacket(packet); } - public String getInitiator() { + public Jid getInitiator() { return this.initiator; } - public String getResponder() { + public Jid getResponder() { return this.responder; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index d937146a..6684a4c6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -14,13 +14,15 @@ import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class JingleConnectionManager extends AbstractConnectionManager { - private List connections = new CopyOnWriteArrayList(); + private List connections = new CopyOnWriteArrayList<>(); - private HashMap primaryCandidates = new HashMap(); + private HashMap primaryCandidates = new HashMap<>(); @SuppressLint("TrulyRandom") private SecureRandom random = new SecureRandom(); @@ -61,7 +63,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { return connection; } - public JingleConnection createNewConnection(JinglePacket packet) { + public JingleConnection createNewConnection(final JinglePacket packet) { JingleConnection connection = new JingleConnection(this); this.connections.add(connection); return connection; @@ -79,7 +81,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { .findDiscoItemByFeature(xmlns); if (proxy != null) { IqPacket iq = new IqPacket(IqPacket.TYPE_GET); - iq.setTo(proxy); + iq.setAttribute("to", proxy); iq.query(xmlns); account.getXmppConnection().sendIqPacket(iq, new OnIqPacketReceived() { @@ -101,8 +103,12 @@ public class JingleConnectionManager extends AbstractConnectionManager { .getAttribute("port"))); candidate .setType(JingleCandidate.TYPE_PROXY); - candidate.setJid(proxy); - candidate.setPriority(655360 + 65535); + try { + candidate.setJid(Jid.fromString(proxy)); + } catch (final InvalidJidException e) { + candidate.setJid(null); + } + candidate.setPriority(655360 + 65535); primaryCandidates.put(account.getJid(), candidate); listener.onPrimaryCandidateFound(true, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index cc1e92f6..e3f4fd61 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -13,12 +13,13 @@ import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class JingleInbandTransport extends JingleTransport { private Account account; - private String counterpart; + private Jid counterpart; private int blockSize; private int bufferSize; private int seq = 0; @@ -44,8 +45,8 @@ public class JingleInbandTransport extends JingleTransport { } }; - public JingleInbandTransport(Account account, String counterpart, - String sid, int blocksize) { + public JingleInbandTransport(final Account account, final Jid counterpart, + final String sid, final int blocksize) { this.account = account; this.counterpart = counterpart; this.blockSize = blocksize; @@ -92,12 +93,10 @@ public class JingleInbandTransport extends JingleTransport { return; } this.remainingSize = file.getExpectedSize(); - } catch (NoSuchAlgorithmException e) { - callback.onFileTransferAborted(); - } catch (IOException e) { + } catch (final NoSuchAlgorithmException | IOException e) { callback.onFileTransferAborted(); } - } + } @Override public void send(DownloadableFile file, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java index 77a73643..4f73a83a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp.jingle.stanzas; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class JinglePacket extends IqPacket { @@ -85,8 +86,8 @@ public class JinglePacket extends IqPacket { return this.jingle.getAttribute("action"); } - public void setInitiator(String initiator) { - this.jingle.setAttribute("initiator", initiator); + public void setInitiator(final Jid initiator) { + this.jingle.setAttribute("initiator", initiator.toString()); } public boolean isAction(String action) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java index ea8f64a9..54028a45 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp.stanzas; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; public class AbstractStanza extends Element { @@ -9,13 +10,21 @@ public class AbstractStanza extends Element { super(name); } - public String getTo() { - return getAttribute("to"); - } + public Jid getTo() { + try { + return Jid.fromString(getAttribute("to")); + } catch (final InvalidJidException e) { + return null; + } + } - public String getFrom() { - return getAttribute("from"); - } + public Jid getFrom() { + try { + return Jid.fromString(getAttribute("from")); + } catch (final InvalidJidException e) { + return null; + } + } public String getId() { return this.getAttribute("id"); From bf9207456e7523c2d18f1f9fa007542b5d0e10ea Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:33:13 -0500 Subject: [PATCH 07/22] Update another chunk of stuff to use JID objects --- .../siacs/conversations/entities/Message.java | 9 +-- .../generator/MessageGenerator.java | 4 +- .../ui/ConferenceDetailsActivity.java | 6 +- .../ui/ContactDetailsActivity.java | 22 ++++-- .../ui/ConversationFragment.java | 17 +++-- .../conversations/ui/EditAccountActivity.java | 71 +++++++++++-------- .../ui/PublishProfilePictureActivity.java | 13 +++- .../siacs/conversations/ui/XmppActivity.java | 41 ++++++----- .../eu/siacs/conversations/xmpp/jid/Jid.java | 4 ++ 9 files changed, 104 insertions(+), 83 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ce21addc..53df1ddf 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -248,13 +248,8 @@ public class Message extends AbstractEntity { this.trueCounterpart = trueCounterpart; } - public String getPresence() { - if (!counterpart.getResourcepart().isEmpty()) { - return counterpart.getResourcepart(); - } else { - // TODO: Return empty string or null? - return null; - } + public Jid getPresence() { + return counterpart; } public void setDownloadable(Downloadable downloadable) { diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index d53346b0..6f076e01 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -114,7 +114,7 @@ public class MessageGenerator extends AbstractGenerator { private MessagePacket generateError(MessagePacket origin) { MessagePacket packet = new MessagePacket(); packet.setId(origin.getId()); - packet.setAttribute("to", origin.getFrom()); + packet.setTo(origin.getFrom()); packet.setBody(origin.getBody()); packet.setType(MessagePacket.TYPE_ERROR); return packet; @@ -170,7 +170,7 @@ public class MessageGenerator extends AbstractGenerator { MessagePacket originalMessage, String namespace) { MessagePacket receivedPacket = new MessagePacket(); receivedPacket.setType(MessagePacket.TYPE_NORMAL); - receivedPacket.setAttribute("to", originalMessage.getFrom()); + receivedPacket.setTo(originalMessage.getFrom()); receivedPacket.setFrom(account.getFullJid()); Element received = receivedPacket.addChild("received", namespace); received.setAttribute("id", originalMessage.getId()); diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index cc9fca26..d480ce40 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -53,7 +53,7 @@ public class ConferenceDetailsActivity extends XmppActivity { } }; - private List users = new ArrayList(); + private List users = new ArrayList<>(); private OnConversationUpdate onConvChanged = new OnConversationUpdate() { @Override @@ -142,7 +142,7 @@ public class ConferenceDetailsActivity extends XmppActivity { @Override protected String getShareableUri() { if (conversation!=null) { - return "xmpp:"+conversation.getContactJid().split("/")[0]+"?join"; + return "xmpp:"+conversation.getContactJid().toBareJid().toString()+"?join"; } else { return ""; } @@ -211,7 +211,7 @@ public class ConferenceDetailsActivity extends XmppActivity { mYourPhoto.setImageBitmap(avatarService().get( conversation.getAccount(), getPixel(48))); setTitle(conversation.getName()); - mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); + mFullJid.setText(conversation.getContactJid().toBareJid().toString()); mYourNick.setText(conversation.getMucOptions().getActualNick()); mRoleAffiliaton = (TextView) findViewById(R.id.muc_role); if (conversation.getMucOptions().online()) { diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 7ac30e39..701edb47 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -35,14 +35,16 @@ import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class ContactDetailsActivity extends XmppActivity { public static final String ACTION_VIEW_CONTACT = "view_contact"; private Contact contact; - private String accountJid; - private String contactJid; + private Jid accountJid; + private Jid contactJid; private TextView contactJidTv; private TextView accountJidTv; @@ -68,7 +70,7 @@ public class ContactDetailsActivity extends XmppActivity { public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); intent.setType(Contacts.CONTENT_ITEM_TYPE); - intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid()); + intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid().toString()); intent.putExtra(Intents.Insert.IM_PROTOCOL, CommonDataKinds.Im.PROTOCOL_JABBER); intent.putExtra("finishActivityOnSaveCompleted", true); @@ -174,9 +176,15 @@ public class ContactDetailsActivity extends XmppActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) { - this.accountJid = getIntent().getExtras().getString("account"); - this.contactJid = getIntent().getExtras().getString("contact"); - } + try { + this.accountJid = Jid.fromString(getIntent().getExtras().getString("account")); + } catch (final InvalidJidException ignored) { + } + try { + this.contactJid = Jid.fromString(getIntent().getExtras().getString("contact")); + } catch (final InvalidJidException ignored) { + } + } setContentView(R.layout.activity_contact_details); contactJidTv = (TextView) findViewById(R.id.details_contactjid); @@ -318,7 +326,7 @@ public class ContactDetailsActivity extends XmppActivity { contactJidTv.setText(contact.getJid() + " (" + contact.getPresences().size() + ")"); } else { - contactJidTv.setText(contact.getJid()); + contactJidTv.setText(contact.getJid().toString()); } accountJidTv.setText(getString(R.string.using_account, contact .getAccount().getJid())); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 8754b953..299f06c0 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -54,6 +54,7 @@ import eu.siacs.conversations.ui.adapter.MessageAdapter; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.jid.Jid; public class ConversationFragment extends Fragment { @@ -92,11 +93,9 @@ public class ConversationFragment extends Fragment { } }; protected ListView messagesView; - protected LayoutInflater inflater; - protected List messageList = new ArrayList(); + protected List messageList = new ArrayList<>(); protected MessageAdapter messageListAdapter; protected Contact contact; - protected String queuedPqpMessage = null; private EditMessage mEditMessage; private ImageButton mSendButton; private RelativeLayout snackbar; @@ -147,7 +146,7 @@ public class ConversationFragment extends Fragment { } } }; - private ConcurrentLinkedQueue mEncryptedMessages = new ConcurrentLinkedQueue(); + private ConcurrentLinkedQueue mEncryptedMessages = new ConcurrentLinkedQueue<>(); private boolean mDecryptJobRunning = false; private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() { @@ -281,10 +280,10 @@ public class ConversationFragment extends Fragment { if (message.getStatus() <= Message.STATUS_RECEIVED) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) { if (message.getPresence() != null) { - highlightInConference(message.getPresence()); + highlightInConference(message.getPresence().toString()); } else { highlightInConference(message - .getCounterpart()); + .getCounterpart().toString()); } } else { Contact contact = message.getConversation() @@ -299,7 +298,7 @@ public class ConversationFragment extends Fragment { } else { Account account = message.getConversation().getAccount(); Intent intent = new Intent(activity, EditAccountActivity.class); - intent.putExtra("jid", account.getJid()); + intent.putExtra("jid", account.getJid().toString()); startActivity(intent); } } @@ -430,9 +429,9 @@ public class ConversationFragment extends Fragment { .createNewConnection(message); } - protected void privateMessageWith(String counterpart) { + protected void privateMessageWith(final Jid counterpart) { this.mEditMessage.setText(""); - this.conversation.setNextPresence(counterpart); + this.conversation.setNextPresence(counterpart.toString()); updateChatMsgHint(); } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index c1da35f5..7cccc31b 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -47,6 +47,8 @@ import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.Validator; import eu.siacs.conversations.xmpp.XmppConnection.Features; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; public class EditAccountActivity extends XmppActivity { @@ -68,7 +70,7 @@ public class EditAccountActivity extends XmppActivity { private RelativeLayout mOtrFingerprintBox; private ImageButton mOtrFingerprintToClipboardButton; - private String jidToEdit; + private Jid jidToEdit; private Account mAccount; private boolean mFetchingAvatar = false; @@ -89,15 +91,14 @@ public class EditAccountActivity extends XmppActivity { return; } boolean registerNewAccount = mRegisterNew.isChecked(); - String[] jidParts = mAccountJid.getText().toString().split("@"); - String username = jidParts[0]; - String server; - if (jidParts.length >= 2) { - server = jidParts[1]; - } else { - server = ""; - } - String password = mPassword.getText().toString(); + final Jid jid; + try { + jid = Jid.fromString(mAccountJid.getText().toString()); + } catch (final InvalidJidException e) { + // TODO: Handle this error? + return; + } + String password = mPassword.getText().toString(); String passwordConfirm = mPasswordConfirm.getText().toString(); if (registerNewAccount) { if (!password.equals(passwordConfirm)) { @@ -109,19 +110,25 @@ public class EditAccountActivity extends XmppActivity { } if (mAccount != null) { mAccount.setPassword(password); - mAccount.setUsername(username); - mAccount.setServer(server); + try { + mAccount.setUsername(jid.hasLocalPart() ? jid.getLocalpart() : ""); + mAccount.setServer(jid.getDomainpart()); + } catch (final InvalidJidException ignored) { + } mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); xmppConnectionService.updateAccount(mAccount); } else { - if (xmppConnectionService.findAccountByJid(mAccountJid - .getText().toString()) != null) { - mAccountJid - .setError(getString(R.string.account_already_exists)); - mAccountJid.requestFocus(); - return; - } - mAccount = new Account(username, server, password); + try { + if (xmppConnectionService.findAccountByJid(Jid.fromString(mAccountJid.getText().toString())) != null) { + mAccountJid + .setError(getString(R.string.account_already_exists)); + mAccountJid.requestFocus(); + return; + } + } catch (InvalidJidException e) { + return; + } + mAccount = new Account(jid.toBareJid(), password); mAccount.setOption(Account.OPTION_USETLS, true); mAccount.setOption(Account.OPTION_USECOMPRESSION, true); mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); @@ -191,8 +198,7 @@ public class EditAccountActivity extends XmppActivity { finishInitialSetup(avatar); } }; - private KnownHostsAdapter mKnownHostsAdapter; - private TextWatcher mTextWatcher = new TextWatcher() { + private TextWatcher mTextWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, @@ -217,7 +223,7 @@ public class EditAccountActivity extends XmppActivity { if (mAccount!=null) { Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); - intent.putExtra("account", mAccount.getJid()); + intent.putExtra("account", mAccount.getJid().toString()); startActivity(intent); } } @@ -235,7 +241,7 @@ public class EditAccountActivity extends XmppActivity { } else { intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); - intent.putExtra("account", mAccount.getJid()); + intent.putExtra("account", mAccount.getJid().toString()); intent.putExtra("setup", true); } startActivity(intent); @@ -358,8 +364,11 @@ public class EditAccountActivity extends XmppActivity { protected void onStart() { super.onStart(); if (getIntent() != null) { - this.jidToEdit = getIntent().getStringExtra("jid"); - if (this.jidToEdit != null) { + try { + this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid")); + } catch (final InvalidJidException ignored) { + } + if (this.jidToEdit != null) { this.mRegisterNew.setVisibility(View.GONE); getActionBar().setTitle(getString(R.string.account_details)); } else { @@ -379,9 +388,9 @@ public class EditAccountActivity extends XmppActivity { @Override protected void onBackendConnected() { - this.mKnownHostsAdapter = new KnownHostsAdapter(this, - android.R.layout.simple_list_item_1, - xmppConnectionService.getKnownHosts()); + KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this, + android.R.layout.simple_list_item_1, + xmppConnectionService.getKnownHosts()); this.xmppConnectionService .setOnAccountListChangedListener(this.mOnAccountUpdateListener); if (this.jidToEdit != null) { @@ -393,12 +402,12 @@ public class EditAccountActivity extends XmppActivity { this.mCancelButton.setEnabled(false); this.mCancelButton.setTextColor(getSecondaryTextColor()); } - this.mAccountJid.setAdapter(this.mKnownHostsAdapter); + this.mAccountJid.setAdapter(mKnownHostsAdapter); updateSaveButton(); } private void updateAccountInformation() { - this.mAccountJid.setText(this.mAccount.getJid()); + this.mAccountJid.setText(this.mAccount.getJid().toString()); this.mPassword.setText(this.mAccount.getPassword()); if (this.jidToEdit != null) { this.mAvatar.setVisibility(View.VISIBLE); diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 6aa40c41..371102ef 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -14,6 +14,8 @@ import android.widget.TextView; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.utils.PhoneHelper; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; public class PublishProfilePictureActivity extends XmppActivity { @@ -148,8 +150,13 @@ public class PublishProfilePictureActivity extends XmppActivity { @Override protected void onBackendConnected() { if (getIntent() != null) { - String jid = getIntent().getStringExtra("account"); - if (jid != null) { + Jid jid; + try { + jid = Jid.fromString(getIntent().getStringExtra("account")); + } catch (InvalidJidException e) { + jid = null; + } + if (jid != null) { this.account = xmppConnectionService.findAccountByJid(jid); if (this.account.getXmppConnection() != null) { this.support = this.account.getXmppConnection() @@ -180,7 +187,7 @@ public class PublishProfilePictureActivity extends XmppActivity { } else { loadImageIntoPreview(avatarUri); } - this.accountTextView.setText(this.account.getJid()); + this.accountTextView.setText(this.account.getJid().toString()); } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 052385f6..d2cf582b 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -65,6 +65,7 @@ import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; import eu.siacs.conversations.utils.ExceptionHelper; +import eu.siacs.conversations.xmpp.jid.Jid; public abstract class XmppActivity extends Activity { @@ -275,14 +276,14 @@ public abstract class XmppActivity extends Activity { public void switchToContactDetails(Contact contact) { Intent intent = new Intent(this, ContactDetailsActivity.class); intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); - intent.putExtra("account", contact.getAccount().getJid()); - intent.putExtra("contact", contact.getJid()); + intent.putExtra("account", contact.getAccount().getJid().toString()); + intent.putExtra("contact", contact.getJid().toString()); startActivity(intent); } public void switchToAccount(Account account) { Intent intent = new Intent(this, EditAccountActivity.class); - intent.putExtra("jid", account.getJid()); + intent.putExtra("jid", account.getJid().toString()); startActivity(intent); } @@ -303,7 +304,7 @@ public abstract class XmppActivity extends Activity { try { startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); - } catch (SendIntentException e) { + } catch (final SendIntentException ignored) { } } @@ -347,9 +348,9 @@ public abstract class XmppActivity extends Activity { } protected void showAddToRosterDialog(final Conversation conversation) { - String jid = conversation.getContactJid(); + final Jid jid = conversation.getContactJid(); AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(jid); + builder.setTitle(jid.toString()); builder.setMessage(getString(R.string.not_in_roster)); builder.setNegativeButton(getString(R.string.cancel), null); builder.setPositiveButton(getString(R.string.add_contact), @@ -357,7 +358,7 @@ public abstract class XmppActivity extends Activity { @Override public void onClick(DialogInterface dialog, int which) { - String jid = conversation.getContactJid(); + final Jid jid = conversation.getContactJid(); Account account = conversation.getAccount(); Contact contact = account.getRoster().getContact(jid); xmppConnectionService.createContact(contact); @@ -369,7 +370,7 @@ public abstract class XmppActivity extends Activity { private void showAskForPresenceDialog(final Contact contact) { AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(contact.getJid()); + builder.setTitle(contact.getJid().toString()); builder.setMessage(R.string.request_presence_updates); builder.setNegativeButton(R.string.cancel, null); builder.setPositiveButton(R.string.request_now, @@ -391,7 +392,7 @@ public abstract class XmppActivity extends Activity { private void warnMutalPresenceSubscription(final Conversation conversation, final OnPresenceSelected listener) { AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(conversation.getContact().getJid()); + builder.setTitle(conversation.getContact().getJid().toString()); builder.setMessage(R.string.without_mutual_presence_updates); builder.setNegativeButton(R.string.cancel, null); builder.setPositiveButton(R.string.ignore, new OnClickListener() { @@ -567,11 +568,10 @@ public abstract class XmppActivity extends Activity { nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { @Override public NdefMessage createNdefMessage(NfcEvent nfcEvent) { - NdefMessage msg = new NdefMessage(new NdefRecord[]{ - NdefRecord.createUri(getShareableUri()), - NdefRecord.createApplicationRecord("eu.siacs.conversations") - }); - return msg; + return new NdefMessage(new NdefRecord[]{ + NdefRecord.createUri(getShareableUri()), + NdefRecord.createApplicationRecord("eu.siacs.conversations") + }); } }, this); } @@ -620,7 +620,7 @@ public abstract class XmppActivity extends Activity { protected Bitmap createQrCodeBitmap(String input, int size) { try { final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); - final Hashtable hints = new Hashtable(); + final Hashtable hints = new Hashtable<>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints); final int width = result.getWidth(); @@ -649,7 +649,7 @@ public abstract class XmppActivity extends Activity { private Message message = null; public BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference(imageView); + imageViewReference = new WeakReference<>(imageView); } @Override @@ -665,7 +665,7 @@ public abstract class XmppActivity extends Activity { @Override protected void onPostExecute(Bitmap bitmap) { - if (imageViewReference != null && bitmap != null) { + if (bitmap != null) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); @@ -695,9 +695,8 @@ public abstract class XmppActivity extends Activity { imageView.setImageDrawable(asyncDrawable); try { task.execute(message); - } catch (RejectedExecutionException e) { - return; - } + } catch (final RejectedExecutionException ignored) { + } } } } @@ -734,7 +733,7 @@ public abstract class XmppActivity extends Activity { public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference( + bitmapWorkerTaskReference = new WeakReference<>( bitmapWorkerTask); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 7a1e1f1b..0afd9102 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -162,6 +162,10 @@ public final class Jid { return result; } + public boolean hasLocalPart() { + return !localpart.isEmpty(); + } + public boolean isBareJid() { return this.resourcepart.isEmpty(); } From f108fc5a5c4542872a059c088aee503236e8b358 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:45:38 -0500 Subject: [PATCH 08/22] Update more files to use JID objects --- .../siacs/conversations/entities/Account.java | 4 +- .../conversations/services/AvatarService.java | 2 +- .../services/XmppConnectionService.java | 12 ++--- .../ui/ChooseContactActivity.java | 6 +-- .../ui/ConversationActivity.java | 3 +- .../ui/ManageAccountActivity.java | 4 +- .../conversations/ui/ShareWithActivity.java | 23 +++++++-- .../ui/StartConversationActivity.java | 48 +++++++++++++------ .../ui/adapter/AccountAdapter.java | 2 +- .../ui/adapter/ConversationAdapter.java | 2 +- .../ui/adapter/ListItemAdapter.java | 2 +- .../ui/adapter/MessageAdapter.java | 19 ++++++-- .../conversations/utils/ExceptionHelper.java | 23 +++++---- .../siacs/conversations/utils/UIHelper.java | 6 +-- 14 files changed, 102 insertions(+), 54 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index e600f37b..ee4cce80 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -336,9 +336,9 @@ public class Account extends AbstractEntity { return this.bookmarks; } - public boolean hasBookmarkFor(String conferenceJid) { + public boolean hasBookmarkFor(final Jid conferenceJid) { for (Bookmark bmark : this.bookmarks) { - if (bmark.getJid().equals(conferenceJid)) { + if (bmark.getJid().equals(conferenceJid.toBareJid())) { return true; } } diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 778fd4dd..c965d6b0 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -173,7 +173,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar( account.getAvatar(), size); if (avatar == null) { - avatar = get(account.getJid(), size); + avatar = get(account.getJid().toString(), size); } mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 27268898..e7897c9b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -566,7 +566,7 @@ public class XmppConnectionService extends Service { if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (!conv.hasValidOtrSession() && (message.getPresence() != null)) { - conv.startOtrSession(this, message.getPresence(), + conv.startOtrSession(this, message.getPresence().toString(), true); message.setStatus(Message.STATUS_WAITING); } else if (conv.hasValidOtrSession() @@ -587,7 +587,7 @@ public class XmppConnectionService extends Service { if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (!conv.hasValidOtrSession() && (message.getPresence() != null)) { - conv.startOtrSession(this, message.getPresence(), true); + conv.startOtrSession(this, message.getPresence().toString(), true); message.setStatus(Message.STATUS_WAITING); } else if (conv.hasValidOtrSession() && conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { @@ -634,7 +634,7 @@ public class XmppConnectionService extends Service { .getUserID()); } else if (!conv.hasValidOtrSession() && message.getPresence() != null) { - conv.startOtrSession(this, message.getPresence(), false); + conv.startOtrSession(this, message.getPresence().toString(), false); } } } @@ -670,9 +670,9 @@ public class XmppConnectionService extends Service { .getPresences(); if (!message.getConversation().hasValidOtrSession()) { if ((message.getPresence() != null) - && (presences.has(message.getPresence()))) { + && (presences.has(message.getPresence().toString()))) { message.getConversation().startOtrSession(this, - message.getPresence(), true); + message.getPresence().toString(), true); } else { if (presences.size() == 1) { String presence = presences.asStringArray()[0]; @@ -702,7 +702,7 @@ public class XmppConnectionService extends Service { Presences presences = message.getConversation().getContact() .getPresences(); if ((message.getPresence() != null) - && (presences.has(message.getPresence()))) { + && (presences.has(message.getPresence().toString()))) { markMessage(message, Message.STATUS_OFFERED); mJingleConnectionManager.createNewConnection(message); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java index f14da352..aa6ed7b4 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -25,7 +25,7 @@ import eu.siacs.conversations.ui.adapter.ListItemAdapter; public class ChooseContactActivity extends XmppActivity { private ListView mListView; - private ArrayList contacts = new ArrayList(); + private ArrayList contacts = new ArrayList<>(); private ArrayAdapter mContactsAdapter; private EditText mSearchEditText; @@ -96,10 +96,10 @@ public class ChooseContactActivity extends XmppActivity { Intent request = getIntent(); Intent data = new Intent(); ListItem mListItem = contacts.get(position); - data.putExtra("contact", mListItem.getJid()); + data.putExtra("contact", mListItem.getJid().toString()); String account = request.getStringExtra("account"); if (account == null && mListItem instanceof Contact) { - account = ((Contact) mListItem).getAccount().getJid(); + account = ((Contact) mListItem).getAccount().getJid().toString(); } data.putExtra("account", account); data.putExtra("conversation", diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index d02a7c7b..443a73db 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -228,8 +228,7 @@ public class ConversationActivity extends XmppActivity implements .useSubjectToIdentifyConference()) { ab.setTitle(getSelectedConversation().getName()); } else { - ab.setTitle(getSelectedConversation().getContactJid() - .split("/")[0]); + ab.setTitle(getSelectedConversation().getContactJid().toBareJid().toString()); } } invalidateOptionsMenu(); diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index 77f8b68a..1bde4dcb 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -81,7 +81,7 @@ public class ManageAccountActivity extends XmppActivity { } else { menu.findItem(R.id.mgmt_account_enable).setVisible(false); } - menu.setHeaderTitle(this.selectedAccount.getJid()); + menu.setHeaderTitle(this.selectedAccount.getJid().toString()); } @Override @@ -166,7 +166,7 @@ public class ManageAccountActivity extends XmppActivity { private void publishAvatar(Account account) { Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); - intent.putExtra("account", account.getJid()); + intent.putExtra("account", account.getJid().toString()); startActivity(intent); } diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java index 9fbc3db1..609dc280 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java @@ -9,6 +9,9 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.adapter.ConversationAdapter; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.app.PendingIntent; import android.content.Intent; import android.net.Uri; @@ -150,13 +153,23 @@ public class ShareWithActivity extends XmppActivity { } private void share() { - Account account = xmppConnectionService.findAccountByJid(share.account); - if (account == null) { + Account account; + try { + account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account)); + } catch (final InvalidJidException e) { + account = null; + } + if (account == null) { return; } - Conversation conversation = xmppConnectionService - .findOrCreateConversation(account, share.contact, false); - share(conversation); + final Conversation conversation; + try { + conversation = xmppConnectionService + .findOrCreateConversation(account, Jid.fromString(share.contact), false); + } catch (final InvalidJidException e) { + return; + } + share(conversation); } private void share(final Conversation conversation) { diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index ed6b2a85..4963d38d 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -63,6 +63,8 @@ import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.ui.adapter.ListItemAdapter; import eu.siacs.conversations.utils.Validator; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class StartConversationActivity extends XmppActivity { @@ -71,7 +73,7 @@ public class StartConversationActivity extends XmppActivity { private ViewPager mViewPager; private MyListFragment mContactsListFragment = new MyListFragment(); - private List contacts = new ArrayList(); + private List contacts = new ArrayList<>(); private ArrayAdapter mContactsAdapter; private MyListFragment mConferenceListFragment = new MyListFragment(); @@ -359,17 +361,26 @@ public class StartConversationActivity extends XmppActivity { return; } if (Validator.isValidJid(jid.getText().toString())) { - String accountJid = (String) spinner - .getSelectedItem(); - String contactJid = jid.getText().toString(); - Account account = xmppConnectionService + final Jid accountJid; + try { + accountJid = Jid.fromString((String) spinner + .getSelectedItem()); + } catch (final InvalidJidException e) { + return; + } + final Jid contactJid; + try { + contactJid = Jid.fromString(jid.getText().toString()); + } catch (final InvalidJidException e) { + return; + } + Account account = xmppConnectionService .findAccountByJid(accountJid); if (account == null) { dialog.dismiss(); return; } - Contact contact = account.getRoster().getContact( - contactJid); + Contact contact = account.getRoster().getContact(contactJid); if (contact.showInRoster()) { jid.setError(getString(R.string.contact_already_exists)); } else { @@ -416,10 +427,19 @@ public class StartConversationActivity extends XmppActivity { return; } if (Validator.isValidJid(jid.getText().toString())) { - String accountJid = (String) spinner - .getSelectedItem(); - String conferenceJid = jid.getText().toString(); - Account account = xmppConnectionService + final Jid accountJid; + try { + accountJid = Jid.fromString((String) spinner.getSelectedItem()); + } catch (final InvalidJidException e) { + return; + } + final Jid conferenceJid; + try { + conferenceJid = Jid.fromString(jid.getText().toString()); + } catch (final InvalidJidException e) { + return; // TODO: Do some error handling... + } + Account account = xmppConnectionService .findAccountByJid(accountJid); if (account == null) { dialog.dismiss(); @@ -471,7 +491,7 @@ public class StartConversationActivity extends XmppActivity { } private void populateAccountSpinner(Spinner spinner) { - ArrayAdapter adapter = new ArrayAdapter(this, + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, mActivatedAccounts); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); @@ -554,7 +574,7 @@ public class StartConversationActivity extends XmppActivity { this.mActivatedAccounts.clear(); for (Account account : xmppConnectionService.getAccounts()) { if (account.getStatus() != Account.STATUS_DISABLED) { - this.mActivatedAccounts.add(account.getJid()); + this.mActivatedAccounts.add(account.getJid().toString()); } } this.mKnownHosts = xmppConnectionService.getKnownHosts(); @@ -779,7 +799,7 @@ public class StartConversationActivity extends XmppActivity { // sample: imto://xmpp/jid@foo.com try { jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1]; - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException ignored) { } } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java index e13b3204..ea527360 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -31,7 +31,7 @@ public class AccountAdapter extends ArrayAdapter { view = inflater.inflate(R.layout.account_row, parent, false); } TextView jid = (TextView) view.findViewById(R.id.account_jid); - jid.setText(account.getJid()); + jid.setText(account.getJid().toString()); TextView statusView = (TextView) view.findViewById(R.id.account_status); ImageView imageView = (ImageView) view.findViewById(R.id.account_image); imageView.setImageBitmap(activity.avatarService().get(account, diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index b5c20dc5..b3df8d72 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -58,7 +58,7 @@ public class ConversationAdapter extends ArrayAdapter { || activity.useSubjectToIdentifyConference()) { convName.setText(conversation.getName()); } else { - convName.setText(conversation.getContactJid().split("/")[0]); + convName.setText(conversation.getContactJid().toBareJid().toString()); } TextView mLastMessage = (TextView) view .findViewById(R.id.conversation_lastmsg); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index efc6b4d9..d78dbd6a 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -34,7 +34,7 @@ public class ListItemAdapter extends ArrayAdapter { TextView jid = (TextView) view.findViewById(R.id.contact_jid); ImageView picture = (ImageView) view.findViewById(R.id.contact_photo); - jid.setText(item.getJid()); + jid.setText(item.getJid().toString()); name.setText(item.getDisplayName()); picture.setImageBitmap(activity.avatarService().get(item, activity.getPixel(48))); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index f2227308..ffd0b4e9 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,5 +1,18 @@ package eu.siacs.conversations.ui.adapter; +import java.util.List; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Message.ImageParams; +import eu.siacs.conversations.ui.ConversationActivity; +import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.content.Intent; import android.graphics.Typeface; import android.text.Spannable; @@ -136,9 +149,9 @@ public class MessageAdapter extends ArrayAdapter { info = contact.getDisplayName(); } else { if (message.getPresence() != null) { - info = message.getPresence(); + info = message.getPresence().toString(); } else { - info = message.getCounterpart(); + info = message.getCounterpart().toString(); } } } @@ -227,7 +240,7 @@ public class MessageAdapter extends ArrayAdapter { privateMarker = activity .getString(R.string.private_message); } else { - String to; + final Jid to; if (message.getPresence() != null) { to = message.getPresence(); } else { diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java index b5fc88bd..fc691057 100644 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java @@ -13,6 +13,9 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; + import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -89,10 +92,13 @@ public class ExceptionHelper { Log.d(Config.LOGTAG, "using account=" + finalAccount.getJid() + " to send in stack trace"); - Conversation conversation = service - .findOrCreateConversation(finalAccount, - "bugs@siacs.eu", false); - Message message = new Message(conversation, report + Conversation conversation = null; + try { + conversation = service.findOrCreateConversation(finalAccount, + Jid.fromString("bugs@siacs.eu"), false); + } catch (final InvalidJidException ignored) { + } + Message message = new Message(conversation, report .toString(), Message.ENCRYPTION_NONE); service.sendMessage(message); } @@ -103,15 +109,12 @@ public class ExceptionHelper { @Override public void onClick(DialogInterface dialog, int which) { preferences.edit().putBoolean("never_send", true) - .commit(); + .apply(); } }); builder.create().show(); - } catch (FileNotFoundException e) { - return; - } catch (IOException e) { - return; - } + } catch (final IOException ignored) { + } } } diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 5141c83c..e0fab299 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -110,7 +110,7 @@ public class UIHelper { List accounts) { NotificationManager mNotificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); - List accountsWproblems = new ArrayList(); + List accountsWproblems = new ArrayList<>(); for (Account account : accounts) { if (account.hasErrorStatus()) { accountsWproblems.add(account); @@ -124,7 +124,7 @@ public class UIHelper { } else if (accountsWproblems.size() == 1) { mBuilder.setContentTitle(context .getString(R.string.problem_connecting_to_account)); - mBuilder.setContentText(accountsWproblems.get(0).getJid()); + mBuilder.setContentText(accountsWproblems.get(0).getJid().toString()); } else { mBuilder.setContentTitle(context .getString(R.string.problem_connecting_to_accounts)); @@ -165,7 +165,7 @@ public class UIHelper { TextView yourprint = (TextView) view .findViewById(R.id.verify_otr_yourprint); - jid.setText(contact.getJid()); + jid.setText(contact.getJid().toString()); fingerprint.setText(conversation.getOtrFingerprint()); yourprint.setText(account.getOtrFingerprint()); builder.setNegativeButton("Cancel", null); From 864f319500937fb46d86104b12ce767dd6725f64 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:46:09 -0500 Subject: [PATCH 09/22] Add a packet JID place I missed... --- src/main/java/eu/siacs/conversations/generator/IqGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index 2f6df523..5d674748 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -19,7 +19,7 @@ public class IqGenerator extends AbstractGenerator { public IqPacket discoResponse(IqPacket request) { IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT); packet.setId(request.getId()); - packet.setAttribute("to", request.getFrom()); + packet.setTo(request.getFrom()); Element query = packet.addChild("query", "http://jabber.org/protocol/disco#info"); query.setAttribute("node", request.query().getAttribute("node")); From 9db624ec7b6323c7e55aab6f8ec8489d1068fb5f Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:49:39 -0500 Subject: [PATCH 10/22] It builds again! --- .../eu/siacs/conversations/entities/Account.java | 14 +++++++------- .../services/XmppConnectionService.java | 7 ++----- .../siacs/conversations/ui/SettingsActivity.java | 6 ++++-- .../siacs/conversations/xmpp/XmppConnection.java | 6 +----- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index ee4cce80..e367b41a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -88,10 +88,7 @@ public class Account extends AbstractEntity { this.uuid = uuid; this.jid = jid; if (jid.getResourcepart().isEmpty()) { - try { - this.setResource("mobile"); - } catch (final InvalidJidException ignored) { - } + this.setResource("mobile"); } this.password = password; this.options = options; @@ -164,9 +161,12 @@ public class Account extends AbstractEntity { return getXmppConnection() != null && getStatus() > STATUS_NO_INTERNET && (getXmppConnection().getAttempt() >= 2); } - public void setResource(final String resource) throws InvalidJidException { - jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); - } + public void setResource(final String resource){ + try { + jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); + } catch (final InvalidJidException ignored) { + } + } public String getResource() { return jid.getResourcepart(); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index e7897c9b..f2f9becd 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -535,11 +535,8 @@ public class XmppConnectionService extends Service { public XmppConnection createConnection(Account account) { SharedPreferences sharedPref = getPreferences(); - try { - account.setResource(sharedPref.getString("resource", "mobile") - .toLowerCase(Locale.getDefault())); - } catch (final InvalidJidException ignored) { - } + account.setResource(sharedPref.getString("resource", "mobile") + .toLowerCase(Locale.getDefault())); XmppConnection connection = new XmppConnection(account, this); connection.setOnMessagePacketReceivedListener(this.mMessageParser); connection.setOnStatusChangedListener(this.statusListener); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index fc6308fc..aba60175 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -5,6 +5,8 @@ import java.util.Arrays; import java.util.Locale; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; + import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Build; @@ -62,8 +64,8 @@ public class SettingsActivity extends XmppActivity implements .toLowerCase(Locale.US); if (xmppConnectionServiceBound) { for (Account account : xmppConnectionService.getAccounts()) { - account.setResource(resource); - if (!account.isOptionSet(Account.OPTION_DISABLED)) { + account.setResource(resource); + if (!account.isOptionSet(Account.OPTION_DISABLED)) { xmppConnectionService.reconnectAccount(account, false); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 9c160384..11cbca81 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -851,11 +851,7 @@ public class XmppConnection implements Runnable { Element streamError = tagReader.readElement(currentTag); if (streamError != null && streamError.hasChild("conflict")) { final String resource = account.getResource().split("\\.")[0]; - try { - account.setResource(resource + "." + nextRandomId()); - } catch (final InvalidJidException ignored) { - // Should never reach here. - } + account.setResource(resource + "." + nextRandomId()); Log.d(Config.LOGTAG, account.getJid() + ": switching resource due to conflict (" + account.getResource() + ")"); From 1f5908b1d1dcc7da971659157dbab9345390768a Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 6 Nov 2014 14:57:49 -0500 Subject: [PATCH 11/22] Fix JID parsing error --- src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 0afd9102..b973ded2 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -78,7 +78,7 @@ public final class Jid { if (localpart.isEmpty() || localpart.length() > 1023) { throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } - domainpartStart = atLoc; + domainpartStart = atLoc + 1; finaljid = lp + "@"; } else { localpart = ""; From dd426ca6de3b764f8c748486b15220b42504930e Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 09:09:28 -0500 Subject: [PATCH 12/22] Format contact names in MUC properly --- .../ui/ConversationActivity.java | 26 ++++++++++--------- .../ui/adapter/MessageAdapter.java | 23 ++++++++-------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 443a73db..c1306210 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -69,7 +69,7 @@ public class ConversationActivity extends XmppActivity implements private View mContentView; - private List conversationList = new ArrayList(); + private List conversationList = new ArrayList<>(); private Conversation selectedConversation = null; private ListView listView; private ConversationFragment mConversationFragment; @@ -160,8 +160,10 @@ public class ConversationActivity extends XmppActivity implements this.listAdapter = new ConversationAdapter(this, conversationList); listView.setAdapter(this.listAdapter); - getActionBar().setDisplayHomeAsUpEnabled(false); - getActionBar().setHomeButtonEnabled(false); + if (getActionBar() != null) { + getActionBar().setDisplayHomeAsUpEnabled(false); + getActionBar().setHomeButtonEnabled(false); + } listView.setOnItemClickListener(new OnItemClickListener() { @@ -599,7 +601,7 @@ public class ConversationActivity extends XmppActivity implements } @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { + public boolean onKeyDown(final int keyCode, final KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (!isConversationsOverviewVisable()) { showConversationsOverview(); @@ -610,7 +612,7 @@ public class ConversationActivity extends XmppActivity implements } @Override - protected void onNewIntent(Intent intent) { + protected void onNewIntent(final Intent intent) { if (xmppConnectionServiceBound) { if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) { handleViewConversationIntent(intent); @@ -644,7 +646,7 @@ public class ConversationActivity extends XmppActivity implements } @Override - public void onSaveInstanceState(Bundle savedInstanceState) { + public void onSaveInstanceState(final Bundle savedInstanceState) { Conversation conversation = getSelectedConversation(); if (conversation != null) { savedInstanceState.putString(STATE_OPEN_CONVERSATION, @@ -713,11 +715,11 @@ public class ConversationActivity extends XmppActivity implements } private void selectConversationByUuid(String uuid) { - for (int i = 0; i < conversationList.size(); ++i) { - if (conversationList.get(i).getUuid().equals(uuid)) { - setSelectedConversation(conversationList.get(i)); - } - } + for (Conversation aConversationList : conversationList) { + if (aConversationList.getUuid().equals(uuid)) { + setSelectedConversation(aConversationList); + } + } } public void registerListener() { @@ -831,7 +833,7 @@ public class ConversationActivity extends XmppActivity implements try { this.startIntentSenderForResult(pi.getIntentSender(), requestCode, null, 0, 0, 0); - } catch (SendIntentException e1) { + } catch (final SendIntentException ignored) { } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index ffd0b4e9..17253cff 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -149,7 +149,7 @@ public class MessageAdapter extends ArrayAdapter { info = contact.getDisplayName(); } else { if (message.getPresence() != null) { - info = message.getPresence().toString(); + info = message.getPresence().getResourcepart(); } else { info = message.getCounterpart().toString(); } @@ -246,8 +246,7 @@ public class MessageAdapter extends ArrayAdapter { } else { to = message.getCounterpart(); } - privateMarker = activity.getString( - R.string.private_message_to, to); + privateMarker = activity.getString(R.string.private_message_to, to); } SpannableString span = new SpannableString(privateMarker + " " + message.getBody()); @@ -436,7 +435,7 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(item.getConversation().getAccount(), activity.getPixel(48))); } - if (viewHolder.contact_picture != null) { + if (viewHolder != null && viewHolder.contact_picture != null) { viewHolder.contact_picture .setOnClickListener(new OnClickListener() { @@ -501,14 +500,16 @@ public class MessageAdapter extends ArrayAdapter { } else { displayInfoMessage(viewHolder, R.string.install_openkeychain); - viewHolder.message_box - .setOnClickListener(new OnClickListener() { + if (viewHolder != null) { + viewHolder.message_box + .setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - activity.showInstallPgpDialog(); - } - }); + @Override + public void onClick(View v) { + activity.showInstallPgpDialog(); + } + }); + } } } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { displayDecryptionFailed(viewHolder); From efa4cec24df7c91e6d57a0f06c970e8193faabf9 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 09:14:37 -0500 Subject: [PATCH 13/22] More formatting fixes in MUC --- .../eu/siacs/conversations/ui/adapter/MessageAdapter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 17253cff..5975f0f8 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -149,7 +149,11 @@ public class MessageAdapter extends ArrayAdapter { info = contact.getDisplayName(); } else { if (message.getPresence() != null) { - info = message.getPresence().getResourcepart(); + if (message.getPresence().isBareJid()) { + info = message.getPresence().toString(); + } else { + info = message.getPresence().getResourcepart(); + } } else { info = message.getCounterpart().toString(); } From 778fb9de6c1b71bbc24d40c0f69830d6a820fb1e Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 09:32:22 -0500 Subject: [PATCH 14/22] Fix letter avatar selection in MUC --- .../eu/siacs/conversations/entities/Message.java | 1 + .../conversations/ui/adapter/MessageAdapter.java | 14 +------------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 53df1ddf..f15b7527 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -249,6 +249,7 @@ public class Message extends AbstractEntity { } public Jid getPresence() { + // TODO: This is now the same as getCounterpart()... find usages in code and remove one? return counterpart; } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 5975f0f8..566a4782 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,18 +1,5 @@ package eu.siacs.conversations.ui.adapter; -import java.util.List; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.Message.ImageParams; -import eu.siacs.conversations.ui.ConversationActivity; -import eu.siacs.conversations.utils.UIHelper; -import eu.siacs.conversations.xmpp.jid.Jid; - import android.content.Intent; import android.graphics.Typeface; import android.text.Spannable; @@ -42,6 +29,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.jid.Jid; public class MessageAdapter extends ArrayAdapter { From e49c2b14edeb3a7a8954493bb033e3679cb7daad Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 17:48:30 -0500 Subject: [PATCH 15/22] Fix bug introduced by rebase --- .../siacs/conversations/ui/adapter/MessageAdapter.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 566a4782..465d7bc3 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -417,11 +417,10 @@ public class MessageAdapter extends ArrayAdapter { if (contact != null) { viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48))); } else if (item.getConversation().getMode() == Conversation.MODE_MULTI) { - String name = item.getPresence(); - if (name == null) { - name = item.getCounterpart(); - } - viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(name, activity.getPixel(48))); + final Jid name = item.getPresence() != null ? item.getPresence() : item.getCounterpart(); + viewHolder.contact_picture.setImageBitmap(activity.avatarService().get( + name.isBareJid() ? name.toString() : name.getResourcepart(), + activity.getPixel(48))); } } else if (type == SENT) { viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(item.getConversation().getAccount(), activity.getPixel(48))); From 5ce0cd3802cae8fd78889ec736632f85a3d23a9c Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 22:21:18 -0500 Subject: [PATCH 16/22] Fields that we sync on should be final --- .../java/eu/siacs/conversations/services/AvatarService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index c965d6b0..e20b55a5 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -28,7 +28,7 @@ public class AvatarService { private static final String PREFIX_ACCOUNT = "account"; private static final String PREFIX_GENERIC = "generic"; - private ArrayList sizes = new ArrayList(); + final private ArrayList sizes = new ArrayList<>(); protected XmppConnectionService mXmppConnectionService = null; From 1a3327f2b12493dcd86b4032127020a41eec620d Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 22:34:54 -0500 Subject: [PATCH 17/22] Create avatar's for JID's w/o localparts --- .../siacs/conversations/entities/Contact.java | 14 +++++++------ .../conversations/services/AvatarService.java | 6 +++--- .../conversations/ui/EditAccountActivity.java | 20 +------------------ .../eu/siacs/conversations/xmpp/jid/Jid.java | 2 +- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 8fa91b02..9a827f85 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -78,14 +78,16 @@ public class Contact implements ListItem { public String getDisplayName() { if (this.systemName != null) { - return this.systemName; - } else if (this.serverName != null) { - return this.serverName; + return this.systemName; + } else if (this.serverName != null) { + return this.serverName; } else if (this.presenceName != null) { - return this.presenceName; + return this.presenceName; + } else if (jid.hasLocalpart()) { + return jid.getLocalpart(); } else { - return jid.getLocalpart(); - } + return jid.getDomainpart(); + } } public String getProfilePhoto() { diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index e20b55a5..6f199807 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -36,7 +36,7 @@ public class AvatarService { this.mXmppConnectionService = service; } - public Bitmap get(Contact contact, int size) { + public Bitmap get(final Contact contact, final int size) { final String KEY = key(contact, size); Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); if (avatar != null) { @@ -49,7 +49,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size); } if (avatar == null) { - avatar = get(contact.getDisplayName(), size); + avatar = get(contact.getDisplayName(), size); } this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; @@ -196,7 +196,7 @@ public class AvatarService { + String.valueOf(size); } - public Bitmap get(String name, int size) { + public Bitmap get(final String name, final int size) { final String KEY = key(name, size); Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); if (bitmap != null) { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 7cccc31b..f9c7d526 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -1,15 +1,10 @@ package eu.siacs.conversations.ui; -import android.app.AlertDialog; import android.app.PendingIntent; import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Point; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -27,21 +22,8 @@ import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; -import com.google.zxing.qrcode.QRCodeWriter; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; - -import java.util.Hashtable; - -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.utils.UIHelper; @@ -111,7 +93,7 @@ public class EditAccountActivity extends XmppActivity { if (mAccount != null) { mAccount.setPassword(password); try { - mAccount.setUsername(jid.hasLocalPart() ? jid.getLocalpart() : ""); + mAccount.setUsername(jid.hasLocalpart() ? jid.getLocalpart() : ""); mAccount.setServer(jid.getDomainpart()); } catch (final InvalidJidException ignored) { } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index b973ded2..a53c8096 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -162,7 +162,7 @@ public final class Jid { return result; } - public boolean hasLocalPart() { + public boolean hasLocalpart() { return !localpart.isEmpty(); } From cc34c60255c4b7c055491d291f0f81f5191caa06 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 22:36:30 -0500 Subject: [PATCH 18/22] Don't crash on packets with no "from" specified --- .../java/eu/siacs/conversations/parser/PresenceParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 8393585e..ba3f1645 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -22,7 +22,8 @@ public class PresenceParser extends AbstractParser implements public void parseConferencePresence(PresencePacket packet, Account account) { PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine(); if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { - final Conversation muc = mXmppConnectionService.find(account, + final Conversation muc = packet.getFrom() == null ? null : mXmppConnectionService.find( + account, packet.getFrom().toBareJid()); if (muc != null) { boolean before = muc.getMucOptions().online(); From 02db197a89fb7b305f03f3bc0f3a55dd0abaa268 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 22:48:17 -0500 Subject: [PATCH 19/22] Fix crash on account creation --- .../conversations/ui/EditAccountActivity.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index f9c7d526..d1aba067 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -232,18 +232,6 @@ public class EditAccountActivity extends XmppActivity { }); } - protected boolean inputDataDiffersFromAccount() { - if (mAccount == null) { - return true; - } else { - return (!mAccount.getJid().equals(mAccountJid.getText().toString())) - || (!mAccount.getPassword().equals( - mPassword.getText().toString()) || mAccount - .isOptionSet(Account.OPTION_REGISTER) != mRegisterNew - .isChecked()); - } - } - protected void updateSaveButton() { if (mAccount != null && mAccount.getStatus() == Account.STATUS_CONNECTING) { @@ -348,7 +336,8 @@ public class EditAccountActivity extends XmppActivity { if (getIntent() != null) { try { this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid")); - } catch (final InvalidJidException ignored) { + } catch (final InvalidJidException | NullPointerException ignored) { + this.jidToEdit = null; } if (this.jidToEdit != null) { this.mRegisterNew.setVisibility(View.GONE); From fc594e9b7302893f8ff0b27ae9db9a2f815a539a Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Fri, 7 Nov 2014 23:08:31 -0500 Subject: [PATCH 20/22] Fix issue with IDN SRV records --- .../java/eu/siacs/conversations/xmpp/XmppConnection.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 11cbca81..534a6667 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; +import java.net.IDN; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; @@ -156,7 +157,7 @@ public class XmppConnection implements Runnable { while (socketError && values.size() > i) { Bundle namePort = (Bundle) values.get(i); try { - String srvRecordServer = namePort.getString("name"); + String srvRecordServer = IDN.toASCII(namePort.getString("name")); int srvRecordPort = namePort.getInt("port"); String srvIpServer = namePort.getString("ipv4"); InetSocketAddress addr; @@ -363,7 +364,7 @@ public class XmppConnection implements Runnable { nextTag = tagReader.readTag(); } if (account.getStatus() == Account.STATUS_ONLINE) { - account.setStatus(Account.STATUS_OFFLINE); + account. setStatus(Account.STATUS_OFFLINE); if (statusListener != null) { statusListener.onStatusChanged(account); } From 7cfcf10f487a6b97231508963807039443da16f2 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sun, 9 Nov 2014 07:20:08 -0500 Subject: [PATCH 21/22] Fix contact highlighting in MUC --- .../java/eu/siacs/conversations/ui/ConversationFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 299f06c0..58e29d30 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -280,10 +280,10 @@ public class ConversationFragment extends Fragment { if (message.getStatus() <= Message.STATUS_RECEIVED) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) { if (message.getPresence() != null) { - highlightInConference(message.getPresence().toString()); + highlightInConference(message.getPresence().getResourcepart()); } else { highlightInConference(message - .getCounterpart().toString()); + .getContact().getDisplayName()); } } else { Contact contact = message.getConversation() From 53c7905631a9cee618157d15b06775c5d633f7a5 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sun, 9 Nov 2014 09:05:02 -0500 Subject: [PATCH 22/22] Check for illegal arguments to the toASCII func --- .../eu/siacs/conversations/xmpp/XmppConnection.java | 8 +++++++- .../java/eu/siacs/conversations/xmpp/jid/Jid.java | 12 ++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 534a6667..2b0f0ecc 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -157,7 +157,13 @@ public class XmppConnection implements Runnable { while (socketError && values.size() > i) { Bundle namePort = (Bundle) values.get(i); try { - String srvRecordServer = IDN.toASCII(namePort.getString("name")); + String srvRecordServer; + try { + srvRecordServer=IDN.toASCII(namePort.getString("name")); + } catch (final IllegalArgumentException e) { + // TODO: Handle me?` + srvRecordServer = ""; + } int srvRecordPort = namePort.getInt("port"); String srvIpServer = namePort.getString("ipv4"); InetSocketAddress addr; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index a53c8096..8e9e0400 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -108,9 +108,17 @@ public final class Jid { // Remove trailling "." before storing the domain part. if (dp.endsWith(".")) { - domainpart = IDN.toASCII(dp.substring(0, dp.length() - 1), IDN.USE_STD3_ASCII_RULES); + try { + domainpart = IDN.toASCII(dp.substring(0, dp.length() - 1), IDN.USE_STD3_ASCII_RULES); + } catch (final IllegalArgumentException e) { + throw new InvalidJidException(e); + } } else { - domainpart = IDN.toASCII(dp, IDN.USE_STD3_ASCII_RULES); + try { + domainpart = IDN.toASCII(dp, IDN.USE_STD3_ASCII_RULES); + } catch (final IllegalArgumentException e) { + throw new InvalidJidException(e); + } } // TODO: Find a proper domain validation library; validate individual parts, separators, etc.