Merge pull request #639 from SamWhited/issue631

Use JID class instead of strings
This commit is contained in:
Daniel Gultsch 2014-11-09 15:20:06 +01:00
commit f65a2188cc
51 changed files with 1152 additions and 782 deletions

View File

@ -20,11 +20,14 @@ allprojects {
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
repositories { repositories {
jcenter()
mavenCentral()
maven { maven {
url "http://jitsi.github.com/otr4j/repository/" url "http://jitsi.github.com/otr4j/repository/"
} }
maven {
url "https://oss.sonatype.org/content/repositories/releases/"
}
jcenter()
mavenCentral()
} }
dependencies { dependencies {
@ -34,6 +37,7 @@ dependencies {
compile 'com.android.support:support-v13:19.1.0' compile 'com.android.support:support-v13:19.1.0'
compile 'org.bouncycastle:bcprov-jdk15on:1.50' compile 'org.bouncycastle:bcprov-jdk15on:1.50'
compile 'net.java:otr4j:0.21' compile 'net.java:otr4j:0.21'
compile 'org.jxmpp:jxmpp-stringprep-libidn:0.4.0'
compile 'com.google.zxing:core:3.1.0' compile 'com.google.zxing:core:3.1.0'
compile 'com.google.zxing:android-integration:3.1.0' compile 'com.google.zxing:android-integration:3.1.0'
} }

View File

@ -85,9 +85,7 @@ 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();
} }
@ -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,9 +77,6 @@ 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;
} }
} }
}); });
@ -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,7 +326,6 @@ 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,7 +352,6 @@ 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,33 @@ 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()) {
this.setResource("mobile");
}
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 +114,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 String getServer() { public Jid getServer() {
return server; return jid.toDomainJid();
} }
public void setServer(String server) { public void setServer(final String server) throws InvalidJidException {
this.server = server; jid = Jid.fromParts(jid.getLocalpart(), server, jid.getResourcepart());
} }
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 +158,22 @@ 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){
this.resource = resource; try {
jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource);
} catch (final InvalidJidException ignored) {
}
} }
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) {
Jid jid = null;
try {
jid = Jid.fromParts(cursor.getString(cursor.getColumnIndex(USERNAME)),
cursor.getString(cursor.getColumnIndex(SERVER)), "mobile");
} catch (final InvalidJidException ignored) {
}
return new Account(cursor.getString(cursor.getColumnIndex(UUID)), return new Account(cursor.getString(cursor.getColumnIndex(UUID)),
cursor.getString(cursor.getColumnIndex(USERNAME)), jid,
cursor.getString(cursor.getColumnIndex(SERVER)),
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) {
} }
} }
@ -332,9 +336,9 @@ public class Account extends AbstractEntity {
return this.bookmarks; return this.bookmarks;
} }
public boolean hasBookmarkFor(String conferenceJid) { public boolean hasBookmarkFor(final Jid conferenceJid) {
for (Bookmark bmark : this.bookmarks) { for (Bookmark bmark : this.bookmarks) {
if (bmark.getJid().equals(conferenceJid)) { if (bmark.getJid().equals(conferenceJid.toBareJid())) {
return true; return true;
} }
} }

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,7 +57,7 @@ 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());
} }
@ -68,15 +70,19 @@ 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 {
return Jid.fromString(jid);
} catch (final InvalidJidException e) {
return null;
}
} else { } 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;
} }
@ -83,8 +83,10 @@ public class Contact implements ListItem {
return this.serverName; return this.serverName;
} else if (this.presenceName != null) { } else if (this.presenceName != null) {
return this.presenceName; return this.presenceName;
} else if (jid.hasLocalpart()) {
return jid.getLocalpart();
} else { } else {
return this.jid.split("@")[0]; return jid.getDomainpart();
} }
} }
@ -92,13 +94,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 +110,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 +125,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)));
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)), 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 +207,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 +234,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 +242,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,20 +282,25 @@ 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;
} }
} }
@ -301,8 +315,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 +349,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,9 +105,7 @@ 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() {
@ -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) {
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)), 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) {
Jid jid;
try {
jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(COUNTERPART)));
} catch (InvalidJidException e) {
jid = null;
}
return new Message(cursor.getString(cursor.getColumnIndex(UUID)), 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,10 +234,13 @@ 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?
}
} }
} }
@ -236,17 +248,9 @@ public class Message extends AbstractEntity {
this.trueCounterpart = trueCounterpart; this.trueCounterpart = trueCounterpart;
} }
public String getPresence() { public Jid getPresence() {
String[] counterparts = this.counterpart.split("/", 2); // TODO: This is now the same as getCounterpart()... find usages in code and remove one?
if (counterparts.length == 2) { return counterpart;
return counterparts[1];
} else {
if (this.counterpart.contains("/")) {
return "";
} else {
return null;
}
}
} }
public void setDownloadable(Downloadable downloadable) { public void setDownloadable(Downloadable downloadable) {
@ -264,7 +268,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 +363,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,14 +68,19 @@ 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) {
case "moderator":
this.role = ROLE_MODERATOR; this.role = ROLE_MODERATOR;
} else if (role.equals("participant")) { break;
case "participant":
this.role = ROLE_PARTICIPANT; this.role = ROLE_PARTICIPANT;
} else if (role.equals("visitor")) { break;
case "visitor":
this.role = ROLE_VISITOR; this.role = ROLE_VISITOR;
} else { break;
default:
this.role = ROLE_NONE; this.role = ROLE_NONE;
break;
} }
} }
@ -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;
@ -145,9 +152,9 @@ public class MucOptions {
} }
public void processPacket(PresencePacket packet, PgpEngine pgp) { public void processPacket(PresencePacket packet, PgpEngine pgp) {
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
if (fromParts.length >= 2) { if (!from.isBareJid()) {
String name = fromParts[1]; final String name = from.getResourcepart();
String type = packet.getAttribute("type"); String type = packet.getAttribute("type");
if (type == null) { if (type == null) {
User user = new User(); User user = new User();
@ -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,9 +334,13 @@ 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) {

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;
@ -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());
@ -119,7 +120,7 @@ public class MessageGenerator extends AbstractGenerator {
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");

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,7 +22,13 @@ 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;
try {
jid = Jid.fromString(item.getAttribute("jid"));
} catch (final InvalidJidException e) {
// TODO: Handle this?
jid = null;
}
String name = item.getAttribute("name"); 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);
@ -59,7 +67,7 @@ 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(); final Jid from = packet.getFrom();
if ((from == null) || (from.equals(account.getJid()))) { 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

@ -11,6 +11,8 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnMessagePacketReceived; import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
@ -21,9 +23,9 @@ public class MessageParser extends AbstractParser implements
} }
private Message parseChat(MessagePacket packet, Account account) { private Message parseChat(MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/", 2); final Jid jid = packet.getFrom().toBareJid();
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], false); .findOrCreateConversation(account, jid.toBareJid(), false);
updateLastseen(packet, account, true); updateLastseen(packet, account, true);
String pgpBody = getPgpBody(packet); String pgpBody = getPgpBody(packet);
Message finishedMessage; Message finishedMessage;
@ -38,11 +40,11 @@ public class MessageParser extends AbstractParser implements
finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.setRemoteMsgId(packet.getId());
finishedMessage.markable = isMarkable(packet); finishedMessage.markable = isMarkable(packet);
if (conversation.getMode() == Conversation.MODE_MULTI if (conversation.getMode() == Conversation.MODE_MULTI
&& fromParts.length >= 2) { && !jid.getResourcepart().isEmpty()) {
finishedMessage.setType(Message.TYPE_PRIVATE); finishedMessage.setType(Message.TYPE_PRIVATE);
finishedMessage.setPresence(fromParts[1]); finishedMessage.setPresence(jid.getResourcepart());
finishedMessage.setTrueCounterpart(conversation.getMucOptions() finishedMessage.setTrueCounterpart(conversation.getMucOptions()
.getTrueCounterpart(fromParts[1])); .getTrueCounterpart(jid.getResourcepart()));
if (conversation.hasDuplicateMessage(finishedMessage)) { if (conversation.hasDuplicateMessage(finishedMessage)) {
return null; return null;
} }
@ -53,16 +55,16 @@ public class MessageParser extends AbstractParser implements
} }
private Message parseOtrChat(MessagePacket packet, Account account) { private Message parseOtrChat(MessagePacket packet, Account account) {
boolean properlyAddressed = (packet.getTo().split("/", 2).length == 2) boolean properlyAddressed = (!packet.getTo().isBareJid())
|| (account.countPresences() == 1); || (account.countPresences() == 1);
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], false); .findOrCreateConversation(account, from.toBareJid(), false);
String presence; String presence;
if (fromParts.length >= 2) { if (from.isBareJid()) {
presence = fromParts[1];
} else {
presence = ""; presence = "";
} else {
presence = from.getResourcepart();
} }
updateLastseen(packet, account, true); updateLastseen(packet, account, true);
String body = packet.getBody(); String body = packet.getBody();
@ -127,24 +129,23 @@ public class MessageParser extends AbstractParser implements
private Message parseGroupchat(MessagePacket packet, Account account) { private Message parseGroupchat(MessagePacket packet, Account account) {
int status; int status;
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
if (mXmppConnectionService.find(account.pendingConferenceLeaves, if (mXmppConnectionService.find(account.pendingConferenceLeaves,
account, fromParts[0]) != null) { account, from.toBareJid()) != null) {
return null; return null;
} }
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], true); .findOrCreateConversation(account, from.toBareJid(), true);
if (packet.hasChild("subject")) { if (packet.hasChild("subject")) {
conversation.getMucOptions().setSubject( conversation.getMucOptions().setSubject(
packet.findChild("subject").getContent()); packet.findChild("subject").getContent());
mXmppConnectionService.updateConversationUi(); mXmppConnectionService.updateConversationUi();
return null; return null;
} }
if ((fromParts.length == 1)) { if (from.isBareJid()) {
return null; return null;
} }
String counterPart = fromParts[1]; if (from.getResourcepart().equals(conversation.getMucOptions().getActualNick())) {
if (counterPart.equals(conversation.getMucOptions().getActualNick())) {
if (mXmppConnectionService.markMessage(conversation, if (mXmppConnectionService.markMessage(conversation,
packet.getId(), Message.STATUS_SEND)) { packet.getId(), Message.STATUS_SEND)) {
return null; return null;
@ -157,17 +158,17 @@ public class MessageParser extends AbstractParser implements
String pgpBody = getPgpBody(packet); String pgpBody = getPgpBody(packet);
Message finishedMessage; Message finishedMessage;
if (pgpBody == null) { if (pgpBody == null) {
finishedMessage = new Message(conversation, counterPart, finishedMessage = new Message(conversation, from,
packet.getBody(), Message.ENCRYPTION_NONE, status); packet.getBody(), Message.ENCRYPTION_NONE, status);
} else { } else {
finishedMessage = new Message(conversation, counterPart, pgpBody, finishedMessage = new Message(conversation, from, pgpBody,
Message.ENCRYPTION_PGP, status); Message.ENCRYPTION_PGP, status);
} }
finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.setRemoteMsgId(packet.getId());
finishedMessage.markable = isMarkable(packet); finishedMessage.markable = isMarkable(packet);
if (status == Message.STATUS_RECEIVED) { if (status == Message.STATUS_RECEIVED) {
finishedMessage.setTrueCounterpart(conversation.getMucOptions() finishedMessage.setTrueCounterpart(conversation.getMucOptions()
.getTrueCounterpart(counterPart)); .getTrueCounterpart(from.getResourcepart()));
} }
if (packet.hasChild("delay") if (packet.hasChild("delay")
&& conversation.hasDuplicateMessage(finishedMessage)) { && conversation.hasDuplicateMessage(finishedMessage)) {
@ -177,9 +178,9 @@ public class MessageParser extends AbstractParser implements
return finishedMessage; return finishedMessage;
} }
private Message parseCarbonMessage(MessagePacket packet, Account account) { private Message parseCarbonMessage(final MessagePacket packet, final Account account) {
int status; int status;
String fullJid; final Jid fullJid;
Element forwarded; Element forwarded;
if (packet.hasChild("received", "urn:xmpp:carbons:2")) { if (packet.hasChild("received", "urn:xmpp:carbons:2")) {
forwarded = packet.findChild("received", "urn:xmpp:carbons:2") forwarded = packet.findChild("received", "urn:xmpp:carbons:2")
@ -205,11 +206,11 @@ public class MessageParser extends AbstractParser implements
parseNonMessage(message, account); parseNonMessage(message, account);
} else if (status == Message.STATUS_SEND } else if (status == Message.STATUS_SEND
&& message.hasChild("displayed", "urn:xmpp:chat-markers:0")) { && message.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
String to = message.getAttribute("to"); final Jid to = message.getTo();
if (to != null) { if (to != null) {
Conversation conversation = mXmppConnectionService.find( final Conversation conversation = mXmppConnectionService.find(
mXmppConnectionService.getConversations(), account, mXmppConnectionService.getConversations(), account,
to.split("/")[0]); to.toBareJid());
if (conversation != null) { if (conversation != null) {
mXmppConnectionService.markRead(conversation, false); mXmppConnectionService.markRead(conversation, false);
} }
@ -218,21 +219,20 @@ public class MessageParser extends AbstractParser implements
return null; return null;
} }
if (status == Message.STATUS_RECEIVED) { if (status == Message.STATUS_RECEIVED) {
fullJid = message.getAttribute("from"); fullJid = message.getFrom();
if (fullJid == null) { if (fullJid == null) {
return null; return null;
} else { } else {
updateLastseen(message, account, true); updateLastseen(message, account, true);
} }
} else { } else {
fullJid = message.getAttribute("to"); fullJid = message.getTo();
if (fullJid == null) { if (fullJid == null) {
return null; return null;
} }
} }
String[] parts = fullJid.split("/", 2);
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, parts[0], false); .findOrCreateConversation(account, fullJid.toBareJid(), false);
String pgpBody = getPgpBody(message); String pgpBody = getPgpBody(message);
Message finishedMessage; Message finishedMessage;
if (pgpBody != null) { if (pgpBody != null) {
@ -247,11 +247,11 @@ public class MessageParser extends AbstractParser implements
finishedMessage.setRemoteMsgId(message.getAttribute("id")); finishedMessage.setRemoteMsgId(message.getAttribute("id"));
finishedMessage.markable = isMarkable(message); finishedMessage.markable = isMarkable(message);
if (conversation.getMode() == Conversation.MODE_MULTI if (conversation.getMode() == Conversation.MODE_MULTI
&& parts.length >= 2) { && !fullJid.isBareJid()) {
finishedMessage.setType(Message.TYPE_PRIVATE); finishedMessage.setType(Message.TYPE_PRIVATE);
finishedMessage.setPresence(parts[1]); finishedMessage.setPresence(fullJid.getResourcepart());
finishedMessage.setTrueCounterpart(conversation.getMucOptions() finishedMessage.setTrueCounterpart(conversation.getMucOptions()
.getTrueCounterpart(parts[1])); .getTrueCounterpart(fullJid.getResourcepart()));
if (conversation.hasDuplicateMessage(finishedMessage)) { if (conversation.hasDuplicateMessage(finishedMessage)) {
return null; return null;
} }
@ -259,39 +259,39 @@ public class MessageParser extends AbstractParser implements
return finishedMessage; return finishedMessage;
} }
private void parseError(MessagePacket packet, Account account) { private void parseError(final MessagePacket packet, final Account account) {
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
mXmppConnectionService.markMessage(account, fromParts[0], mXmppConnectionService.markMessage(account, from.toBareJid(),
packet.getId(), Message.STATUS_SEND_FAILED); packet.getId(), Message.STATUS_SEND_FAILED);
} }
private void parseNonMessage(Element packet, Account account) { private void parseNonMessage(Element packet, Account account) {
String from = packet.getAttribute("from"); final Jid from = packet.getFrom();
if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) { if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) {
Element event = packet.findChild("event", Element event = packet.findChild("event",
"http://jabber.org/protocol/pubsub#event"); "http://jabber.org/protocol/pubsub#event");
parseEvent(event, packet.getAttribute("from"), account); parseEvent(event, from, account);
} else if (from != null } else if (from != null
&& packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) { && packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
String id = packet String id = packet
.findChild("displayed", "urn:xmpp:chat-markers:0") .findChild("displayed", "urn:xmpp:chat-markers:0")
.getAttribute("id"); .getAttribute("id");
updateLastseen(packet, account, true); updateLastseen(packet, account, true);
mXmppConnectionService.markMessage(account, from.split("/", 2)[0], mXmppConnectionService.markMessage(account, from.toBareJid(),
id, Message.STATUS_SEND_DISPLAYED); id, Message.STATUS_SEND_DISPLAYED);
} else if (from != null } else if (from != null
&& packet.hasChild("received", "urn:xmpp:chat-markers:0")) { && packet.hasChild("received", "urn:xmpp:chat-markers:0")) {
String id = packet.findChild("received", "urn:xmpp:chat-markers:0") String id = packet.findChild("received", "urn:xmpp:chat-markers:0")
.getAttribute("id"); .getAttribute("id");
updateLastseen(packet, account, false); updateLastseen(packet, account, false);
mXmppConnectionService.markMessage(account, from.split("/", 2)[0], mXmppConnectionService.markMessage(account, from.toBareJid(),
id, Message.STATUS_SEND_RECEIVED); id, Message.STATUS_SEND_RECEIVED);
} else if (from != null } else if (from != null
&& packet.hasChild("received", "urn:xmpp:receipts")) { && packet.hasChild("received", "urn:xmpp:receipts")) {
String id = packet.findChild("received", "urn:xmpp:receipts") String id = packet.findChild("received", "urn:xmpp:receipts")
.getAttribute("id"); .getAttribute("id");
updateLastseen(packet, account, false); updateLastseen(packet, account, false);
mXmppConnectionService.markMessage(account, from.split("/", 2)[0], mXmppConnectionService.markMessage(account, from.toBareJid(),
id, Message.STATUS_SEND_RECEIVED); id, Message.STATUS_SEND_RECEIVED);
} else if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { } else if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
Element x = packet.findChild("x", Element x = packet.findChild("x",
@ -299,7 +299,7 @@ public class MessageParser extends AbstractParser implements
if (x.hasChild("invite")) { if (x.hasChild("invite")) {
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, .findOrCreateConversation(account,
packet.getAttribute("from"), true); packet.getFrom(), true);
if (!conversation.getMucOptions().online()) { if (!conversation.getMucOptions().online()) {
if (x.hasChild("password")) { if (x.hasChild("password")) {
Element password = x.findChild("password"); Element password = x.findChild("password");
@ -314,7 +314,12 @@ public class MessageParser extends AbstractParser implements
} }
} else if (packet.hasChild("x", "jabber:x:conference")) { } else if (packet.hasChild("x", "jabber:x:conference")) {
Element x = packet.findChild("x", "jabber:x:conference"); Element x = packet.findChild("x", "jabber:x:conference");
String jid = x.getAttribute("jid"); Jid jid;
try {
jid = Jid.fromString(x.getAttribute("jid"));
} catch (InvalidJidException e) {
jid = null;
}
String password = x.getAttribute("password"); String password = x.getAttribute("password");
if (jid != null) { if (jid != null) {
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
@ -332,7 +337,7 @@ public class MessageParser extends AbstractParser implements
} }
} }
private void parseEvent(Element event, String from, Account account) { private void parseEvent(final Element event, final Jid from, final Account account) {
Element items = event.findChild("items"); Element items = event.findChild("items");
String node = items.getAttribute("node"); String node = items.getAttribute("node");
if (node != null) { if (node != null) {

View File

@ -9,6 +9,7 @@ import eu.siacs.conversations.generator.PresenceGenerator;
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.OnPresencePacketReceived; import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket; import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
public class PresenceParser extends AbstractParser implements public class PresenceParser extends AbstractParser implements
@ -21,8 +22,9 @@ public class PresenceParser extends AbstractParser implements
public void parseConferencePresence(PresencePacket packet, Account account) { public void parseConferencePresence(PresencePacket packet, Account account) {
PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine(); PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine();
if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
Conversation muc = mXmppConnectionService.find(account, packet final Conversation muc = packet.getFrom() == null ? null : mXmppConnectionService.find(
.getAttribute("from").split("/", 2)[0]); account,
packet.getFrom().toBareJid());
if (muc != null) { if (muc != null) {
boolean before = muc.getMucOptions().online(); boolean before = muc.getMucOptions().online();
muc.getMucOptions().processPacket(packet, mPgpEngine); muc.getMucOptions().processPacket(packet, mPgpEngine);
@ -32,8 +34,8 @@ public class PresenceParser extends AbstractParser implements
mXmppConnectionService.getAvatarService().clear(muc); mXmppConnectionService.getAvatarService().clear(muc);
} }
} else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) {
Conversation muc = mXmppConnectionService.find(account, packet final Conversation muc = mXmppConnectionService.find(account,
.getAttribute("from").split("/", 2)[0]); packet.getFrom().toBareJid());
if (muc != null) { if (muc != null) {
boolean before = muc.getMucOptions().online(); boolean before = muc.getMucOptions().online();
muc.getMucOptions().processPacket(packet, mPgpEngine); muc.getMucOptions().processPacket(packet, mPgpEngine);
@ -51,15 +53,15 @@ public class PresenceParser extends AbstractParser implements
if (packet.getFrom() == null) { if (packet.getFrom() == null) {
return; return;
} }
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
String type = packet.getAttribute("type"); String type = packet.getAttribute("type");
if (fromParts[0].equals(account.getJid())) { if (from.toBareJid().equals(account.getJid())) {
if (fromParts.length == 2) { if (!from.getResourcepart().isEmpty()) {
if (type == null) { if (type == null) {
account.updatePresence(fromParts[1], account.updatePresence(from.getResourcepart(),
Presences.parseShow(packet.findChild("show"))); Presences.parseShow(packet.findChild("show")));
} else if (type.equals("unavailable")) { } else if (type.equals("unavailable")) {
account.removePresence(fromParts[1]); account.removePresence(from.getResourcepart());
account.deactivateGracePeriod(); account.deactivateGracePeriod();
} }
} }
@ -67,8 +69,8 @@ public class PresenceParser extends AbstractParser implements
Contact contact = account.getRoster().getContact(packet.getFrom()); Contact contact = account.getRoster().getContact(packet.getFrom());
if (type == null) { if (type == null) {
String presence; String presence;
if (fromParts.length >= 2) { if (!from.getResourcepart().isEmpty()) {
presence = fromParts[1]; presence = from.getResourcepart();
} else { } else {
presence = ""; presence = "";
} }
@ -95,10 +97,10 @@ public class PresenceParser extends AbstractParser implements
mXmppConnectionService.onContactStatusChanged mXmppConnectionService.onContactStatusChanged
.onContactStatusChanged(contact, online); .onContactStatusChanged(contact, online);
} else if (type.equals("unavailable")) { } else if (type.equals("unavailable")) {
if (fromParts.length != 2) { if (from.isBareJid()) {
contact.clearPresences(); contact.clearPresences();
} else { } else {
contact.removePresence(fromParts[1]); contact.removePresence(from.getResourcepart());
} }
mXmppConnectionService.onContactStatusChanged mXmppConnectionService.onContactStatusChanged
.onContactStatusChanged(contact, false); .onContactStatusChanged(contact, false);

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

@ -28,7 +28,7 @@ public class AvatarService {
private static final String PREFIX_ACCOUNT = "account"; private static final String PREFIX_ACCOUNT = "account";
private static final String PREFIX_GENERIC = "generic"; private static final String PREFIX_GENERIC = "generic";
private ArrayList<Integer> sizes = new ArrayList<Integer>(); final private ArrayList<Integer> sizes = new ArrayList<>();
protected XmppConnectionService mXmppConnectionService = null; protected XmppConnectionService mXmppConnectionService = null;
@ -36,7 +36,7 @@ public class AvatarService {
this.mXmppConnectionService = service; this.mXmppConnectionService = service;
} }
public Bitmap get(Contact contact, int size) { public Bitmap get(final Contact contact, final int size) {
final String KEY = key(contact, size); final String KEY = key(contact, size);
Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
if (avatar != null) { if (avatar != null) {
@ -173,7 +173,7 @@ public class AvatarService {
avatar = mXmppConnectionService.getFileBackend().getAvatar( avatar = mXmppConnectionService.getFileBackend().getAvatar(
account.getAvatar(), size); account.getAvatar(), size);
if (avatar == null) { if (avatar == null) {
avatar = get(account.getJid(), size); avatar = get(account.getJid().toString(), size);
} }
mXmppConnectionService.getBitmapCache().put(KEY, avatar); mXmppConnectionService.getBitmapCache().put(KEY, avatar);
return avatar; return avatar;
@ -196,7 +196,7 @@ public class AvatarService {
+ String.valueOf(size); + String.valueOf(size);
} }
public Bitmap get(String name, int size) { public Bitmap get(final String name, final int size) {
final String KEY = key(name, size); final String KEY = key(name, size);
Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
if (bitmap != null) { if (bitmap != null) {

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,10 +181,10 @@ 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()) {
@ -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;
@ -564,7 +563,7 @@ public class XmppConnectionService extends Service {
if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (message.getEncryption() == Message.ENCRYPTION_OTR) {
if (!conv.hasValidOtrSession() if (!conv.hasValidOtrSession()
&& (message.getPresence() != null)) { && (message.getPresence() != null)) {
conv.startOtrSession(this, message.getPresence(), conv.startOtrSession(this, message.getPresence().toString(),
true); true);
message.setStatus(Message.STATUS_WAITING); message.setStatus(Message.STATUS_WAITING);
} else if (conv.hasValidOtrSession() } else if (conv.hasValidOtrSession()
@ -585,7 +584,7 @@ public class XmppConnectionService extends Service {
if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (message.getEncryption() == Message.ENCRYPTION_OTR) {
if (!conv.hasValidOtrSession() if (!conv.hasValidOtrSession()
&& (message.getPresence() != null)) { && (message.getPresence() != null)) {
conv.startOtrSession(this, message.getPresence(), true); conv.startOtrSession(this, message.getPresence().toString(), true);
message.setStatus(Message.STATUS_WAITING); message.setStatus(Message.STATUS_WAITING);
} else if (conv.hasValidOtrSession() } else if (conv.hasValidOtrSession()
&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { && conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
@ -632,7 +631,7 @@ public class XmppConnectionService extends Service {
.getUserID()); .getUserID());
} else if (!conv.hasValidOtrSession() } else if (!conv.hasValidOtrSession()
&& message.getPresence() != null) { && message.getPresence() != null) {
conv.startOtrSession(this, message.getPresence(), false); conv.startOtrSession(this, message.getPresence().toString(), false);
} }
} }
} }
@ -668,9 +667,9 @@ public class XmppConnectionService extends Service {
.getPresences(); .getPresences();
if (!message.getConversation().hasValidOtrSession()) { if (!message.getConversation().hasValidOtrSession()) {
if ((message.getPresence() != null) if ((message.getPresence() != null)
&& (presences.has(message.getPresence()))) { && (presences.has(message.getPresence().toString()))) {
message.getConversation().startOtrSession(this, message.getConversation().startOtrSession(this,
message.getPresence(), true); message.getPresence().toString(), true);
} else { } else {
if (presences.size() == 1) { if (presences.size() == 1) {
String presence = presences.asStringArray()[0]; String presence = presences.asStringArray()[0];
@ -700,7 +699,7 @@ public class XmppConnectionService extends Service {
Presences presences = message.getConversation().getContact() Presences presences = message.getConversation().getContact()
.getPresences(); .getPresences();
if ((message.getPresence() != null) if ((message.getPresence() != null)
&& (presences.has(message.getPresence()))) { && (presences.has(message.getPresence().toString()))) {
markMessage(message, Message.STATUS_OFFERED); markMessage(message, Message.STATUS_OFFERED);
mJingleConnectionManager.createNewConnection(message); mJingleConnectionManager.createNewConnection(message);
} else { } else {
@ -757,7 +756,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 +805,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 +832,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 +930,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 +966,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,8 +1168,7 @@ 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);
@ -1182,8 +1186,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 +1264,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 +1293,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,8 +1311,7 @@ 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);
@ -1365,8 +1368,7 @@ 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());
@ -1397,7 +1399,7 @@ 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
@ -1596,7 +1598,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 +1650,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 +1732,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 +1758,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 +1812,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 +1830,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 +1893,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 +1933,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

@ -25,7 +25,7 @@ import eu.siacs.conversations.ui.adapter.ListItemAdapter;
public class ChooseContactActivity extends XmppActivity { public class ChooseContactActivity extends XmppActivity {
private ListView mListView; private ListView mListView;
private ArrayList<ListItem> contacts = new ArrayList<ListItem>(); private ArrayList<ListItem> contacts = new ArrayList<>();
private ArrayAdapter<ListItem> mContactsAdapter; private ArrayAdapter<ListItem> mContactsAdapter;
private EditText mSearchEditText; private EditText mSearchEditText;
@ -96,10 +96,10 @@ public class ChooseContactActivity extends XmppActivity {
Intent request = getIntent(); Intent request = getIntent();
Intent data = new Intent(); Intent data = new Intent();
ListItem mListItem = contacts.get(position); ListItem mListItem = contacts.get(position);
data.putExtra("contact", mListItem.getJid()); data.putExtra("contact", mListItem.getJid().toString());
String account = request.getStringExtra("account"); String account = request.getStringExtra("account");
if (account == null && mListItem instanceof Contact) { if (account == null && mListItem instanceof Contact) {
account = ((Contact) mListItem).getAccount().getJid(); account = ((Contact) mListItem).getAccount().getJid().toString();
} }
data.putExtra("account", account); data.putExtra("account", account);
data.putExtra("conversation", data.putExtra("conversation",

View File

@ -53,7 +53,7 @@ public class ConferenceDetailsActivity extends XmppActivity {
} }
}; };
private List<User> users = new ArrayList<MucOptions.User>(); private List<User> users = new ArrayList<>();
private OnConversationUpdate onConvChanged = new OnConversationUpdate() { private OnConversationUpdate onConvChanged = new OnConversationUpdate() {
@Override @Override
@ -142,7 +142,7 @@ public class ConferenceDetailsActivity extends XmppActivity {
@Override @Override
protected String getShareableUri() { protected String getShareableUri() {
if (conversation!=null) { if (conversation!=null) {
return "xmpp:"+conversation.getContactJid().split("/")[0]+"?join"; return "xmpp:"+conversation.getContactJid().toBareJid().toString()+"?join";
} else { } else {
return ""; return "";
} }
@ -211,7 +211,7 @@ public class ConferenceDetailsActivity extends XmppActivity {
mYourPhoto.setImageBitmap(avatarService().get( mYourPhoto.setImageBitmap(avatarService().get(
conversation.getAccount(), getPixel(48))); conversation.getAccount(), getPixel(48)));
setTitle(conversation.getName()); setTitle(conversation.getName());
mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); mFullJid.setText(conversation.getContactJid().toBareJid().toString());
mYourNick.setText(conversation.getMucOptions().getActualNick()); mYourNick.setText(conversation.getMucOptions().getActualNick());
mRoleAffiliaton = (TextView) findViewById(R.id.muc_role); mRoleAffiliaton = (TextView) findViewById(R.id.muc_role);
if (conversation.getMucOptions().online()) { if (conversation.getMucOptions().online()) {

View File

@ -35,14 +35,16 @@ import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
public class ContactDetailsActivity extends XmppActivity { public class ContactDetailsActivity extends XmppActivity {
public static final String ACTION_VIEW_CONTACT = "view_contact"; public static final String ACTION_VIEW_CONTACT = "view_contact";
private Contact contact; private Contact contact;
private String accountJid; private Jid accountJid;
private String contactJid; private Jid contactJid;
private TextView contactJidTv; private TextView contactJidTv;
private TextView accountJidTv; private TextView accountJidTv;
@ -68,7 +70,7 @@ public class ContactDetailsActivity extends XmppActivity {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
intent.setType(Contacts.CONTENT_ITEM_TYPE); intent.setType(Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid()); intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid().toString());
intent.putExtra(Intents.Insert.IM_PROTOCOL, intent.putExtra(Intents.Insert.IM_PROTOCOL,
CommonDataKinds.Im.PROTOCOL_JABBER); CommonDataKinds.Im.PROTOCOL_JABBER);
intent.putExtra("finishActivityOnSaveCompleted", true); intent.putExtra("finishActivityOnSaveCompleted", true);
@ -174,8 +176,14 @@ public class ContactDetailsActivity extends XmppActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) { if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
this.accountJid = getIntent().getExtras().getString("account"); try {
this.contactJid = getIntent().getExtras().getString("contact"); this.accountJid = Jid.fromString(getIntent().getExtras().getString("account"));
} catch (final InvalidJidException ignored) {
}
try {
this.contactJid = Jid.fromString(getIntent().getExtras().getString("contact"));
} catch (final InvalidJidException ignored) {
}
} }
setContentView(R.layout.activity_contact_details); setContentView(R.layout.activity_contact_details);
@ -318,7 +326,7 @@ public class ContactDetailsActivity extends XmppActivity {
contactJidTv.setText(contact.getJid() + " (" contactJidTv.setText(contact.getJid() + " ("
+ contact.getPresences().size() + ")"); + contact.getPresences().size() + ")");
} else { } else {
contactJidTv.setText(contact.getJid()); contactJidTv.setText(contact.getJid().toString());
} }
accountJidTv.setText(getString(R.string.using_account, contact accountJidTv.setText(getString(R.string.using_account, contact
.getAccount().getJid())); .getAccount().getJid()));

View File

@ -69,7 +69,7 @@ public class ConversationActivity extends XmppActivity implements
private View mContentView; private View mContentView;
private List<Conversation> conversationList = new ArrayList<Conversation>(); private List<Conversation> conversationList = new ArrayList<>();
private Conversation selectedConversation = null; private Conversation selectedConversation = null;
private ListView listView; private ListView listView;
private ConversationFragment mConversationFragment; private ConversationFragment mConversationFragment;
@ -160,8 +160,10 @@ public class ConversationActivity extends XmppActivity implements
this.listAdapter = new ConversationAdapter(this, conversationList); this.listAdapter = new ConversationAdapter(this, conversationList);
listView.setAdapter(this.listAdapter); listView.setAdapter(this.listAdapter);
if (getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(false); getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false); getActionBar().setHomeButtonEnabled(false);
}
listView.setOnItemClickListener(new OnItemClickListener() { listView.setOnItemClickListener(new OnItemClickListener() {
@ -228,8 +230,7 @@ public class ConversationActivity extends XmppActivity implements
.useSubjectToIdentifyConference()) { .useSubjectToIdentifyConference()) {
ab.setTitle(getSelectedConversation().getName()); ab.setTitle(getSelectedConversation().getName());
} else { } else {
ab.setTitle(getSelectedConversation().getContactJid() ab.setTitle(getSelectedConversation().getContactJid().toBareJid().toString());
.split("/")[0]);
} }
} }
invalidateOptionsMenu(); invalidateOptionsMenu();
@ -600,7 +601,7 @@ public class ConversationActivity extends XmppActivity implements
} }
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
if (!isConversationsOverviewVisable()) { if (!isConversationsOverviewVisable()) {
showConversationsOverview(); showConversationsOverview();
@ -611,7 +612,7 @@ public class ConversationActivity extends XmppActivity implements
} }
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(final Intent intent) {
if (xmppConnectionServiceBound) { if (xmppConnectionServiceBound) {
if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) { if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) {
handleViewConversationIntent(intent); handleViewConversationIntent(intent);
@ -645,7 +646,7 @@ public class ConversationActivity extends XmppActivity implements
} }
@Override @Override
public void onSaveInstanceState(Bundle savedInstanceState) { public void onSaveInstanceState(final Bundle savedInstanceState) {
Conversation conversation = getSelectedConversation(); Conversation conversation = getSelectedConversation();
if (conversation != null) { if (conversation != null) {
savedInstanceState.putString(STATE_OPEN_CONVERSATION, savedInstanceState.putString(STATE_OPEN_CONVERSATION,
@ -714,9 +715,9 @@ public class ConversationActivity extends XmppActivity implements
} }
private void selectConversationByUuid(String uuid) { private void selectConversationByUuid(String uuid) {
for (int i = 0; i < conversationList.size(); ++i) { for (Conversation aConversationList : conversationList) {
if (conversationList.get(i).getUuid().equals(uuid)) { if (aConversationList.getUuid().equals(uuid)) {
setSelectedConversation(conversationList.get(i)); setSelectedConversation(aConversationList);
} }
} }
} }
@ -832,7 +833,7 @@ public class ConversationActivity extends XmppActivity implements
try { try {
this.startIntentSenderForResult(pi.getIntentSender(), requestCode, this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
null, 0, 0, 0); null, 0, 0, 0);
} catch (SendIntentException e1) { } catch (final SendIntentException ignored) {
} }
} }

View File

@ -54,6 +54,7 @@ import eu.siacs.conversations.ui.adapter.MessageAdapter;
import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jid.Jid;
public class ConversationFragment extends Fragment { public class ConversationFragment extends Fragment {
@ -92,11 +93,9 @@ public class ConversationFragment extends Fragment {
} }
}; };
protected ListView messagesView; protected ListView messagesView;
protected LayoutInflater inflater; protected List<Message> messageList = new ArrayList<>();
protected List<Message> messageList = new ArrayList<Message>();
protected MessageAdapter messageListAdapter; protected MessageAdapter messageListAdapter;
protected Contact contact; protected Contact contact;
protected String queuedPqpMessage = null;
private EditMessage mEditMessage; private EditMessage mEditMessage;
private ImageButton mSendButton; private ImageButton mSendButton;
private RelativeLayout snackbar; private RelativeLayout snackbar;
@ -147,7 +146,7 @@ public class ConversationFragment extends Fragment {
} }
} }
}; };
private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<Message>(); private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<>();
private boolean mDecryptJobRunning = false; private boolean mDecryptJobRunning = false;
private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() { private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
@ -281,10 +280,10 @@ public class ConversationFragment extends Fragment {
if (message.getStatus() <= Message.STATUS_RECEIVED) { if (message.getStatus() <= Message.STATUS_RECEIVED) {
if (message.getConversation().getMode() == Conversation.MODE_MULTI) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
if (message.getPresence() != null) { if (message.getPresence() != null) {
highlightInConference(message.getPresence()); highlightInConference(message.getPresence().getResourcepart());
} else { } else {
highlightInConference(message highlightInConference(message
.getCounterpart()); .getContact().getDisplayName());
} }
} else { } else {
Contact contact = message.getConversation() Contact contact = message.getConversation()
@ -299,7 +298,7 @@ public class ConversationFragment extends Fragment {
} else { } else {
Account account = message.getConversation().getAccount(); Account account = message.getConversation().getAccount();
Intent intent = new Intent(activity, EditAccountActivity.class); Intent intent = new Intent(activity, EditAccountActivity.class);
intent.putExtra("jid", account.getJid()); intent.putExtra("jid", account.getJid().toString());
startActivity(intent); startActivity(intent);
} }
} }
@ -430,9 +429,9 @@ public class ConversationFragment extends Fragment {
.createNewConnection(message); .createNewConnection(message);
} }
protected void privateMessageWith(String counterpart) { protected void privateMessageWith(final Jid counterpart) {
this.mEditMessage.setText(""); this.mEditMessage.setText("");
this.conversation.setNextPresence(counterpart); this.conversation.setNextPresence(counterpart.toString());
updateChatMsgHint(); updateChatMsgHint();
} }

View File

@ -1,15 +1,10 @@
package eu.siacs.conversations.ui; package eu.siacs.conversations.ui;
import android.app.AlertDialog;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -27,26 +22,15 @@ import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.Hashtable;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.utils.Validator; import eu.siacs.conversations.utils.Validator;
import eu.siacs.conversations.xmpp.XmppConnection.Features; import eu.siacs.conversations.xmpp.XmppConnection.Features;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.pep.Avatar;
public class EditAccountActivity extends XmppActivity { public class EditAccountActivity extends XmppActivity {
@ -68,7 +52,7 @@ public class EditAccountActivity extends XmppActivity {
private RelativeLayout mOtrFingerprintBox; private RelativeLayout mOtrFingerprintBox;
private ImageButton mOtrFingerprintToClipboardButton; private ImageButton mOtrFingerprintToClipboardButton;
private String jidToEdit; private Jid jidToEdit;
private Account mAccount; private Account mAccount;
private boolean mFetchingAvatar = false; private boolean mFetchingAvatar = false;
@ -89,13 +73,12 @@ public class EditAccountActivity extends XmppActivity {
return; return;
} }
boolean registerNewAccount = mRegisterNew.isChecked(); boolean registerNewAccount = mRegisterNew.isChecked();
String[] jidParts = mAccountJid.getText().toString().split("@"); final Jid jid;
String username = jidParts[0]; try {
String server; jid = Jid.fromString(mAccountJid.getText().toString());
if (jidParts.length >= 2) { } catch (final InvalidJidException e) {
server = jidParts[1]; // TODO: Handle this error?
} else { return;
server = "";
} }
String password = mPassword.getText().toString(); String password = mPassword.getText().toString();
String passwordConfirm = mPasswordConfirm.getText().toString(); String passwordConfirm = mPasswordConfirm.getText().toString();
@ -109,19 +92,25 @@ public class EditAccountActivity extends XmppActivity {
} }
if (mAccount != null) { if (mAccount != null) {
mAccount.setPassword(password); mAccount.setPassword(password);
mAccount.setUsername(username); try {
mAccount.setServer(server); mAccount.setUsername(jid.hasLocalpart() ? jid.getLocalpart() : "");
mAccount.setServer(jid.getDomainpart());
} catch (final InvalidJidException ignored) {
}
mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
xmppConnectionService.updateAccount(mAccount); xmppConnectionService.updateAccount(mAccount);
} else { } else {
if (xmppConnectionService.findAccountByJid(mAccountJid try {
.getText().toString()) != null) { if (xmppConnectionService.findAccountByJid(Jid.fromString(mAccountJid.getText().toString())) != null) {
mAccountJid mAccountJid
.setError(getString(R.string.account_already_exists)); .setError(getString(R.string.account_already_exists));
mAccountJid.requestFocus(); mAccountJid.requestFocus();
return; return;
} }
mAccount = new Account(username, server, password); } catch (InvalidJidException e) {
return;
}
mAccount = new Account(jid.toBareJid(), password);
mAccount.setOption(Account.OPTION_USETLS, true); mAccount.setOption(Account.OPTION_USETLS, true);
mAccount.setOption(Account.OPTION_USECOMPRESSION, true); mAccount.setOption(Account.OPTION_USECOMPRESSION, true);
mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
@ -191,7 +180,6 @@ public class EditAccountActivity extends XmppActivity {
finishInitialSetup(avatar); finishInitialSetup(avatar);
} }
}; };
private KnownHostsAdapter mKnownHostsAdapter;
private TextWatcher mTextWatcher = new TextWatcher() { private TextWatcher mTextWatcher = new TextWatcher() {
@Override @Override
@ -217,7 +205,7 @@ public class EditAccountActivity extends XmppActivity {
if (mAccount!=null) { if (mAccount!=null) {
Intent intent = new Intent(getApplicationContext(), Intent intent = new Intent(getApplicationContext(),
PublishProfilePictureActivity.class); PublishProfilePictureActivity.class);
intent.putExtra("account", mAccount.getJid()); intent.putExtra("account", mAccount.getJid().toString());
startActivity(intent); startActivity(intent);
} }
} }
@ -235,7 +223,7 @@ public class EditAccountActivity extends XmppActivity {
} else { } else {
intent = new Intent(getApplicationContext(), intent = new Intent(getApplicationContext(),
PublishProfilePictureActivity.class); PublishProfilePictureActivity.class);
intent.putExtra("account", mAccount.getJid()); intent.putExtra("account", mAccount.getJid().toString());
intent.putExtra("setup", true); intent.putExtra("setup", true);
} }
startActivity(intent); startActivity(intent);
@ -244,18 +232,6 @@ public class EditAccountActivity extends XmppActivity {
}); });
} }
protected boolean inputDataDiffersFromAccount() {
if (mAccount == null) {
return true;
} else {
return (!mAccount.getJid().equals(mAccountJid.getText().toString()))
|| (!mAccount.getPassword().equals(
mPassword.getText().toString()) || mAccount
.isOptionSet(Account.OPTION_REGISTER) != mRegisterNew
.isChecked());
}
}
protected void updateSaveButton() { protected void updateSaveButton() {
if (mAccount != null if (mAccount != null
&& mAccount.getStatus() == Account.STATUS_CONNECTING) { && mAccount.getStatus() == Account.STATUS_CONNECTING) {
@ -358,7 +334,11 @@ public class EditAccountActivity extends XmppActivity {
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
if (getIntent() != null) { if (getIntent() != null) {
this.jidToEdit = getIntent().getStringExtra("jid"); try {
this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid"));
} catch (final InvalidJidException | NullPointerException ignored) {
this.jidToEdit = null;
}
if (this.jidToEdit != null) { if (this.jidToEdit != null) {
this.mRegisterNew.setVisibility(View.GONE); this.mRegisterNew.setVisibility(View.GONE);
getActionBar().setTitle(getString(R.string.account_details)); getActionBar().setTitle(getString(R.string.account_details));
@ -379,7 +359,7 @@ public class EditAccountActivity extends XmppActivity {
@Override @Override
protected void onBackendConnected() { protected void onBackendConnected() {
this.mKnownHostsAdapter = new KnownHostsAdapter(this, KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
android.R.layout.simple_list_item_1, android.R.layout.simple_list_item_1,
xmppConnectionService.getKnownHosts()); xmppConnectionService.getKnownHosts());
this.xmppConnectionService this.xmppConnectionService
@ -393,12 +373,12 @@ public class EditAccountActivity extends XmppActivity {
this.mCancelButton.setEnabled(false); this.mCancelButton.setEnabled(false);
this.mCancelButton.setTextColor(getSecondaryTextColor()); this.mCancelButton.setTextColor(getSecondaryTextColor());
} }
this.mAccountJid.setAdapter(this.mKnownHostsAdapter); this.mAccountJid.setAdapter(mKnownHostsAdapter);
updateSaveButton(); updateSaveButton();
} }
private void updateAccountInformation() { private void updateAccountInformation() {
this.mAccountJid.setText(this.mAccount.getJid()); this.mAccountJid.setText(this.mAccount.getJid().toString());
this.mPassword.setText(this.mAccount.getPassword()); this.mPassword.setText(this.mAccount.getPassword());
if (this.jidToEdit != null) { if (this.jidToEdit != null) {
this.mAvatar.setVisibility(View.VISIBLE); this.mAvatar.setVisibility(View.VISIBLE);

View File

@ -81,7 +81,7 @@ public class ManageAccountActivity extends XmppActivity {
} else { } else {
menu.findItem(R.id.mgmt_account_enable).setVisible(false); menu.findItem(R.id.mgmt_account_enable).setVisible(false);
} }
menu.setHeaderTitle(this.selectedAccount.getJid()); menu.setHeaderTitle(this.selectedAccount.getJid().toString());
} }
@Override @Override
@ -166,7 +166,7 @@ public class ManageAccountActivity extends XmppActivity {
private void publishAvatar(Account account) { private void publishAvatar(Account account) {
Intent intent = new Intent(getApplicationContext(), Intent intent = new Intent(getApplicationContext(),
PublishProfilePictureActivity.class); PublishProfilePictureActivity.class);
intent.putExtra("account", account.getJid()); intent.putExtra("account", account.getJid().toString());
startActivity(intent); startActivity(intent);
} }

View File

@ -14,6 +14,8 @@ import android.widget.TextView;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.pep.Avatar;
public class PublishProfilePictureActivity extends XmppActivity { public class PublishProfilePictureActivity extends XmppActivity {
@ -148,7 +150,12 @@ public class PublishProfilePictureActivity extends XmppActivity {
@Override @Override
protected void onBackendConnected() { protected void onBackendConnected() {
if (getIntent() != null) { if (getIntent() != null) {
String jid = getIntent().getStringExtra("account"); Jid jid;
try {
jid = Jid.fromString(getIntent().getStringExtra("account"));
} catch (InvalidJidException e) {
jid = null;
}
if (jid != null) { if (jid != null) {
this.account = xmppConnectionService.findAccountByJid(jid); this.account = xmppConnectionService.findAccountByJid(jid);
if (this.account.getXmppConnection() != null) { if (this.account.getXmppConnection() != null) {
@ -180,7 +187,7 @@ public class PublishProfilePictureActivity extends XmppActivity {
} else { } else {
loadImageIntoPreview(avatarUri); loadImageIntoPreview(avatarUri);
} }
this.accountTextView.setText(this.account.getJid()); this.accountTextView.setText(this.account.getJid().toString());
} }
} }

View File

@ -5,6 +5,8 @@ import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Build; import android.os.Build;

View File

@ -9,6 +9,9 @@ import eu.siacs.conversations.entities.Account;
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.ui.adapter.ConversationAdapter; import eu.siacs.conversations.ui.adapter.ConversationAdapter;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -150,12 +153,22 @@ public class ShareWithActivity extends XmppActivity {
} }
private void share() { private void share() {
Account account = xmppConnectionService.findAccountByJid(share.account); Account account;
try {
account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account));
} catch (final InvalidJidException e) {
account = null;
}
if (account == null) { if (account == null) {
return; return;
} }
Conversation conversation = xmppConnectionService final Conversation conversation;
.findOrCreateConversation(account, share.contact, false); try {
conversation = xmppConnectionService
.findOrCreateConversation(account, Jid.fromString(share.contact), false);
} catch (final InvalidJidException e) {
return;
}
share(conversation); share(conversation);
} }

View File

@ -63,6 +63,8 @@ import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.adapter.ListItemAdapter; import eu.siacs.conversations.ui.adapter.ListItemAdapter;
import eu.siacs.conversations.utils.Validator; import eu.siacs.conversations.utils.Validator;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
public class StartConversationActivity extends XmppActivity { public class StartConversationActivity extends XmppActivity {
@ -71,7 +73,7 @@ public class StartConversationActivity extends XmppActivity {
private ViewPager mViewPager; private ViewPager mViewPager;
private MyListFragment mContactsListFragment = new MyListFragment(); private MyListFragment mContactsListFragment = new MyListFragment();
private List<ListItem> contacts = new ArrayList<ListItem>(); private List<ListItem> contacts = new ArrayList<>();
private ArrayAdapter<ListItem> mContactsAdapter; private ArrayAdapter<ListItem> mContactsAdapter;
private MyListFragment mConferenceListFragment = new MyListFragment(); private MyListFragment mConferenceListFragment = new MyListFragment();
@ -359,17 +361,26 @@ public class StartConversationActivity extends XmppActivity {
return; return;
} }
if (Validator.isValidJid(jid.getText().toString())) { if (Validator.isValidJid(jid.getText().toString())) {
String accountJid = (String) spinner final Jid accountJid;
.getSelectedItem(); try {
String contactJid = jid.getText().toString(); accountJid = Jid.fromString((String) spinner
.getSelectedItem());
} catch (final InvalidJidException e) {
return;
}
final Jid contactJid;
try {
contactJid = Jid.fromString(jid.getText().toString());
} catch (final InvalidJidException e) {
return;
}
Account account = xmppConnectionService Account account = xmppConnectionService
.findAccountByJid(accountJid); .findAccountByJid(accountJid);
if (account == null) { if (account == null) {
dialog.dismiss(); dialog.dismiss();
return; return;
} }
Contact contact = account.getRoster().getContact( Contact contact = account.getRoster().getContact(contactJid);
contactJid);
if (contact.showInRoster()) { if (contact.showInRoster()) {
jid.setError(getString(R.string.contact_already_exists)); jid.setError(getString(R.string.contact_already_exists));
} else { } else {
@ -416,9 +427,18 @@ public class StartConversationActivity extends XmppActivity {
return; return;
} }
if (Validator.isValidJid(jid.getText().toString())) { if (Validator.isValidJid(jid.getText().toString())) {
String accountJid = (String) spinner final Jid accountJid;
.getSelectedItem(); try {
String conferenceJid = jid.getText().toString(); accountJid = Jid.fromString((String) spinner.getSelectedItem());
} catch (final InvalidJidException e) {
return;
}
final Jid conferenceJid;
try {
conferenceJid = Jid.fromString(jid.getText().toString());
} catch (final InvalidJidException e) {
return; // TODO: Do some error handling...
}
Account account = xmppConnectionService Account account = xmppConnectionService
.findAccountByJid(accountJid); .findAccountByJid(accountJid);
if (account == null) { if (account == null) {
@ -471,7 +491,7 @@ public class StartConversationActivity extends XmppActivity {
} }
private void populateAccountSpinner(Spinner spinner) { private void populateAccountSpinner(Spinner spinner) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, mActivatedAccounts); android.R.layout.simple_spinner_item, mActivatedAccounts);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter); spinner.setAdapter(adapter);
@ -554,7 +574,7 @@ public class StartConversationActivity extends XmppActivity {
this.mActivatedAccounts.clear(); this.mActivatedAccounts.clear();
for (Account account : xmppConnectionService.getAccounts()) { for (Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.STATUS_DISABLED) { if (account.getStatus() != Account.STATUS_DISABLED) {
this.mActivatedAccounts.add(account.getJid()); this.mActivatedAccounts.add(account.getJid().toString());
} }
} }
this.mKnownHosts = xmppConnectionService.getKnownHosts(); this.mKnownHosts = xmppConnectionService.getKnownHosts();
@ -779,7 +799,7 @@ public class StartConversationActivity extends XmppActivity {
// sample: imto://xmpp/jid@foo.com // sample: imto://xmpp/jid@foo.com
try { try {
jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1]; jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1];
} catch (UnsupportedEncodingException e) { } catch (final UnsupportedEncodingException ignored) {
} }
} }
} }

View File

@ -65,6 +65,7 @@ import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
import eu.siacs.conversations.utils.ExceptionHelper; import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.xmpp.jid.Jid;
public abstract class XmppActivity extends Activity { public abstract class XmppActivity extends Activity {
@ -275,14 +276,14 @@ public abstract class XmppActivity extends Activity {
public void switchToContactDetails(Contact contact) { public void switchToContactDetails(Contact contact) {
Intent intent = new Intent(this, ContactDetailsActivity.class); Intent intent = new Intent(this, ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
intent.putExtra("account", contact.getAccount().getJid()); intent.putExtra("account", contact.getAccount().getJid().toString());
intent.putExtra("contact", contact.getJid()); intent.putExtra("contact", contact.getJid().toString());
startActivity(intent); startActivity(intent);
} }
public void switchToAccount(Account account) { public void switchToAccount(Account account) {
Intent intent = new Intent(this, EditAccountActivity.class); Intent intent = new Intent(this, EditAccountActivity.class);
intent.putExtra("jid", account.getJid()); intent.putExtra("jid", account.getJid().toString());
startActivity(intent); startActivity(intent);
} }
@ -303,7 +304,7 @@ public abstract class XmppActivity extends Activity {
try { try {
startIntentSenderForResult(pi.getIntentSender(), startIntentSenderForResult(pi.getIntentSender(),
REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
} catch (SendIntentException e) { } catch (final SendIntentException ignored) {
} }
} }
@ -347,9 +348,9 @@ public abstract class XmppActivity extends Activity {
} }
protected void showAddToRosterDialog(final Conversation conversation) { protected void showAddToRosterDialog(final Conversation conversation) {
String jid = conversation.getContactJid(); final Jid jid = conversation.getContactJid();
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(jid); builder.setTitle(jid.toString());
builder.setMessage(getString(R.string.not_in_roster)); builder.setMessage(getString(R.string.not_in_roster));
builder.setNegativeButton(getString(R.string.cancel), null); builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.add_contact), builder.setPositiveButton(getString(R.string.add_contact),
@ -357,7 +358,7 @@ public abstract class XmppActivity extends Activity {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String jid = conversation.getContactJid(); final Jid jid = conversation.getContactJid();
Account account = conversation.getAccount(); Account account = conversation.getAccount();
Contact contact = account.getRoster().getContact(jid); Contact contact = account.getRoster().getContact(jid);
xmppConnectionService.createContact(contact); xmppConnectionService.createContact(contact);
@ -369,7 +370,7 @@ public abstract class XmppActivity extends Activity {
private void showAskForPresenceDialog(final Contact contact) { private void showAskForPresenceDialog(final Contact contact) {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(contact.getJid()); builder.setTitle(contact.getJid().toString());
builder.setMessage(R.string.request_presence_updates); builder.setMessage(R.string.request_presence_updates);
builder.setNegativeButton(R.string.cancel, null); builder.setNegativeButton(R.string.cancel, null);
builder.setPositiveButton(R.string.request_now, builder.setPositiveButton(R.string.request_now,
@ -391,7 +392,7 @@ public abstract class XmppActivity extends Activity {
private void warnMutalPresenceSubscription(final Conversation conversation, private void warnMutalPresenceSubscription(final Conversation conversation,
final OnPresenceSelected listener) { final OnPresenceSelected listener) {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(conversation.getContact().getJid()); builder.setTitle(conversation.getContact().getJid().toString());
builder.setMessage(R.string.without_mutual_presence_updates); builder.setMessage(R.string.without_mutual_presence_updates);
builder.setNegativeButton(R.string.cancel, null); builder.setNegativeButton(R.string.cancel, null);
builder.setPositiveButton(R.string.ignore, new OnClickListener() { builder.setPositiveButton(R.string.ignore, new OnClickListener() {
@ -567,11 +568,10 @@ public abstract class XmppActivity extends Activity {
nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
@Override @Override
public NdefMessage createNdefMessage(NfcEvent nfcEvent) { public NdefMessage createNdefMessage(NfcEvent nfcEvent) {
NdefMessage msg = new NdefMessage(new NdefRecord[]{ return new NdefMessage(new NdefRecord[]{
NdefRecord.createUri(getShareableUri()), NdefRecord.createUri(getShareableUri()),
NdefRecord.createApplicationRecord("eu.siacs.conversations") NdefRecord.createApplicationRecord("eu.siacs.conversations")
}); });
return msg;
} }
}, this); }, this);
} }
@ -620,7 +620,7 @@ public abstract class XmppActivity extends Activity {
protected Bitmap createQrCodeBitmap(String input, int size) { protected Bitmap createQrCodeBitmap(String input, int size) {
try { try {
final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter();
final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); final Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints); final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints);
final int width = result.getWidth(); final int width = result.getWidth();
@ -649,7 +649,7 @@ public abstract class XmppActivity extends Activity {
private Message message = null; private Message message = null;
public BitmapWorkerTask(ImageView imageView) { public BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView); imageViewReference = new WeakReference<>(imageView);
} }
@Override @Override
@ -665,7 +665,7 @@ public abstract class XmppActivity extends Activity {
@Override @Override
protected void onPostExecute(Bitmap bitmap) { protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) { if (bitmap != null) {
final ImageView imageView = imageViewReference.get(); final ImageView imageView = imageViewReference.get();
if (imageView != null) { if (imageView != null) {
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap);
@ -695,8 +695,7 @@ public abstract class XmppActivity extends Activity {
imageView.setImageDrawable(asyncDrawable); imageView.setImageDrawable(asyncDrawable);
try { try {
task.execute(message); task.execute(message);
} catch (RejectedExecutionException e) { } catch (final RejectedExecutionException ignored) {
return;
} }
} }
} }
@ -734,7 +733,7 @@ public abstract class XmppActivity extends Activity {
public AsyncDrawable(Resources res, Bitmap bitmap, public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) { BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap); super(res, bitmap);
bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>( bitmapWorkerTaskReference = new WeakReference<>(
bitmapWorkerTask); bitmapWorkerTask);
} }

View File

@ -31,7 +31,7 @@ public class AccountAdapter extends ArrayAdapter<Account> {
view = inflater.inflate(R.layout.account_row, parent, false); view = inflater.inflate(R.layout.account_row, parent, false);
} }
TextView jid = (TextView) view.findViewById(R.id.account_jid); TextView jid = (TextView) view.findViewById(R.id.account_jid);
jid.setText(account.getJid()); jid.setText(account.getJid().toString());
TextView statusView = (TextView) view.findViewById(R.id.account_status); TextView statusView = (TextView) view.findViewById(R.id.account_status);
ImageView imageView = (ImageView) view.findViewById(R.id.account_image); ImageView imageView = (ImageView) view.findViewById(R.id.account_image);
imageView.setImageBitmap(activity.avatarService().get(account, imageView.setImageBitmap(activity.avatarService().get(account,

View File

@ -58,7 +58,7 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
|| activity.useSubjectToIdentifyConference()) { || activity.useSubjectToIdentifyConference()) {
convName.setText(conversation.getName()); convName.setText(conversation.getName());
} else { } else {
convName.setText(conversation.getContactJid().split("/")[0]); convName.setText(conversation.getContactJid().toBareJid().toString());
} }
TextView mLastMessage = (TextView) view TextView mLastMessage = (TextView) view
.findViewById(R.id.conversation_lastmsg); .findViewById(R.id.conversation_lastmsg);

View File

@ -34,7 +34,7 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
TextView jid = (TextView) view.findViewById(R.id.contact_jid); TextView jid = (TextView) view.findViewById(R.id.contact_jid);
ImageView picture = (ImageView) view.findViewById(R.id.contact_photo); ImageView picture = (ImageView) view.findViewById(R.id.contact_photo);
jid.setText(item.getJid()); jid.setText(item.getJid().toString());
name.setText(item.getDisplayName()); name.setText(item.getDisplayName());
picture.setImageBitmap(activity.avatarService().get(item, picture.setImageBitmap(activity.avatarService().get(item,
activity.getPixel(48))); activity.getPixel(48)));

View File

@ -29,6 +29,7 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.entities.Message.ImageParams;
import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.jid.Jid;
public class MessageAdapter extends ArrayAdapter<Message> { public class MessageAdapter extends ArrayAdapter<Message> {
@ -136,9 +137,13 @@ public class MessageAdapter extends ArrayAdapter<Message> {
info = contact.getDisplayName(); info = contact.getDisplayName();
} else { } else {
if (message.getPresence() != null) { if (message.getPresence() != null) {
info = message.getPresence(); if (message.getPresence().isBareJid()) {
info = message.getPresence().toString();
} else { } else {
info = message.getCounterpart(); info = message.getPresence().getResourcepart();
}
} else {
info = message.getCounterpart().toString();
} }
} }
} }
@ -227,14 +232,13 @@ public class MessageAdapter extends ArrayAdapter<Message> {
privateMarker = activity privateMarker = activity
.getString(R.string.private_message); .getString(R.string.private_message);
} else { } else {
String to; final Jid to;
if (message.getPresence() != null) { if (message.getPresence() != null) {
to = message.getPresence(); to = message.getPresence();
} else { } else {
to = message.getCounterpart(); to = message.getCounterpart();
} }
privateMarker = activity.getString( privateMarker = activity.getString(R.string.private_message_to, to);
R.string.private_message_to, to);
} }
SpannableString span = new SpannableString(privateMarker + " " SpannableString span = new SpannableString(privateMarker + " "
+ message.getBody()); + message.getBody());
@ -413,17 +417,16 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (contact != null) { if (contact != null) {
viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48))); viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48)));
} else if (item.getConversation().getMode() == Conversation.MODE_MULTI) { } else if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
String name = item.getPresence(); final Jid name = item.getPresence() != null ? item.getPresence() : item.getCounterpart();
if (name == null) { viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(
name = item.getCounterpart(); name.isBareJid() ? name.toString() : name.getResourcepart(),
} activity.getPixel(48)));
viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(name, activity.getPixel(48)));
} }
} else if (type == SENT) { } else if (type == SENT) {
viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(item.getConversation().getAccount(), activity.getPixel(48))); viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(item.getConversation().getAccount(), activity.getPixel(48)));
} }
if (viewHolder.contact_picture != null) { if (viewHolder != null && viewHolder.contact_picture != null) {
viewHolder.contact_picture viewHolder.contact_picture
.setOnClickListener(new OnClickListener() { .setOnClickListener(new OnClickListener() {
@ -488,6 +491,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else { } else {
displayInfoMessage(viewHolder, displayInfoMessage(viewHolder,
R.string.install_openkeychain); R.string.install_openkeychain);
if (viewHolder != null) {
viewHolder.message_box viewHolder.message_box
.setOnClickListener(new OnClickListener() { .setOnClickListener(new OnClickListener() {
@ -496,6 +500,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
activity.showInstallPgpDialog(); activity.showInstallPgpDialog();
} }
}); });
}
} }
} else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
displayDecryptionFailed(viewHolder); displayDecryptionFailed(viewHolder);

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

@ -13,6 +13,9 @@ import eu.siacs.conversations.entities.Account;
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.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -89,9 +92,12 @@ public class ExceptionHelper {
Log.d(Config.LOGTAG, "using account=" Log.d(Config.LOGTAG, "using account="
+ finalAccount.getJid() + finalAccount.getJid()
+ " to send in stack trace"); + " to send in stack trace");
Conversation conversation = service Conversation conversation = null;
.findOrCreateConversation(finalAccount, try {
"bugs@siacs.eu", false); conversation = service.findOrCreateConversation(finalAccount,
Jid.fromString("bugs@siacs.eu"), false);
} catch (final InvalidJidException ignored) {
}
Message message = new Message(conversation, report Message message = new Message(conversation, report
.toString(), Message.ENCRYPTION_NONE); .toString(), Message.ENCRYPTION_NONE);
service.sendMessage(message); service.sendMessage(message);
@ -103,14 +109,11 @@ public class ExceptionHelper {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
preferences.edit().putBoolean("never_send", true) preferences.edit().putBoolean("never_send", true)
.commit(); .apply();
} }
}); });
builder.create().show(); builder.create().show();
} catch (FileNotFoundException e) { } catch (final IOException ignored) {
return;
} catch (IOException e) {
return;
} }
} }

View File

@ -110,7 +110,7 @@ public class UIHelper {
List<Account> accounts) { List<Account> accounts) {
NotificationManager mNotificationManager = (NotificationManager) context NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE); .getSystemService(Context.NOTIFICATION_SERVICE);
List<Account> accountsWproblems = new ArrayList<Account>(); List<Account> accountsWproblems = new ArrayList<>();
for (Account account : accounts) { for (Account account : accounts) {
if (account.hasErrorStatus()) { if (account.hasErrorStatus()) {
accountsWproblems.add(account); accountsWproblems.add(account);
@ -124,7 +124,7 @@ public class UIHelper {
} else if (accountsWproblems.size() == 1) { } else if (accountsWproblems.size() == 1) {
mBuilder.setContentTitle(context mBuilder.setContentTitle(context
.getString(R.string.problem_connecting_to_account)); .getString(R.string.problem_connecting_to_account));
mBuilder.setContentText(accountsWproblems.get(0).getJid()); mBuilder.setContentText(accountsWproblems.get(0).getJid().toString());
} else { } else {
mBuilder.setContentTitle(context mBuilder.setContentTitle(context
.getString(R.string.problem_connecting_to_accounts)); .getString(R.string.problem_connecting_to_accounts));
@ -165,7 +165,7 @@ public class UIHelper {
TextView yourprint = (TextView) view TextView yourprint = (TextView) view
.findViewById(R.id.verify_otr_yourprint); .findViewById(R.id.verify_otr_yourprint);
jid.setText(contact.getJid()); jid.setText(contact.getJid().toString());
fingerprint.setText(conversation.getOtrFingerprint()); fingerprint.setText(conversation.getOtrFingerprint());
yourprint.setText(account.getOtrFingerprint()); yourprint.setText(account.getOtrFingerprint());
builder.setNegativeButton("Cancel", null); builder.setNegativeButton("Cancel", null);

View File

@ -5,12 +5,14 @@ import java.util.Hashtable;
import java.util.List; import java.util.List;
import eu.siacs.conversations.utils.XmlHelper; import eu.siacs.conversations.utils.XmlHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
public class Element { public class Element {
protected String name; protected String name;
protected Hashtable<String, String> attributes = new Hashtable<String, String>(); protected Hashtable<String, String> attributes = new Hashtable<>();
protected String content; protected String content;
protected List<Element> children = new ArrayList<Element>(); protected List<Element> children = new ArrayList<>();
public Element(String name) { public Element(String name) {
this.name = name; this.name = name;
@ -103,6 +105,42 @@ public class Element {
} }
} }
public Jid getJid() {
final String jid = this.getAttribute("jid");
if (jid != null && !jid.isEmpty()) {
try {
return Jid.fromString(jid);
} catch (final InvalidJidException e) {
return null;
}
}
return null;
}
public Jid getTo() {
final String to = this.getAttribute("to");
if (to != null && !to.isEmpty()) {
try {
return Jid.fromString(to);
} catch (final InvalidJidException e) {
return null;
}
}
return null;
}
public Jid getFrom() {
final String from = this.getAttribute("from");
if (from != null && !from.isEmpty()) {
try {
return Jid.fromString(from);
} catch (final InvalidJidException e) {
return null;
}
}
return null;
}
public Hashtable<String, String> getAttributes() { public Hashtable<String, String> getAttributes() {
return this.attributes; return this.attributes;
} }

View File

@ -18,6 +18,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.IDN;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -48,6 +49,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 +79,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 +94,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 +107,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 +132,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 +148,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) {
@ -152,18 +157,24 @@ public class XmppConnection implements Runnable {
while (socketError && values.size() > i) { while (socketError && values.size() > i) {
Bundle namePort = (Bundle) values.get(i); Bundle namePort = (Bundle) values.get(i);
try { try {
String srvRecordServer = namePort.getString("name"); String srvRecordServer;
try {
srvRecordServer=IDN.toASCII(namePort.getString("name"));
} catch (final IllegalArgumentException e) {
// TODO: Handle me?`
srvRecordServer = "";
}
int srvRecordPort = namePort.getInt("port"); int srvRecordPort = namePort.getInt("port");
String srvIpServer = namePort.getString("ipv4"); String srvIpServer = namePort.getString("ipv4");
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 +182,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 +194,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,41 +233,28 @@ 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() + ": " + e.getMessage()); Log.d(Config.LOGTAG, account.getJid().toString() + ": " + 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;
} }
} }
@ -266,7 +264,7 @@ public class XmppConnection implements Runnable {
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 +277,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 +298,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 +316,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 +332,7 @@ public class XmppConnection implements Runnable {
} }
} }
messageReceipts.clear(); messageReceipts.clear();
} catch (NumberFormatException e) { } catch (final NumberFormatException ignored) {
} }
sendInitialPing(); sendInitialPing();
@ -357,7 +355,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 +378,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 +386,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 +505,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 +535,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 +549,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 +574,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,10 +587,8 @@ 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();
} }
} }
@ -676,7 +671,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,9 +737,13 @@ 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 {
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")) { if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) {
smVersion = 3; smVersion = 3;
EnablePacket enable = new EnablePacket(smVersion); EnablePacket enable = new EnablePacket(smVersion);
@ -783,24 +782,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,19 +812,23 @@ 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,7 +857,7 @@ 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()); account.setResource(resource + "." + nextRandomId());
Log.d(Config.LOGTAG, Log.d(Config.LOGTAG,
account.getJid() + ": switching resource due to conflict (" account.getJid() + ": switching resource due to conflict ("
@ -864,8 +867,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 +1006,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,11 +1082,9 @@ 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() {
@ -1095,12 +1096,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 +1109,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

@ -0,0 +1,48 @@
package eu.siacs.conversations.xmpp.jid;
public class InvalidJidException extends Exception {
// This is probably not the "Java way", but the "Java way" means we'd have a ton of extra tiny,
// annoying classes floating around. I like this.
public final static String INVALID_LENGTH = "JID must be between 0 and 3071 characters";
public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters";
public final static String INVALID_CHARACTER = "JID contains an invalid character";
public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID";
/**
* Constructs a new {@code Exception} that includes the current stack trace.
*/
public InvalidJidException() {
}
/**
* Constructs a new {@code Exception} with the current stack trace and the
* specified detail message.
*
* @param detailMessage the detail message for this exception.
*/
public InvalidJidException(final String detailMessage) {
super(detailMessage);
}
/**
* Constructs a new {@code Exception} with the current stack trace, the
* specified detail message and the specified cause.
*
* @param detailMessage the detail message for this exception.
* @param throwable the cause of this exception.
*/
public InvalidJidException(final String detailMessage, final Throwable throwable) {
super(detailMessage, throwable);
}
/**
* Constructs a new {@code Exception} with the current stack trace and the
* specified cause.
*
* @param throwable the cause of this exception.
*/
public InvalidJidException(final Throwable throwable) {
super(throwable);
}
}

View File

@ -0,0 +1,180 @@
package eu.siacs.conversations.xmpp.jid;
import java.net.IDN;
import gnu.inet.encoding.Stringprep;
import gnu.inet.encoding.StringprepException;
/**
* The `Jid' class provides an immutable representation of a JID.
*/
public final class Jid {
private final String localpart;
private final String domainpart;
private final String resourcepart;
// It's much more efficient to store the ful JID as well as the parts instead of figuring them
// all out every time (since some characters are displayed but aren't used for comparisons).
private final String displayjid;
public String getLocalpart() {
return localpart;
}
public String getDomainpart() {
return IDN.toUnicode(domainpart);
}
public String getResourcepart() {
return resourcepart;
}
public static Jid fromString(final String jid) throws InvalidJidException {
return new Jid(jid);
}
public static Jid fromParts(final String localpart,
final String domainpart,
final String resourcepart) throws InvalidJidException {
String out;
if (localpart == null || localpart.isEmpty()) {
out = domainpart;
} else {
out = localpart + "@" + domainpart;
}
if (resourcepart != null && !resourcepart.isEmpty()) {
out = out + "/" + resourcepart;
}
return new Jid(out);
}
private Jid(final String jid) throws InvalidJidException {
// Hackish Android way to count the number of chars in a string... should work everywhere.
final int atCount = jid.length() - jid.replace("@", "").length();
final int slashCount = jid.length() - jid.replace("/", "").length();
// Throw an error if there's anything obvious wrong with the JID...
if (jid.isEmpty() || jid.length() > 3071) {
throw new InvalidJidException(InvalidJidException.INVALID_LENGTH);
}
if (atCount > 1 || slashCount > 1 ||
jid.startsWith("@") || jid.endsWith("@") ||
jid.startsWith("/") || jid.endsWith("/")) {
throw new InvalidJidException(InvalidJidException.INVALID_CHARACTER);
}
String finaljid;
final int domainpartStart;
if (atCount == 1) {
final int atLoc = jid.indexOf("@");
final String lp = jid.substring(0, atLoc);
try {
localpart = Stringprep.nodeprep(lp);
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
if (localpart.isEmpty() || localpart.length() > 1023) {
throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
}
domainpartStart = atLoc + 1;
finaljid = lp + "@";
} else {
localpart = "";
finaljid = "";
domainpartStart = 0;
}
final String dp;
if (slashCount == 1) {
final int slashLoc = jid.indexOf("/");
final String rp = jid.substring(slashLoc + 1, jid.length());
try {
resourcepart = Stringprep.resourceprep(rp);
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
if (resourcepart.isEmpty() || resourcepart.length() > 1023) {
throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
}
dp = jid.substring(domainpartStart, slashLoc);
finaljid = finaljid + dp + "/" + rp;
} else {
resourcepart = "";
dp = jid.substring(domainpartStart, jid.length());
finaljid = finaljid + dp;
}
// Remove trailling "." before storing the domain part.
if (dp.endsWith(".")) {
try {
domainpart = IDN.toASCII(dp.substring(0, dp.length() - 1), IDN.USE_STD3_ASCII_RULES);
} catch (final IllegalArgumentException e) {
throw new InvalidJidException(e);
}
} else {
try {
domainpart = IDN.toASCII(dp, IDN.USE_STD3_ASCII_RULES);
} catch (final IllegalArgumentException e) {
throw new InvalidJidException(e);
}
}
// TODO: Find a proper domain validation library; validate individual parts, separators, etc.
if (domainpart.isEmpty() || domainpart.length() > 1023) {
throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
}
this.displayjid = finaljid;
}
public Jid toBareJid() {
try {
return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, "");
} catch (final InvalidJidException e) {
// 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;
}
}
@Override
public String toString() {
return displayjid;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Jid jid = (Jid) o;
return jid.hashCode() == this.hashCode();
}
@Override
public int hashCode() {
int result = localpart.hashCode();
result = 31 * result + domainpart.hashCode();
result = 31 * result + resourcepart.hashCode();
return result;
}
public boolean hasLocalpart() {
return !localpart.isEmpty();
}
public boolean isBareJid() {
return this.resourcepart.isEmpty();
}
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid;
public class JingleCandidate { public class JingleCandidate {
@ -17,7 +18,7 @@ public class JingleCandidate {
private String host; private String host;
private int port; private int port;
private int type; private int type;
private String jid; private Jid jid;
private int priority; private int priority;
public JingleCandidate(String cid, boolean ours) { public JingleCandidate(String cid, boolean ours) {
@ -37,11 +38,11 @@ public class JingleCandidate {
return this.host; return this.host;
} }
public void setJid(String jid) { public void setJid(final Jid jid) {
this.jid = jid; this.jid = jid;
} }
public String getJid() { public Jid getJid() {
return this.jid; return this.jid;
} }
@ -58,12 +59,16 @@ public class JingleCandidate {
} }
public void setType(String type) { public void setType(String type) {
if ("proxy".equals(type)) { switch (type) {
case "proxy":
this.type = TYPE_PROXY; this.type = TYPE_PROXY;
} else if ("direct".equals(type)) { break;
case "direct":
this.type = TYPE_DIRECT; this.type = TYPE_DIRECT;
} else { break;
default:
this.type = TYPE_UNKNOWN; this.type = TYPE_UNKNOWN;
break;
} }
} }
@ -93,7 +98,7 @@ public class JingleCandidate {
} }
public static List<JingleCandidate> parse(List<Element> canditates) { public static List<JingleCandidate> parse(List<Element> canditates) {
List<JingleCandidate> parsedCandidates = new ArrayList<JingleCandidate>(); List<JingleCandidate> parsedCandidates = new ArrayList<>();
for (Element c : canditates) { for (Element c : canditates) {
parsedCandidates.add(JingleCandidate.parse(c)); parsedCandidates.add(JingleCandidate.parse(c));
} }
@ -104,7 +109,7 @@ public class JingleCandidate {
JingleCandidate parsedCandidate = new JingleCandidate( JingleCandidate parsedCandidate = new JingleCandidate(
candidate.getAttribute("cid"), false); candidate.getAttribute("cid"), false);
parsedCandidate.setHost(candidate.getAttribute("host")); parsedCandidate.setHost(candidate.getAttribute("host"));
parsedCandidate.setJid(candidate.getAttribute("jid")); parsedCandidate.setJid(candidate.getJid());
parsedCandidate.setType(candidate.getAttribute("type")); parsedCandidate.setType(candidate.getAttribute("type"));
parsedCandidate.setPriority(Integer.parseInt(candidate parsedCandidate.setPriority(Integer.parseInt(candidate
.getAttribute("priority"))); .getAttribute("priority")));
@ -118,7 +123,7 @@ public class JingleCandidate {
element.setAttribute("cid", this.getCid()); element.setAttribute("cid", this.getCid());
element.setAttribute("host", this.getHost()); element.setAttribute("host", this.getHost());
element.setAttribute("port", Integer.toString(this.getPort())); element.setAttribute("port", Integer.toString(this.getPort()));
element.setAttribute("jid", this.getJid()); element.setAttribute("jid", this.getJid().toString());
element.setAttribute("priority", Integer.toString(this.getPriority())); element.setAttribute("priority", Integer.toString(this.getPriority()));
if (this.getType() == TYPE_DIRECT) { if (this.getType() == TYPE_DIRECT) {
element.setAttribute("type", "direct"); element.setAttribute("type", "direct");

View File

@ -21,6 +21,7 @@ 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.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.jingle.stanzas.Content; import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason; import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
@ -49,10 +50,10 @@ public class JingleConnection implements Downloadable {
private Message message; private Message message;
private String sessionId; private String sessionId;
private Account account; private Account account;
private String initiator; private Jid initiator;
private String responder; private Jid responder;
private List<JingleCandidate> candidates = new ArrayList<JingleCandidate>(); private List<JingleCandidate> candidates = new ArrayList<>();
private ConcurrentHashMap<String, JingleSocks5Transport> connections = new ConcurrentHashMap<String, JingleSocks5Transport>(); private ConcurrentHashMap<String, JingleSocks5Transport> connections = new ConcurrentHashMap<>();
private String transportId; private String transportId;
private Element fileOffer; private Element fileOffer;
@ -150,7 +151,7 @@ public class JingleConnection implements Downloadable {
return this.account; return this.account;
} }
public String getCounterPart() { public Jid getCounterPart() {
return this.message.getCounterpart(); return this.message.getCounterpart();
} }
@ -254,14 +255,14 @@ public class JingleConnection implements Downloadable {
this.mJingleStatus = JINGLE_STATUS_INITIATED; this.mJingleStatus = JINGLE_STATUS_INITIATED;
Conversation conversation = this.mXmppConnectionService Conversation conversation = this.mXmppConnectionService
.findOrCreateConversation(account, .findOrCreateConversation(account,
packet.getFrom().split("/", 2)[0], false); packet.getFrom().toBareJid(), false);
this.message = new Message(conversation, "", Message.ENCRYPTION_NONE); this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
this.message.setStatus(Message.STATUS_RECEIVED); this.message.setStatus(Message.STATUS_RECEIVED);
this.message.setType(Message.TYPE_IMAGE); this.message.setType(Message.TYPE_IMAGE);
this.mStatus = Downloadable.STATUS_OFFER; this.mStatus = Downloadable.STATUS_OFFER;
this.message.setDownloadable(this); this.message.setDownloadable(this);
String[] fromParts = packet.getFrom().split("/", 2); final Jid from = packet.getFrom();
this.message.setPresence(fromParts[1]); this.message.setPresence(from.isBareJid() ? "" : from.getResourcepart());
this.account = account; this.account = account;
this.initiator = packet.getFrom(); this.initiator = packet.getFrom();
this.responder = this.account.getFullJid(); this.responder = this.account.getFullJid();
@ -375,7 +376,7 @@ public class JingleConnection implements Downloadable {
} }
private List<Element> getCandidatesAsElements() { private List<Element> getCandidatesAsElements() {
List<Element> elements = new ArrayList<Element>(); List<Element> elements = new ArrayList<>();
for (JingleCandidate c : this.candidates) { for (JingleCandidate c : this.candidates) {
elements.add(c.toElement()); elements.add(c.toElement());
} }
@ -547,7 +548,7 @@ public class JingleConnection implements Downloadable {
activation.query("http://jabber.org/protocol/bytestreams") activation.query("http://jabber.org/protocol/bytestreams")
.setAttribute("sid", this.getSessionId()); .setAttribute("sid", this.getSessionId());
activation.query().addChild("activate") activation.query().addChild("activate")
.setContent(this.getCounterPart()); .setContent(this.getCounterPart().toString());
this.account.getXmppConnection().sendIqPacket(activation, this.account.getXmppConnection().sendIqPacket(activation,
new OnIqPacketReceived() { new OnIqPacketReceived() {
@ -810,11 +811,11 @@ public class JingleConnection implements Downloadable {
this.sendJinglePacket(packet); this.sendJinglePacket(packet);
} }
public String getInitiator() { public Jid getInitiator() {
return this.initiator; return this.initiator;
} }
public String getResponder() { public Jid getResponder() {
return this.responder; return this.responder;
} }

View File

@ -14,13 +14,15 @@ import eu.siacs.conversations.services.AbstractConnectionManager;
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.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JingleConnectionManager extends AbstractConnectionManager { public class JingleConnectionManager extends AbstractConnectionManager {
private List<JingleConnection> connections = new CopyOnWriteArrayList<JingleConnection>(); private List<JingleConnection> connections = new CopyOnWriteArrayList<>();
private HashMap<String, JingleCandidate> primaryCandidates = new HashMap<String, JingleCandidate>(); private HashMap<Jid, JingleCandidate> primaryCandidates = new HashMap<>();
@SuppressLint("TrulyRandom") @SuppressLint("TrulyRandom")
private SecureRandom random = new SecureRandom(); private SecureRandom random = new SecureRandom();
@ -61,7 +63,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
return connection; return connection;
} }
public JingleConnection createNewConnection(JinglePacket packet) { public JingleConnection createNewConnection(final JinglePacket packet) {
JingleConnection connection = new JingleConnection(this); JingleConnection connection = new JingleConnection(this);
this.connections.add(connection); this.connections.add(connection);
return connection; return connection;
@ -79,7 +81,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
.findDiscoItemByFeature(xmlns); .findDiscoItemByFeature(xmlns);
if (proxy != null) { if (proxy != null) {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET); IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setTo(proxy); iq.setAttribute("to", proxy);
iq.query(xmlns); iq.query(xmlns);
account.getXmppConnection().sendIqPacket(iq, account.getXmppConnection().sendIqPacket(iq,
new OnIqPacketReceived() { new OnIqPacketReceived() {
@ -101,7 +103,11 @@ public class JingleConnectionManager extends AbstractConnectionManager {
.getAttribute("port"))); .getAttribute("port")));
candidate candidate
.setType(JingleCandidate.TYPE_PROXY); .setType(JingleCandidate.TYPE_PROXY);
candidate.setJid(proxy); try {
candidate.setJid(Jid.fromString(proxy));
} catch (final InvalidJidException e) {
candidate.setJid(null);
}
candidate.setPriority(655360 + 65535); candidate.setPriority(655360 + 65535);
primaryCandidates.put(account.getJid(), primaryCandidates.put(account.getJid(),
candidate); candidate);

View File

@ -13,12 +13,13 @@ import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
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.Jid;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JingleInbandTransport extends JingleTransport { public class JingleInbandTransport extends JingleTransport {
private Account account; private Account account;
private String counterpart; private Jid counterpart;
private int blockSize; private int blockSize;
private int bufferSize; private int bufferSize;
private int seq = 0; private int seq = 0;
@ -44,8 +45,8 @@ public class JingleInbandTransport extends JingleTransport {
} }
}; };
public JingleInbandTransport(Account account, String counterpart, public JingleInbandTransport(final Account account, final Jid counterpart,
String sid, int blocksize) { final String sid, final int blocksize) {
this.account = account; this.account = account;
this.counterpart = counterpart; this.counterpart = counterpart;
this.blockSize = blocksize; this.blockSize = blocksize;
@ -92,9 +93,7 @@ public class JingleInbandTransport extends JingleTransport {
return; return;
} }
this.remainingSize = file.getExpectedSize(); this.remainingSize = file.getExpectedSize();
} catch (NoSuchAlgorithmException e) { } catch (final NoSuchAlgorithmException | IOException e) {
callback.onFileTransferAborted();
} catch (IOException e) {
callback.onFileTransferAborted(); callback.onFileTransferAborted();
} }
} }

View File

@ -1,6 +1,7 @@
package eu.siacs.conversations.xmpp.jingle.stanzas; package eu.siacs.conversations.xmpp.jingle.stanzas;
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.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JinglePacket extends IqPacket { public class JinglePacket extends IqPacket {
@ -85,8 +86,8 @@ public class JinglePacket extends IqPacket {
return this.jingle.getAttribute("action"); return this.jingle.getAttribute("action");
} }
public void setInitiator(String initiator) { public void setInitiator(final Jid initiator) {
this.jingle.setAttribute("initiator", initiator); this.jingle.setAttribute("initiator", initiator.toString());
} }
public boolean isAction(String action) { public boolean isAction(String action) {

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,8 @@
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.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
public class AbstractStanza extends Element { public class AbstractStanza extends Element {
@ -8,27 +10,35 @@ public class AbstractStanza extends Element {
super(name); super(name);
} }
public String getTo() { public Jid getTo() {
return getAttribute("to"); try {
return Jid.fromString(getAttribute("to"));
} catch (final InvalidJidException e) {
return null;
}
} }
public String getFrom() { public Jid getFrom() {
return getAttribute("from"); try {
return Jid.fromString(getAttribute("from"));
} catch (final InvalidJidException e) {
return null;
}
} }
public String getId() { public String getId() {
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);
} }
} }