Move a chunk of classes over to using JID objects

This commit is contained in:
Sam Whited 2014-11-05 15:55:47 -05:00
parent a990861316
commit 9053f4aca0
22 changed files with 526 additions and 475 deletions

View File

@ -85,13 +85,11 @@ public class OtrEngine implements OtrEngineHost {
this.account.setKey("otr_p", privateKeySpec.getP().toString(16)); this.account.setKey("otr_p", privateKeySpec.getP().toString(16));
this.account.setKey("otr_q", privateKeySpec.getQ().toString(16)); this.account.setKey("otr_q", privateKeySpec.getQ().toString(16));
this.account.setKey("otr_y", publicKeySpec.getY().toString(16)); this.account.setKey("otr_y", publicKeySpec.getY().toString(16));
} catch (NoSuchAlgorithmException e) { } catch (final NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public void askForSecret(SessionID arg0, InstanceTag arg1, String arg2) { public void askForSecret(SessionID arg0, InstanceTag arg1, String arg2) {
@ -157,9 +155,9 @@ public class OtrEngine implements OtrEngineHost {
MessagePacket packet = new MessagePacket(); MessagePacket packet = new MessagePacket();
packet.setFrom(account.getFullJid()); packet.setFrom(account.getFullJid());
if (session.getUserID().isEmpty()) { if (session.getUserID().isEmpty()) {
packet.setTo(session.getAccountID()); packet.setAttribute("to", session.getAccountID());
} else { } else {
packet.setTo(session.getAccountID() + "/" + session.getUserID()); packet.setAttribute("to", session.getAccountID() + "/" + session.getUserID());
} }
packet.setBody(body); packet.setBody(body);
packet.addChild("private", "urn:xmpp:carbons:2"); packet.addChild("private", "urn:xmpp:carbons:2");

View File

@ -41,7 +41,7 @@ public class PgpEngine {
Intent params = new Intent(); Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message
.getConversation().getAccount().getJid()); .getConversation().getAccount().getJid().toString());
if (message.getType() == Message.TYPE_TEXT) { if (message.getType() == Message.TYPE_TEXT) {
InputStream is = new ByteArrayInputStream(message.getBody() InputStream is = new ByteArrayInputStream(message.getBody()
.getBytes()); .getBytes());
@ -77,10 +77,7 @@ public class PgpEngine {
return; return;
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, message); callback.error(R.string.openpgp_error, message);
return; }
default:
return;
}
} }
}); });
} else if (message.getType() == Message.TYPE_IMAGE) { } else if (message.getType() == Message.TYPE_IMAGE) {
@ -135,15 +132,10 @@ public class PgpEngine {
return; return;
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, message); callback.error(R.string.openpgp_error, message);
return;
default:
return;
} }
} }
}); });
} catch (FileNotFoundException e) { } catch (final IOException e) {
callback.error(R.string.error_decrypting_file, message);
} catch (IOException e) {
callback.error(R.string.error_decrypting_file, message); callback.error(R.string.error_decrypting_file, message);
} }
@ -164,7 +156,7 @@ public class PgpEngine {
.getMucOptions().getPgpKeyIds()); .getMucOptions().getPgpKeyIds());
} }
params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message
.getConversation().getAccount().getJid()); .getConversation().getAccount().getJid().toString());
if (message.getType() == Message.TYPE_TEXT) { if (message.getType() == Message.TYPE_TEXT) {
params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); 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); 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) { if (status == null) {
status = ""; status = "";
} }
StringBuilder pgpSig = new StringBuilder(); final StringBuilder pgpSig = new StringBuilder();
pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----"); pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
pgpSig.append('\n'); pgpSig.append('\n');
pgpSig.append('\n'); pgpSig.append('\n');
@ -269,7 +257,7 @@ public class PgpEngine {
Intent params = new Intent(); Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); 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()); InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
Intent result = api.executeApi(params, is, os); Intent result = api.executeApi(params, is, os);
@ -296,7 +284,7 @@ public class PgpEngine {
Intent params = new Intent(); Intent params = new Intent();
params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
params.setAction(OpenPgpApi.ACTION_SIGN); 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()); InputStream is = new ByteArrayInputStream(status.getBytes());
final OutputStream os = new ByteArrayOutputStream(); final OutputStream os = new ByteArrayOutputStream();
api.executeApiAsync(params, is, os, new IOpenPgpCallback() { api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
@ -338,8 +326,7 @@ public class PgpEngine {
return; return;
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, account); callback.error(R.string.openpgp_error, account);
return; }
}
} }
}); });
} }
@ -349,7 +336,7 @@ public class PgpEngine {
params.setAction(OpenPgpApi.ACTION_GET_KEY); params.setAction(OpenPgpApi.ACTION_GET_KEY);
params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId()); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId());
params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount() params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount()
.getJid()); .getJid().toString());
api.executeApiAsync(params, null, null, new IOpenPgpCallback() { api.executeApiAsync(params, null, null, new IOpenPgpCallback() {
@Override @Override
@ -365,8 +352,7 @@ public class PgpEngine {
return; return;
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, contact); callback.error(R.string.openpgp_error, contact);
return; }
}
} }
}); });
} }
@ -376,7 +362,7 @@ public class PgpEngine {
params.setAction(OpenPgpApi.ACTION_GET_KEY); params.setAction(OpenPgpApi.ACTION_GET_KEY);
params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId()); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, contact.getPgpKeyId());
params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount() params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, contact.getAccount()
.getJid()); .getJid().toString());
Intent result = api.executeApi(params, null, null); Intent result = api.executeApi(params, null, null);
return (PendingIntent) result return (PendingIntent) result
.getParcelableExtra(OpenPgpApi.RESULT_INTENT); .getParcelableExtra(OpenPgpApi.RESULT_INTENT);
@ -386,7 +372,7 @@ public class PgpEngine {
Intent params = new Intent(); Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_GET_KEY); params.setAction(OpenPgpApi.ACTION_GET_KEY);
params.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpKeyId); 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); Intent result = api.executeApi(params, null, null);
return (PendingIntent) result return (PendingIntent) result
.getParcelableExtra(OpenPgpApi.RESULT_INTENT); .getParcelableExtra(OpenPgpApi.RESULT_INTENT);

View File

@ -2,7 +2,6 @@ package eu.siacs.conversations.entities;
import java.security.interfaces.DSAPublicKey; import java.security.interfaces.DSAPublicKey;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import net.java.otr4j.crypto.OtrCryptoEngineImpl; 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.crypto.OtrEngine;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xmpp.XmppConnection; 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.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.os.SystemClock; 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_SUCCESSFULL = 9;
public static final int STATUS_REGISTRATION_NOT_SUPPORTED = 10; public static final int STATUS_REGISTRATION_NOT_SUPPORTED = 10;
protected String username; protected Jid jid;
protected String server;
protected String password; protected String password;
protected int options = 0; protected int options = 0;
protected String rosterVersion; protected String rosterVersion;
protected String resource = "mobile";
protected int status = -1; protected int status = -1;
protected JSONObject keys = new JSONObject(); protected JSONObject keys = new JSONObject();
protected String avatar; protected String avatar;
@ -69,31 +69,36 @@ public class Account extends AbstractEntity {
private String otrFingerprint; private String otrFingerprint;
private Roster roster = null; private Roster roster = null;
private List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>(); private List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<Conversation>(); public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<>();
public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<Conversation>(); public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<>();
public Account() { public Account() {
this.uuid = "0"; this.uuid = "0";
} }
public Account(String username, String server, String password) { public Account(final Jid jid, final String password) {
this(java.util.UUID.randomUUID().toString(), username, server, this(java.util.UUID.randomUUID().toString(), jid,
password, 0, null, "", null); password, 0, null, "", null);
} }
public Account(String uuid, String username, String server, public Account(final String uuid, final Jid jid,
String password, int options, String rosterVersion, String keys, final String password, final int options, final String rosterVersion, final String keys,
String avatar) { final String avatar) {
this.uuid = uuid; this.uuid = uuid;
this.username = username; this.jid = jid;
this.server = server; if (jid.getResourcepart().isEmpty()) {
try {
this.setResource("mobile");
} catch (final InvalidJidException ignored) {
}
}
this.password = password; this.password = password;
this.options = options; this.options = options;
this.rosterVersion = rosterVersion; this.rosterVersion = rosterVersion;
try { try {
this.keys = new JSONObject(keys); this.keys = new JSONObject(keys);
} catch (JSONException e) { } catch (final JSONException ignored) {
} }
this.avatar = avatar; this.avatar = avatar;
@ -112,30 +117,30 @@ public class Account extends AbstractEntity {
} }
public String getUsername() { public String getUsername() {
return username; return jid.getLocalpart();
} }
public void setUsername(String username) { public void setUsername(final String username) throws InvalidJidException {
this.username = username; jid = Jid.fromParts(username, jid.getDomainpart(), jid.getResourcepart());
}
public Jid getServer() {
return jid.toDomainJid();
} }
public String getServer() { public void setServer(final String server) throws InvalidJidException {
return server; jid = Jid.fromParts(jid.getLocalpart(), server, jid.getResourcepart());
}
public void setServer(String server) {
this.server = server;
} }
public String getPassword() { public String getPassword() {
return password; return password;
} }
public void setPassword(String password) { public void setPassword(final String password) {
this.password = password; this.password = password;
} }
public void setStatus(int status) { public void setStatus(final int status) {
this.status = status; this.status = status;
} }
@ -156,25 +161,19 @@ public class Account extends AbstractEntity {
} }
public boolean hasErrorStatus() { public boolean hasErrorStatus() {
if (getXmppConnection() == null) { return getXmppConnection() != null && getStatus() > STATUS_NO_INTERNET && (getXmppConnection().getAttempt() >= 2);
return false;
} else {
return getStatus() > STATUS_NO_INTERNET
&& (getXmppConnection().getAttempt() >= 2);
}
} }
public void setResource(String resource) { public void setResource(final String resource) throws InvalidJidException {
this.resource = resource; jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource);
} }
public String getResource() { public String getResource() {
return this.resource; return jid.getResourcepart();
} }
public String getJid() { public Jid getJid() {
return username.toLowerCase(Locale.getDefault()) + "@" return jid.toBareJid();
+ server.toLowerCase(Locale.getDefault());
} }
public JSONObject getKeys() { public JSONObject getKeys() {
@ -210,8 +209,8 @@ public class Account extends AbstractEntity {
public ContentValues getContentValues() { public ContentValues getContentValues() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(UUID, uuid); values.put(UUID, uuid);
values.put(USERNAME, username); values.put(USERNAME, jid.getLocalpart());
values.put(SERVER, server); values.put(SERVER, jid.getDomainpart());
values.put(PASSWORD, password); values.put(PASSWORD, password);
values.put(OPTIONS, options); values.put(OPTIONS, options);
values.put(KEYS, this.keys.toString()); values.put(KEYS, this.keys.toString());
@ -221,9 +220,14 @@ public class Account extends AbstractEntity {
} }
public static Account fromCursor(Cursor cursor) { public static Account fromCursor(Cursor cursor) {
return new Account(cursor.getString(cursor.getColumnIndex(UUID)), Jid jid = null;
cursor.getString(cursor.getColumnIndex(USERNAME)), try {
cursor.getString(cursor.getColumnIndex(SERVER)), 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.getString(cursor.getColumnIndex(PASSWORD)),
cursor.getInt(cursor.getColumnIndex(OPTIONS)), cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(ROSTERVERSION)), cursor.getString(cursor.getColumnIndex(ROSTERVERSION)),
@ -246,8 +250,8 @@ public class Account extends AbstractEntity {
this.xmppConnection = connection; this.xmppConnection = connection;
} }
public String getFullJid() { public Jid getFullJid() {
return this.getJid() + "/" + this.resource; return this.getJid();
} }
public String getOtrFingerprint() { public String getOtrFingerprint() {
@ -265,7 +269,7 @@ public class Account extends AbstractEntity {
builder.insert(26, " "); builder.insert(26, " ");
builder.insert(35, " "); builder.insert(35, " ");
this.otrFingerprint = builder.toString(); this.otrFingerprint = builder.toString();
} catch (OtrCryptoException e) { } catch (final OtrCryptoException ignored) {
} }
} }

View File

@ -3,15 +3,17 @@ package eu.siacs.conversations.entities;
import java.util.Locale; import java.util.Locale;
import eu.siacs.conversations.xml.Element; 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 { public class Bookmark extends Element implements ListItem {
private Account account; private Account account;
private Conversation mJoinedConversation; private Conversation mJoinedConversation;
public Bookmark(Account account, String jid) { public Bookmark(final Account account, final Jid jid) {
super("conference"); super("conference");
this.setAttribute("jid", jid); this.setAttribute("jid", jid.toString());
this.account = account; this.account = account;
} }
@ -55,10 +57,10 @@ public class Bookmark extends Element implements ListItem {
} }
@Override @Override
public int compareTo(ListItem another) { public int compareTo(final ListItem another) {
return this.getDisplayName().compareToIgnoreCase( return this.getDisplayName().compareToIgnoreCase(
another.getDisplayName()); another.getDisplayName());
} }
@Override @Override
public String getDisplayName() { public String getDisplayName() {
@ -68,16 +70,20 @@ public class Bookmark extends Element implements ListItem {
} else if (getName() != null) { } else if (getName() != null) {
return getName(); return getName();
} else { } else {
return this.getJid().split("@")[0]; return this.getJid().getLocalpart();
} }
} }
@Override @Override
public String getJid() { public Jid getJid() {
String jid = this.getAttribute("jid"); final String jid = this.getAttribute("jid");
if (jid != null) { if (jid != null) {
return jid.toLowerCase(Locale.US); try {
} else { return Jid.fromString(jid);
} catch (final InvalidJidException e) {
return null;
}
} else {
return null; return null;
} }
} }
@ -108,7 +114,7 @@ public class Bookmark extends Element implements ListItem {
public boolean match(String needle) { public boolean match(String needle) {
return needle == null return needle == null
|| getJid().contains(needle.toLowerCase(Locale.US)) || getJid().toString().toLowerCase(Locale.US).contains(needle.toLowerCase(Locale.US))
|| getDisplayName().toLowerCase(Locale.US).contains( || getDisplayName().toLowerCase(Locale.US).contains(
needle.toLowerCase(Locale.US)); needle.toLowerCase(Locale.US));
} }

View File

@ -1,16 +1,18 @@
package eu.siacs.conversations.entities; package eu.siacs.conversations.entities;
import java.util.HashSet; import android.content.ContentValues;
import java.util.Locale; import android.database.Cursor;
import java.util.Set;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.HashSet;
import java.util.Set;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import android.content.ContentValues; import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import android.database.Cursor; import eu.siacs.conversations.xmpp.jid.Jid;
public class Contact implements ListItem { public class Contact implements ListItem {
public static final String TABLENAME = "contacts"; public static final String TABLENAME = "contacts";
@ -31,7 +33,7 @@ public class Contact implements ListItem {
protected String systemName; protected String systemName;
protected String serverName; protected String serverName;
protected String presenceName; protected String presenceName;
protected String jid; protected Jid jid;
protected int subscription = 0; protected int subscription = 0;
protected String systemAccount; protected String systemAccount;
protected String photoUri; protected String photoUri;
@ -41,12 +43,10 @@ public class Contact implements ListItem {
protected Account account; protected Account account;
protected boolean inRoster = true;
public Lastseen lastseen = new Lastseen(); public Lastseen lastseen = new Lastseen();
public Contact(final String account, final String systemName, final String serverName, 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 String systemAccount, final String keys, final String avatar,
final Lastseen lastseen) { final Lastseen lastseen) {
this(account, systemName, serverName, jid, subscription, photoUri, systemAccount, keys, 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, 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 String systemAccount, final String keys, final String avatar) {
this.accountUuid = account; this.accountUuid = account;
this.systemName = systemName; this.systemName = systemName;
@ -72,7 +72,7 @@ public class Contact implements ListItem {
this.avatar = avatar; this.avatar = avatar;
} }
public Contact(final String jid) { public Contact(final Jid jid) {
this.jid = jid; this.jid = jid;
} }
@ -84,7 +84,7 @@ public class Contact implements ListItem {
} else if (this.presenceName != null) { } else if (this.presenceName != null) {
return this.presenceName; return this.presenceName;
} else { } else {
return this.jid.split("@")[0]; return jid.getLocalpart();
} }
} }
@ -92,13 +92,13 @@ public class Contact implements ListItem {
return this.photoUri; return this.photoUri;
} }
public String getJid() { public Jid getJid() {
return this.jid.toLowerCase(Locale.getDefault()); return jid;
} }
public boolean match(String needle) { public boolean match(String needle) {
return needle == null return needle == null
|| jid.contains(needle.toLowerCase()) || jid.toString().contains(needle.toLowerCase())
|| getDisplayName().toLowerCase() || getDisplayName().toLowerCase()
.contains(needle.toLowerCase()); .contains(needle.toLowerCase());
} }
@ -108,7 +108,7 @@ public class Contact implements ListItem {
values.put(ACCOUNT, accountUuid); values.put(ACCOUNT, accountUuid);
values.put(SYSTEMNAME, systemName); values.put(SYSTEMNAME, systemName);
values.put(SERVERNAME, serverName); values.put(SERVERNAME, serverName);
values.put(JID, jid); values.put(JID, jid.toString());
values.put(OPTIONS, subscription); values.put(OPTIONS, subscription);
values.put(SYSTEMACCOUNT, systemAccount); values.put(SYSTEMACCOUNT, systemAccount);
values.put(PHOTOURI, photoUri); values.put(PHOTOURI, photoUri);
@ -123,10 +123,17 @@ public class Contact implements ListItem {
final Lastseen lastseen = new Lastseen( final Lastseen lastseen = new Lastseen(
cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)), cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)),
cursor.getLong(cursor.getColumnIndex(LAST_TIME))); 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(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)), cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(JID)), jid,
cursor.getInt(cursor.getColumnIndex(OPTIONS)), cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)), cursor.getString(cursor.getColumnIndex(PHOTOURI)),
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)), cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
@ -198,7 +205,7 @@ public class Contact implements ListItem {
} }
public Set<String> getOtrFingerprints() { public Set<String> getOtrFingerprints() {
Set<String> set = new HashSet<String>(); Set<String> set = new HashSet<>();
try { try {
if (this.keys.has("otr_fingerprints")) { if (this.keys.has("otr_fingerprints")) {
JSONArray fingerprints = this.keys JSONArray fingerprints = this.keys
@ -225,7 +232,7 @@ public class Contact implements ListItem {
} }
fingerprints.put(print); fingerprints.put(print);
this.keys.put("otr_fingerprints", fingerprints); 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) { public void setPgpKeyId(long keyId) {
try { try {
this.keys.put("pgp_keyid", keyId); 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"); String subscription = item.getAttribute("subscription");
if (subscription != null) { if (subscription != null) {
if (subscription.equals("to")) { switch (subscription) {
this.resetOption(Contact.Options.FROM); case "to":
this.setOption(Contact.Options.TO); this.resetOption(Options.FROM);
} else if (subscription.equals("from")) { this.setOption(Options.TO);
this.resetOption(Contact.Options.TO); break;
this.setOption(Contact.Options.FROM); case "from":
this.resetOption(Contact.Options.PREEMPTIVE_GRANT); this.resetOption(Options.TO);
} else if (subscription.equals("both")) { this.setOption(Options.FROM);
this.setOption(Contact.Options.TO); this.resetOption(Options.PREEMPTIVE_GRANT);
this.setOption(Contact.Options.FROM); break;
this.resetOption(Contact.Options.PREEMPTIVE_GRANT); case "both":
} else if (subscription.equals("none")) { this.setOption(Options.TO);
this.resetOption(Contact.Options.FROM); this.setOption(Options.FROM);
this.resetOption(Contact.Options.TO); 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 // do NOT override asking if pending push request
@ -301,8 +313,8 @@ public class Contact implements ListItem {
} }
public Element asElement() { public Element asElement() {
Element item = new Element("item"); final Element item = new Element("item");
item.setAttribute("jid", this.jid); item.setAttribute("jid", this.jid.toString());
if (this.serverName != null) { if (this.serverName != null) {
item.setAttribute("name", this.serverName); item.setAttribute("name", this.serverName);
} }
@ -335,18 +347,13 @@ public class Contact implements ListItem {
} }
@Override @Override
public int compareTo(ListItem another) { public int compareTo(final ListItem another) {
return this.getDisplayName().compareToIgnoreCase( return this.getDisplayName().compareToIgnoreCase(
another.getDisplayName()); another.getDisplayName());
} }
public String getServer() { public Jid getServer() {
String[] split = getJid().split("@"); return getJid().toDomainJid();
if (split.length >= 2) {
return split[1];
} else {
return null;
}
} }
public boolean setAvatar(String filename) { public boolean setAvatar(String filename) {

View File

@ -1,13 +1,8 @@
package eu.siacs.conversations.entities; package eu.siacs.conversations.entities;
import java.security.interfaces.DSAPublicKey; import android.content.ContentValues;
import java.util.ArrayList; import android.database.Cursor;
import java.util.List; import android.os.SystemClock;
import org.json.JSONException;
import org.json.JSONObject;
import eu.siacs.conversations.services.XmppConnectionService;
import net.java.otr4j.OtrException; import net.java.otr4j.OtrException;
import net.java.otr4j.crypto.OtrCryptoEngineImpl; 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.SessionID;
import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus; import net.java.otr4j.session.SessionStatus;
import android.content.ContentValues;
import android.database.Cursor; import org.json.JSONException;
import android.os.SystemClock; 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 class Conversation extends AbstractEntity {
public static final String TABLENAME = "conversations"; public static final String TABLENAME = "conversations";
@ -45,7 +48,7 @@ public class Conversation extends AbstractEntity {
private String name; private String name;
private String contactUuid; private String contactUuid;
private String accountUuid; private String accountUuid;
private String contactJid; private Jid contactJid;
private int status; private int status;
private long created; private long created;
private int mode; private int mode;
@ -54,7 +57,7 @@ public class Conversation extends AbstractEntity {
private String nextPresence; private String nextPresence;
protected ArrayList<Message> messages = new ArrayList<Message>(); protected ArrayList<Message> messages = new ArrayList<>();
protected Account account = null; protected Account account = null;
private transient SessionImpl otrSession; private transient SessionImpl otrSession;
@ -71,17 +74,17 @@ public class Conversation extends AbstractEntity {
private Bookmark bookmark; private Bookmark bookmark;
public Conversation(String name, Account account, String contactJid, public Conversation(final String name, final Account account, final Jid contactJid,
int mode) { final int mode) {
this(java.util.UUID.randomUUID().toString(), name, null, account this(java.util.UUID.randomUUID().toString(), name, null, account
.getUuid(), contactJid, System.currentTimeMillis(), .getUuid(), contactJid, System.currentTimeMillis(),
STATUS_AVAILABLE, mode, ""); STATUS_AVAILABLE, mode, "");
this.account = account; this.account = account;
} }
public Conversation(String uuid, String name, String contactUuid, public Conversation(final String uuid, final String name, final String contactUuid,
String accountUuid, String contactJid, long created, int status, final String accountUuid, final Jid contactJid, final long created, final int status,
int mode, String attributes) { final int mode, final String attributes) {
this.uuid = uuid; this.uuid = uuid;
this.name = name; this.name = name;
this.contactUuid = contactUuid; this.contactUuid = contactUuid;
@ -91,10 +94,7 @@ public class Conversation extends AbstractEntity {
this.status = status; this.status = status;
this.mode = mode; this.mode = mode;
try { try {
if (attributes == null) { this.attributes = new JSONObject(attributes == null ? "" : attributes);
attributes = new String();
}
this.attributes = new JSONObject(attributes);
} catch (JSONException e) { } catch (JSONException e) {
this.attributes = new JSONObject(); this.attributes = new JSONObject();
} }
@ -105,10 +105,8 @@ public class Conversation extends AbstractEntity {
} }
public boolean isRead() { public boolean isRead() {
if ((this.messages == null) || (this.messages.size() == 0)) return (this.messages == null) || (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead();
return true; }
return this.messages.get(this.messages.size() - 1).isRead();
}
public void markRead() { public void markRead() {
if (this.messages == null) { if (this.messages == null) {
@ -186,7 +184,7 @@ public class Conversation extends AbstractEntity {
this.account = account; this.account = account;
} }
public String getContactJid() { public Jid getContactJid() {
return this.contactJid; return this.contactJid;
} }
@ -204,7 +202,7 @@ public class Conversation extends AbstractEntity {
values.put(NAME, name); values.put(NAME, name);
values.put(CONTACT, contactUuid); values.put(CONTACT, contactUuid);
values.put(ACCOUNT, accountUuid); values.put(ACCOUNT, accountUuid);
values.put(CONTACTJID, contactJid); values.put(CONTACTJID, contactJid.toString());
values.put(CREATED, created); values.put(CREATED, created);
values.put(STATUS, status); values.put(STATUS, status);
values.put(MODE, mode); values.put(MODE, mode);
@ -213,11 +211,18 @@ public class Conversation extends AbstractEntity {
} }
public static Conversation fromCursor(Cursor cursor) { 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(NAME)),
cursor.getString(cursor.getColumnIndex(CONTACT)), cursor.getString(cursor.getColumnIndex(CONTACT)),
cursor.getString(cursor.getColumnIndex(ACCOUNT)), cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(CONTACTJID)), jid,
cursor.getLong(cursor.getColumnIndex(CREATED)), cursor.getLong(cursor.getColumnIndex(CREATED)),
cursor.getInt(cursor.getColumnIndex(STATUS)), cursor.getInt(cursor.getColumnIndex(STATUS)),
cursor.getInt(cursor.getColumnIndex(MODE)), cursor.getInt(cursor.getColumnIndex(MODE)),
@ -241,8 +246,9 @@ public class Conversation extends AbstractEntity {
if (this.otrSession != null) { if (this.otrSession != null) {
return this.otrSession; return this.otrSession;
} else { } else {
SessionID sessionId = new SessionID(this.getContactJid().split("/", final SessionID sessionId = new SessionID(this.getContactJid().toBareJid().toString(),
2)[0], presence, "xmpp"); presence,
"xmpp");
this.otrSession = new SessionImpl(sessionId, getAccount() this.otrSession = new SessionImpl(sessionId, getAccount()
.getOtrEngine(service)); .getOtrEngine(service));
try { try {
@ -317,7 +323,7 @@ public class Conversation extends AbstractEntity {
builder.insert(26, " "); builder.insert(26, " ");
builder.insert(35, " "); builder.insert(35, " ");
this.otrFingerprint = builder.toString(); this.otrFingerprint = builder.toString();
} catch (OtrCryptoException e) { } catch (final OtrCryptoException ignored) {
} }
} }
@ -335,7 +341,7 @@ public class Conversation extends AbstractEntity {
this.mucOptions = null; this.mucOptions = null;
} }
public void setContactJid(String jid) { public void setContactJid(final Jid jid) {
this.contactJid = jid; this.contactJid = jid;
} }

View File

@ -1,7 +1,9 @@
package eu.siacs.conversations.entities; package eu.siacs.conversations.entities;
import eu.siacs.conversations.xmpp.jid.Jid;
public interface ListItem extends Comparable<ListItem> { public interface ListItem extends Comparable<ListItem> {
public String getDisplayName(); public String getDisplayName();
public String getJid(); public Jid getJid();
} }

View File

@ -5,6 +5,9 @@ import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import eu.siacs.conversations.Config; 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.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
@ -44,7 +47,7 @@ public class Message extends AbstractEntity {
public static String REMOTE_MSG_ID = "remoteMsgId"; public static String REMOTE_MSG_ID = "remoteMsgId";
protected String conversationUuid; protected String conversationUuid;
protected String counterpart; protected Jid counterpart;
protected String trueCounterpart; protected String trueCounterpart;
protected String body; protected String body;
protected String encryptedBody; protected String encryptedBody;
@ -74,17 +77,17 @@ public class Message extends AbstractEntity {
this.conversation = conversation; this.conversation = conversation;
} }
public Message(Conversation conversation, String counterpart, String body, public Message(final Conversation conversation, final Jid counterpart, final String body,
int encryption, int status) { final int encryption, final int status) {
this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), this(java.util.UUID.randomUUID().toString(), conversation.getUuid(),
counterpart, null, body, System.currentTimeMillis(), counterpart, null, body, System.currentTimeMillis(),
encryption, status, TYPE_TEXT, null); encryption, status, TYPE_TEXT, null);
this.conversation = conversation; this.conversation = conversation;
} }
public Message(String uuid, String conversationUUid, String counterpart, public Message(final String uuid, final String conversationUUid, final Jid counterpart,
String trueCounterpart, String body, long timeSent, int encryption, final String trueCounterpart, final String body, final long timeSent,
int status, int type, String remoteMsgId) { final int encryption, final int status, final int type, final String remoteMsgId) {
this.uuid = uuid; this.uuid = uuid;
this.conversationUuid = conversationUUid; this.conversationUuid = conversationUUid;
this.counterpart = counterpart; this.counterpart = counterpart;
@ -102,7 +105,7 @@ public class Message extends AbstractEntity {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(UUID, uuid); values.put(UUID, uuid);
values.put(CONVERSATION, conversationUuid); values.put(CONVERSATION, conversationUuid);
values.put(COUNTERPART, counterpart); values.put(COUNTERPART, counterpart.toString());
values.put(TRUE_COUNTERPART, trueCounterpart); values.put(TRUE_COUNTERPART, trueCounterpart);
values.put(BODY, body); values.put(BODY, body);
values.put(TIME_SENT, timeSent); values.put(TIME_SENT, timeSent);
@ -121,7 +124,7 @@ public class Message extends AbstractEntity {
return this.conversation; return this.conversation;
} }
public String getCounterpart() { public Jid getCounterpart() {
return counterpart; return counterpart;
} }
@ -163,9 +166,15 @@ public class Message extends AbstractEntity {
} }
public static Message fromCursor(Cursor cursor) { 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(CONVERSATION)),
cursor.getString(cursor.getColumnIndex(COUNTERPART)), jid,
cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)), cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)),
cursor.getString(cursor.getColumnIndex(BODY)), cursor.getString(cursor.getColumnIndex(BODY)),
cursor.getLong(cursor.getColumnIndex(TIME_SENT)), cursor.getLong(cursor.getColumnIndex(TIME_SENT)),
@ -225,11 +234,14 @@ public class Message extends AbstractEntity {
public void setPresence(String presence) { public void setPresence(String presence) {
if (presence == null) { if (presence == null) {
this.counterpart = this.counterpart.split("/", 2)[0]; this.counterpart = this.counterpart.toBareJid();
} else { } else {
this.counterpart = this.counterpart.split("/", 2)[0] + "/" try {
+ presence; this.counterpart = Jid.fromString(this.counterpart.toBareJid() + "/" + presence);
} } catch (final InvalidJidException ignored) {
// TODO: Handle this?
}
}
} }
public void setTrueCounterpart(String trueCounterpart) { public void setTrueCounterpart(String trueCounterpart) {
@ -237,15 +249,11 @@ public class Message extends AbstractEntity {
} }
public String getPresence() { public String getPresence() {
String[] counterparts = this.counterpart.split("/", 2); if (!counterpart.getResourcepart().isEmpty()) {
if (counterparts.length == 2) { return counterpart.getResourcepart();
return counterparts[1];
} else { } else {
if (this.counterpart.contains("/")) { // TODO: Return empty string or null?
return ""; return null;
} else {
return null;
}
} }
} }
@ -264,7 +272,7 @@ public class Message extends AbstractEntity {
return message; return message;
} }
public void setCounterpart(String counterpart) { public void setCounterpart(final Jid counterpart) {
this.counterpart = counterpart; this.counterpart = counterpart;
} }
@ -359,11 +367,7 @@ public class Message extends AbstractEntity {
public boolean wasMergedIntoPrevious() { public boolean wasMergedIntoPrevious() {
Message prev = this.prev(); Message prev = this.prev();
if (prev == null) { return prev != null && prev.mergeable(this);
return false;
} else {
return prev.mergeable(this);
}
} }
public boolean trusted() { public boolean trusted() {

View File

@ -6,6 +6,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.xml.Element; 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 eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -66,15 +68,20 @@ public class MucOptions {
public void setRole(String role) { public void setRole(String role) {
role = role.toLowerCase(); role = role.toLowerCase();
if (role.equals("moderator")) { switch (role) {
this.role = ROLE_MODERATOR; case "moderator":
} else if (role.equals("participant")) { this.role = ROLE_MODERATOR;
this.role = ROLE_PARTICIPANT; break;
} else if (role.equals("visitor")) { case "participant":
this.role = ROLE_VISITOR; this.role = ROLE_PARTICIPANT;
} else { break;
this.role = ROLE_NONE; case "visitor":
} this.role = ROLE_VISITOR;
break;
default:
this.role = ROLE_NONE;
break;
}
} }
public int getAffiliation() { public int getAffiliation() {
@ -109,7 +116,7 @@ public class MucOptions {
} }
private Account account; private Account account;
private List<User> users = new CopyOnWriteArrayList<User>(); private List<User> users = new CopyOnWriteArrayList<>();
private Conversation conversation; private Conversation conversation;
private boolean isOnline = false; private boolean isOnline = false;
private int error = ERROR_ROOM_NOT_FOUND; private int error = ERROR_ROOM_NOT_FOUND;
@ -233,13 +240,12 @@ public class MucOptions {
} }
public String getProposedNick() { public String getProposedNick() {
String[] mucParts = conversation.getContactJid().split("/", 2);
if (conversation.getBookmark() != null if (conversation.getBookmark() != null
&& conversation.getBookmark().getNick() != null) { && conversation.getBookmark().getNick() != null) {
return conversation.getBookmark().getNick(); return conversation.getBookmark().getNick();
} else { } else {
if (mucParts.length == 2) { if (!conversation.getContactJid().getResourcepart().isEmpty()) {
return mucParts[1]; return conversation.getContactJid().getResourcepart();
} else { } else {
return account.getUsername(); return account.getUsername();
} }
@ -297,7 +303,7 @@ public class MucOptions {
} }
public long[] getPgpKeyIds() { public long[] getPgpKeyIds() {
List<Long> ids = new ArrayList<Long>(); List<Long> ids = new ArrayList<>();
for (User user : getUsers()) { for (User user : getUsers()) {
if (user.getPgpKeyId() != 0) { if (user.getPgpKeyId() != 0) {
ids.add(user.getPgpKeyId()); ids.add(user.getPgpKeyId());
@ -328,10 +334,14 @@ public class MucOptions {
return true; return true;
} }
public String getJoinJid() { public Jid getJoinJid() {
return this.conversation.getContactJid().split("/", 2)[0] + "/" try {
+ this.joinnick; return Jid.fromString(this.conversation.getContactJid().toBareJid().toString() + "/"
} + this.joinnick);
} catch (final InvalidJidException e) {
return null;
}
}
public String getTrueCounterpart(String counterpart) { public String getTrueCounterpart(String counterpart) {
for (User user : this.getUsers()) { for (User user : this.getUsers()) {

View File

@ -2,12 +2,13 @@ package eu.siacs.conversations.entities;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import eu.siacs.conversations.xmpp.jid.Jid;
public class Roster { public class Roster {
Account account; Account account;
ConcurrentHashMap<String, Contact> contacts = new ConcurrentHashMap<String, Contact>(); final ConcurrentHashMap<String, Contact> contacts = new ConcurrentHashMap<>();
private String version = null; private String version = null;
public Roster(Account account) { public Roster(Account account) {
@ -27,14 +28,14 @@ public class Roster {
} }
} }
public Contact getContact(String jid) { public Contact getContact(final Jid jid) {
String cleanJid = jid.split("/", 2)[0].toLowerCase(Locale.getDefault()); final Jid bareJid = jid.toBareJid();
if (contacts.containsKey(cleanJid)) { if (contacts.containsKey(bareJid.toString())) {
return contacts.get(cleanJid); return contacts.get(bareJid.toString());
} else { } else {
Contact contact = new Contact(cleanJid); Contact contact = new Contact(bareJid);
contact.setAccount(account); contact.setAccount(account);
contacts.put(cleanJid, contact); contacts.put(bareJid.toString(), contact);
return contact; return contact;
} }
} }
@ -60,13 +61,13 @@ public class Roster {
} }
public List<Contact> getContacts() { 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.setAccount(account);
contact.setOption(Contact.Options.IN_ROSTER); contact.setOption(Contact.Options.IN_ROSTER);
contacts.put(contact.getJid(), contact); contacts.put(contact.getJid().toBareJid().toString(), contact);
} }
public void setVersion(String version) { public void setVersion(String version) {

View File

@ -6,6 +6,7 @@ import java.util.List;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; 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.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
@ -18,7 +19,7 @@ public class IqGenerator extends AbstractGenerator {
public IqPacket discoResponse(IqPacket request) { public IqPacket discoResponse(IqPacket request) {
IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT); IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT);
packet.setId(request.getId()); packet.setId(request.getId());
packet.setTo(request.getFrom()); packet.setAttribute("to", request.getFrom());
Element query = packet.addChild("query", Element query = packet.addChild("query",
"http://jabber.org/protocol/disco#info"); "http://jabber.org/protocol/disco#info");
query.setAttribute("node", request.query().getAttribute("node")); query.setAttribute("node", request.query().getAttribute("node"));
@ -86,8 +87,8 @@ public class IqGenerator extends AbstractGenerator {
return packet; return packet;
} }
public IqPacket retrieveAvatarMetaData(String to) { public IqPacket retrieveAvatarMetaData(final Jid to) {
IqPacket packet = retrieve("urn:xmpp:avatar:metadata", null); final IqPacket packet = retrieve("urn:xmpp:avatar:metadata", null);
if (to != null) { if (to != null) {
packet.setTo(to); packet.setTo(to);
} }

View File

@ -12,6 +12,7 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class MessageGenerator extends AbstractGenerator { public class MessageGenerator extends AbstractGenerator {
@ -34,7 +35,7 @@ public class MessageGenerator extends AbstractGenerator {
packet.setTo(message.getCounterpart()); packet.setTo(message.getCounterpart());
packet.setType(MessagePacket.TYPE_CHAT); packet.setType(MessagePacket.TYPE_CHAT);
} else { } else {
packet.setTo(message.getCounterpart().split("/", 2)[0]); packet.setTo(message.getCounterpart().toBareJid());
packet.setType(MessagePacket.TYPE_GROUPCHAT); packet.setType(MessagePacket.TYPE_GROUPCHAT);
} }
packet.setFrom(account.getFullJid()); packet.setFrom(account.getFullJid());
@ -113,13 +114,13 @@ public class MessageGenerator extends AbstractGenerator {
private MessagePacket generateError(MessagePacket origin) { private MessagePacket generateError(MessagePacket origin) {
MessagePacket packet = new MessagePacket(); MessagePacket packet = new MessagePacket();
packet.setId(origin.getId()); packet.setId(origin.getId());
packet.setTo(origin.getFrom()); packet.setAttribute("to", origin.getFrom());
packet.setBody(origin.getBody()); packet.setBody(origin.getBody());
packet.setType(MessagePacket.TYPE_ERROR); packet.setType(MessagePacket.TYPE_ERROR);
return packet; 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(); MessagePacket packet = new MessagePacket();
packet.setType(MessagePacket.TYPE_NORMAL); packet.setType(MessagePacket.TYPE_NORMAL);
packet.setTo(to); packet.setTo(to);
@ -134,7 +135,7 @@ public class MessageGenerator extends AbstractGenerator {
String subject) { String subject) {
MessagePacket packet = new MessagePacket(); MessagePacket packet = new MessagePacket();
packet.setType(MessagePacket.TYPE_GROUPCHAT); packet.setType(MessagePacket.TYPE_GROUPCHAT);
packet.setTo(conversation.getContactJid().split("/", 2)[0]); packet.setTo(conversation.getContactJid().toBareJid());
Element subjectChild = new Element("subject"); Element subjectChild = new Element("subject");
subjectChild.setContent(subject); subjectChild.setContent(subject);
packet.addChild(subjectChild); packet.addChild(subjectChild);
@ -142,19 +143,19 @@ public class MessageGenerator extends AbstractGenerator {
return packet; return packet;
} }
public MessagePacket directInvite(Conversation conversation, String contact) { public MessagePacket directInvite(final Conversation conversation, final Jid contact) {
MessagePacket packet = new MessagePacket(); MessagePacket packet = new MessagePacket();
packet.setType(MessagePacket.TYPE_NORMAL); packet.setType(MessagePacket.TYPE_NORMAL);
packet.setTo(contact); packet.setTo(contact);
packet.setFrom(conversation.getAccount().getFullJid()); packet.setFrom(conversation.getAccount().getFullJid());
Element x = packet.addChild("x", "jabber:x:conference"); 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; return packet;
} }
public MessagePacket invite(Conversation conversation, String contact) { public MessagePacket invite(Conversation conversation, String contact) {
MessagePacket packet = new MessagePacket(); MessagePacket packet = new MessagePacket();
packet.setTo(conversation.getContactJid().split("/", 2)[0]); packet.setTo(conversation.getContactJid().toBareJid());
packet.setFrom(conversation.getAccount().getFullJid()); packet.setFrom(conversation.getAccount().getFullJid());
Element x = new Element("x"); Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user"); x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
@ -169,7 +170,7 @@ public class MessageGenerator extends AbstractGenerator {
MessagePacket originalMessage, String namespace) { MessagePacket originalMessage, String namespace) {
MessagePacket receivedPacket = new MessagePacket(); MessagePacket receivedPacket = new MessagePacket();
receivedPacket.setType(MessagePacket.TYPE_NORMAL); receivedPacket.setType(MessagePacket.TYPE_NORMAL);
receivedPacket.setTo(originalMessage.getFrom()); receivedPacket.setAttribute("to", originalMessage.getFrom());
receivedPacket.setFrom(account.getFullJid()); receivedPacket.setFrom(account.getFullJid());
Element received = receivedPacket.addChild("received", namespace); Element received = receivedPacket.addChild("received", namespace);
received.setAttribute("id", originalMessage.getId()); received.setAttribute("id", originalMessage.getId());

View File

@ -15,8 +15,8 @@ public class PresenceGenerator extends AbstractGenerator {
private PresencePacket subscription(String type, Contact contact) { private PresencePacket subscription(String type, Contact contact) {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("type", type); packet.setAttribute("type", type);
packet.setAttribute("to", contact.getJid()); packet.setTo(contact.getJid());
packet.setAttribute("from", contact.getAccount().getJid()); packet.setFrom(contact.getAccount().getJid());
return packet; return packet;
} }
@ -38,7 +38,7 @@ public class PresenceGenerator extends AbstractGenerator {
public PresencePacket sendPresence(Account account) { public PresencePacket sendPresence(Account account) {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("from", account.getFullJid()); packet.setFrom(account.getFullJid());
String sig = account.getPgpSignature(); String sig = account.getPgpSignature();
if (sig != null) { if (sig != null) {
packet.addChild("status").setContent("online"); packet.addChild("status").setContent("online");

View File

@ -11,6 +11,8 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
public abstract class AbstractParser { public abstract class AbstractParser {
@ -22,7 +24,7 @@ public abstract class AbstractParser {
protected long getTimestamp(Element packet) { protected long getTimestamp(Element packet) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
ArrayList<String> stamps = new ArrayList<String>(); ArrayList<String> stamps = new ArrayList<>();
for (Element child : packet.getChildren()) { for (Element child : packet.getChildren()) {
if (child.getName().equals("delay")) { if (child.getName().equals("delay")) {
stamps.add(child.getAttribute("stamp").replace("Z", "+0000")); stamps.add(child.getAttribute("stamp").replace("Z", "+0000"));
@ -58,21 +60,21 @@ public abstract class AbstractParser {
} }
} }
protected void updateLastseen(Element packet, Account account, protected void updateLastseen(final Element packet, final Account account,
boolean presenceOverwrite) { final boolean presenceOverwrite) {
String[] fromParts = packet.getAttribute("from").split("/", 2); Jid from;
String from = fromParts[0]; try {
String presence = null; from = Jid.fromString(packet.getAttribute("from")).toBareJid();
if (fromParts.length >= 2) { } catch (final InvalidJidException e) {
presence = fromParts[1]; // TODO: Handle this?
} else { from = null;
presence = ""; }
} String presence = from == null || from.getResourcepart().isEmpty() ? "" : from.getResourcepart();
Contact contact = account.getRoster().getContact(from); Contact contact = account.getRoster().getContact(from);
long timestamp = getTimestamp(packet); long timestamp = getTimestamp(packet);
if (timestamp >= contact.lastseen.time) { if (timestamp >= contact.lastseen.time) {
contact.lastseen.time = timestamp; contact.lastseen.time = timestamp;
if ((presence != null) && (presenceOverwrite)) { if (!presence.isEmpty() && presenceOverwrite) {
contact.lastseen.presence = presence; contact.lastseen.presence = presence;
} }
} }

View File

@ -5,6 +5,8 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived; 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; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class IqParser extends AbstractParser implements OnIqPacketReceived { public class IqParser extends AbstractParser implements OnIqPacketReceived {
@ -20,8 +22,14 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
} }
for (Element item : query.getChildren()) { for (Element item : query.getChildren()) {
if (item.getName().equals("item")) { if (item.getName().equals("item")) {
String jid = item.getAttribute("jid"); Jid jid;
String name = item.getAttribute("name"); 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"); String subscription = item.getAttribute("subscription");
Contact contact = account.getRoster().getContact(jid); Contact contact = account.getRoster().getContact(jid);
if (!contact.getOption(Contact.Options.DIRTY_PUSH)) { if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
@ -59,8 +67,13 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.hasChild("query", "jabber:iq:roster")) { if (packet.hasChild("query", "jabber:iq:roster")) {
String from = packet.getFrom(); Jid from = null;
if ((from == null) || (from.equals(account.getJid()))) { 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"); Element query = packet.findChild("query");
this.rosterItems(account, query); this.rosterItems(account, query);
} }

View File

@ -9,6 +9,8 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.entities.Roster;
import eu.siacs.conversations.xmpp.jid.Jid;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteCantOpenDatabaseException; import android.database.sqlite.SQLiteCantOpenDatabaseException;
@ -147,7 +149,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
} }
public CopyOnWriteArrayList<Conversation> getConversations(int status) { public CopyOnWriteArrayList<Conversation> getConversations(int status) {
CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<Conversation>(); CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { Integer.toString(status) }; String[] selectionArgs = { Integer.toString(status) };
Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME
@ -165,7 +167,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public ArrayList<Message> getMessages(Conversation conversation, int limit, public ArrayList<Message> getMessages(Conversation conversation, int limit,
long timestamp) { long timestamp) {
ArrayList<Message> list = new ArrayList<Message>(); ArrayList<Message> list = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor; Cursor cursor;
if (timestamp == -1) { if (timestamp == -1) {
@ -192,9 +194,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
return list; return list;
} }
public Conversation findConversation(Account account, String contactJid) { public Conversation findConversation(final Account account, final Jid contactJid) {
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { account.getUuid(), contactJid + "%" }; String[] selectionArgs = { account.getUuid(), contactJid.toBareJid().toString() + "%" };
Cursor cursor = db.query(Conversation.TABLENAME, null, Cursor cursor = db.query(Conversation.TABLENAME, null,
Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID
+ " like ?", selectionArgs, null, null, null); + " like ?", selectionArgs, null, null, null);
@ -212,7 +214,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
} }
public List<Account> getAccounts() { public List<Account> getAccounts() {
List<Account> list = new ArrayList<Account>(); List<Account> list = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(Account.TABLENAME, null, null, null, null, Cursor cursor = db.query(Account.TABLENAME, null, null, null, null,
null, null); null, null);
@ -276,15 +278,15 @@ public class DatabaseBackend extends SQLiteOpenHelper {
cursor.close(); cursor.close();
} }
public void writeRoster(Roster roster) { public void writeRoster(final Roster roster) {
Account account = roster.getAccount(); final Account account = roster.getAccount();
SQLiteDatabase db = this.getWritableDatabase(); final SQLiteDatabase db = this.getWritableDatabase();
for (Contact contact : roster.getContacts()) { for (Contact contact : roster.getContacts()) {
if (contact.getOption(Contact.Options.IN_ROSTER)) { if (contact.getOption(Contact.Options.IN_ROSTER)) {
db.insert(Contact.TABLENAME, null, contact.getContentValues()); db.insert(Contact.TABLENAME, null, contact.getContentValues());
} else { } else {
String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?"; 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); db.delete(Contact.TABLENAME, where, whereArgs);
} }
} }
@ -341,7 +343,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
} }
public List<Message> getImageMessages(Conversation conversation) { public List<Message> getImageMessages(Conversation conversation) {
ArrayList<Message> list = new ArrayList<Message>(); ArrayList<Message> list = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor; Cursor cursor;
String[] selectionArgs = { conversation.getUuid(), String.valueOf(Message.TYPE_IMAGE) }; String[] selectionArgs = { conversation.getUuid(), String.valueOf(Message.TYPE_IMAGE) };

View File

@ -55,6 +55,8 @@ import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.OnMessageAcknowledged; import eu.siacs.conversations.xmpp.OnMessageAcknowledged;
import eu.siacs.conversations.xmpp.OnStatusChanged; import eu.siacs.conversations.xmpp.OnStatusChanged;
import eu.siacs.conversations.xmpp.XmppConnection; 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.JingleConnectionManager;
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
@ -91,8 +93,6 @@ public class XmppConnectionService extends Service {
public DatabaseBackend databaseBackend; public DatabaseBackend databaseBackend;
private FileBackend fileBackend = new FileBackend(this); private FileBackend fileBackend = new FileBackend(this);
public long startDate;
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
public static String ACTION_CLEAR_NOTIFICATION = "clear_notification"; public static String ACTION_CLEAR_NOTIFICATION = "clear_notification";
@ -171,7 +171,6 @@ public class XmppConnectionService extends Service {
XmppConnection connection = account.getXmppConnection(); XmppConnection connection = account.getXmppConnection();
if (mOnAccountUpdate != null) { if (mOnAccountUpdate != null) {
mOnAccountUpdate.onAccountUpdate(); mOnAccountUpdate.onAccountUpdate();
;
} }
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
for (Conversation conversation : account.pendingConferenceLeaves) { for (Conversation conversation : account.pendingConferenceLeaves) {
@ -182,12 +181,12 @@ public class XmppConnectionService extends Service {
} }
mJingleConnectionManager.cancelInTransmission(); mJingleConnectionManager.cancelInTransmission();
List<Conversation> conversations = getConversations(); List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); ++i) { for (Conversation conversation : conversations) {
if (conversations.get(i).getAccount() == account) { if (conversation.getAccount() == account) {
conversations.get(i).startOtrIfNeeded(); conversation.startOtrIfNeeded();
sendUnsendMessages(conversations.get(i)); sendUnsendMessages(conversation);
} }
} }
if (connection != null && connection.getFeatures().csi()) { if (connection != null && connection.getFeatures().csi()) {
if (checkListeners()) { if (checkListeners()) {
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid()
@ -335,7 +334,7 @@ public class XmppConnectionService extends Service {
return find(bookmark.getAccount(), bookmark.getJid()); 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); return find(getConversations(), account, jid);
} }
@ -415,7 +414,7 @@ public class XmppConnectionService extends Service {
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); wakeLock.release();
} catch (RuntimeException re) { } catch (final RuntimeException ignored) {
} }
} }
return START_STICKY; return START_STICKY;
@ -536,9 +535,12 @@ public class XmppConnectionService extends Service {
public XmppConnection createConnection(Account account) { public XmppConnection createConnection(Account account) {
SharedPreferences sharedPref = getPreferences(); SharedPreferences sharedPref = getPreferences();
account.setResource(sharedPref.getString("resource", "mobile") try {
.toLowerCase(Locale.getDefault())); account.setResource(sharedPref.getString("resource", "mobile")
XmppConnection connection = new XmppConnection(account, this); .toLowerCase(Locale.getDefault()));
} catch (final InvalidJidException ignored) {
}
XmppConnection connection = new XmppConnection(account, this);
connection.setOnMessagePacketReceivedListener(this.mMessageParser); connection.setOnMessagePacketReceivedListener(this.mMessageParser);
connection.setOnStatusChangedListener(this.statusListener); connection.setOnStatusChangedListener(this.statusListener);
connection.setOnPresencePacketReceivedListener(this.mPresenceParser); connection.setOnPresencePacketReceivedListener(this.mPresenceParser);
@ -757,7 +759,7 @@ public class XmppConnectionService extends Service {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
Element query = packet.query(); Element query = packet.query();
List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>(); List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
Element storage = query.findChild("storage", Element storage = query.findChild("storage",
"storage:bookmarks"); "storage:bookmarks");
if (storage != null) { if (storage != null) {
@ -806,8 +808,14 @@ public class XmppConnectionService extends Service {
} }
for (Bundle phoneContact : phoneContacts) { for (Bundle phoneContact : phoneContacts) {
for (Account account : accounts) { for (Account account : accounts) {
String jid = phoneContact.getString("jid"); Jid jid;
Contact contact = account.getRoster() 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); .getContact(jid);
String systemAccount = phoneContact String systemAccount = phoneContact
.getInt("phoneid") .getInt("phoneid")
@ -827,7 +835,7 @@ public class XmppConnectionService extends Service {
public List<Conversation> getConversations() { public List<Conversation> getConversations() {
if (this.conversations == null) { if (this.conversations == null) {
Hashtable<String, Account> accountLookupTable = new Hashtable<String, Account>(); Hashtable<String, Account> accountLookupTable = new Hashtable<>();
for (Account account : this.accounts) { for (Account account : this.accounts) {
accountLookupTable.put(account.getUuid(), account); accountLookupTable.put(account.getUuid(), account);
} }
@ -925,20 +933,20 @@ public class XmppConnectionService extends Service {
return null; return null;
} }
public Conversation find(List<Conversation> haystack, Account account, public Conversation find(final List<Conversation> haystack,
String jid) { final Account account,
final Jid jid) {
for (Conversation conversation : haystack) { for (Conversation conversation : haystack) {
if ((account == null || conversation.getAccount() == account) if ((account == null || conversation.getAccount() == account)
&& (conversation.getContactJid().split("/", 2)[0] && (conversation.getContactJid().toBareJid().equals(jid.toBareJid()))) {
.equalsIgnoreCase(jid))) {
return conversation; return conversation;
} }
} }
return null; return null;
} }
public Conversation findOrCreateConversation(Account account, String jid, public Conversation findOrCreateConversation(final Account account, final Jid jid,
boolean muc) { final boolean muc) {
Conversation conversation = find(account, jid); Conversation conversation = find(account, jid);
if (conversation != null) { if (conversation != null) {
return conversation; return conversation;
@ -961,7 +969,7 @@ public class XmppConnectionService extends Service {
if (contact != null) { if (contact != null) {
conversationName = contact.getDisplayName(); conversationName = contact.getDisplayName();
} else { } else {
conversationName = jid.split("@")[0]; conversationName = jid.getLocalpart();
} }
if (muc) { if (muc) {
conversation = new Conversation(conversationName, account, jid, conversation = new Conversation(conversationName, account, jid,
@ -1163,13 +1171,12 @@ public class XmppConnectionService extends Service {
public void connectMultiModeConversations(Account account) { public void connectMultiModeConversations(Account account) {
List<Conversation> conversations = getConversations(); List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); i++) { for (Conversation conversation : conversations) {
Conversation conversation = conversations.get(i); if ((conversation.getMode() == Conversation.MODE_MULTI)
if ((conversation.getMode() == Conversation.MODE_MULTI) && (conversation.getAccount() == account)) {
&& (conversation.getAccount() == account)) { joinMuc(conversation);
joinMuc(conversation); }
} }
}
} }
public void joinMuc(Conversation conversation) { public void joinMuc(Conversation conversation) {
@ -1182,8 +1189,8 @@ public class XmppConnectionService extends Service {
String nick = conversation.getMucOptions().getProposedNick(); String nick = conversation.getMucOptions().getProposedNick();
conversation.getMucOptions().setJoinNick(nick); conversation.getMucOptions().setJoinNick(nick);
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
String joinJid = conversation.getMucOptions().getJoinJid(); final Jid joinJid = conversation.getMucOptions().getJoinJid();
packet.setAttribute("to", conversation.getMucOptions().getJoinJid()); packet.setTo(conversation.getMucOptions().getJoinJid());
Element x = new Element("x"); Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc"); x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
if (conversation.getMucOptions().getPassword() != null) { if (conversation.getMucOptions().getPassword() != null) {
@ -1260,8 +1267,8 @@ public class XmppConnectionService extends Service {
}); });
options.flagAboutToRename(); options.flagAboutToRename();
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("to", options.getJoinJid()); packet.setTo(options.getJoinJid());
packet.setAttribute("from", conversation.getAccount().getFullJid()); packet.setFrom(conversation.getAccount().getFullJid());
String sig = account.getPgpSignature(); String sig = account.getPgpSignature();
if (sig != null) { if (sig != null) {
@ -1289,8 +1296,8 @@ public class XmppConnectionService extends Service {
account.pendingConferenceLeaves.remove(conversation); account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("to", conversation.getMucOptions().getJoinJid()); packet.setTo(conversation.getMucOptions().getJoinJid());
packet.setAttribute("from", conversation.getAccount().getFullJid()); packet.setFrom(conversation.getAccount().getFullJid());
packet.setAttribute("type", "unavailable"); packet.setAttribute("type", "unavailable");
sendPresencePacket(conversation.getAccount(), packet); sendPresencePacket(conversation.getAccount(), packet);
conversation.getMucOptions().setOffline(); conversation.getMucOptions().setOffline();
@ -1307,20 +1314,19 @@ public class XmppConnectionService extends Service {
|| (account.getStatus() == Account.STATUS_DISABLED)) { || (account.getStatus() == Account.STATUS_DISABLED)) {
if (!force) { if (!force) {
List<Conversation> conversations = getConversations(); List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); i++) { for (Conversation conversation : conversations) {
Conversation conversation = conversations.get(i); if (conversation.getAccount() == account) {
if (conversation.getAccount() == account) { if (conversation.getMode() == Conversation.MODE_MULTI) {
if (conversation.getMode() == Conversation.MODE_MULTI) { leaveMuc(conversation);
leaveMuc(conversation); } else {
} else { if (conversation.endOtrIfNeeded()) {
if (conversation.endOtrIfNeeded()) { Log.d(Config.LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid() + ": ended otr session with "
+ ": ended otr session with " + conversation.getContactJid());
+ conversation.getContactJid()); }
} }
} }
} }
}
} }
account.getXmppConnection().disconnect(force); account.getXmppConnection().disconnect(force);
} }
@ -1365,24 +1371,23 @@ public class XmppConnectionService extends Service {
account.getJid() + " otr session established with " account.getJid() + " otr session established with "
+ conversation.getContactJid() + "/" + conversation.getContactJid() + "/"
+ otrSession.getSessionID().getUserID()); + otrSession.getSessionID().getUserID());
for (int i = 0; i < messages.size(); ++i) { for (Message msg : messages) {
Message msg = messages.get(i); if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING)
if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING) && (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) { msg.setPresence(otrSession.getSessionID().getUserID());
msg.setPresence(otrSession.getSessionID().getUserID()); if (msg.getType() == Message.TYPE_TEXT) {
if (msg.getType() == Message.TYPE_TEXT) { MessagePacket outPacket = mMessageGenerator
MessagePacket outPacket = mMessageGenerator .generateOtrChat(msg, true);
.generateOtrChat(msg, true); if (outPacket != null) {
if (outPacket != null) { msg.setStatus(Message.STATUS_SEND);
msg.setStatus(Message.STATUS_SEND); databaseBackend.updateMessage(msg);
databaseBackend.updateMessage(msg); sendMessagePacket(account, outPacket);
sendMessagePacket(account, outPacket); }
} } else if (msg.getType() == Message.TYPE_IMAGE) {
} else if (msg.getType() == Message.TYPE_IMAGE) { mJingleConnectionManager.createNewConnection(msg);
mJingleConnectionManager.createNewConnection(msg); }
} }
} }
}
updateConversationUi(); updateConversationUi();
} }
@ -1397,8 +1402,8 @@ public class XmppConnectionService extends Service {
packet.setFrom(account.getFullJid()); packet.setFrom(account.getFullJid());
packet.addChild("private", "urn:xmpp:carbons:2"); packet.addChild("private", "urn:xmpp:carbons:2");
packet.addChild("no-copy", "urn:xmpp:hints"); packet.addChild("no-copy", "urn:xmpp:hints");
packet.setTo(otrSession.getSessionID().getAccountID() + "/" packet.setAttribute("to", otrSession.getSessionID().getAccountID() + "/"
+ otrSession.getSessionID().getUserID()); + otrSession.getSessionID().getUserID());
try { try {
packet.setBody(otrSession packet.setBody(otrSession
.transformSending(CryptoHelper.FILETRANSFER .transformSending(CryptoHelper.FILETRANSFER
@ -1596,7 +1601,7 @@ public class XmppConnectionService extends Service {
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element item = iq.query("jabber:iq:roster").addChild("item"); Element item = iq.query("jabber:iq:roster").addChild("item");
item.setAttribute("jid", contact.getJid()); item.setAttribute("jid", contact.getJid().toString());
item.setAttribute("subscription", "remove"); item.setAttribute("subscription", "remove");
account.getXmppConnection().sendIqPacket(iq, null); account.getXmppConnection().sendIqPacket(iq, null);
} }
@ -1648,8 +1653,8 @@ public class XmppConnectionService extends Service {
} }
} }
public boolean markMessage(Account account, String recipient, String uuid, public boolean markMessage(final Account account, final Jid recipient, final String uuid,
int status) { final int status) {
if (uuid == null) { if (uuid == null) {
return false; return false;
} else { } 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) { for (Account account : this.accounts) {
if (account.getJid().equals(accountJid)) { if (account.getJid().equals(accountJid)) {
return account; return account;
@ -1756,7 +1761,7 @@ public class XmppConnectionService extends Service {
Log.d(Config.LOGTAG, conversation.getAccount().getJid() Log.d(Config.LOGTAG, conversation.getAccount().getJid()
+ ": sending read marker for " + conversation.getName()); + ": sending read marker for " + conversation.getName());
Account account = conversation.getAccount(); Account account = conversation.getAccount();
String to = conversation.getContactJid(); final Jid to = conversation.getContactJid();
this.sendMessagePacket(conversation.getAccount(), this.sendMessagePacket(conversation.getAccount(),
mMessageGenerator.confirm(account, to, id)); mMessageGenerator.confirm(account, to, id));
} }
@ -1810,14 +1815,14 @@ public class XmppConnectionService extends Service {
} }
public List<String> getKnownHosts() { public List<String> getKnownHosts() {
List<String> hosts = new ArrayList<String>(); List<String> hosts = new ArrayList<>();
for (Account account : getAccounts()) { for (Account account : getAccounts()) {
if (!hosts.contains(account.getServer())) { if (!hosts.contains(account.getServer().toString())) {
hosts.add(account.getServer()); hosts.add(account.getServer().toString());
} }
for (Contact contact : account.getRoster().getContacts()) { for (Contact contact : account.getRoster().getContacts()) {
if (contact.showInRoster()) { if (contact.showInRoster()) {
String server = contact.getServer(); final String server = contact.getServer().toString();
if (server != null && !hosts.contains(server)) { if (server != null && !hosts.contains(server)) {
hosts.add(server); hosts.add(server);
} }
@ -1828,7 +1833,7 @@ public class XmppConnectionService extends Service {
} }
public List<String> getKnownConferenceHosts() { public List<String> getKnownConferenceHosts() {
ArrayList<String> mucServers = new ArrayList<String>(); ArrayList<String> mucServers = new ArrayList<>();
for (Account account : accounts) { for (Account account : accounts) {
if (account.getXmppConnection() != null) { if (account.getXmppConnection() != null) {
String server = account.getXmppConnection().getMucServer(); String server = account.getXmppConnection().getMucServer();
@ -1891,7 +1896,7 @@ public class XmppConnectionService extends Service {
} }
public List<Contact> findContacts(String jid) { public List<Contact> findContacts(String jid) {
ArrayList<Contact> contacts = new ArrayList<Contact>(); ArrayList<Contact> contacts = new ArrayList<>();
for (Account account : getAccounts()) { for (Account account : getAccounts()) {
if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!account.isOptionSet(Account.OPTION_DISABLED)) {
Contact contact = account.getRoster().getContactFromRoster(jid); Contact contact = account.getRoster().getContactFromRoster(jid);
@ -1931,7 +1936,7 @@ public class XmppConnectionService extends Service {
} }
public void resendFailedMessages(Message message) { public void resendFailedMessages(Message message) {
List<Message> messages = new ArrayList<Message>(); List<Message> messages = new ArrayList<>();
Message current = message; Message current = message;
while(current.getStatus() == Message.STATUS_SEND_FAILED) { while(current.getStatus() == Message.STATUS_SEND_FAILED) {
messages.add(current); messages.add(current);

View File

@ -11,6 +11,7 @@ import de.measite.minidns.record.AAAA;
import de.measite.minidns.record.Data; import de.measite.minidns.record.Data;
import de.measite.minidns.util.NameUtil; import de.measite.minidns.util.NameUtil;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.xmpp.jid.Jid;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
@ -26,7 +27,8 @@ import android.util.Log;
public class DNSHelper { public class DNSHelper {
protected static Client client = new Client(); 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(); String dns[] = client.findDNS();
if (dns != null) { if (dns != null) {
@ -62,9 +64,9 @@ public class DNSHelper {
// a random order respecting the weight, and dump that priority by // a random order respecting the weight, and dump that priority by
// priority // priority
TreeMap<Integer, ArrayList<SRV>> priorities = new TreeMap<Integer, ArrayList<SRV>>(); TreeMap<Integer, ArrayList<SRV>> priorities = new TreeMap<>();
TreeMap<String, ArrayList<String>> ips4 = new TreeMap<String, ArrayList<String>>(); TreeMap<String, ArrayList<String>> ips4 = new TreeMap<>();
TreeMap<String, ArrayList<String>> ips6 = new TreeMap<String, ArrayList<String>>(); TreeMap<String, ArrayList<String>> ips6 = new TreeMap<>();
for (Record[] rrset : new Record[][] { message.getAnswers(), for (Record[] rrset : new Record[][] { message.getAnswers(),
message.getAdditionalResourceRecords() }) { message.getAdditionalResourceRecords() }) {
@ -97,7 +99,7 @@ public class DNSHelper {
} }
Random rnd = new Random(); Random rnd = new Random();
ArrayList<SRV> result = new ArrayList<SRV>( ArrayList<SRV> result = new ArrayList<>(
priorities.size() * 2 + 1); priorities.size() * 2 + 1);
for (ArrayList<SRV> s : priorities.values()) { for (ArrayList<SRV> s : priorities.values()) {
@ -136,7 +138,7 @@ public class DNSHelper {
bundle.putString("error", "nosrv"); bundle.putString("error", "nosrv");
return bundle; return bundle;
} }
ArrayList<Bundle> values = new ArrayList<Bundle>(); ArrayList<Bundle> values = new ArrayList<>();
for (SRV srv : result) { for (SRV srv : result) {
Bundle namePort = new Bundle(); Bundle namePort = new Bundle();
namePort.putString("name", srv.getName()); namePort.putString("name", srv.getName());

View File

@ -48,6 +48,8 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Tag; import eu.siacs.conversations.xml.Tag;
import eu.siacs.conversations.xml.TagWriter; import eu.siacs.conversations.xml.TagWriter;
import eu.siacs.conversations.xml.XmlReader; 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.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
@ -76,10 +78,12 @@ public class XmppConnection implements Runnable {
private boolean shouldBind = true; private boolean shouldBind = true;
private boolean shouldAuthenticate = true; private boolean shouldAuthenticate = true;
private Element streamFeatures; private Element streamFeatures;
private HashMap<String, List<String>> disco = new HashMap<String, List<String>>(); private HashMap<String, List<String>> disco = new HashMap<>();
private String streamId = null; private String streamId = null;
private int smVersion = 3; private int smVersion = 3;
private SparseArray<String> messageReceipts = new SparseArray<String>(); private SparseArray<String> messageReceipts = new SparseArray<>();
private boolean usingCompression = false; private boolean usingCompression = false;
private boolean usingEncryption = false; private boolean usingEncryption = false;
private int stanzasReceived = 0; private int stanzasReceived = 0;
@ -89,7 +93,7 @@ public class XmppConnection implements Runnable {
private long lastConnect = 0; private long lastConnect = 0;
private long lastSessionStarted = 0; private long lastSessionStarted = 0;
private int attempt = 0; private int attempt = 0;
private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<String, PacketReceived>(); private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<>();
private OnPresencePacketReceived presenceListener = null; private OnPresencePacketReceived presenceListener = null;
private OnJinglePacketReceived jingleListener = null; private OnJinglePacketReceived jingleListener = null;
private OnIqPacketReceived unregisteredIqListener = null; private OnIqPacketReceived unregisteredIqListener = null;
@ -102,7 +106,7 @@ public class XmppConnection implements Runnable {
public XmppConnection(Account account, XmppConnectionService service) { public XmppConnection(Account account, XmppConnectionService service) {
this.account = account; this.account = account;
this.wakeLock = service.getPowerManager().newWakeLock( this.wakeLock = service.getPowerManager().newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, account.getJid()); PowerManager.PARTIAL_WAKE_LOCK, account.getJid().toString());
tagWriter = new TagWriter(); tagWriter = new TagWriter();
mXmppConnectionService = service; mXmppConnectionService = service;
applicationContext = service.getApplicationContext(); applicationContext = service.getApplicationContext();
@ -127,7 +131,7 @@ public class XmppConnection implements Runnable {
} }
protected void connect() { protected void connect() {
Log.d(Config.LOGTAG, account.getJid() + ": connecting"); Log.d(Config.LOGTAG, account.getJid().toString() + ": connecting");
usingCompression = false; usingCompression = false;
usingEncryption = false; usingEncryption = false;
lastConnect = SystemClock.elapsedRealtime(); lastConnect = SystemClock.elapsedRealtime();
@ -143,7 +147,7 @@ public class XmppConnection implements Runnable {
Bundle result = DNSHelper.getSRVRecord(account.getServer()); Bundle result = DNSHelper.getSRVRecord(account.getServer());
ArrayList<Parcelable> values = result.getParcelableArrayList("values"); ArrayList<Parcelable> values = result.getParcelableArrayList("values");
if ("timeout".equals(result.getString("error"))) { 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); this.changeStatus(Account.STATUS_OFFLINE);
return; return;
} else if (values != null) { } else if (values != null) {
@ -158,12 +162,12 @@ public class XmppConnection implements Runnable {
InetSocketAddress addr; InetSocketAddress addr;
if (srvIpServer != null) { if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort); addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": using values from dns " + srvRecordServer + ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort); + "[" + srvIpServer + "]:" + srvRecordPort);
} else { } else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort); addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": using values from dns " + ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort); + srvRecordServer + ":" + srvRecordPort);
} }
@ -171,10 +175,10 @@ public class XmppConnection implements Runnable {
socket.connect(addr, 20000); socket.connect(addr, 20000);
socketError = false; socketError = false;
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage());
i++; i++;
} catch (IOException e) { } catch (IOException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage()); Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage());
i++; i++;
} }
} }
@ -183,16 +187,16 @@ public class XmppConnection implements Runnable {
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); wakeLock.release();
} catch (RuntimeException re) { } catch (final RuntimeException ignored) {
} }
} }
return; return;
} }
} else if (result.containsKey("error") } else if (result.containsKey("error")
&& "nosrv".equals(result.getString("error", null))) { && "nosrv".equals(result.getString("error", null))) {
socket = new Socket(account.getServer(), 5222); socket = new Socket(account.getServer().getDomainpart(), 5222);
} else { } else {
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": timeout in DNS resolution"); + ": timeout in DNS resolution");
changeStatus(Account.STATUS_OFFLINE); changeStatus(Account.STATUS_OFFLINE);
return; return;
@ -222,51 +226,38 @@ public class XmppConnection implements Runnable {
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); wakeLock.release();
} catch (RuntimeException re) { } catch (final RuntimeException ignored) {
} }
} }
return; } catch (final IOException | XmlPullParserException e) {
} catch (IOException e) { Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage());
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); wakeLock.release();
} catch (RuntimeException re) { } catch (final RuntimeException ignored) {
} }
} }
return; } catch (NoSuchAlgorithmException e) {
} catch (NoSuchAlgorithmException e) { Log.d(Config.LOGTAG, account.getJid().toString() + ": " + e.getMessage());
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
Log.d(Config.LOGTAG, "compression exception " + e.getMessage()); Log.d(Config.LOGTAG, "compression exception " + e.getMessage());
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); 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 @Override
public void run() { public void run() {
connect(); connect();
} }
private void processStream(Tag currentTag) throws XmlPullParserException, private void processStream(final Tag currentTag) throws XmlPullParserException,
IOException, NoSuchAlgorithmException { IOException, NoSuchAlgorithmException {
Tag nextTag = tagReader.readTag(); Tag nextTag = tagReader.readTag();
while ((nextTag != null) && (!nextTag.isEnd("stream"))) { while ((nextTag != null) && (!nextTag.isEnd("stream"))) {
@ -279,7 +270,7 @@ public class XmppConnection implements Runnable {
} else if (nextTag.isStart("compressed")) { } else if (nextTag.isStart("compressed")) {
switchOverToZLib(nextTag); switchOverToZLib(nextTag);
} else if (nextTag.isStart("success")) { } 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.readTag();
tagReader.reset(); tagReader.reset();
sendStartStream(); sendStartStream();
@ -300,11 +291,11 @@ public class XmppConnection implements Runnable {
Element enabled = tagReader.readElement(nextTag); Element enabled = tagReader.readElement(nextTag);
if ("true".equals(enabled.getAttribute("resume"))) { if ("true".equals(enabled.getAttribute("resume"))) {
this.streamId = enabled.getAttribute("id"); this.streamId = enabled.getAttribute("id");
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": stream managment(" + smVersion + ": stream managment(" + smVersion
+ ") enabled (resumable)"); + ") enabled (resumable)");
} else { } else {
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": stream managment(" + smVersion + ") enabled"); + ": stream managment(" + smVersion + ") enabled");
} }
this.lastSessionStarted = SystemClock.elapsedRealtime(); this.lastSessionStarted = SystemClock.elapsedRealtime();
@ -318,11 +309,11 @@ public class XmppConnection implements Runnable {
try { try {
int serverCount = Integer.parseInt(h); int serverCount = Integer.parseInt(h);
if (serverCount != stanzasSent) { if (serverCount != stanzasSent) {
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": session resumed with lost packages"); + ": session resumed with lost packages");
stanzasSent = serverCount; stanzasSent = serverCount;
} else { } else {
Log.d(Config.LOGTAG, account.getJid() Log.d(Config.LOGTAG, account.getJid().toString()
+ ": session resumed"); + ": session resumed");
} }
if (acknowledgedListener != null) { if (acknowledgedListener != null) {
@ -334,7 +325,7 @@ public class XmppConnection implements Runnable {
} }
} }
messageReceipts.clear(); messageReceipts.clear();
} catch (NumberFormatException e) { } catch (final NumberFormatException ignored) {
} }
sendInitialPing(); sendInitialPing();
@ -357,7 +348,7 @@ public class XmppConnection implements Runnable {
} }
} else if (nextTag.isStart("failed")) { } else if (nextTag.isStart("failed")) {
tagReader.readElement(nextTag); tagReader.readElement(nextTag);
Log.d(Config.LOGTAG, account.getJid() + ": resumption failed"); Log.d(Config.LOGTAG, account.getJid().toString() + ": resumption failed");
streamId = null; streamId = null;
if (account.getStatus() != Account.STATUS_ONLINE) { if (account.getStatus() != Account.STATUS_ONLINE) {
sendBindRequest(); sendBindRequest();
@ -380,7 +371,7 @@ public class XmppConnection implements Runnable {
} }
private void sendInitialPing() { 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); IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setFrom(account.getFullJid()); iq.setFrom(account.getFullJid());
iq.addChild("ping", "urn:xmpp:ping"); iq.addChild("ping", "urn:xmpp:ping");
@ -388,7 +379,7 @@ public class XmppConnection implements Runnable {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { 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()); + ": online with resource " + account.getResource());
changeStatus(Account.STATUS_ONLINE); changeStatus(Account.STATUS_ONLINE);
} }
@ -507,7 +498,7 @@ public class XmppConnection implements Runnable {
tagWriter.writeElement(compress); tagWriter.writeElement(compress);
} }
private void switchOverToZLib(Tag currentTag) private void switchOverToZLib(final Tag currentTag)
throws XmlPullParserException, IOException, throws XmlPullParserException, IOException,
NoSuchAlgorithmException { NoSuchAlgorithmException {
tagReader.readTag(); // read tag close tagReader.readTag(); // read tag close
@ -537,7 +528,7 @@ public class XmppConnection implements Runnable {
return getPreferences().getBoolean("enable_legacy_ssl", false); return getPreferences().getBoolean("enable_legacy_ssl", false);
} }
private void switchOverToTls(Tag currentTag) throws XmlPullParserException, private void switchOverToTls(final Tag currentTag) throws XmlPullParserException,
IOException { IOException {
tagReader.readTag(); tagReader.readTag();
try { try {
@ -551,24 +542,23 @@ public class XmppConnection implements Runnable {
throw new IOException("SSLSocketFactory was null"); 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) { if (socket == null) {
throw new IOException("socket was 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(), socket.getInetAddress().getHostAddress(), socket.getPort(),
true); true);
// Support all protocols except legacy SSL. // Support all protocols except legacy SSL.
// The min SDK version prevents us having to worry about SSLv2. In // The min SDK version prevents us having to worry about SSLv2. In
// future, this may be // future, this may be true of SSLv3 as well.
// true of SSLv3 as well.
final String[] supportProtocols; final String[] supportProtocols;
if (enableLegacySSL()) { if (enableLegacySSL()) {
supportProtocols = sslSocket.getSupportedProtocols(); supportProtocols = sslSocket.getSupportedProtocols();
} else { } else {
final List<String> supportedProtocols = new LinkedList<String>( final List<String> supportedProtocols = new LinkedList<>(
Arrays.asList(sslSocket.getSupportedProtocols())); Arrays.asList(sslSocket.getSupportedProtocols()));
supportedProtocols.remove("SSLv3"); supportedProtocols.remove("SSLv3");
supportProtocols = new String[supportedProtocols.size()]; supportProtocols = new String[supportedProtocols.size()];
@ -577,7 +567,7 @@ public class XmppConnection implements Runnable {
sslSocket.setEnabledProtocols(supportProtocols); sslSocket.setEnabledProtocols(supportProtocols);
if (verifier != null if (verifier != null
&& !verifier.verify(account.getServer(), && !verifier.verify(account.getServer().getDomainpart(),
sslSocket.getSession())) { sslSocket.getSession())) {
sslSocket.close(); sslSocket.close();
throw new IOException("host mismatch in TLS connection"); throw new IOException("host mismatch in TLS connection");
@ -590,12 +580,10 @@ public class XmppConnection implements Runnable {
usingEncryption = true; usingEncryption = true;
processStream(tagReader.readTag()); processStream(tagReader.readTag());
sslSocket.close(); sslSocket.close();
} catch (NoSuchAlgorithmException e1) { } catch (final NoSuchAlgorithmException | KeyManagementException e1) {
e1.printStackTrace(); e1.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} }
} }
private void sendSaslAuthPlain() throws IOException { private void sendSaslAuthPlain() throws IOException {
String saslString = CryptoHelper.saslPlain(account.getUsername(), String saslString = CryptoHelper.saslPlain(account.getUsername(),
@ -676,7 +664,7 @@ public class XmppConnection implements Runnable {
} }
private List<String> extractMechanisms(Element stream) { private List<String> extractMechanisms(Element stream) {
ArrayList<String> mechanisms = new ArrayList<String>(stream ArrayList<String> mechanisms = new ArrayList<>(stream
.getChildren().size()); .getChildren().size());
for (Element child : stream.getChildren()) { for (Element child : stream.getChildren()) {
mechanisms.add(child.getContent()); mechanisms.add(child.getContent());
@ -742,10 +730,14 @@ public class XmppConnection implements Runnable {
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
Element bind = packet.findChild("bind"); Element bind = packet.findChild("bind");
if (bind != null) { if (bind != null) {
Element jid = bind.findChild("jid"); final Element jid = bind.findChild("jid");
if (jid != null && jid.getContent() != null) { if (jid != null && jid.getContent() != null) {
account.setResource(jid.getContent().split("/", 2)[1]); try {
if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { 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; smVersion = 3;
EnablePacket enable = new EnablePacket(smVersion); EnablePacket enable = new EnablePacket(smVersion);
tagWriter.writeStanzaAsync(enable); tagWriter.writeStanzaAsync(enable);
@ -783,24 +775,24 @@ public class XmppConnection implements Runnable {
} }
} }
private void sendServiceDiscoveryInfo(final String server) { private void sendServiceDiscoveryInfo(final Jid server) {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET); final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setTo(server); iq.setTo(server.toDomainJid());
iq.query("http://jabber.org/protocol/disco#info"); iq.query("http://jabber.org/protocol/disco#info");
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
List<Element> elements = packet.query().getChildren(); final List<Element> elements = packet.query().getChildren();
List<String> features = new ArrayList<String>(); final List<String> features = new ArrayList<>();
for (int i = 0; i < elements.size(); ++i) { for (Element element : elements) {
if (elements.get(i).getName().equals("feature")) { if (element.getName().equals("feature")) {
features.add(elements.get(i).getAttribute("var")); features.add(element.getAttribute("var"));
} }
} }
disco.put(server, features); disco.put(server.toDomainJid().toString(), features);
if (account.getServer().equals(server)) { if (account.getServer().equals(server.toDomainJid())) {
enableAdvancedStreamFeatures(); enableAdvancedStreamFeatures();
} }
} }
@ -813,21 +805,25 @@ public class XmppConnection implements Runnable {
} }
} }
private void sendServiceDiscoveryItems(final String server) { private void sendServiceDiscoveryItems(final Jid server) {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET); final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setTo(server); iq.setTo(server.toDomainJid());
iq.query("http://jabber.org/protocol/disco#items"); iq.query("http://jabber.org/protocol/disco#items");
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
List<Element> elements = packet.query().getChildren(); List<Element> elements = packet.query().getChildren();
for (int i = 0; i < elements.size(); ++i) { for (Element element : elements) {
if (elements.get(i).getName().equals("item")) { if (element.getName().equals("item")) {
String jid = elements.get(i).getAttribute("jid"); final String jid = element.getAttribute("jid");
sendServiceDiscoveryInfo(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 { throws XmlPullParserException, IOException {
Element streamError = tagReader.readElement(currentTag); Element streamError = tagReader.readElement(currentTag);
if (streamError != null && streamError.hasChild("conflict")) { if (streamError != null && streamError.hasChild("conflict")) {
String resource = account.getResource().split("\\.")[0]; final String resource = account.getResource().split("\\.")[0];
account.setResource(resource + "." + nextRandomId()); try {
Log.d(Config.LOGTAG, account.setResource(resource + "." + nextRandomId());
} catch (final InvalidJidException ignored) {
// Should never reach here.
}
Log.d(Config.LOGTAG,
account.getJid() + ": switching resource due to conflict (" account.getJid() + ": switching resource due to conflict ("
+ account.getResource() + ")"); + account.getResource() + ")");
} }
@ -864,8 +864,8 @@ public class XmppConnection implements Runnable {
private void sendStartStream() throws IOException { private void sendStartStream() throws IOException {
Tag stream = Tag.start("stream:stream"); Tag stream = Tag.start("stream:stream");
stream.setAttribute("from", account.getJid()); stream.setAttribute("from", account.getJid().toString());
stream.setAttribute("to", account.getServer()); stream.setAttribute("to", account.getServer().toString());
stream.setAttribute("version", "1.0"); stream.setAttribute("version", "1.0");
stream.setAttribute("xml:lang", "en"); stream.setAttribute("xml:lang", "en");
stream.setAttribute("xmlns", "jabber:client"); stream.setAttribute("xmlns", "jabber:client");
@ -1003,7 +1003,7 @@ public class XmppConnection implements Runnable {
} }
public List<String> findDiscoItemsByFeature(String feature) { public List<String> findDiscoItemsByFeature(String feature) {
List<String> items = new ArrayList<String>(); final List<String> items = new ArrayList<>();
for (Entry<String, List<String>> cursor : disco.entrySet()) { for (Entry<String, List<String>> cursor : disco.entrySet()) {
if (cursor.getValue().contains(feature)) { if (cursor.getValue().contains(feature)) {
items.add(cursor.getKey()); items.add(cursor.getKey());
@ -1079,12 +1079,10 @@ public class XmppConnection implements Runnable {
this.connection = connection; this.connection = connection;
} }
private boolean hasDiscoFeature(String server, String feature) { private boolean hasDiscoFeature(final Jid server, final String feature) {
if (!connection.disco.containsKey(server)) { return connection.disco.containsKey(server.toDomainJid().toString()) &&
return false; connection.disco.get(server.toDomainJid().toString()).contains(feature);
} }
return connection.disco.get(server).contains(feature);
}
public boolean carbons() { public boolean carbons() {
return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2"); return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2");
@ -1095,12 +1093,7 @@ public class XmppConnection implements Runnable {
} }
public boolean csi() { public boolean csi() {
if (connection.streamFeatures == null) { return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0");
return false;
} else {
return connection.streamFeatures.hasChild("csi",
"urn:xmpp:csi:0");
}
} }
public boolean pubsub() { public boolean pubsub() {
@ -1113,11 +1106,7 @@ public class XmppConnection implements Runnable {
} }
public boolean rosterVersioning() { public boolean rosterVersioning() {
if (connection.streamFeatures == null) { return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver");
return false;
} else {
return connection.streamFeatures.hasChild("ver");
}
} }
public boolean streamhost() { public boolean streamhost() {

View File

@ -19,7 +19,7 @@ public final class Jid {
private final String displayjid; private final String displayjid;
public String getLocalpart() { public String getLocalpart() {
return IDN.toUnicode(localpart); return localpart;
} }
public String getDomainpart() { public String getDomainpart() {
@ -27,10 +27,10 @@ public final class Jid {
} }
public String getResourcepart() { 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); return new Jid(jid);
} }
@ -121,11 +121,20 @@ public final class Jid {
this.displayjid = finaljid; this.displayjid = finaljid;
} }
public Jid getBareJid() { public Jid toBareJid() {
try { try {
return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, ""); return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, "");
} catch (final InvalidJidException e) { } 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; return null;
} }
} }

View File

@ -1,6 +1,8 @@
package eu.siacs.conversations.xmpp.pep; package eu.siacs.conversations.xmpp.pep;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
import android.util.Base64; import android.util.Base64;
public class Avatar { public class Avatar {
@ -10,7 +12,7 @@ public class Avatar {
public int height; public int height;
public int width; public int width;
public long size; public long size;
public String owner; public Jid owner;
public byte[] getImageAsBytes() { public byte[] getImageAsBytes() {
return Base64.decode(image, Base64.DEFAULT); return Base64.decode(image, Base64.DEFAULT);

View File

@ -1,6 +1,7 @@
package eu.siacs.conversations.xmpp.stanzas; package eu.siacs.conversations.xmpp.stanzas;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
public class AbstractStanza extends Element { public class AbstractStanza extends Element {
@ -20,15 +21,15 @@ public class AbstractStanza extends Element {
return this.getAttribute("id"); return this.getAttribute("id");
} }
public void setTo(String to) { public void setTo(final Jid to) {
setAttribute("to", to); setAttribute("to", to.toString());
} }
public void setFrom(String from) { public void setFrom(final Jid from) {
setAttribute("from", from); setAttribute("from", from.toString());
} }
public void setId(String id) { public void setId(final String id) {
setAttribute("id", id); setAttribute("id", id);
} }
} }