diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/entities')
11 files changed, 549 insertions, 397 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 80a9d62f..1d0a025f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -1,9 +1,8 @@ package eu.siacs.conversations.entities; -import java.security.interfaces.DSAPublicKey; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.CopyOnWriteArrayList; +import android.content.ContentValues; +import android.database.Cursor; +import android.os.SystemClock; import net.java.otr4j.crypto.OtrCryptoEngineImpl; import net.java.otr4j.crypto.OtrCryptoException; @@ -11,14 +10,17 @@ import net.java.otr4j.crypto.OtrCryptoException; import org.json.JSONException; import org.json.JSONObject; +import java.security.interfaces.DSAPublicKey; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrEngine; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.XmppConnection; -import android.content.ContentValues; -import android.database.Cursor; -import android.os.SystemClock; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Account extends AbstractEntity { @@ -32,73 +34,138 @@ public class Account extends AbstractEntity { public static final String KEYS = "keys"; public static final String AVATAR = "avatar"; + public static final String PINNED_MECHANISM_KEY = "pinned_mechanism"; + public static final int OPTION_USETLS = 0; public static final int OPTION_DISABLED = 1; public static final int OPTION_REGISTER = 2; public static final int OPTION_USECOMPRESSION = 3; - public static final int STATUS_CONNECTING = 0; - public static final int STATUS_DISABLED = -2; - public static final int STATUS_OFFLINE = -1; - public static final int STATUS_ONLINE = 1; - public static final int STATUS_NO_INTERNET = 2; - public static final int STATUS_UNAUTHORIZED = 3; - public static final int STATUS_SERVER_NOT_FOUND = 5; - - public static final int STATUS_REGISTRATION_FAILED = 7; - public static final int STATUS_REGISTRATION_CONFLICT = 8; - public static final int STATUS_REGISTRATION_SUCCESSFULL = 9; - public static final int STATUS_REGISTRATION_NOT_SUPPORTED = 10; - - protected String username; - protected String server; + public static enum State { + DISABLED, + OFFLINE, + CONNECTING, + ONLINE, + NO_INTERNET, + UNAUTHORIZED(true), + SERVER_NOT_FOUND(true), + REGISTRATION_FAILED(true), + REGISTRATION_CONFLICT(true), + REGISTRATION_SUCCESSFUL, + REGISTRATION_NOT_SUPPORTED(true), + SECURITY_ERROR(true), + INCOMPATIBLE_SERVER(true); + + private boolean isError; + + public boolean isError() { + return this.isError; + } + + private State(final boolean isError) { + this.isError = isError; + } + + private State() { + this(false); + } + + public int getReadableId() { + switch (this) { + case DISABLED: + return R.string.account_status_disabled; + case ONLINE: + return R.string.account_status_online; + case CONNECTING: + return R.string.account_status_connecting; + case OFFLINE: + return R.string.account_status_offline; + case UNAUTHORIZED: + return R.string.account_status_unauthorized; + case SERVER_NOT_FOUND: + return R.string.account_status_not_found; + case NO_INTERNET: + return R.string.account_status_no_internet; + case REGISTRATION_FAILED: + return R.string.account_status_regis_fail; + case REGISTRATION_CONFLICT: + return R.string.account_status_regis_conflict; + case REGISTRATION_SUCCESSFUL: + return R.string.account_status_regis_success; + case REGISTRATION_NOT_SUPPORTED: + return R.string.account_status_regis_not_sup; + case SECURITY_ERROR: + return R.string.account_status_security_error; + case INCOMPATIBLE_SERVER: + return R.string.account_status_incompatible_server; + default: + return R.string.account_status_unknown; + } + } + } + + public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<>(); + public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<>(); + protected Jid jid; protected String password; protected int options = 0; protected String rosterVersion; - protected String resource = "mobile"; - protected int status = -1; + protected State status = State.OFFLINE; protected JSONObject keys = new JSONObject(); protected String avatar; - protected boolean online = false; - private OtrEngine otrEngine = null; private XmppConnection xmppConnection = null; private Presences presences = new Presences(); private long mEndGracePeriod = 0L; private String otrFingerprint; private Roster roster = null; - - private List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>(); - public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<Conversation>(); - public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<Conversation>(); + private List<Bookmark> bookmarks = 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.isBareJid()) { + this.setResource("mobile"); + } 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; } + public static Account fromCursor(Cursor cursor) { + 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)), + cursor.getString(cursor.getColumnIndex(KEYS)), + cursor.getString(cursor.getColumnIndex(AVATAR))); + } + public boolean isOptionSet(int option) { return ((options & (1 << option)) != 0); } @@ -112,69 +179,62 @@ 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 String getServer() { - return server; + public Jid getServer() { + return jid.toDomainJid(); } - 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) { - this.status = status; - } - - public int getStatus() { + public State getStatus() { if (isOptionSet(OPTION_DISABLED)) { - return STATUS_DISABLED; + return State.DISABLED; } else { return this.status; } } + public void setStatus(final State status) { + this.status = status; + } + public boolean errorStatus() { - int s = getStatus(); - return (s == STATUS_REGISTRATION_FAILED - || s == STATUS_REGISTRATION_CONFLICT - || s == STATUS_REGISTRATION_NOT_SUPPORTED - || s == STATUS_SERVER_NOT_FOUND || s == STATUS_UNAUTHORIZED); + return getStatus().isError(); } public boolean hasErrorStatus() { - if (getXmppConnection() == null) { - return false; - } else { - return getStatus() > STATUS_NO_INTERNET - && (getXmppConnection().getAttempt() >= 2); - } + return getXmppConnection() != null && getStatus().isError() && getXmppConnection().getAttempt() >= 2; } - public void setResource(String resource) { - this.resource = resource; + public String getResource() { + return jid.getResourcepart(); } - public String getResource() { - return this.resource; + public void setResource(final String resource) { + try { + jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); + } catch (final InvalidJidException ignored) { + } } - public String getJid() { - return username.toLowerCase(Locale.getDefault()) + "@" - + server.toLowerCase(Locale.getDefault()); + public Jid getJid() { + return jid; } public JSONObject getKeys() { @@ -210,8 +270,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()); @@ -220,21 +280,11 @@ public class Account extends AbstractEntity { return values; } - public static Account fromCursor(Cursor cursor) { - return new Account(cursor.getString(cursor.getColumnIndex(UUID)), - cursor.getString(cursor.getColumnIndex(USERNAME)), - cursor.getString(cursor.getColumnIndex(SERVER)), - cursor.getString(cursor.getColumnIndex(PASSWORD)), - cursor.getInt(cursor.getColumnIndex(OPTIONS)), - cursor.getString(cursor.getColumnIndex(ROSTERVERSION)), - cursor.getString(cursor.getColumnIndex(KEYS)), - cursor.getString(cursor.getColumnIndex(AVATAR))); + public void initOtrEngine(XmppConnectionService context) { + this.otrEngine = new OtrEngine(context, this); } - public OtrEngine getOtrEngine(XmppConnectionService context) { - if (otrEngine == null) { - otrEngine = new OtrEngine(context, this); - } + public OtrEngine getOtrEngine() { return this.otrEngine; } @@ -246,30 +296,24 @@ public class Account extends AbstractEntity { this.xmppConnection = connection; } - public String getFullJid() { - return this.getJid() + "/" + this.resource; - } - public String getOtrFingerprint() { if (this.otrFingerprint == null) { try { - DSAPublicKey pubkey = (DSAPublicKey) this.otrEngine - .getPublicKey(); - if (pubkey == null) { + if (this.otrEngine == null) { return null; } - StringBuilder builder = new StringBuilder( - new OtrCryptoEngineImpl().getFingerprint(pubkey)); - builder.insert(8, " "); - builder.insert(17, " "); - builder.insert(26, " "); - builder.insert(35, " "); - this.otrFingerprint = builder.toString(); - } catch (OtrCryptoException e) { - + DSAPublicKey publicKey = (DSAPublicKey) this.otrEngine.getPublicKey(); + if (publicKey == null) { + return null; + } + this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey); + return this.otrFingerprint; + } catch (final OtrCryptoException ignored) { + return null; } + } else { + return this.otrFingerprint; } - return this.otrFingerprint; } public String getRosterVersion() { @@ -284,11 +328,6 @@ public class Account extends AbstractEntity { this.rosterVersion = version; } - public String getOtrFingerprint(XmppConnectionService service) { - this.getOtrEngine(service); - return this.getOtrFingerprint(); - } - public void updatePresence(String resource, int status) { this.presences.updatePresence(resource, status); } @@ -324,17 +363,17 @@ public class Account extends AbstractEntity { return this.roster; } - public void setBookmarks(List<Bookmark> bookmarks) { - this.bookmarks = bookmarks; - } - public List<Bookmark> getBookmarks() { return this.bookmarks; } - public boolean hasBookmarkFor(String conferenceJid) { + public void setBookmarks(List<Bookmark> bookmarks) { + this.bookmarks = bookmarks; + } + + public boolean hasBookmarkFor(final Jid conferenceJid) { for (Bookmark bmark : this.bookmarks) { - if (bmark.getJid().equals(conferenceJid)) { + if (bmark.getJid().equals(conferenceJid.toBareJid())) { return true; } } @@ -354,39 +393,9 @@ public class Account extends AbstractEntity { return this.avatar; } - public int getReadableStatusId() { - switch (getStatus()) { - - case Account.STATUS_DISABLED: - return R.string.account_status_disabled; - case Account.STATUS_ONLINE: - return R.string.account_status_online; - case Account.STATUS_CONNECTING: - return R.string.account_status_connecting; - case Account.STATUS_OFFLINE: - return R.string.account_status_offline; - case Account.STATUS_UNAUTHORIZED: - return R.string.account_status_unauthorized; - case Account.STATUS_SERVER_NOT_FOUND: - return R.string.account_status_not_found; - case Account.STATUS_NO_INTERNET: - return R.string.account_status_no_internet; - case Account.STATUS_REGISTRATION_FAILED: - return R.string.account_status_regis_fail; - case Account.STATUS_REGISTRATION_CONFLICT: - return R.string.account_status_regis_conflict; - case Account.STATUS_REGISTRATION_SUCCESSFULL: - return R.string.account_status_regis_success; - case Account.STATUS_REGISTRATION_NOT_SUPPORTED: - return R.string.account_status_regis_not_sup; - default: - return R.string.account_status_unknown; - } - } - public void activateGracePeriod() { this.mEndGracePeriod = SystemClock.elapsedRealtime() - + (Config.CARBON_GRACE_PERIOD * 1000); + + (Config.CARBON_GRACE_PERIOD * 1000); } public void deactivateGracePeriod() { @@ -396,4 +405,13 @@ public class Account extends AbstractEntity { public boolean inGracePeriod() { return SystemClock.elapsedRealtime() < this.mEndGracePeriod; } + + public String getShareableUri() { + String fingerprint = this.getOtrFingerprint(); + if (fingerprint != null) { + return "xmpp:" + this.getJid().toBareJid().toString() + "?otr-fingerprint="+fingerprint; + } else { + return "xmpp:" + this.getJid().toBareJid().toString(); + } + } } 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..32e4601d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -1,16 +1,19 @@ 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.ArrayList; +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 +34,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 +44,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 +56,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,33 +73,35 @@ public class Contact implements ListItem { this.avatar = avatar; } - public Contact(final String jid) { + public Contact(final Jid jid) { this.jid = jid; } 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 this.jid.split("@")[0]; - } + return jid.getDomainpart(); + } } public String getProfilePhoto() { 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 +111,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 +126,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)), @@ -197,24 +207,26 @@ public class Contact implements ListItem { return systemAccount; } - public Set<String> getOtrFingerprints() { - Set<String> set = new HashSet<String>(); + public ArrayList<String> getOtrFingerprints() { + ArrayList<String> fingerprints = new ArrayList<String>(); try { if (this.keys.has("otr_fingerprints")) { - JSONArray fingerprints = this.keys + JSONArray prints = this.keys .getJSONArray("otr_fingerprints"); - for (int i = 0; i < fingerprints.length(); ++i) { - set.add(fingerprints.getString(i)); + for (int i = 0; i < prints.length(); ++i) { + fingerprints.add(prints.getString(i)); } } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + } catch (final JSONException ignored) { + } - return set; + return fingerprints; } - public void addOtrFingerprint(String print) { + public boolean addOtrFingerprint(String print) { + if (getOtrFingerprints().contains(print)) { + return false; + } try { JSONArray fingerprints; if (!this.keys.has("otr_fingerprints")) { @@ -225,15 +237,16 @@ public class Contact implements ListItem { } fingerprints.put(print); this.keys.put("otr_fingerprints", fingerprints); - } catch (JSONException e) { - + return true; + } catch (final JSONException ignored) { + return false; } } public void setPgpKeyId(long keyId) { try { this.keys.put("pgp_keyid", keyId); - } catch (JSONException e) { + } catch (final JSONException ignored) { } } @@ -273,21 +286,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 +319,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 +353,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) { @@ -387,4 +400,13 @@ public class Contact implements ListItem { public boolean trusted() { return getOption(Options.FROM) && getOption(Options.TO); } + + public String getShareableUri() { + if (getOtrFingerprints().size() >= 1) { + String otr = getOtrFingerprints().get(0); + return "xmpp:"+getJid().toBareJid().toString()+"?otr-fingerprint="+otr.replace(" ",""); + } else { + return "xmpp:"+getJid().toBareJid().toString(); + } + } } diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 9d4c36db..b1df7ec7 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,43 +48,42 @@ 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; private JSONObject attributes = new JSONObject(); - private String nextPresence; + private Jid nextCounterpart; - protected ArrayList<Message> messages = new ArrayList<Message>(); + protected ArrayList<Message> messages = new ArrayList<>(); protected Account account = null; private transient SessionImpl otrSession; private transient String otrFingerprint = null; + private Smp mSmp = new Smp(); private String nextMessage; private transient MucOptions mucOptions = null; - // private transient String latestMarkableMessageId; - private byte[] symmetricKey; 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 +93,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 +104,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 +183,7 @@ public class Conversation extends AbstractEntity { this.account = account; } - public String getContactJid() { + public Jid getContactJid() { return this.contactJid; } @@ -204,7 +201,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 +210,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)), @@ -236,15 +240,14 @@ public class Conversation extends AbstractEntity { this.mode = mode; } - public SessionImpl startOtrSession(XmppConnectionService service, - String presence, boolean sendStart) { + public SessionImpl startOtrSession(String presence, boolean sendStart) { if (this.otrSession != null) { return this.otrSession; } else { - SessionID sessionId = new SessionID(this.getContactJid().split("/", - 2)[0], presence, "xmpp"); - this.otrSession = new SessionImpl(sessionId, getAccount() - .getOtrEngine(service)); + final SessionID sessionId = new SessionID(this.getContactJid().toBareJid().toString(), + presence, + "xmpp"); + this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine()); try { if (sendStart) { this.otrSession.startSession(); @@ -265,6 +268,13 @@ public class Conversation extends AbstractEntity { public void resetOtrSession() { this.otrFingerprint = null; this.otrSession = null; + this.mSmp.hint = null; + this.mSmp.secret = null; + this.mSmp.status = Smp.STATUS_NONE; + } + + public Smp smp() { + return mSmp; } public void startOtrIfNeeded() { @@ -317,13 +327,21 @@ public class Conversation extends AbstractEntity { builder.insert(26, " "); builder.insert(35, " "); this.otrFingerprint = builder.toString(); - } catch (OtrCryptoException e) { + } catch (final OtrCryptoException ignored) { } } return this.otrFingerprint; } + public void verifyOtrFingerprint() { + getContact().addOtrFingerprint(getOtrFingerprint()); + } + + public boolean isOtrFingerprintVerified() { + return getContact().getOtrFingerprints().contains(getOtrFingerprint()); + } + public synchronized MucOptions getMucOptions() { if (this.mucOptions == null) { this.mucOptions = new MucOptions(this); @@ -335,16 +353,16 @@ public class Conversation extends AbstractEntity { this.mucOptions = null; } - public void setContactJid(String jid) { + public void setContactJid(final Jid jid) { this.contactJid = jid; } - public void setNextPresence(String presence) { - this.nextPresence = presence; + public void setNextCounterpart(Jid jid) { + this.nextCounterpart = jid; } - public String getNextPresence() { - return this.nextPresence; + public Jid getNextCounterpart() { + return this.nextCounterpart; } public int getLatestEncryption() { @@ -397,6 +415,10 @@ public class Conversation extends AbstractEntity { } } + public boolean smpRequested() { + return smp().status == Smp.STATUS_CONTACT_REQUESTED; + } + public void setNextMessage(String message) { this.nextMessage = message; } @@ -497,4 +519,16 @@ public class Conversation extends AbstractEntity { this.messages.addAll(index, messages); } } + + public class Smp { + public static final int STATUS_NONE = 0; + public static final int STATUS_CONTACT_REQUESTED = 1; + public static final int STATUS_WE_REQUESTED = 2; + public static final int STATUS_FAILED = 3; + public static final int STATUS_VERIFIED = 4; + + public String secret = null; + public String hint = null; + public int status = 0; + } } diff --git a/src/main/java/eu/siacs/conversations/entities/Downloadable.java b/src/main/java/eu/siacs/conversations/entities/Downloadable.java index e4c85336..d25bf93a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Downloadable.java +++ b/src/main/java/eu/siacs/conversations/entities/Downloadable.java @@ -2,7 +2,7 @@ package eu.siacs.conversations.entities; public interface Downloadable { - public final String[] VALID_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; + public final String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; public final String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; public static final int STATUS_UNKNOWN = 0x200; @@ -12,10 +12,17 @@ public interface Downloadable { public static final int STATUS_DOWNLOADING = 0x204; public static final int STATUS_DELETED = 0x205; public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206; + public static final int STATUS_UPLOADING = 0x207; public boolean start(); public int getStatus(); public long getFileSize(); + + public int getProgress(); + + public String getMimeType(); + + public void cancel(); } diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index 1605c75b..25f33907 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -6,6 +6,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.net.URLConnection; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; @@ -28,6 +29,7 @@ public class DownloadableFile extends File { private long expectedSize = 0; private String sha1sum; private Key aeskey; + private String mime; private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; @@ -52,6 +54,18 @@ public class DownloadableFile extends File { } } + public String getMimeType() { + String path = this.getAbsolutePath(); + String mime = URLConnection.guessContentTypeFromName(path); + if (mime != null) { + return mime; + } else if (mime == null && path.endsWith(".webp")) { + return "image/webp"; + } else { + return ""; + } + } + public void setExpectedSize(long size) { this.expectedSize = size; } diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java b/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java new file mode 100644 index 00000000..03fceceb --- /dev/null +++ b/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java @@ -0,0 +1,39 @@ +package eu.siacs.conversations.entities; + +public class DownloadablePlaceholder implements Downloadable { + + private int status; + + public DownloadablePlaceholder(int status) { + this.status = status; + } + @Override + public boolean start() { + return false; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public long getFileSize() { + return 0; + } + + @Override + public int getProgress() { + return 0; + } + + @Override + public String getMimeType() { + return ""; + } + + @Override + public void cancel() { + + } +} 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<ListItem> { 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..33f3443b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -1,12 +1,15 @@ package eu.siacs.conversations.entities; +import android.content.ContentValues; +import android.database.Cursor; + import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; -import android.content.ContentValues; -import android.database.Cursor; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class Message extends AbstractEntity { @@ -29,7 +32,7 @@ public class Message extends AbstractEntity { public static final int TYPE_TEXT = 0; public static final int TYPE_IMAGE = 1; - public static final int TYPE_AUDIO = 2; + public static final int TYPE_FILE = 2; public static final int TYPE_STATUS = 3; public static final int TYPE_PRIVATE = 4; @@ -42,9 +45,10 @@ public class Message extends AbstractEntity { public static String STATUS = "status"; public static String TYPE = "type"; public static String REMOTE_MSG_ID = "remoteMsgId"; - + public static String RELATIVE_FILE_PATH = "relativeFilePath"; + public boolean markable = false; protected String conversationUuid; - protected String counterpart; + protected Jid counterpart; protected String trueCounterpart; protected String body; protected String encryptedBody; @@ -52,13 +56,11 @@ public class Message extends AbstractEntity { protected int encryption; protected int status; protected int type; + protected String relativeFilePath; protected boolean read = true; protected String remoteMsgId = null; - protected Conversation conversation = null; protected Downloadable downloadable = null; - public boolean markable = false; - private Message mNextMessage = null; private Message mPreviousMessage = null; @@ -67,24 +69,20 @@ public class Message extends AbstractEntity { } public Message(Conversation conversation, String body, int encryption) { - this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), - conversation.getContactJid(), null, body, System - .currentTimeMillis(), encryption, - Message.STATUS_UNSEND, TYPE_TEXT, null); - this.conversation = conversation; + this(conversation,body,encryption,STATUS_UNSEND); } - public Message(Conversation conversation, String counterpart, String body, - int encryption, int status) { + public Message(Conversation conversation, String body, int encryption, int status) { this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), - counterpart, null, body, System.currentTimeMillis(), - encryption, status, TYPE_TEXT, null); + conversation.getContactJid().toBareJid(), null, body, System + .currentTimeMillis(), encryption, + status, TYPE_TEXT, null,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, final String relativeFilePath) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -95,6 +93,39 @@ public class Message extends AbstractEntity { this.status = status; this.type = type; this.remoteMsgId = remoteMsgId; + this.relativeFilePath = relativeFilePath; + } + + public static Message fromCursor(Cursor cursor) { + Jid jid; + try { + String value = cursor.getString(cursor.getColumnIndex(COUNTERPART)); + if (value!=null) { + jid = Jid.fromString(value); + } else { + jid = null; + } + } catch (InvalidJidException e) { + jid = null; + } + return new Message(cursor.getString(cursor.getColumnIndex(UUID)), + cursor.getString(cursor.getColumnIndex(CONVERSATION)), + jid, + cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)), + cursor.getString(cursor.getColumnIndex(BODY)), + cursor.getLong(cursor.getColumnIndex(TIME_SENT)), + cursor.getInt(cursor.getColumnIndex(ENCRYPTION)), + cursor.getInt(cursor.getColumnIndex(STATUS)), + cursor.getInt(cursor.getColumnIndex(TYPE)), + cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), + cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH))); + } + + public static Message createStatusMessage(Conversation conversation) { + Message message = new Message(); + message.setType(Message.TYPE_STATUS); + message.setConversation(conversation); + return message; } @Override @@ -102,7 +133,11 @@ public class Message extends AbstractEntity { ContentValues values = new ContentValues(); values.put(UUID, uuid); values.put(CONVERSATION, conversationUuid); - values.put(COUNTERPART, counterpart); + if (counterpart == null) { + values.putNull(COUNTERPART); + } else { + values.put(COUNTERPART, counterpart.toString()); + } values.put(TRUE_COUNTERPART, trueCounterpart); values.put(BODY, body); values.put(TIME_SENT, timeSent); @@ -110,6 +145,7 @@ public class Message extends AbstractEntity { values.put(STATUS, status); values.put(TYPE, type); values.put(REMOTE_MSG_ID, remoteMsgId); + values.put(RELATIVE_FILE_PATH, relativeFilePath); return values; } @@ -121,10 +157,18 @@ public class Message extends AbstractEntity { return this.conversation; } - public String getCounterpart() { + public void setConversation(Conversation conv) { + this.conversation = conv; + } + + public Jid getCounterpart() { return counterpart; } + public void setCounterpart(final Jid counterpart) { + this.counterpart = counterpart; + } + public Contact getContact() { if (this.conversation.getMode() == Conversation.MODE_SINGLE) { return this.conversation.getContact(); @@ -142,6 +186,10 @@ public class Message extends AbstractEntity { return body; } + public void setBody(String body) { + this.body = body; + } + public long getTimeSent() { return timeSent; } @@ -150,37 +198,32 @@ public class Message extends AbstractEntity { return encryption; } + public void setEncryption(int encryption) { + this.encryption = encryption; + } + public int getStatus() { return status; } - public String getRemoteMsgId() { - return this.remoteMsgId; + public void setStatus(int status) { + this.status = status; } - public void setRemoteMsgId(String id) { - this.remoteMsgId = id; + public void setRelativeFilePath(String path) { + this.relativeFilePath = path; } - public static Message fromCursor(Cursor cursor) { - return new Message(cursor.getString(cursor.getColumnIndex(UUID)), - cursor.getString(cursor.getColumnIndex(CONVERSATION)), - cursor.getString(cursor.getColumnIndex(COUNTERPART)), - cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)), - cursor.getString(cursor.getColumnIndex(BODY)), - cursor.getLong(cursor.getColumnIndex(TIME_SENT)), - cursor.getInt(cursor.getColumnIndex(ENCRYPTION)), - cursor.getInt(cursor.getColumnIndex(STATUS)), - cursor.getInt(cursor.getColumnIndex(TYPE)), - cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID))); + public String getRelativeFilePath() { + return this.relativeFilePath; } - public void setConversation(Conversation conv) { - this.conversation = conv; + public String getRemoteMsgId() { + return this.remoteMsgId; } - public void setStatus(int status) { - this.status = status; + public void setRemoteMsgId(String id) { + this.remoteMsgId = id; } public boolean isRead() { @@ -199,14 +242,6 @@ public class Message extends AbstractEntity { this.timeSent = time; } - public void setEncryption(int encryption) { - this.encryption = encryption; - } - - public void setBody(String body) { - this.body = body; - } - public String getEncryptedBody() { return this.encryptedBody; } @@ -215,57 +250,24 @@ public class Message extends AbstractEntity { this.encryptedBody = body; } - public void setType(int type) { - this.type = type; - } - public int getType() { return this.type; } - public void setPresence(String presence) { - if (presence == null) { - this.counterpart = this.counterpart.split("/", 2)[0]; - } else { - this.counterpart = this.counterpart.split("/", 2)[0] + "/" - + presence; - } + public void setType(int type) { + this.type = type; } public void setTrueCounterpart(String trueCounterpart) { this.trueCounterpart = trueCounterpart; } - public String getPresence() { - String[] counterparts = this.counterpart.split("/", 2); - if (counterparts.length == 2) { - return counterparts[1]; - } else { - if (this.counterpart.contains("/")) { - return ""; - } else { - return null; - } - } - } - - public void setDownloadable(Downloadable downloadable) { - this.downloadable = downloadable; - } - public Downloadable getDownloadable() { return this.downloadable; } - public static Message createStatusMessage(Conversation conversation) { - Message message = new Message(); - message.setType(Message.TYPE_STATUS); - message.setConversation(conversation); - return message; - } - - public void setCounterpart(String counterpart) { - this.counterpart = counterpart; + public void setDownloadable(Downloadable downloadable) { + this.downloadable = downloadable; } public boolean equals(Message message) { @@ -320,13 +322,14 @@ public class Message extends AbstractEntity { && message.getEncryption() != Message.ENCRYPTION_PGP && this.getType() == message.getType() && this.getEncryption() == message.getEncryption() + && this.getCounterpart() != null && this.getCounterpart().equals(message.getCounterpart()) && (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && ((this .getStatus() == message.getStatus() || ((this.getStatus() == Message.STATUS_SEND || this .getStatus() == Message.STATUS_SEND_RECEIVED) && (message .getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_SEND || message - .getStatus() == Message.STATUS_SEND_DISPLAYED)))) + .getStatus() == Message.STATUS_SEND_DISPLAYED)))) && !message.bodyContainsDownloadable() && !this.bodyContainsDownloadable()); } @@ -359,13 +362,9 @@ 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() { Contact contact = this.getContact(); return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); @@ -390,15 +389,15 @@ public class Message extends AbstractEntity { } String[] extensionParts = filename.split("\\."); if (extensionParts.length == 2 - && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( - extensionParts[extensionParts.length - 1])) { + && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( + extensionParts[extensionParts.length - 1])) { return true; } else if (extensionParts.length == 3 && Arrays - .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1]) - && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( - extensionParts[extensionParts.length - 2])) { + .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) + .contains(extensionParts[extensionParts.length - 1]) + && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( + extensionParts[extensionParts.length - 2])) { return true; } else { return false; @@ -410,7 +409,7 @@ public class Message extends AbstractEntity { public ImageParams getImageParams() { ImageParams params = getLegacyImageParams(); - if (params!=null) { + if (params != null) { return params; } params = new ImageParams(); @@ -473,7 +472,7 @@ public class Message extends AbstractEntity { } return params; } - + public ImageParams getLegacyImageParams() { ImageParams params = new ImageParams(); if (body == null) { diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 01190374..6eb1d43c 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<User> users = new CopyOnWriteArrayList<User>(); + private List<User> users = new CopyOnWriteArrayList<>(); private Conversation conversation; private boolean isOnline = false; private int error = ERROR_ROOM_NOT_FOUND; @@ -145,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(); @@ -236,13 +243,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().isBareJid()) { + return conversation.getContactJid().getResourcepart(); } else { return account.getUsername(); } @@ -300,7 +306,7 @@ public class MucOptions { } public long[] getPgpKeyIds() { - List<Long> ids = new ArrayList<Long>(); + List<Long> ids = new ArrayList<>(); for (User user : getUsers()) { if (user.getPgpKeyId() != 0) { ids.add(user.getPgpKeyId()); @@ -331,10 +337,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<String, Contact> contacts = new ConcurrentHashMap<String, Contact>(); + final ConcurrentHashMap<String, Contact> 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<Contact> getContacts() { - return new ArrayList<Contact>(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) { |