From 332fe0fd194a80501cf935f22faed645f3032b57 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 9 Apr 2015 12:46:54 +0200 Subject: don't resume old session when changing resource --- src/main/java/eu/siacs/conversations/entities/Account.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 2bc2c954..fe103094 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -229,11 +229,17 @@ public class Account extends AbstractEntity { return jid.getResourcepart(); } - public void setResource(final String resource) { - try { - jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); - } catch (final InvalidJidException ignored) { + public boolean setResource(final String resource) { + final String oldResource = jid.getResourcepart(); + if (oldResource == null || !oldResource.equals(resource)) { + try { + jid = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), resource); + return true; + } catch (final InvalidJidException ignored) { + return true; + } } + return false; } public Jid getJid() { -- cgit v1.2.3 From 6da77bdf3b38fab3daa0de8776082038d8d62a78 Mon Sep 17 00:00:00 2001 From: lookshe Date: Mon, 13 Apr 2015 10:57:30 +0200 Subject: Bugfix for issue #1121 check with lowercase to also match JPEG, JPeg ... changed image url in comment --- .../eu/siacs/conversations/entities/Message.java | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 8015eead..21aa7779 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -430,23 +430,31 @@ public class Message extends AbstractEntity { } public boolean bodyContainsDownloadable() { + /** + * there are a few cases where spaces result in an unwanted behavior, e.g. + * "http://example.com/image.jpg" text that will not be shown /abc.png" + * or more than one image link in one message. + */ + if (body.contains(" ")) { + return false; + } try { - URL url = new URL(this.getBody()); + URL url = new URL(body); if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { return false; } - if (url.getPath() == null) { - return false; - } - String[] pathParts = url.getPath().split("/"); - String filename; - if (pathParts.length > 0) { - filename = pathParts[pathParts.length - 1].toLowerCase(); - } else { + + String sUrlPath = url.getPath(); + if (sUrlPath == null || sUrlPath.isEmpty()) { return false; } - String[] extensionParts = filename.split("\\."); + + int iSlashIndex = sUrlPath.lastIndexOf('/') + 1; + + String sLastUrlPath = sUrlPath.substring(iSlashIndex).toLowerCase(); + + String[] extensionParts = sLastUrlPath.split("\\."); if (extensionParts.length == 2 && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( extensionParts[extensionParts.length - 1])) { -- cgit v1.2.3 From 62faa163f0d5fc2d8d53067cc328f1905d1df370 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 13 Apr 2015 18:18:25 +0200 Subject: fixed typos --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 21aa7779..7ea3d60b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -432,7 +432,7 @@ public class Message extends AbstractEntity { public boolean bodyContainsDownloadable() { /** * there are a few cases where spaces result in an unwanted behavior, e.g. - * "http://example.com/image.jpg" text that will not be shown /abc.png" + * "http://example.com/image.jpg text that will not be shown /abc.png" * or more than one image link in one message. */ if (body.contains(" ")) { -- cgit v1.2.3 From 5136bf9832b9a7aeb59926b42fe6a6632452c1ef Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 5 May 2015 06:17:34 +0200 Subject: r/o support for vcard avatars. pep avatars will be prefered --- .../eu/siacs/conversations/entities/Contact.java | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index cef03ebe..4ad105b1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -15,6 +15,7 @@ import eu.siacs.conversations.utils.UIHelper; 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.pep.Avatar; public class Contact implements ListItem, Blockable { public static final String TABLENAME = "contacts"; @@ -40,11 +41,11 @@ public class Contact implements ListItem, Blockable { protected int subscription = 0; protected String systemAccount; protected String photoUri; - protected String avatar; protected JSONObject keys = new JSONObject(); protected JSONArray groups = new JSONArray(); protected Presences presences = new Presences(); protected Account account; + protected Avatar avatar; public Contact(final String account, final String systemName, final String serverName, final Jid jid, final int subscription, final String photoUri, @@ -61,7 +62,11 @@ public class Contact implements ListItem, Blockable { } catch (JSONException e) { this.keys = new JSONObject(); } - this.avatar = avatar; + if (avatar != null) { + this.avatar = new Avatar(); + this.avatar.sha1sum = avatar; + this.avatar.origin = Avatar.Origin.VCARD; //always assume worst + } try { this.groups = (groups == null ? new JSONArray() : new JSONArray(groups)); } catch (JSONException e) { @@ -187,7 +192,7 @@ public class Contact implements ListItem, Blockable { values.put(SYSTEMACCOUNT, systemAccount); values.put(PHOTOURI, photoUri); values.put(KEYS, keys.toString()); - values.put(AVATAR, avatar); + values.put(AVATAR, avatar == null ? null : avatar.getFilename()); values.put(LAST_PRESENCE, lastseen.presence); values.put(LAST_TIME, lastseen.time); values.put(GROUPS, groups.toString()); @@ -411,17 +416,20 @@ public class Contact implements ListItem, Blockable { return getJid().toDomainJid(); } - public boolean setAvatar(String filename) { - if (this.avatar != null && this.avatar.equals(filename)) { + public boolean setAvatar(Avatar avatar) { + if (this.avatar != null && this.avatar.equals(avatar)) { return false; } else { - this.avatar = filename; + if (this.avatar != null && this.avatar.origin == Avatar.Origin.PEP && avatar.origin == Avatar.Origin.VCARD) { + return false; + } + this.avatar = avatar; return true; } } public String getAvatar() { - return this.avatar; + return avatar == null ? null : avatar.getFilename(); } public boolean deleteOtrFingerprint(String fingerprint) { @@ -478,6 +486,10 @@ public class Contact implements ListItem, Blockable { } } + public boolean isSelf() { + return account.getJid().toBareJid().equals(getJid().toBareJid()); + } + public static class Lastseen { public long time; public String presence; -- cgit v1.2.3 From 4c486f5e583ddfc1f53f296d8a6fa9672981440a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 10 May 2015 03:12:44 +0200 Subject: paint single unicode hearts as red and slightly larger --- .../eu/siacs/conversations/entities/Message.java | 72 ++++++++++++---------- 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 7ea3d60b..95e27c79 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -9,6 +9,7 @@ import java.util.Arrays; import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.GeoHelper; +import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -95,9 +96,9 @@ public class Message extends AbstractEntity { } private Message(final String uuid, final String conversationUUid, final Jid counterpart, - final Jid trueCounterpart, final String body, final long timeSent, - final int encryption, final int status, final int type, final String remoteMsgId, - final String relativeFilePath, final String serverMsgId) { + final Jid trueCounterpart, final String body, final long timeSent, + final int encryption, final int status, final int type, final String remoteMsgId, + final String relativeFilePath, final String serverMsgId) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -179,7 +180,7 @@ public class Message extends AbstractEntity { values.put(TYPE, type); values.put(REMOTE_MSG_ID, remoteMsgId); values.put(RELATIVE_FILE_PATH, relativeFilePath); - values.put(SERVER_MSG_ID,serverMsgId); + values.put(SERVER_MSG_ID, serverMsgId); return values; } @@ -211,7 +212,7 @@ public class Message extends AbstractEntity { return null; } else { return this.conversation.getAccount().getRoster() - .getContactFromRoster(this.trueCounterpart); + .getContactFromRoster(this.trueCounterpart); } } } @@ -359,34 +360,36 @@ public class Message extends AbstractEntity { public boolean mergeable(final Message message) { return message != null && - (message.getType() == Message.TYPE_TEXT && - this.getDownloadable() == null && - message.getDownloadable() == null && - message.getEncryption() != Message.ENCRYPTION_PGP && - this.getType() == message.getType() && - //this.getStatus() == message.getStatus() && - isStatusMergeable(this.getStatus(),message.getStatus()) && - this.getEncryption() == message.getEncryption() && - this.getCounterpart() != null && - this.getCounterpart().equals(message.getCounterpart()) && - (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && - !GeoHelper.isGeoUri(message.getBody()) && - !GeoHelper.isGeoUri(this.body) && - !message.bodyContainsDownloadable() && - !this.bodyContainsDownloadable() && - !message.getBody().startsWith(ME_COMMAND) && - !this.getBody().startsWith(ME_COMMAND) - ); + (message.getType() == Message.TYPE_TEXT && + this.getDownloadable() == null && + message.getDownloadable() == null && + message.getEncryption() != Message.ENCRYPTION_PGP && + this.getType() == message.getType() && + //this.getStatus() == message.getStatus() && + isStatusMergeable(this.getStatus(), message.getStatus()) && + this.getEncryption() == message.getEncryption() && + this.getCounterpart() != null && + this.getCounterpart().equals(message.getCounterpart()) && + (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && + !GeoHelper.isGeoUri(message.getBody()) && + !GeoHelper.isGeoUri(this.body) && + !message.bodyContainsDownloadable() && + !this.bodyContainsDownloadable() && + !message.getBody().startsWith(ME_COMMAND) && + !this.getBody().startsWith(ME_COMMAND) && + !this.bodyIsHeart() && + !message.bodyIsHeart() + ); } private static boolean isStatusMergeable(int a, int b) { return a == b || ( - ( a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_UNSEND) - || (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_SEND) - || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND) - || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND_RECEIVED) - || (a == Message.STATUS_SEND && b == Message.STATUS_UNSEND) - || (a == Message.STATUS_SEND && b == Message.STATUS_SEND_RECEIVED) + (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_UNSEND) + || (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_SEND) + || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND) + || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND_RECEIVED) + || (a == Message.STATUS_SEND && b == Message.STATUS_UNSEND) + || (a == Message.STATUS_SEND && b == Message.STATUS_SEND_RECEIVED) ); } @@ -443,7 +446,7 @@ public class Message extends AbstractEntity { if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { return false; - } + } String sUrlPath = url.getPath(); if (sUrlPath == null || sUrlPath.isEmpty()) { @@ -457,14 +460,14 @@ public class Message extends AbstractEntity { String[] extensionParts = sLastUrlPath.split("\\."); if (extensionParts.length == 2 && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 1])) { + extensionParts[extensionParts.length - 1])) { return true; } else if (extensionParts.length == 3 && Arrays .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) .contains(extensionParts[extensionParts.length - 1]) && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 2])) { + extensionParts[extensionParts.length - 2])) { return true; } else { return false; @@ -474,6 +477,11 @@ public class Message extends AbstractEntity { } } + public boolean bodyIsHeart() { + return body != null && + (body.trim().equals(UIHelper.BLACK_HEART_SUIT) || body.trim().equals(UIHelper.HEAVY_BLACK_HEART_SUIT)); + } + public ImageParams getImageParams() { ImageParams params = getLegacyImageParams(); if (params != null) { -- cgit v1.2.3 From 1e28f600386f1f1dcd734363c932d5ccbd6267fb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 10 May 2015 03:14:13 +0200 Subject: changed conversation red to material red --- src/main/java/eu/siacs/conversations/entities/Contact.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 4ad105b1..9dbca59a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -140,10 +140,10 @@ public class Contact implements ListItem, Blockable { tags.add(new Tag("away", 0xffff9800)); break; case Presences.XA: - tags.add(new Tag("not available", 0xffe51c23)); + tags.add(new Tag("not available", 0xfff44336)); break; case Presences.DND: - tags.add(new Tag("dnd", 0xffe51c23)); + tags.add(new Tag("dnd", 0xfff44336)); break; } if (isBlocked()) { -- cgit v1.2.3 From 33d1621e3b2c9a34689dfddc71eeb9ee4d91c348 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 10 May 2015 11:56:23 +0200 Subject: added white heart to new rendering as well --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 95e27c79..4dac0b98 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -479,7 +479,9 @@ public class Message extends AbstractEntity { public boolean bodyIsHeart() { return body != null && - (body.trim().equals(UIHelper.BLACK_HEART_SUIT) || body.trim().equals(UIHelper.HEAVY_BLACK_HEART_SUIT)); + (body.trim().equals(UIHelper.BLACK_HEART_SUIT) + || body.trim().equals(UIHelper.HEAVY_BLACK_HEART_SUIT) + || body.trim().equals(UIHelper.WHITE_HEART_SUIT)); } public ImageParams getImageParams() { -- cgit v1.2.3 From 239e86a98a4af8ab7ce7f6b96bed0bb4dc9e4bb5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 10 May 2015 12:04:11 +0200 Subject: optimized heart render code a bit --- src/main/java/eu/siacs/conversations/entities/Message.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 4dac0b98..c87e5518 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -478,10 +478,7 @@ public class Message extends AbstractEntity { } public boolean bodyIsHeart() { - return body != null && - (body.trim().equals(UIHelper.BLACK_HEART_SUIT) - || body.trim().equals(UIHelper.HEAVY_BLACK_HEART_SUIT) - || body.trim().equals(UIHelper.WHITE_HEART_SUIT)); + return body != null && UIHelper.HEARTS.contains(body.trim()); } public ImageParams getImageParams() { -- cgit v1.2.3 From 22b12091a103a164a1d54874ad376d02dfee1519 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 11 May 2015 07:57:52 +0200 Subject: rewrote parts of message adapter to avoid using NULL views --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index bfee5007..95a8c957 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -16,6 +16,7 @@ import java.security.interfaces.DSAPublicKey; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Iterator; import java.util.List; import eu.siacs.conversations.Config; @@ -218,6 +219,11 @@ public class Conversation extends AbstractEntity implements Blockable { messages.clear(); messages.addAll(this.messages); } + for(Iterator iterator = messages.iterator(); iterator.hasNext();) { + if (iterator.next().wasMergedIntoPrevious()) { + iterator.remove(); + } + } } @Override -- cgit v1.2.3 From 53e43daa0d8143d9a5abcd1391153b88a4702914 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 11 May 2015 09:08:56 +0200 Subject: add a little bit of space between merged messages. --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index c87e5518..3c144f5c 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -396,7 +396,7 @@ public class Message extends AbstractEntity { public String getMergedBody() { final Message next = this.next(); if (this.mergeable(next)) { - return getBody().trim() + '\n' + next.getMergedBody(); + return getBody().trim() + "\n\n" + next.getMergedBody(); } return getBody().trim(); } -- cgit v1.2.3 From b6f85ba0dd765e72a89a85461b3f8c48f038270c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 11 May 2015 14:18:30 +0200 Subject: avoid using paragraph style breaks by accident --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 3c144f5c..217b82bb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -17,6 +17,8 @@ public class Message extends AbstractEntity { public static final String TABLENAME = "messages"; + public static final String MERGE_SEPARATOR = "\u2029\n\n"; + public static final int STATUS_RECEIVED = 0; public static final int STATUS_UNSEND = 1; public static final int STATUS_SEND = 2; @@ -396,7 +398,7 @@ public class Message extends AbstractEntity { public String getMergedBody() { final Message next = this.next(); if (this.mergeable(next)) { - return getBody().trim() + "\n\n" + next.getMergedBody(); + return getBody().trim() + MERGE_SEPARATOR + next.getMergedBody(); } return getBody().trim(); } -- cgit v1.2.3 From 93e444ac3ad4b39415d7097566c319904ff14bcd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 12 May 2015 03:57:05 +0200 Subject: don't set unknown error in muc --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index addee8db..d867a370 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -343,8 +343,6 @@ public class MucOptions { setError(ERROR_BANNED); } else if (error != null && error.hasChild("registration-required")) { setError(ERROR_MEMBERS_ONLY); - } else { - setError(ERROR_UNKNOWN); } } } -- cgit v1.2.3 From 51aeeb766c5c0ad649abad7777bb5e194a6ae997 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 13 May 2015 11:56:59 +0200 Subject: use zero width white space as message seperator --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 217b82bb..a8bb9c55 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -17,7 +17,7 @@ public class Message extends AbstractEntity { public static final String TABLENAME = "messages"; - public static final String MERGE_SEPARATOR = "\u2029\n\n"; + public static final String MERGE_SEPARATOR = "\u200B\n\n"; public static final int STATUS_RECEIVED = 0; public static final int STATUS_UNSEND = 1; -- cgit v1.2.3 From fce30f22c9c75fb4bc12992e6d7e7161ce5148b1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 16 May 2015 12:49:04 +0200 Subject: made white space check in bodyContainsDownloadable less aggresive --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index a8bb9c55..38152edb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -440,7 +440,7 @@ public class Message extends AbstractEntity { * "http://example.com/image.jpg text that will not be shown /abc.png" * or more than one image link in one message. */ - if (body.contains(" ")) { + if (body.trim().contains(" ")) { return false; } try { -- cgit v1.2.3 From e32f380dae4913d8152fc92b76193de241089cf8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 14 May 2015 14:42:21 +0200 Subject: provide helper function for getting the content of a child directly --- .../java/eu/siacs/conversations/entities/Bookmark.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index f81f1a87..cc6f146b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -75,12 +75,7 @@ public class Bookmark extends Element implements ListItem { } public String getNick() { - Element nick = this.findChild("nick"); - if (nick != null) { - return nick.getContent(); - } else { - return null; - } + return this.findChildContent("nick"); } public void setNick(String nick) { @@ -96,12 +91,7 @@ public class Bookmark extends Element implements ListItem { } public String getPassword() { - Element password = this.findChild("password"); - if (password != null) { - return password.getContent(); - } else { - return null; - } + return this.findChildContent("password"); } public void setPassword(String password) { -- cgit v1.2.3 From b731995a517932d1c86877da13dd69d66cbb23c1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 15 May 2015 06:31:27 +0200 Subject: added mam stuff to new message parser --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 38152edb..90b74a53 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -328,7 +328,7 @@ public class Message extends AbstractEntity { return this.remoteMsgId == null && this.counterpart.equals(message.getCounterpart()) && this.body.equals(message.getBody()) - && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.PING_TIMEOUT * 500; + && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; } } -- cgit v1.2.3 From dc91ff8f291d4b142d28e77137a74dc8e7205149 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 26 May 2015 04:36:32 +0200 Subject: renamed OtrEngine to OtrService --- .../java/eu/siacs/conversations/entities/Account.java | 16 ++++++++-------- .../eu/siacs/conversations/entities/Conversation.java | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index fe103094..6e6dcb6a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -19,7 +19,7 @@ import java.util.concurrent.CopyOnWriteArraySet; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.crypto.OtrEngine; +import eu.siacs.conversations.crypto.OtrService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -117,7 +117,7 @@ public class Account extends AbstractEntity { protected JSONObject keys = new JSONObject(); protected String avatar; protected boolean online = false; - private OtrEngine otrEngine = null; + private OtrService mOtrService = null; private XmppConnection xmppConnection = null; private long mEndGracePeriod = 0L; private String otrFingerprint; @@ -273,12 +273,12 @@ public class Account extends AbstractEntity { return values; } - public void initOtrEngine(final XmppConnectionService context) { - this.otrEngine = new OtrEngine(context, this); + public void initAccountServices(final XmppConnectionService context) { + this.mOtrService = new OtrService(context, this); } - public OtrEngine getOtrEngine() { - return this.otrEngine; + public OtrService getOtrService() { + return this.mOtrService; } public XmppConnection getXmppConnection() { @@ -292,10 +292,10 @@ public class Account extends AbstractEntity { public String getOtrFingerprint() { if (this.otrFingerprint == null) { try { - if (this.otrEngine == null) { + if (this.mOtrService == null) { return null; } - final PublicKey publicKey = this.otrEngine.getPublicKey(); + final PublicKey publicKey = this.mOtrService.getPublicKey(); if (publicKey == null || !(publicKey instanceof DSAPublicKey)) { return null; } diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 95a8c957..b5f604b0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -419,7 +419,7 @@ public class Conversation extends AbstractEntity implements Blockable { final SessionID sessionId = new SessionID(this.getJid().toBareJid().toString(), presence, "xmpp"); - this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine()); + this.otrSession = new SessionImpl(sessionId, getAccount().getOtrService()); try { if (sendStart) { this.otrSession.startSession(); @@ -491,7 +491,7 @@ public class Conversation extends AbstractEntity implements Blockable { return null; } DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession().getRemotePublicKey(); - this.otrFingerprint = getAccount().getOtrEngine().getFingerprint(remotePubKey); + this.otrFingerprint = getAccount().getOtrService().getFingerprint(remotePubKey); } catch (final OtrCryptoException | UnsupportedOperationException ignored) { return null; } -- cgit v1.2.3 From fe1cff016f3e1bccaf8287fb490380281cb13983 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 2 Jun 2015 13:33:20 +0200 Subject: avoid unnessary muc mam queries when message count is 0 after subject --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index b5f604b0..289ed4ea 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -249,6 +249,12 @@ public class Conversation extends AbstractEntity implements Blockable { this.mLastReceivedOtrMessageId = id; } + public int countMessages() { + synchronized (this.messages) { + return this.messages.size(); + } + } + public interface OnMessageFound { public void onMessageFound(final Message message); -- cgit v1.2.3 From 53e8964dc17e5c994eda369e78c3bb81133abd9b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 3 Jun 2015 14:05:54 +0200 Subject: reworked handeling of system contacts --- src/main/java/eu/siacs/conversations/entities/Contact.java | 12 ++++++++++-- src/main/java/eu/siacs/conversations/entities/Roster.java | 14 +++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 9dbca59a..e546f214 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -237,8 +237,16 @@ public class Contact implements ListItem, Blockable { return this.presences.getMostAvailableStatus(); } - public void setPhotoUri(String uri) { - this.photoUri = uri; + public boolean setPhotoUri(String uri) { + if (uri != null && !uri.equals(this.photoUri)) { + this.photoUri = uri; + return true; + } else if (this.photoUri != null && uri == null) { + this.photoUri = null; + return true; + } else { + return false; + } } public void setServerName(String serverName) { diff --git a/src/main/java/eu/siacs/conversations/entities/Roster.java b/src/main/java/eu/siacs/conversations/entities/Roster.java index ce058004..d6777ef6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Roster.java +++ b/src/main/java/eu/siacs/conversations/entities/Roster.java @@ -2,6 +2,7 @@ package eu.siacs.conversations.entities; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import eu.siacs.conversations.xmpp.jid.Jid; @@ -55,12 +56,15 @@ public class Roster { } } - public void clearSystemAccounts() { - for (Contact contact : getContacts()) { - contact.setPhotoUri(null); - contact.setSystemName(null); - contact.setSystemAccount(null); + public List getWithSystemAccounts() { + List with = getContacts(); + for(Iterator iterator = with.iterator(); iterator.hasNext();) { + Contact contact = iterator.next(); + if (contact.getSystemAccount() == null) { + iterator.remove(); + } } + return with; } public List getContacts() { -- cgit v1.2.3 From 58201b440856a60d45d3a72cf6aaacd3a36dc828 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 10 Jun 2015 03:30:17 +0200 Subject: changed paragraph divider --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 90b74a53..a63d033d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -17,7 +17,7 @@ public class Message extends AbstractEntity { public static final String TABLENAME = "messages"; - public static final String MERGE_SEPARATOR = "\u200B\n\n"; + public static final String MERGE_SEPARATOR = " \u200B\n\n"; public static final int STATUS_RECEIVED = 0; public static final int STATUS_UNSEND = 1; -- cgit v1.2.3 From 9eb9a522050589e60bc7c76b2b040b1dadb7fd1d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 28 Jun 2015 11:19:07 +0200 Subject: initial http upload support be careful: little error handling and no encryption --- .../siacs/conversations/entities/Downloadable.java | 32 ++++++++++------------ .../entities/DownloadablePlaceholder.java | 5 ---- .../eu/siacs/conversations/entities/Message.java | 8 ++++++ 3 files changed, 23 insertions(+), 22 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Downloadable.java b/src/main/java/eu/siacs/conversations/entities/Downloadable.java index d25bf93a..c32165e8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Downloadable.java +++ b/src/main/java/eu/siacs/conversations/entities/Downloadable.java @@ -2,27 +2,25 @@ package eu.siacs.conversations.entities; public interface Downloadable { - public final String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; - public final String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; + String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; + String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; - public static final int STATUS_UNKNOWN = 0x200; - public static final int STATUS_CHECKING = 0x201; - public static final int STATUS_FAILED = 0x202; - public static final int STATUS_OFFER = 0x203; - public static final int STATUS_DOWNLOADING = 0x204; - public static final int STATUS_DELETED = 0x205; - public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206; - public static final int STATUS_UPLOADING = 0x207; + int STATUS_UNKNOWN = 0x200; + int STATUS_CHECKING = 0x201; + int STATUS_FAILED = 0x202; + int STATUS_OFFER = 0x203; + int STATUS_DOWNLOADING = 0x204; + int STATUS_DELETED = 0x205; + int STATUS_OFFER_CHECK_FILESIZE = 0x206; + int STATUS_UPLOADING = 0x207; - public boolean start(); + boolean start(); - public int getStatus(); + int getStatus(); - public long getFileSize(); + long getFileSize(); - public int getProgress(); + int getProgress(); - public String getMimeType(); - - public void cancel(); + void cancel(); } diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java b/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java index 03fceceb..cce22ea3 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java @@ -27,11 +27,6 @@ public class DownloadablePlaceholder implements Downloadable { return 0; } - @Override - public String getMimeType() { - return ""; - } - @Override public void cancel() { diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index a63d033d..d80400d8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -586,6 +586,14 @@ public class Message extends AbstractEntity { return type == TYPE_FILE || type == TYPE_IMAGE; } + public boolean hasFileOnRemoteHost() { + return isFileOrImage() && getImageParams().url != null; + } + + public boolean needsUploading() { + return isFileOrImage() && getImageParams().url == null; + } + public class ImageParams { public URL url; public long size = 0; -- cgit v1.2.3 From 7e11570f2c2eeeab17b4c024442bb849b40899df Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 28 Jun 2015 13:14:21 +0200 Subject: show attach button in conferences when http upload is available --- src/main/java/eu/siacs/conversations/entities/Account.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 6e6dcb6a..f472361f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -44,6 +44,10 @@ public class Account extends AbstractEntity { public static final int OPTION_REGISTER = 2; public static final int OPTION_USECOMPRESSION = 3; + public boolean httpUploadAvailable() { + return xmppConnection != null && xmppConnection.getFeatures().httpUpload(); + } + public static enum State { DISABLED, OFFLINE, -- cgit v1.2.3 From d7de3113795738ada1488f673f6e7b651e166058 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 30 Jun 2015 13:52:53 +0200 Subject: refactored bodyContainsDownloadable to be more flexible --- .../eu/siacs/conversations/entities/Message.java | 68 +++++++++++----------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index d80400d8..bf68d018 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -375,8 +375,8 @@ public class Message extends AbstractEntity { (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && !GeoHelper.isGeoUri(message.getBody()) && !GeoHelper.isGeoUri(this.body) && - !message.bodyContainsDownloadable() && - !this.bodyContainsDownloadable() && + message.treatAsDownloadable() == Decision.NO && + this.treatAsDownloadable() == Decision.NO && !message.getBody().startsWith(ME_COMMAND) && !this.getBody().startsWith(ME_COMMAND) && !this.bodyIsHeart() && @@ -434,48 +434,50 @@ public class Message extends AbstractEntity { return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); } - public boolean bodyContainsDownloadable() { - /** - * there are a few cases where spaces result in an unwanted behavior, e.g. - * "http://example.com/image.jpg text that will not be shown /abc.png" - * or more than one image link in one message. - */ + public enum Decision { + YES, + NO, + ASK + } + + public Decision treatAsDownloadable() { if (body.trim().contains(" ")) { - return false; + return Decision.NO; } try { URL url = new URL(body); - if (!url.getProtocol().equalsIgnoreCase("http") - && !url.getProtocol().equalsIgnoreCase("https")) { - return false; + if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { + return Decision.NO; } - - String sUrlPath = url.getPath(); - if (sUrlPath == null || sUrlPath.isEmpty()) { - return false; + String path = url.getPath(); + if (path == null || path.isEmpty()) { + return Decision.NO; } - int iSlashIndex = sUrlPath.lastIndexOf('/') + 1; - - String sLastUrlPath = sUrlPath.substring(iSlashIndex).toLowerCase(); - - String[] extensionParts = sLastUrlPath.split("\\."); - if (extensionParts.length == 2 - && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 1])) { - return true; - } else if (extensionParts.length == 3 - && Arrays + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); + String[] extensionParts = filename.split("\\."); + String extension; + String ref = url.getRef(); + if (extensionParts.length == 2) { + extension = extensionParts[extensionParts.length - 1]; + } else if (extensionParts.length == 3 && Arrays .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1]) - && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 2])) { - return true; + .contains(extensionParts[extensionParts.length - 1])) { + extension = extensionParts[extensionParts.length -2]; } else { - return false; + return Decision.NO; } + + if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { + return Decision.YES; + } else if (ref != null && ref.matches("([A-Fa-f0-9]{2}){48}")) { + return Decision.ASK; + } else { + return Decision.NO; + } + } catch (MalformedURLException e) { - return false; + return Decision.NO; } } -- cgit v1.2.3 From aca9d8036c53c0d0689ed94d67d7c5071d74b14e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 30 Jun 2015 17:15:02 +0200 Subject: made httpconnection (download) ready all kind of files --- .../eu/siacs/conversations/entities/Message.java | 108 +++++++++++---------- 1 file changed, 55 insertions(+), 53 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index bf68d018..1f622bf4 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -485,12 +485,12 @@ public class Message extends AbstractEntity { return body != null && UIHelper.HEARTS.contains(body.trim()); } - public ImageParams getImageParams() { - ImageParams params = getLegacyImageParams(); + public FileParams getFileParams() { + FileParams params = getLegacyFileParams(); if (params != null) { return params; } - params = new ImageParams(); + params = new FileParams(); if (this.downloadable != null) { params.size = this.downloadable.getFileSize(); } @@ -498,61 +498,64 @@ public class Message extends AbstractEntity { return params; } String parts[] = body.split("\\|"); - if (parts.length == 1) { - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { - params.origin = parts[0]; + switch (parts.length) { + case 1: + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + try { + params.url = new URL(parts[0]); + } catch (MalformedURLException e1) { + params.url = null; + } + } + break; + case 2: + case 4: try { params.url = new URL(parts[0]); } catch (MalformedURLException e1) { params.url = null; } - } - } else if (parts.length == 3) { - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { - params.size = 0; - } - try { - params.width = Integer.parseInt(parts[1]); - } catch (NumberFormatException e) { - params.width = 0; - } - try { - params.height = Integer.parseInt(parts[2]); - } catch (NumberFormatException e) { - params.height = 0; - } - } else if (parts.length == 4) { - params.origin = parts[0]; - try { - params.url = new URL(parts[0]); - } catch (MalformedURLException e1) { - params.url = null; - } - try { - params.size = Long.parseLong(parts[1]); - } catch (NumberFormatException e) { - params.size = 0; - } - try { - params.width = Integer.parseInt(parts[2]); - } catch (NumberFormatException e) { - params.width = 0; - } - try { - params.height = Integer.parseInt(parts[3]); - } catch (NumberFormatException e) { - params.height = 0; - } + try { + params.size = Long.parseLong(parts[1]); + } catch (NumberFormatException e) { + params.size = 0; + } + try { + params.width = Integer.parseInt(parts[2]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + params.width = 0; + } + try { + params.height = Integer.parseInt(parts[3]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + params.height = 0; + } + break; + case 3: + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + params.size = 0; + } + try { + params.width = Integer.parseInt(parts[1]); + } catch (NumberFormatException e) { + params.width = 0; + } + try { + params.height = Integer.parseInt(parts[2]); + } catch (NumberFormatException e) { + params.height = 0; + } + break; } return params; } - public ImageParams getLegacyImageParams() { - ImageParams params = new ImageParams(); + public FileParams getLegacyFileParams() { + FileParams params = new FileParams(); if (body == null) { return params; } @@ -589,18 +592,17 @@ public class Message extends AbstractEntity { } public boolean hasFileOnRemoteHost() { - return isFileOrImage() && getImageParams().url != null; + return isFileOrImage() && getFileParams().url != null; } public boolean needsUploading() { - return isFileOrImage() && getImageParams().url == null; + return isFileOrImage() && getFileParams().url == null; } - public class ImageParams { + public class FileParams { public URL url; public long size = 0; public int width = 0; public int height = 0; - public String origin; } } -- cgit v1.2.3 From c20a088ea811ab702244006fa2588cbdf7be0099 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 1 Jul 2015 16:01:18 +0200 Subject: changed mime type handling --- .../conversations/entities/DownloadableFile.java | 17 ++--- .../eu/siacs/conversations/entities/Message.java | 85 ++++++++++++++-------- 2 files changed, 63 insertions(+), 39 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index 7c8f95d1..ae9ba1f1 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -20,6 +20,8 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.MimeUtils; + import android.util.Log; public class DownloadableFile extends File { @@ -56,16 +58,11 @@ public class DownloadableFile extends File { public String getMimeType() { String path = this.getAbsolutePath(); - try { - String mime = URLConnection.guessContentTypeFromName(path.replace("#","")); - if (mime != null) { - return mime; - } else if (mime == null && path.endsWith(".webp")) { - return "image/webp"; - } else { - return ""; - } - } catch (final StringIndexOutOfBoundsException e) { + int start = path.lastIndexOf('.') + 1; + if (start < path.length()) { + String mime = MimeUtils.guessMimeTypeFromExtension(path.substring(start)); + return mime == null ? "" : mime; + } else { return ""; } } diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 1f622bf4..0b938639 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -9,6 +9,7 @@ import java.util.Arrays; import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.GeoHelper; +import eu.siacs.conversations.utils.MimeUtils; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -375,8 +376,8 @@ public class Message extends AbstractEntity { (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && !GeoHelper.isGeoUri(message.getBody()) && !GeoHelper.isGeoUri(this.body) && - message.treatAsDownloadable() == Decision.NO && - this.treatAsDownloadable() == Decision.NO && + message.treatAsDownloadable() == Decision.NEVER && + this.treatAsDownloadable() == Decision.NEVER && !message.getBody().startsWith(ME_COMMAND) && !this.getBody().startsWith(ME_COMMAND) && !this.bodyIsHeart() && @@ -435,49 +436,75 @@ public class Message extends AbstractEntity { } public enum Decision { - YES, - NO, - ASK + MUST, + SHOULD, + NEVER, + } + + private static String extractRelevantExtension(URL url) { + String path = url.getPath(); + if (path == null || path.isEmpty()) { + return null; + } + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); + String[] extensionParts = filename.split("\\."); + if (extensionParts.length == 2) { + return extensionParts[extensionParts.length - 1]; + } else if (extensionParts.length == 3 && Arrays + .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) + .contains(extensionParts[extensionParts.length - 1])) { + return extensionParts[extensionParts.length -2]; + } + return null; + } + + public String getMimeType() { + if (relativeFilePath != null) { + int start = relativeFilePath.lastIndexOf('.') + 1; + if (start < relativeFilePath.length()) { + return MimeUtils.guessMimeTypeFromExtension(relativeFilePath.substring(start)); + } else { + return null; + } + } else { + try { + return MimeUtils.guessExtensionFromMimeType(extractRelevantExtension(new URL(body.trim()))); + } catch (MalformedURLException e) { + return null; + } + } } public Decision treatAsDownloadable() { if (body.trim().contains(" ")) { - return Decision.NO; + return Decision.NEVER; } try { URL url = new URL(body); if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { - return Decision.NO; + return Decision.NEVER; } - String path = url.getPath(); - if (path == null || path.isEmpty()) { - return Decision.NO; + String extension = extractRelevantExtension(url); + if (extension == null) { + return Decision.NEVER; } - - String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); - String[] extensionParts = filename.split("\\."); - String extension; String ref = url.getRef(); - if (extensionParts.length == 2) { - extension = extensionParts[extensionParts.length - 1]; - } else if (extensionParts.length == 3 && Arrays - .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1])) { - extension = extensionParts[extensionParts.length -2]; - } else { - return Decision.NO; - } + boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); - if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { - return Decision.YES; - } else if (ref != null && ref.matches("([A-Fa-f0-9]{2}){48}")) { - return Decision.ASK; + if (encrypted) { + if (MimeUtils.guessMimeTypeFromExtension(extension) != null) { + return Decision.MUST; + } else { + return Decision.NEVER; + } + } else if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { + return Decision.SHOULD; } else { - return Decision.NO; + return Decision.NEVER; } } catch (MalformedURLException e) { - return Decision.NO; + return Decision.NEVER; } } -- cgit v1.2.3 From f5ba9d4223ca8e5dc9ce00024f69a8374d170a31 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 2 Jul 2015 23:13:00 +0200 Subject: refactored message context menu --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 0b938639..d15f3bbd 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -468,7 +468,7 @@ public class Message extends AbstractEntity { } } else { try { - return MimeUtils.guessExtensionFromMimeType(extractRelevantExtension(new URL(body.trim()))); + return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(body.trim()))); } catch (MalformedURLException e) { return null; } -- cgit v1.2.3 From e4d1bd415dcd61013005075af3e6a03b9de24d74 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 2 Jul 2015 23:19:50 +0200 Subject: also offer http download for some 'well known extensions' --- src/main/java/eu/siacs/conversations/entities/Downloadable.java | 2 ++ src/main/java/eu/siacs/conversations/entities/Message.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Downloadable.java b/src/main/java/eu/siacs/conversations/entities/Downloadable.java index c32165e8..8fae91bb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Downloadable.java +++ b/src/main/java/eu/siacs/conversations/entities/Downloadable.java @@ -4,6 +4,7 @@ public interface Downloadable { String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; + String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a"}; int STATUS_UNKNOWN = 0x200; int STATUS_CHECKING = 0x201; @@ -14,6 +15,7 @@ public interface Downloadable { int STATUS_OFFER_CHECK_FILESIZE = 0x206; int STATUS_UPLOADING = 0x207; + boolean start(); int getStatus(); diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index d15f3bbd..ac5a9d56 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -497,7 +497,8 @@ public class Message extends AbstractEntity { } else { return Decision.NEVER; } - } else if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension)) { + } else if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension) + || Arrays.asList(Downloadable.WELL_KNOWN_EXTENSIONS).contains(extension)) { return Decision.SHOULD; } else { return Decision.NEVER; -- cgit v1.2.3 From d30fb6f0a15fe574069694732bb23c339f0c30d1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 3 Jul 2015 21:32:46 +0200 Subject: avoid very rare npe --- src/main/java/eu/siacs/conversations/entities/Roster.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Roster.java b/src/main/java/eu/siacs/conversations/entities/Roster.java index d6777ef6..628a31d1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Roster.java +++ b/src/main/java/eu/siacs/conversations/entities/Roster.java @@ -74,6 +74,9 @@ public class Roster { } public void initContact(final Contact contact) { + if (contact == null) { + return; + } contact.setAccount(account); contact.setOption(Contact.Options.IN_ROSTER); synchronized (this.contacts) { -- cgit v1.2.3 From bef731a3c8ec2d4cefb70e6a7fe4232825a1d876 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 5 Jul 2015 11:59:38 +0200 Subject: refactored sendMessage and merged with resendMessage --- .../eu/siacs/conversations/entities/Message.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ac5a9d56..078a4565 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -435,6 +435,26 @@ public class Message extends AbstractEntity { return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); } + public boolean fixCounterpart() { + Presences presences = conversation.getContact().getPresences(); + if (counterpart != null && presences.has(counterpart.getResourcepart())) { + return true; + } else if (presences.size() >= 1) { + try { + counterpart = Jid.fromParts(conversation.getJid().getLocalpart(), + conversation.getJid().getDomainpart(), + presences.asStringArray()[0]); + return true; + } catch (InvalidJidException e) { + counterpart = null; + return false; + } + } else { + counterpart = null; + return false; + } + } + public enum Decision { MUST, SHOULD, -- cgit v1.2.3 From ce79f4bbe3e6f4254d143125807327ff02f1a29c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 10 Jul 2015 15:11:03 +0200 Subject: renamed downloadable to transferable --- .../siacs/conversations/entities/Downloadable.java | 28 ------------------ .../entities/DownloadablePlaceholder.java | 34 ---------------------- .../eu/siacs/conversations/entities/Message.java | 24 +++++++-------- .../siacs/conversations/entities/Transferable.java | 28 ++++++++++++++++++ .../entities/TransferablePlaceholder.java | 34 ++++++++++++++++++++++ 5 files changed, 74 insertions(+), 74 deletions(-) delete mode 100644 src/main/java/eu/siacs/conversations/entities/Downloadable.java delete mode 100644 src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java create mode 100644 src/main/java/eu/siacs/conversations/entities/Transferable.java create mode 100644 src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Downloadable.java b/src/main/java/eu/siacs/conversations/entities/Downloadable.java deleted file mode 100644 index 8fae91bb..00000000 --- a/src/main/java/eu/siacs/conversations/entities/Downloadable.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.siacs.conversations.entities; - -public interface Downloadable { - - String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; - String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; - String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a"}; - - int STATUS_UNKNOWN = 0x200; - int STATUS_CHECKING = 0x201; - int STATUS_FAILED = 0x202; - int STATUS_OFFER = 0x203; - int STATUS_DOWNLOADING = 0x204; - int STATUS_DELETED = 0x205; - int STATUS_OFFER_CHECK_FILESIZE = 0x206; - int STATUS_UPLOADING = 0x207; - - - boolean start(); - - int getStatus(); - - long getFileSize(); - - int getProgress(); - - void cancel(); -} diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java b/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java deleted file mode 100644 index cce22ea3..00000000 --- a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java +++ /dev/null @@ -1,34 +0,0 @@ -package eu.siacs.conversations.entities; - -public class DownloadablePlaceholder implements Downloadable { - - private int status; - - public DownloadablePlaceholder(int status) { - this.status = status; - } - @Override - public boolean start() { - return false; - } - - @Override - public int getStatus() { - return status; - } - - @Override - public long getFileSize() { - return 0; - } - - @Override - public int getProgress() { - return 0; - } - - @Override - public void cancel() { - - } -} diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 078a4565..28ef89df 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -70,7 +70,7 @@ public class Message extends AbstractEntity { protected String remoteMsgId = null; protected String serverMsgId = null; protected Conversation conversation = null; - protected Downloadable downloadable = null; + protected Transferable transferable = null; private Message mNextMessage = null; private Message mPreviousMessage = null; @@ -308,12 +308,12 @@ public class Message extends AbstractEntity { this.trueCounterpart = trueCounterpart; } - public Downloadable getDownloadable() { - return this.downloadable; + public Transferable getTransferable() { + return this.transferable; } - public void setDownloadable(Downloadable downloadable) { - this.downloadable = downloadable; + public void setTransferable(Transferable transferable) { + this.transferable = transferable; } public boolean equals(Message message) { @@ -364,8 +364,8 @@ public class Message extends AbstractEntity { public boolean mergeable(final Message message) { return message != null && (message.getType() == Message.TYPE_TEXT && - this.getDownloadable() == null && - message.getDownloadable() == null && + this.getTransferable() == null && + message.getTransferable() == null && message.getEncryption() != Message.ENCRYPTION_PGP && this.getType() == message.getType() && //this.getStatus() == message.getStatus() && @@ -471,7 +471,7 @@ public class Message extends AbstractEntity { if (extensionParts.length == 2) { return extensionParts[extensionParts.length - 1]; } else if (extensionParts.length == 3 && Arrays - .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) + .asList(Transferable.VALID_CRYPTO_EXTENSIONS) .contains(extensionParts[extensionParts.length - 1])) { return extensionParts[extensionParts.length -2]; } @@ -517,8 +517,8 @@ public class Message extends AbstractEntity { } else { return Decision.NEVER; } - } else if (Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains(extension) - || Arrays.asList(Downloadable.WELL_KNOWN_EXTENSIONS).contains(extension)) { + } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension) + || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) { return Decision.SHOULD; } else { return Decision.NEVER; @@ -539,8 +539,8 @@ public class Message extends AbstractEntity { return params; } params = new FileParams(); - if (this.downloadable != null) { - params.size = this.downloadable.getFileSize(); + if (this.transferable != null) { + params.size = this.transferable.getFileSize(); } if (body == null) { return params; diff --git a/src/main/java/eu/siacs/conversations/entities/Transferable.java b/src/main/java/eu/siacs/conversations/entities/Transferable.java new file mode 100644 index 00000000..2db6e3c9 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/entities/Transferable.java @@ -0,0 +1,28 @@ +package eu.siacs.conversations.entities; + +public interface Transferable { + + String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; + String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; + String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a"}; + + int STATUS_UNKNOWN = 0x200; + int STATUS_CHECKING = 0x201; + int STATUS_FAILED = 0x202; + int STATUS_OFFER = 0x203; + int STATUS_DOWNLOADING = 0x204; + int STATUS_DELETED = 0x205; + int STATUS_OFFER_CHECK_FILESIZE = 0x206; + int STATUS_UPLOADING = 0x207; + + + boolean start(); + + int getStatus(); + + long getFileSize(); + + int getProgress(); + + void cancel(); +} diff --git a/src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java b/src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java new file mode 100644 index 00000000..e065953e --- /dev/null +++ b/src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java @@ -0,0 +1,34 @@ +package eu.siacs.conversations.entities; + +public class TransferablePlaceholder implements Transferable { + + private int status; + + public TransferablePlaceholder(int status) { + this.status = status; + } + @Override + public boolean start() { + return false; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public long getFileSize() { + return 0; + } + + @Override + public int getProgress() { + return 0; + } + + @Override + public void cancel() { + + } +} -- cgit v1.2.3 From ce527c8b7699dda3cb9c5df3e482eeeeb42a1568 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 18 Jul 2015 00:01:34 +0200 Subject: account for downloaded http files in dup checker --- .../eu/siacs/conversations/entities/Message.java | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 28ef89df..957c2a6d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -321,15 +321,25 @@ public class Message extends AbstractEntity { return this.serverMsgId.equals(message.getServerMsgId()); } else if (this.body == null || this.counterpart == null) { return false; - } else if (message.getRemoteMsgId() != null) { - return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) - && this.counterpart.equals(message.getCounterpart()) - && this.body.equals(message.getBody()); } else { - return this.remoteMsgId == null - && this.counterpart.equals(message.getCounterpart()) - && this.body.equals(message.getBody()) - && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; + String body, otherBody; + if (this.hasFileOnRemoteHost()) { + body = getFileParams().url.toString(); + otherBody = message.body == null ? null : message.body.trim(); + } else { + body = this.body; + otherBody = message.body; + } + if (message.getRemoteMsgId() != null) { + return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) + && this.counterpart.equals(message.getCounterpart()) + && body.equals(otherBody); + } else { + return this.remoteMsgId == null + && this.counterpart.equals(message.getCounterpart()) + && body.equals(otherBody) + && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; + } } } -- cgit v1.2.3 From b8048a5538293b3855c2b2eae55d35645e614f11 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Fri, 29 May 2015 11:17:26 +0200 Subject: CryptoNext persistance layer mockup Initial sketch of the peripheral storage infrastructure for the new axolotl-based encryption scheme. --- .../eu/siacs/conversations/entities/Account.java | 4 + .../eu/siacs/conversations/entities/Contact.java | 182 +++++++++++++-------- .../eu/siacs/conversations/entities/Message.java | 13 ++ 3 files changed, 135 insertions(+), 64 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index f472361f..38312566 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -254,6 +254,10 @@ public class Account extends AbstractEntity { return keys; } + public String getKey(final String name) { + return this.keys.optString(name, null); + } + public boolean setKey(final String keyName, final String keyValue) { try { this.keys.put(keyName, keyValue); diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index e546f214..2f9b375d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -2,15 +2,19 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; +import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libaxolotl.InvalidKeyException; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -183,20 +187,22 @@ public class Contact implements ListItem, Blockable { } public ContentValues getContentValues() { - final ContentValues values = new ContentValues(); - values.put(ACCOUNT, accountUuid); - values.put(SYSTEMNAME, systemName); - values.put(SERVERNAME, serverName); - values.put(JID, jid.toString()); - values.put(OPTIONS, subscription); - values.put(SYSTEMACCOUNT, systemAccount); - values.put(PHOTOURI, photoUri); - values.put(KEYS, keys.toString()); - values.put(AVATAR, avatar == null ? null : avatar.getFilename()); - values.put(LAST_PRESENCE, lastseen.presence); - values.put(LAST_TIME, lastseen.time); - values.put(GROUPS, groups.toString()); - return values; + synchronized (this.keys) { + final ContentValues values = new ContentValues(); + values.put(ACCOUNT, accountUuid); + values.put(SYSTEMNAME, systemName); + values.put(SERVERNAME, serverName); + values.put(JID, jid.toString()); + values.put(OPTIONS, subscription); + values.put(SYSTEMACCOUNT, systemAccount); + values.put(PHOTOURI, photoUri); + values.put(KEYS, keys.toString()); + values.put(AVATAR, avatar == null ? null : avatar.getFilename()); + values.put(LAST_PRESENCE, lastseen.presence); + values.put(LAST_TIME, lastseen.time); + values.put(GROUPS, groups.toString()); + return values; + } } public int getSubscription() { @@ -281,63 +287,109 @@ public class Contact implements ListItem, Blockable { } public ArrayList getOtrFingerprints() { - final ArrayList fingerprints = new ArrayList(); - try { - if (this.keys.has("otr_fingerprints")) { - final JSONArray prints = this.keys.getJSONArray("otr_fingerprints"); - for (int i = 0; i < prints.length(); ++i) { - final String print = prints.isNull(i) ? null : prints.getString(i); - if (print != null && !print.isEmpty()) { - fingerprints.add(prints.getString(i)); + synchronized (this.keys) { + final ArrayList fingerprints = new ArrayList(); + try { + if (this.keys.has("otr_fingerprints")) { + final JSONArray prints = this.keys.getJSONArray("otr_fingerprints"); + for (int i = 0; i < prints.length(); ++i) { + final String print = prints.isNull(i) ? null : prints.getString(i); + if (print != null && !print.isEmpty()) { + fingerprints.add(prints.getString(i)); + } } } - } - } catch (final JSONException ignored) { + } catch (final JSONException ignored) { + } + return fingerprints; } - return fingerprints; } - public boolean addOtrFingerprint(String print) { - if (getOtrFingerprints().contains(print)) { - return false; + synchronized (this.keys) { + if (getOtrFingerprints().contains(print)) { + return false; + } + try { + JSONArray fingerprints; + if (!this.keys.has("otr_fingerprints")) { + fingerprints = new JSONArray(); + } else { + fingerprints = this.keys.getJSONArray("otr_fingerprints"); + } + fingerprints.put(print); + this.keys.put("otr_fingerprints", fingerprints); + return true; + } catch (final JSONException ignored) { + return false; + } } - try { - JSONArray fingerprints; - if (!this.keys.has("otr_fingerprints")) { - fingerprints = new JSONArray(); + } + public long getPgpKeyId() { + synchronized (this.keys) { + if (this.keys.has("pgp_keyid")) { + try { + return this.keys.getLong("pgp_keyid"); + } catch (JSONException e) { + return 0; + } } else { - fingerprints = this.keys.getJSONArray("otr_fingerprints"); + return 0; } - fingerprints.put(print); - this.keys.put("otr_fingerprints", fingerprints); - return true; - } catch (final JSONException ignored) { - return false; } } - public long getPgpKeyId() { - if (this.keys.has("pgp_keyid")) { + public void setPgpKeyId(long keyId) { + synchronized (this.keys) { try { - return this.keys.getLong("pgp_keyid"); - } catch (JSONException e) { - return 0; + this.keys.put("pgp_keyid", keyId); + } catch (final JSONException ignored) { } - } else { - return 0; } } - public void setPgpKeyId(long keyId) { - try { - this.keys.put("pgp_keyid", keyId); - } catch (final JSONException ignored) { + public List getTrustedAxolotlIdentityKeys() { + synchronized (this.keys) { + JSONArray serializedKeyItems = this.keys.optJSONArray("axolotl_identity_key"); + List identityKeys = new ArrayList<>(); + if(serializedKeyItems != null) { + for(int i = 0; i Date: Thu, 25 Jun 2015 16:56:34 +0200 Subject: Reworked axolotl protocol layer Numerous fixes --- .../eu/siacs/conversations/entities/Account.java | 7 +++ .../eu/siacs/conversations/entities/Contact.java | 62 +++++++++++++++------- .../eu/siacs/conversations/entities/Message.java | 14 ++--- 3 files changed, 54 insertions(+), 29 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 38312566..7a2dc3f7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -20,6 +20,7 @@ import java.util.concurrent.CopyOnWriteArraySet; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrService; +import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -122,6 +123,7 @@ public class Account extends AbstractEntity { protected String avatar; protected boolean online = false; private OtrService mOtrService = null; + private AxolotlService axolotlService = null; private XmppConnection xmppConnection = null; private long mEndGracePeriod = 0L; private String otrFingerprint; @@ -281,8 +283,13 @@ public class Account extends AbstractEntity { return values; } + public AxolotlService getAxolotlService() { + return axolotlService; + } + public void initAccountServices(final XmppConnectionService context) { this.mOtrService = new OtrService(context, this); + this.axolotlService = new AxolotlService(this, context); } public OtrService getOtrService() { diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 2f9b375d..45b55e49 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -2,6 +2,7 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; +import android.util.Base64; import android.util.Log; import org.json.JSONArray; @@ -349,20 +350,38 @@ public class Contact implements ListItem, Blockable { } } - public List getTrustedAxolotlIdentityKeys() { + public List getAxolotlIdentityKeys() { synchronized (this.keys) { JSONArray serializedKeyItems = this.keys.optJSONArray("axolotl_identity_key"); List identityKeys = new ArrayList<>(); + List toDelete = new ArrayList<>(); if(serializedKeyItems != null) { for(int i = 0; i Date: Fri, 26 Jun 2015 15:41:02 +0200 Subject: Reformat code to use tabs This really sucks to do it like this. Sorry. :( --- .../eu/siacs/conversations/entities/Contact.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 45b55e49..240d5223 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -310,7 +310,7 @@ public class Contact implements ListItem, Blockable { synchronized (this.keys) { if (getOtrFingerprints().contains(print)) { return false; - } + } try { JSONArray fingerprints; if (!this.keys.has("otr_fingerprints")) { @@ -392,12 +392,12 @@ public class Contact implements ListItem, Blockable { public boolean addAxolotlIdentityKey(IdentityKey identityKey) { synchronized (this.keys) { if(!getAxolotlIdentityKeys().contains(identityKey)) { - JSONArray keysList; - try { - keysList = this.keys.getJSONArray("axolotl_identity_key"); - } catch (JSONException e) { - keysList = new JSONArray(); - } + JSONArray keysList; + try { + keysList = this.keys.getJSONArray("axolotl_identity_key"); + } catch (JSONException e) { + keysList = new JSONArray(); + } keysList.put(Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT)); try { @@ -406,10 +406,10 @@ public class Contact implements ListItem, Blockable { Log.e(Config.LOGTAG, "Error adding Identity Key to Contact " + this.getJid() + ": " + e.getMessage()); return false; } - return true; + return true; } else { - return false; - } + return false; + } } } -- cgit v1.2.3 From 3815d4efa378846c8aef840ad659268a0bef1536 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Mon, 29 Jun 2015 14:22:26 +0200 Subject: Fetch bundles on-demand, encrypt in background Bundles are now fetched on demand when a session needs to be established. This should lessen the chance of changes to the bundles occuring before they're used, as well as lessen the load of fetching bundles. Also, the message encryption is now done in a background thread, as this can be somewhat costly if many sessions are present. This is probably not going to be an issue in real use, but it's good practice anyway. --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 289ed4ea..2efd8a29 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -179,13 +179,13 @@ public class Conversation extends AbstractEntity implements Blockable { } } - public void findUnsentMessagesWithOtrEncryption(OnMessageFound onMessageFound) { + public void findUnsentMessagesWithEncryption(int encryptionType, OnMessageFound onMessageFound) { synchronized (this.messages) { for (Message message : this.messages) { if ((message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_WAITING) - && (message.getEncryption() == Message.ENCRYPTION_OTR)) { + && (message.getEncryption() == encryptionType)) { onMessageFound.onMessageFound(message); - } + } } } } -- cgit v1.2.3 From 1b0596d57473f7aafa633ed2d5f3b3610a653a51 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Mon, 29 Jun 2015 14:25:23 +0200 Subject: Tag messages with originating session This can be used later in order to display trust status of messages, as well as for potential resending of messages in case of preKey conflicts. --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 336af972..b1dffc82 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -670,4 +670,8 @@ public class Message extends AbstractEntity { public boolean isTrusted() { return this.axolotlSession != null && this.axolotlSession.isTrusted(); } + + public void setAxolotlSession(AxolotlService.XmppAxolotlSession session) { + this.axolotlSession = session; + } } -- cgit v1.2.3 From 491f623708437f418497ecace2876e9c81708e72 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Tue, 7 Jul 2015 19:27:12 +0200 Subject: Fix displaying Contact IdentityKeys Migrate ContactDetailsActivity to use new SQL IdentityKeys storage, remove dead code from Contact class. --- .../eu/siacs/conversations/entities/Contact.java | 64 ---------------------- 1 file changed, 64 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 240d5223..fdb5f932 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -350,70 +350,6 @@ public class Contact implements ListItem, Blockable { } } - public List getAxolotlIdentityKeys() { - synchronized (this.keys) { - JSONArray serializedKeyItems = this.keys.optJSONArray("axolotl_identity_key"); - List identityKeys = new ArrayList<>(); - List toDelete = new ArrayList<>(); - if(serializedKeyItems != null) { - for(int i = 0; i Date: Thu, 9 Jul 2015 14:23:17 +0200 Subject: Overhauled Message tagging Messages are now tagged with the IdentityKey fingerprint of the originating session. IdentityKeys have one of three trust states: undecided (default), trusted, and untrusted/not yet trusted. --- .../java/eu/siacs/conversations/entities/Message.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index b1dffc82..9695e6fa 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -54,6 +54,7 @@ public class Message extends AbstractEntity { public static final String REMOTE_MSG_ID = "remoteMsgId"; public static final String SERVER_MSG_ID = "serverMsgId"; public static final String RELATIVE_FILE_PATH = "relativeFilePath"; + public static final String FINGERPRINT = "axolotl_fingerprint"; public static final String ME_COMMAND = "/me "; @@ -67,7 +68,6 @@ public class Message extends AbstractEntity { protected int encryption; protected int status; protected int type; - private AxolotlService.XmppAxolotlSession axolotlSession = null; protected String relativeFilePath; protected boolean read = true; protected String remoteMsgId = null; @@ -76,6 +76,7 @@ public class Message extends AbstractEntity { protected Transferable transferable = null; private Message mNextMessage = null; private Message mPreviousMessage = null; + private String axolotlFingerprint = null; private Message() { @@ -97,6 +98,7 @@ public class Message extends AbstractEntity { TYPE_TEXT, null, null, + null, null); this.conversation = conversation; } @@ -104,7 +106,7 @@ public class Message extends AbstractEntity { private Message(final String uuid, final String conversationUUid, final Jid counterpart, final Jid trueCounterpart, final String body, final long timeSent, final int encryption, final int status, final int type, final String remoteMsgId, - final String relativeFilePath, final String serverMsgId) { + final String relativeFilePath, final String serverMsgId, final String fingerprint) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -117,6 +119,7 @@ public class Message extends AbstractEntity { this.remoteMsgId = remoteMsgId; this.relativeFilePath = relativeFilePath; this.serverMsgId = serverMsgId; + this.axolotlFingerprint = fingerprint; } public static Message fromCursor(Cursor cursor) { @@ -153,7 +156,8 @@ public class Message extends AbstractEntity { cursor.getInt(cursor.getColumnIndex(TYPE)), cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)), - cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID))); + cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), + cursor.getString(cursor.getColumnIndex(FINGERPRINT))); } public static Message createStatusMessage(Conversation conversation, String body) { @@ -187,6 +191,7 @@ public class Message extends AbstractEntity { values.put(REMOTE_MSG_ID, remoteMsgId); values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(SERVER_MSG_ID, serverMsgId); + values.put(FINGERPRINT, axolotlFingerprint); return values; } @@ -667,11 +672,7 @@ public class Message extends AbstractEntity { public int height = 0; } - public boolean isTrusted() { - return this.axolotlSession != null && this.axolotlSession.isTrusted(); - } - - public void setAxolotlSession(AxolotlService.XmppAxolotlSession session) { - this.axolotlSession = session; + public void setAxolotlFingerprint(String fingerprint) { + this.axolotlFingerprint = fingerprint; } } -- cgit v1.2.3 From 9e8d9a64012531be8f6f72835c6f879d2a4451a1 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Fri, 10 Jul 2015 03:00:40 +0200 Subject: Show trust status of messages' originating session Shade lock icon red if message was received in a session that has not been marked trusted by the user or fingerprint is unknown --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 9695e6fa..ac6c6625 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -675,4 +675,8 @@ public class Message extends AbstractEntity { public void setAxolotlFingerprint(String fingerprint) { this.axolotlFingerprint = fingerprint; } + + public String getAxolotlFingerprint() { + return axolotlFingerprint; + } } -- cgit v1.2.3 From e8ec2ee628076aa43132c3214b786ddde64f93a6 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Wed, 15 Jul 2015 15:45:12 +0200 Subject: Don't merge messages with different trust statuses --- src/main/java/eu/siacs/conversations/entities/Message.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ac6c6625..698775c8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -399,7 +399,8 @@ public class Message extends AbstractEntity { !message.getBody().startsWith(ME_COMMAND) && !this.getBody().startsWith(ME_COMMAND) && !this.bodyIsHeart() && - !message.bodyIsHeart() + !message.bodyIsHeart() && + this.isTrusted() == message.isTrusted() ); } @@ -679,4 +680,9 @@ public class Message extends AbstractEntity { public String getAxolotlFingerprint() { return axolotlFingerprint; } + + public boolean isTrusted() { + return conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint) + == AxolotlService.SQLiteAxolotlStore.Trust.TRUSTED; + } } -- cgit v1.2.3 From 012f036840ade8f46462eafcc96d1f223f8ba845 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Mon, 20 Jul 2015 14:26:29 +0200 Subject: Optimize imports --- src/main/java/eu/siacs/conversations/entities/Contact.java | 5 ----- src/main/java/eu/siacs/conversations/entities/DownloadableFile.java | 5 ++--- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 4 ++-- 3 files changed, 4 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index fdb5f932..f924c05a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -2,20 +2,15 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; -import android.util.Base64; -import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.InvalidKeyException; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.InvalidJidException; diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index ae9ba1f1..ca325448 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -1,12 +1,13 @@ package eu.siacs.conversations.entities; +import android.util.Log; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; -import java.net.URLConnection; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; @@ -22,8 +23,6 @@ import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.MimeUtils; -import android.util.Log; - public class DownloadableFile extends File { private static final long serialVersionUID = 2247012619505115863L; diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index d867a370..6ff6b8c9 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.entities; +import android.annotation.SuppressLint; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -11,8 +13,6 @@ import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; -import android.annotation.SuppressLint; - @SuppressLint("DefaultLocale") public class MucOptions { -- cgit v1.2.3 From f7634a85be516feef753bdb32fed8df7da1573ed Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 22 Jul 2015 15:31:00 +0200 Subject: treat private, non-anonymous mucs like 1:1 chats notification wise --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 2efd8a29..6d99e358 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -519,6 +519,13 @@ public class Conversation extends AbstractEntity implements Blockable { return getContact().getOtrFingerprints().contains(getOtrFingerprint()); } + /** + * short for is Private and Non-anonymous + */ + public boolean isPnNA() { + return mode == MODE_SINGLE || (getMucOptions().membersOnly() && getMucOptions().nonanonymous()); + } + public synchronized MucOptions getMucOptions() { if (this.mucOptions == null) { this.mucOptions = new MucOptions(this); -- cgit v1.2.3 From cd204d5931a6cf0289d2df120f278864b8b94fdf Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 22 Jul 2015 15:57:17 +0200 Subject: show warning when trying to highlight users that have left the conference --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 6ff6b8c9..52a862ef 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -264,6 +264,15 @@ public class MucOptions { users.add(user); } + public boolean isUserInRoom(String name) { + for (int i = 0; i < users.size(); ++i) { + if (users.get(i).getName().equals(name)) { + return true; + } + } + return false; + } + public void processPacket(PresencePacket packet, PgpEngine pgp) { final Jid from = packet.getFrom(); if (!from.isBareJid()) { -- cgit v1.2.3 From 8f14d2bfbd1e3e6697a5afccfc2512f98b55b702 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 28 Jul 2015 23:00:30 +0200 Subject: removed recursion in message.getMerged*() --- .../eu/siacs/conversations/entities/Message.java | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 698775c8..b4bb31a8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -416,11 +416,14 @@ public class Message extends AbstractEntity { } public String getMergedBody() { - final Message next = this.next(); - if (this.mergeable(next)) { - return getBody().trim() + MERGE_SEPARATOR + next.getMergedBody(); + StringBuilder body = new StringBuilder(this.body.trim()); + Message current = this; + while(current.mergeable(current.next())) { + current = current.next(); + body.append(MERGE_SEPARATOR); + body.append(current.getBody().trim()); } - return getBody().trim(); + return body.toString(); } public boolean hasMeCommand() { @@ -428,20 +431,23 @@ public class Message extends AbstractEntity { } public int getMergedStatus() { - final Message next = this.next(); - if (this.mergeable(next)) { - return next.getStatus(); + int status = this.status; + Message current = this; + while(current.mergeable(current.next())) { + current = current.next(); + status = current.status; } - return getStatus(); + return status; } public long getMergedTimeSent() { - Message next = this.next(); - if (this.mergeable(next)) { - return next.getMergedTimeSent(); - } else { - return getTimeSent(); + long time = this.timeSent; + Message current = this; + while(current.mergeable(current.next())) { + current = current.next(); + time = current.timeSent; } + return time; } public boolean wasMergedIntoPrevious() { -- cgit v1.2.3 From efcefc2e6301f6255ebcb3e11f0f0a51731bacca Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Tue, 28 Jul 2015 22:00:54 +0200 Subject: Refactor out inner classes, cache trust store Moves SQLiteAxolotlStore and XmppAxolotlSession into proper classes. IdentityKeys trust statuses are now cached in an LruCache to prevent hammering the database when rendering the UI. --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index b4bb31a8..14f96296 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -8,7 +8,7 @@ import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; -import eu.siacs.conversations.crypto.axolotl.AxolotlService; +import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.MimeUtils; import eu.siacs.conversations.utils.UIHelper; @@ -689,6 +689,6 @@ public class Message extends AbstractEntity { public boolean isTrusted() { return conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint) - == AxolotlService.SQLiteAxolotlStore.Trust.TRUSTED; + == SQLiteAxolotlStore.Trust.TRUSTED; } } -- cgit v1.2.3 From e6df4d81d23e4b7c0c3798f114714dd3caebfe8c Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Wed, 29 Jul 2015 16:41:58 +0200 Subject: Tag carbon messages in parser, adapt session logic Messages sent from another device of the own account are now explicitly tagged as carboned message. The session detection logic now uses this tag to find "session borders". --- .../eu/siacs/conversations/entities/Message.java | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 14f96296..99b78d14 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -51,6 +51,7 @@ public class Message extends AbstractEntity { public static final String ENCRYPTION = "encryption"; public static final String STATUS = "status"; public static final String TYPE = "type"; + public static final String CARBON = "carbon"; public static final String REMOTE_MSG_ID = "remoteMsgId"; public static final String SERVER_MSG_ID = "serverMsgId"; public static final String RELATIVE_FILE_PATH = "relativeFilePath"; @@ -68,6 +69,7 @@ public class Message extends AbstractEntity { protected int encryption; protected int status; protected int type; + protected boolean carbon = false; protected String relativeFilePath; protected boolean read = true; protected String remoteMsgId = null; @@ -85,8 +87,11 @@ public class Message extends AbstractEntity { public Message(Conversation conversation, String body, int encryption) { this(conversation, body, encryption, STATUS_UNSEND); } - public Message(Conversation conversation, String body, int encryption, int status) { + this(conversation, body, encryption, status, false); + } + + public Message(Conversation conversation, String body, int encryption, int status, boolean carbon) { this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), conversation.getJid() == null ? null : conversation.getJid().toBareJid(), @@ -96,6 +101,7 @@ public class Message extends AbstractEntity { encryption, status, TYPE_TEXT, + false, null, null, null, @@ -105,8 +111,9 @@ public class Message extends AbstractEntity { private Message(final String uuid, final String conversationUUid, final Jid counterpart, final Jid trueCounterpart, final String body, final long timeSent, - final int encryption, final int status, final int type, final String remoteMsgId, - final String relativeFilePath, final String serverMsgId, final String fingerprint) { + final int encryption, final int status, final int type, final boolean carbon, + final String remoteMsgId, final String relativeFilePath, + final String serverMsgId, final String fingerprint) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -116,6 +123,7 @@ public class Message extends AbstractEntity { this.encryption = encryption; this.status = status; this.type = type; + this.carbon = carbon; this.remoteMsgId = remoteMsgId; this.relativeFilePath = relativeFilePath; this.serverMsgId = serverMsgId; @@ -154,6 +162,7 @@ public class Message extends AbstractEntity { cursor.getInt(cursor.getColumnIndex(ENCRYPTION)), cursor.getInt(cursor.getColumnIndex(STATUS)), cursor.getInt(cursor.getColumnIndex(TYPE)), + cursor.getInt(cursor.getColumnIndex(CARBON))>0, cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)), cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), @@ -188,6 +197,7 @@ public class Message extends AbstractEntity { values.put(ENCRYPTION, encryption); values.put(STATUS, status); values.put(TYPE, type); + values.put(CARBON, carbon ? 1 : 0); values.put(REMOTE_MSG_ID, remoteMsgId); values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(SERVER_MSG_ID, serverMsgId); @@ -312,6 +322,14 @@ public class Message extends AbstractEntity { this.type = type; } + public boolean isCarbon() { + return carbon; + } + + public void setCarbon(boolean carbon) { + this.carbon = carbon; + } + public void setTrueCounterpart(Jid trueCounterpart) { this.trueCounterpart = trueCounterpart; } -- cgit v1.2.3 From 58d80f58be2f75b858e93766c61857a78d161005 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 29 Jul 2015 23:45:37 +0200 Subject: use gcm for file encryption over http --- .../conversations/entities/DownloadableFile.java | 97 ++-------------------- 1 file changed, 8 insertions(+), 89 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index ca325448..452bf815 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -1,26 +1,7 @@ package eu.siacs.conversations.entities; -import android.util.Log; - import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import eu.siacs.conversations.Config; + import eu.siacs.conversations.utils.MimeUtils; public class DownloadableFile extends File { @@ -29,8 +10,7 @@ public class DownloadableFile extends File { private long expectedSize = 0; private String sha1sum; - private Key aeskey; - private String mime; + private byte[] aeskey; private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; @@ -84,85 +64,24 @@ public class DownloadableFile extends File { byte[] iv = new byte[16]; System.arraycopy(key, 0, iv, 0, 16); System.arraycopy(key, 16, secretKey, 0, 32); - this.aeskey = new SecretKeySpec(secretKey, "AES"); + this.aeskey = secretKey; this.iv = iv; } else if (key.length >= 32) { byte[] secretKey = new byte[32]; System.arraycopy(key, 0, secretKey, 0, 32); - this.aeskey = new SecretKeySpec(secretKey, "AES"); + this.aeskey = secretKey; } else if (key.length >= 16) { byte[] secretKey = new byte[16]; System.arraycopy(key, 0, secretKey, 0, 16); - this.aeskey = new SecretKeySpec(secretKey, "AES"); + this.aeskey = secretKey; } } - public Key getKey() { + public byte[] getKey() { return this.aeskey; } - public InputStream createInputStream() { - if (this.getKey() == null) { - try { - return new FileInputStream(this); - } catch (FileNotFoundException e) { - return null; - } - } else { - try { - IvParameterSpec ips = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, this.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted input stream"); - return new CipherInputStream(new FileInputStream(this), cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } catch (FileNotFoundException e) { - return null; - } - } - } - - public OutputStream createOutputStream() { - if (this.getKey() == null) { - try { - return new FileOutputStream(this); - } catch (FileNotFoundException e) { - return null; - } - } else { - try { - IvParameterSpec ips = new IvParameterSpec(this.iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.DECRYPT_MODE, this.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted output stream"); - return new CipherOutputStream(new FileOutputStream(this), - cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } catch (FileNotFoundException e) { - return null; - } - } + public byte[] getIv() { + return this.iv; } } -- cgit v1.2.3 From 74ab36fda2d977e1b97b755a8298c488e6d74ba2 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Thu, 30 Jul 2015 19:16:58 +0200 Subject: Fix session logic: enforce same type of encryption --- .../eu/siacs/conversations/entities/Message.java | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 99b78d14..e6687701 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -709,4 +709,35 @@ public class Message extends AbstractEntity { return conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint) == SQLiteAxolotlStore.Trust.TRUSTED; } + + private int getPreviousEncryption() { + for (Message iterator = this.prev(); iterator != null; iterator = iterator.prev()){ + if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) { + continue; + } + return iterator.getEncryption(); + } + return ENCRYPTION_NONE; + } + + private int getNextEncryption() { + for (Message iterator = this.next(); iterator != null; iterator = iterator.next()){ + if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) { + continue; + } + return iterator.getEncryption(); + } + return conversation.getNextEncryption(false); + } + + public boolean isValidInSession() { + int pastEncryption = this.getPreviousEncryption(); + int futureEncryption = this.getNextEncryption(); + + boolean inUnencryptedSession = pastEncryption == ENCRYPTION_NONE + || futureEncryption == ENCRYPTION_NONE + || pastEncryption != futureEncryption; + + return inUnencryptedSession || this.getEncryption() == pastEncryption; + } } -- cgit v1.2.3 From 658919f239e9c816f958d17df9ba5ee79b6549b2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 31 Jul 2015 00:52:46 +0200 Subject: improved 'next encryption' selection --- .../siacs/conversations/entities/Conversation.java | 63 ++++++++++++---------- .../eu/siacs/conversations/entities/Message.java | 2 +- 2 files changed, 37 insertions(+), 28 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 6d99e358..9f9f34cf 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -549,42 +549,51 @@ public class Conversation extends AbstractEntity implements Blockable { return this.nextCounterpart; } - public int getLatestEncryption() { - int latestEncryption = this.getLatestMessage().getEncryption(); - if ((latestEncryption == Message.ENCRYPTION_DECRYPTED) - || (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) { - return Message.ENCRYPTION_PGP; - } else { - return latestEncryption; + private int getMostRecentlyUsedOutgoingEncryption() { + synchronized (this.messages) { + for(int i = this.messages.size() -1; i >= 0; --i) { + final Message m = this.messages.get(0); + if (!m.isCarbon() && m.getStatus() != Message.STATUS_RECEIVED) { + final int e = m.getEncryption(); + if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) { + return Message.ENCRYPTION_PGP; + } else { + return e; + } + } + } } + return Message.ENCRYPTION_NONE; } - public int getNextEncryption(boolean force) { - int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1); - if (next == -1) { - int latest = this.getLatestEncryption(); - if (latest == Message.ENCRYPTION_NONE) { - if (force && getMode() == MODE_SINGLE) { - return Message.ENCRYPTION_OTR; - } else if (getContact().getPresences().size() == 1) { - if (getContact().getOtrFingerprints().size() >= 1) { - return Message.ENCRYPTION_OTR; + private int getMostRecentlyUsedIncomingEncryption() { + synchronized (this.messages) { + for(int i = this.messages.size() -1; i >= 0; --i) { + final Message m = this.messages.get(0); + if (m.getStatus() == Message.STATUS_RECEIVED) { + final int e = m.getEncryption(); + if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) { + return Message.ENCRYPTION_PGP; } else { - return latest; + return e; } - } else { - return latest; } - } else { - return latest; } } - if (next == Message.ENCRYPTION_NONE && force - && getMode() == MODE_SINGLE) { - return Message.ENCRYPTION_OTR; - } else { - return next; + return Message.ENCRYPTION_NONE; + } + + public int getNextEncryption() { + int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1); + if (next == -1) { + int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); + if (outgoing == Message.ENCRYPTION_NONE) { + return this.getMostRecentlyUsedIncomingEncryption(); + } else { + return outgoing; + } } + return next; } public void setNextEncryption(int encryption) { diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index e6687701..6c2a1cc0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -727,7 +727,7 @@ public class Message extends AbstractEntity { } return iterator.getEncryption(); } - return conversation.getNextEncryption(false); + return conversation.getNextEncryption(); } public boolean isValidInSession() { -- cgit v1.2.3 From 60cd307f73d5f31f25ba84541fbe1cce4aae2bc2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 1 Aug 2015 01:19:16 +0200 Subject: enable axolotl encryption for jingle supported file transfers --- .../conversations/entities/DownloadableFile.java | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index 452bf815..d35a4b01 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -24,15 +24,7 @@ public class DownloadableFile extends File { } public long getExpectedSize() { - if (this.aeskey != null) { - if (this.expectedSize == 0) { - return 0; - } else { - return (this.expectedSize / 16 + 1) * 16; - } - } else { - return this.expectedSize; - } + return this.expectedSize; } public String getMimeType() { @@ -58,25 +50,33 @@ public class DownloadableFile extends File { this.sha1sum = sum; } - public void setKey(byte[] key) { - if (key.length == 48) { + public void setKeyAndIv(byte[] keyIvCombo) { + if (keyIvCombo.length == 48) { byte[] secretKey = new byte[32]; byte[] iv = new byte[16]; - System.arraycopy(key, 0, iv, 0, 16); - System.arraycopy(key, 16, secretKey, 0, 32); + System.arraycopy(keyIvCombo, 0, iv, 0, 16); + System.arraycopy(keyIvCombo, 16, secretKey, 0, 32); this.aeskey = secretKey; this.iv = iv; - } else if (key.length >= 32) { + } else if (keyIvCombo.length >= 32) { byte[] secretKey = new byte[32]; - System.arraycopy(key, 0, secretKey, 0, 32); + System.arraycopy(keyIvCombo, 0, secretKey, 0, 32); this.aeskey = secretKey; - } else if (key.length >= 16) { + } else if (keyIvCombo.length >= 16) { byte[] secretKey = new byte[16]; - System.arraycopy(key, 0, secretKey, 0, 16); + System.arraycopy(keyIvCombo, 0, secretKey, 0, 16); this.aeskey = secretKey; } } + public void setKey(byte[] key) { + this.aeskey = key; + } + + public void setIv(byte[] iv) { + this.iv = iv; + } + public byte[] getKey() { return this.aeskey; } -- cgit v1.2.3 From 6cd9383e53900e03d324b227c0f01b1537881148 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Sat, 1 Aug 2015 18:27:52 +0200 Subject: Let UNTRUSTED/UNDECIDED keys become INACTIVE --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 6c2a1cc0..0eff99cf 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -8,7 +8,7 @@ import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; -import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.MimeUtils; import eu.siacs.conversations.utils.UIHelper; @@ -707,7 +707,7 @@ public class Message extends AbstractEntity { public boolean isTrusted() { return conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint) - == SQLiteAxolotlStore.Trust.TRUSTED; + == XmppAxolotlSession.Trust.TRUSTED; } private int getPreviousEncryption() { -- cgit v1.2.3 From 8043833156119eef4662c50f30ca647bfc6d4438 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 19:40:45 +0200 Subject: bugfix: next encryption is now being properly detected --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 9f9f34cf..36d6b43b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -552,7 +552,7 @@ public class Conversation extends AbstractEntity implements Blockable { private int getMostRecentlyUsedOutgoingEncryption() { synchronized (this.messages) { for(int i = this.messages.size() -1; i >= 0; --i) { - final Message m = this.messages.get(0); + final Message m = this.messages.get(i); if (!m.isCarbon() && m.getStatus() != Message.STATUS_RECEIVED) { final int e = m.getEncryption(); if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) { @@ -569,7 +569,7 @@ public class Conversation extends AbstractEntity implements Blockable { private int getMostRecentlyUsedIncomingEncryption() { synchronized (this.messages) { for(int i = this.messages.size() -1; i >= 0; --i) { - final Message m = this.messages.get(0); + final Message m = this.messages.get(i); if (m.getStatus() == Message.STATUS_RECEIVED) { final int e = m.getEncryption(); if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) { -- cgit v1.2.3 From ea2ce78d6e0b37db21ebffd9f0f991ab25e17f1a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 26 Aug 2015 12:11:12 +0200 Subject: be more restrictive about marking messages as sent_received in muc parser --- .../siacs/conversations/entities/Conversation.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 36d6b43b..e6c044a1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -201,14 +201,25 @@ public class Conversation extends AbstractEntity implements Blockable { } } - public Message findSentMessageWithUuid(String uuid) { + public Message findSentMessageWithUuidOrRemoteId(String id) { synchronized (this.messages) { for (Message message : this.messages) { - if (uuid.equals(message.getUuid()) - || (message.getStatus() >= Message.STATUS_SEND && uuid - .equals(message.getRemoteMsgId()))) { + if (id.equals(message.getUuid()) + || (message.getStatus() >= Message.STATUS_SEND + && id.equals(message.getRemoteMsgId()))) { return message; - } + } + } + } + return null; + } + + public Message findSentMessageWithUuid(String id) { + synchronized (this.messages) { + for (Message message : this.messages) { + if (id.equals(message.getUuid())) { + return message; + } } } return null; -- cgit v1.2.3 From b0c19d6bac396b5f30432a8ea5e1ef5e89a89048 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 30 Aug 2015 11:24:37 +0200 Subject: fixed bug that prevented newly opened conversations to load the entire history via mam. fixes #1328 --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index e6c044a1..1af87c42 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -673,6 +673,10 @@ public class Conversation extends AbstractEntity implements Blockable { } } + public void resetLastMessageTransmitted() { + this.setAttribute(ATTRIBUTE_LAST_MESSAGE_TRANSMITTED,String.valueOf(-1)); + } + public boolean setLastMessageTransmitted(long value) { long before = getLastMessageTransmitted(); if (value - before > 1000) { -- cgit v1.2.3 From fc594e249a89d0bd333bca1a9958a53b7640e659 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Sep 2015 22:37:52 +0200 Subject: added special error state for dns timeout --- src/main/java/eu/siacs/conversations/entities/Account.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 7a2dc3f7..002c276e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -62,7 +62,8 @@ public class Account extends AbstractEntity { REGISTRATION_SUCCESSFUL, REGISTRATION_NOT_SUPPORTED(true), SECURITY_ERROR(true), - INCOMPATIBLE_SERVER(true); + INCOMPATIBLE_SERVER(true), + DNS_TIMEOUT(true); private final boolean isError; @@ -106,6 +107,8 @@ public class Account extends AbstractEntity { return R.string.account_status_security_error; case INCOMPATIBLE_SERVER: return R.string.account_status_incompatible_server; + case DNS_TIMEOUT: + return R.string.account_status_dns_timeout; default: return R.string.account_status_unknown; } -- cgit v1.2.3 From 7eb228d1a598258fe915c6ca722b7fa1a7c49ddf Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Sep 2015 19:58:53 +0200 Subject: Issues with URLs with multiple dots in file. fixes #1373 --- .../eu/siacs/conversations/entities/Message.java | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 0eff99cf..bfb26446 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -506,17 +506,25 @@ public class Message extends AbstractEntity { private static String extractRelevantExtension(URL url) { String path = url.getPath(); + return extractRelevantExtension(path); + } + + private static String extractRelevantExtension(String path) { if (path == null || path.isEmpty()) { return null; } + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); - String[] extensionParts = filename.split("\\."); - if (extensionParts.length == 2) { - return extensionParts[extensionParts.length - 1]; - } else if (extensionParts.length == 3 && Arrays - .asList(Transferable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1])) { - return extensionParts[extensionParts.length -2]; + int dotPosition = filename.lastIndexOf("."); + + if (dotPosition != -1) { + String extension = filename.substring(dotPosition + 1); + // we want the real file extension, not the crypto one + if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) { + return extractRelevantExtension(path.substring(0,dotPosition)); + } else { + return extension; + } } return null; } -- cgit v1.2.3 From 4220fa948b731501c27e8c49774a563cbc07063a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 12 Sep 2015 10:42:56 +0200 Subject: added mp4 to well known extensions. fixes #1403 --- src/main/java/eu/siacs/conversations/entities/Transferable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Transferable.java b/src/main/java/eu/siacs/conversations/entities/Transferable.java index 2db6e3c9..016c81bd 100644 --- a/src/main/java/eu/siacs/conversations/entities/Transferable.java +++ b/src/main/java/eu/siacs/conversations/entities/Transferable.java @@ -4,7 +4,7 @@ public interface Transferable { String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; - String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a"}; + String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a","mp4"}; int STATUS_UNKNOWN = 0x200; int STATUS_CHECKING = 0x201; -- cgit v1.2.3 From 96575d6290d3fc28c79ec37c493e1062735cbf41 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 13 Sep 2015 17:13:46 +0200 Subject: added possibiltiy to set conferences as moderated (only visible in advanced mode) --- .../siacs/conversations/entities/MucOptions.java | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 52a862ef..cf49cf65 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -23,7 +23,7 @@ public class MucOptions { OUTCAST("outcast", 0, R.string.outcast), NONE("none", 1, R.string.no_affiliation); - private Affiliation(String string, int rank, int resId) { + Affiliation(String string, int rank, int resId) { this.string = string; this.resId = resId; this.rank = rank; @@ -52,18 +52,20 @@ public class MucOptions { } public enum Role { - MODERATOR("moderator", R.string.moderator), - VISITOR("visitor", R.string.visitor), - PARTICIPANT("participant", R.string.participant), - NONE("none", R.string.no_role); + MODERATOR("moderator", R.string.moderator,3), + VISITOR("visitor", R.string.visitor,1), + PARTICIPANT("participant", R.string.participant,2), + NONE("none", R.string.no_role,0); - private Role(String string, int resId) { + private Role(String string, int resId, int rank) { this.string = string; this.resId = resId; + this.rank = rank; } private String string; private int resId; + private int rank; public int getResId() { return resId; @@ -73,6 +75,10 @@ public class MucOptions { public String toString() { return this.string; } + + public boolean ranks(Role role) { + return rank >= role.rank; + } } public static final int ERROR_NO_ERROR = 0; @@ -233,6 +239,10 @@ public class MucOptions { return !membersOnly() || self.getAffiliation().ranks(Affiliation.ADMIN); } + public boolean participating() { + return !online() || self.getRole().ranks(Role.PARTICIPANT); + } + public boolean membersOnly() { return hasFeature("muc_membersonly"); } @@ -245,6 +255,10 @@ public class MucOptions { return hasFeature("muc_persistent"); } + public boolean moderated() { + return hasFeature("muc_moderated"); + } + public void deleteUser(String name) { for (int i = 0; i < users.size(); ++i) { if (users.get(i).getName().equals(name)) { -- cgit v1.2.3 From b9002d7fd5455ca2c13934748531b30a97799a9f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 15 Sep 2015 22:52:35 +0200 Subject: added missing type='submit' to mam queries fixed some nasty inheritance problems along the way fixes #1411 --- src/main/java/eu/siacs/conversations/entities/Bookmark.java | 10 +++------- .../java/eu/siacs/conversations/entities/Conversation.java | 4 ++-- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index cc6f146b..0210da24 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -50,8 +50,8 @@ public class Bookmark extends Element implements ListItem { if (this.mJoinedConversation != null && (this.mJoinedConversation.getMucOptions().getSubject() != null)) { return this.mJoinedConversation.getMucOptions().getSubject(); - } else if (getName() != null) { - return getName(); + } else if (getBookmarkName() != null) { + return getBookmarkName(); } else { return this.getJid().getLocalpart(); } @@ -134,14 +134,10 @@ public class Bookmark extends Element implements ListItem { this.mJoinedConversation = conversation; } - public String getName() { + public String getBookmarkName() { return this.getAttribute("name"); } - public void setName(String name) { - this.name = name; - } - public void unregisterConversation() { if (this.mJoinedConversation != null) { this.mJoinedConversation.deregisterWithBookmark(); diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 1af87c42..f4d116fe 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -340,8 +340,8 @@ public class Conversation extends AbstractEntity implements Blockable { if (getMode() == MODE_MULTI) { if (getMucOptions().getSubject() != null) { return getMucOptions().getSubject(); - } else if (bookmark != null && bookmark.getName() != null) { - return bookmark.getName(); + } else if (bookmark != null && bookmark.getBookmarkName() != null) { + return bookmark.getBookmarkName(); } else { String generatedName = getMucOptions().createNameFromParticipants(); if (generatedName != null) { -- cgit v1.2.3 From 5fb77a9739912c9a418b91cb2acfe54c3c88825d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 28 Sep 2015 15:36:55 +0200 Subject: fixed NPE when executing rename callback in muc --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index cf49cf65..cf078ee5 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -308,7 +308,9 @@ public class MucOptions { this.error = ERROR_NO_ERROR; self = user; if (mNickChangingInProgress) { - onRenameListener.onSuccess(); + if (onRenameListener != null) { + onRenameListener.onSuccess(); + } mNickChangingInProgress = false; } else if (this.onJoinListener != null) { this.onJoinListener.onSuccess(); -- cgit v1.2.3 From 403db3b0800ec0dcca5fd1f5c8d94ad1f8ee9e5d Mon Sep 17 00:00:00 2001 From: saqura Date: Fri, 2 Oct 2015 22:00:11 +0200 Subject: Show whether MAM is supported in MUCs The conference details in "Advanced Mode" now indicate whether MAM is supported by the conference server. --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index cf078ee5..dc070164 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -247,6 +247,11 @@ public class MucOptions { return hasFeature("muc_membersonly"); } + public boolean mamSupport() { + // Update with "urn:xmpp:mam:1" once we support it + return hasFeature("urn:xmpp:mam:0"); + } + public boolean nonanonymous() { return hasFeature("muc_nonanonymous"); } -- cgit v1.2.3 From b23cb5a9e43d804551dc18f399ffbec991479ee6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 9 Oct 2015 13:37:08 +0200 Subject: initial UI work to allow setting up accounts from certifcates --- .../java/eu/siacs/conversations/entities/Account.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 002c276e..0eb38c9f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -194,18 +194,14 @@ public class Account extends AbstractEntity { return jid.getLocalpart(); } - public void setUsername(final String username) throws InvalidJidException { - jid = Jid.fromParts(username, jid.getDomainpart(), jid.getResourcepart()); + public void setJid(final Jid jid) { + this.jid = jid; } public Jid getServer() { return jid.toDomainJid(); } - public void setServer(final String server) throws InvalidJidException { - jid = Jid.fromParts(jid.getLocalpart(), server, jid.getResourcepart()); - } - public String getPassword() { return password; } @@ -272,6 +268,14 @@ public class Account extends AbstractEntity { } } + public boolean setPrivateKeyAlias(String alias) { + return setKey("private_key_alias", alias); + } + + public String getPrivateKeyAlias() { + return getKey("private_key_alias"); + } + @Override public ContentValues getContentValues() { final ContentValues values = new ContentValues(); -- cgit v1.2.3 From 5f9476448f54113e27f04f38fd64959b13bcd97b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 14 Oct 2015 21:18:34 +0200 Subject: make unread status and notifications presistent across restarts --- .../siacs/conversations/entities/Conversation.java | 28 ++++++++++++++++------ .../eu/siacs/conversations/entities/Message.java | 16 +++++++------ 2 files changed, 30 insertions(+), 14 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f4d116fe..f2c4fed4 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -111,6 +111,16 @@ public class Conversation extends AbstractEntity implements Blockable { } } + public void findUnreadMessages(OnMessageFound onMessageFound) { + synchronized (this.messages) { + for(Message message : this.messages) { + if (!message.isRead()) { + onMessageFound.onMessageFound(message); + } + } + } + } + public void findMessagesWithFiles(final OnMessageFound onMessageFound) { synchronized (this.messages) { for (final Message message : this.messages) { @@ -266,9 +276,8 @@ public class Conversation extends AbstractEntity implements Blockable { } } - public interface OnMessageFound { - public void onMessageFound(final Message message); + void onMessageFound(final Message message); } public Conversation(final String name, final Account account, final Jid contactJid, @@ -301,13 +310,18 @@ public class Conversation extends AbstractEntity implements Blockable { return (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead(); } - public void markRead() { - for (int i = this.messages.size() - 1; i >= 0; --i) { - if (messages.get(i).isRead()) { - break; + public List markRead() { + final List unread = new ArrayList<>(); + synchronized (this.messages) { + for (int i = this.messages.size() - 1; i >= 0; --i) { + if (this.messages.get(i).isRead()) { + break; + } + this.messages.get(i).markRead(); + unread.add(this.messages.get(i)); } - this.messages.get(i).markRead(); } + return unread; } public Message getLatestMarkableMessage() { diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index bfb26446..36cc0842 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -56,6 +56,7 @@ public class Message extends AbstractEntity { public static final String SERVER_MSG_ID = "serverMsgId"; public static final String RELATIVE_FILE_PATH = "relativeFilePath"; public static final String FINGERPRINT = "axolotl_fingerprint"; + public static final String READ = "read"; public static final String ME_COMMAND = "/me "; @@ -87,11 +88,8 @@ public class Message extends AbstractEntity { public Message(Conversation conversation, String body, int encryption) { this(conversation, body, encryption, STATUS_UNSEND); } - public Message(Conversation conversation, String body, int encryption, int status) { - this(conversation, body, encryption, status, false); - } - public Message(Conversation conversation, String body, int encryption, int status, boolean carbon) { + public Message(Conversation conversation, String body, int encryption, int status) { this(java.util.UUID.randomUUID().toString(), conversation.getUuid(), conversation.getJid() == null ? null : conversation.getJid().toBareJid(), @@ -105,7 +103,8 @@ public class Message extends AbstractEntity { null, null, null, - null); + null, + true); this.conversation = conversation; } @@ -113,7 +112,7 @@ public class Message extends AbstractEntity { final Jid trueCounterpart, final String body, final long timeSent, final int encryption, final int status, final int type, final boolean carbon, final String remoteMsgId, final String relativeFilePath, - final String serverMsgId, final String fingerprint) { + final String serverMsgId, final String fingerprint, final boolean read) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -128,6 +127,7 @@ public class Message extends AbstractEntity { this.relativeFilePath = relativeFilePath; this.serverMsgId = serverMsgId; this.axolotlFingerprint = fingerprint; + this.read = read; } public static Message fromCursor(Cursor cursor) { @@ -166,7 +166,8 @@ public class Message extends AbstractEntity { cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)), cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), - cursor.getString(cursor.getColumnIndex(FINGERPRINT))); + cursor.getString(cursor.getColumnIndex(FINGERPRINT)), + cursor.getInt(cursor.getColumnIndex(READ)) > 0); } public static Message createStatusMessage(Conversation conversation, String body) { @@ -202,6 +203,7 @@ public class Message extends AbstractEntity { values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(SERVER_MSG_ID, serverMsgId); values.put(FINGERPRINT, axolotlFingerprint); + values.put(READ,read); return values; } -- cgit v1.2.3 From cfeb67d71da01bc95ed713d6591fa6e79fc08dd6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 16 Oct 2015 23:48:42 +0200 Subject: introduced code to verify omemo device keys with x509 certificates. cleaned up TrustKeysActivity to automatically close if there is nothing to do --- src/main/java/eu/siacs/conversations/entities/Account.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 0eb38c9f..ebfd9805 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -297,6 +297,9 @@ public class Account extends AbstractEntity { public void initAccountServices(final XmppConnectionService context) { this.mOtrService = new OtrService(context, this); this.axolotlService = new AxolotlService(this, context); + if (xmppConnection != null) { + xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService); + } } public OtrService getOtrService() { -- cgit v1.2.3 From 3c45f00443e56557183f94d1152a0847342db510 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 21 Oct 2015 17:41:44 +0200 Subject: fixed read conversations showing up as notifications after a restart --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f2c4fed4..5f3f1a6e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -313,12 +313,11 @@ public class Conversation extends AbstractEntity implements Blockable { public List markRead() { final List unread = new ArrayList<>(); synchronized (this.messages) { - for (int i = this.messages.size() - 1; i >= 0; --i) { - if (this.messages.get(i).isRead()) { - break; + for(Message message : this.messages) { + if (!message.isRead()) { + message.markRead(); + unread.add(message); } - this.messages.get(i).markRead(); - unread.add(this.messages.get(i)); } } return unread; -- cgit v1.2.3 From e747ecef4d6b9573be84229692ddc0cb9b2fe8e2 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Mon, 26 Oct 2015 20:13:48 -0500 Subject: Don't synchronize on non-final field --- src/main/java/eu/siacs/conversations/entities/Presences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index bccf3117..4729a11b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -15,7 +15,7 @@ public class Presences { public static final int DND = 3; public static final int OFFLINE = 4; - private Hashtable presences = new Hashtable(); + private final Hashtable presences = new Hashtable<>(); public Hashtable getPresences() { return this.presences; -- cgit v1.2.3 From 29a849cb92c0dc902acd3aa54d0d2f07583bce72 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 15 Oct 2015 23:21:47 +0100 Subject: Decrypt PGP messages in background --- src/main/java/eu/siacs/conversations/entities/Account.java | 7 +++++++ src/main/java/eu/siacs/conversations/entities/Conversation.java | 1 + 2 files changed, 8 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index ebfd9805..06f2264b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -4,6 +4,7 @@ import android.content.ContentValues; import android.database.Cursor; import android.os.SystemClock; +import eu.siacs.conversations.crypto.PgpDecryptionService; import net.java.otr4j.crypto.OtrCryptoEngineImpl; import net.java.otr4j.crypto.OtrCryptoException; @@ -127,6 +128,7 @@ public class Account extends AbstractEntity { protected boolean online = false; private OtrService mOtrService = null; private AxolotlService axolotlService = null; + private PgpDecryptionService pgpDecryptionService = null; private XmppConnection xmppConnection = null; private long mEndGracePeriod = 0L; private String otrFingerprint; @@ -300,12 +302,17 @@ public class Account extends AbstractEntity { if (xmppConnection != null) { xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService); } + this.pgpDecryptionService = new PgpDecryptionService(context); } public OtrService getOtrService() { return this.mOtrService; } + public PgpDecryptionService getPgpDecryptionService() { + return pgpDecryptionService; + } + public XmppConnection getXmppConnection() { return this.xmppConnection; } diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 5f3f1a6e..473ef0fe 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -777,6 +777,7 @@ public class Conversation extends AbstractEntity implements Blockable { synchronized (this.messages) { this.messages.addAll(index, messages); } + account.getPgpDecryptionService().addAll(messages); } public void sort() { -- cgit v1.2.3 From c7ff196f58b5576ca1aeb5fd6d51bbe500754f06 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 29 Oct 2015 13:41:08 +0100 Subject: push CN into nick pep node when uploading certificate. subscribe to nick node --- .../java/eu/siacs/conversations/entities/Account.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index ebfd9805..c5791625 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -37,6 +37,7 @@ public class Account extends AbstractEntity { public static final String ROSTERVERSION = "rosterversion"; public static final String KEYS = "keys"; public static final String AVATAR = "avatar"; + public static final String DISPLAY_NAME = "display_name"; public static final String PINNED_MECHANISM_KEY = "pinned_mechanism"; @@ -49,6 +50,14 @@ public class Account extends AbstractEntity { return xmppConnection != null && xmppConnection.getFeatures().httpUpload(); } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + public static enum State { DISABLED, OFFLINE, @@ -124,6 +133,7 @@ public class Account extends AbstractEntity { protected State status = State.OFFLINE; protected JSONObject keys = new JSONObject(); protected String avatar; + protected String displayName = null; protected boolean online = false; private OtrService mOtrService = null; private AxolotlService axolotlService = null; @@ -140,12 +150,12 @@ public class Account extends AbstractEntity { public Account(final Jid jid, final String password) { this(java.util.UUID.randomUUID().toString(), jid, - password, 0, null, "", null); + password, 0, null, "", null, null); } public Account(final String uuid, final Jid jid, final String password, final int options, final String rosterVersion, final String keys, - final String avatar) { + final String avatar, String displayName) { this.uuid = uuid; this.jid = jid; if (jid.isBareJid()) { @@ -160,6 +170,7 @@ public class Account extends AbstractEntity { this.keys = new JSONObject(); } this.avatar = avatar; + this.displayName = displayName; } public static Account fromCursor(final Cursor cursor) { @@ -175,7 +186,8 @@ public class Account extends AbstractEntity { cursor.getInt(cursor.getColumnIndex(OPTIONS)), cursor.getString(cursor.getColumnIndex(ROSTERVERSION)), cursor.getString(cursor.getColumnIndex(KEYS)), - cursor.getString(cursor.getColumnIndex(AVATAR))); + cursor.getString(cursor.getColumnIndex(AVATAR)), + cursor.getString(cursor.getColumnIndex(DISPLAY_NAME))); } public boolean isOptionSet(final int option) { @@ -287,6 +299,7 @@ public class Account extends AbstractEntity { values.put(KEYS, this.keys.toString()); values.put(ROSTERVERSION, rosterVersion); values.put(AVATAR, avatar); + values.put(DISPLAY_NAME, displayName); return values; } -- cgit v1.2.3 From bca29cf7fd6fcf7438f39d81833cda18a94eefd9 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 31 Oct 2015 10:57:57 +0100 Subject: explicitly mark verified omemo keys in UI --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 36cc0842..808bb1b6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -716,8 +716,8 @@ public class Message extends AbstractEntity { } public boolean isTrusted() { - return conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint) - == XmppAxolotlSession.Trust.TRUSTED; + XmppAxolotlSession.Trust t = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint); + return t != null && t.trusted(); } private int getPreviousEncryption() { -- cgit v1.2.3 From fac1d4e0bdfcfdf01a30f2d9f88ec2c84560e33c Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 29 Oct 2015 13:03:41 +0000 Subject: Use OpenPGP-API 9.0 --- .../eu/siacs/conversations/entities/Account.java | 38 ++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index fbee5b8a..abf0a2a5 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -127,6 +127,10 @@ public class Account extends AbstractEntity { public List pendingConferenceJoins = new CopyOnWriteArrayList<>(); public List pendingConferenceLeaves = new CopyOnWriteArrayList<>(); + + private static final String KEY_PGP_SIGNATURE = "pgp_signature"; + private static final String KEY_PGP_ID = "pgp_id"; + protected Jid jid; protected String password; protected int options = 0; @@ -371,9 +375,9 @@ public class Account extends AbstractEntity { } public String getPgpSignature() { - if (keys.has("pgp_signature")) { + if (keys.has(KEY_PGP_SIGNATURE)) { try { - return keys.getString("pgp_signature"); + return keys.getString(KEY_PGP_SIGNATURE); } catch (final JSONException e) { return null; } @@ -382,6 +386,36 @@ public class Account extends AbstractEntity { } } + public boolean setPgpSignature(String signature) { + try { + keys.put(KEY_PGP_SIGNATURE, signature); + } catch (JSONException e) { + return false; + } + return true; + } + + public long getPgpId() { + if (keys.has(KEY_PGP_ID)) { + try { + return keys.getLong(KEY_PGP_ID); + } catch (JSONException e) { + return -1; + } + } else { + return -1; + } + } + + public boolean setPgpSignId(long pgpID) { + try { + keys.put(KEY_PGP_ID, pgpID); + } catch (JSONException e) { + return false; + } + return true; + } + public Roster getRoster() { return this.roster; } -- cgit v1.2.3 From a557d38e4d0bd55442012f7f8a5be62532f7bfe9 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 25 Nov 2015 20:47:02 +0100 Subject: pgp fixes and revert configuration changes --- .../eu/siacs/conversations/entities/Message.java | 2 +- .../siacs/conversations/entities/MucOptions.java | 27 ++++------------------ 2 files changed, 5 insertions(+), 24 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 808bb1b6..1eafa45f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -523,7 +523,7 @@ public class Message extends AbstractEntity { String extension = filename.substring(dotPosition + 1); // we want the real file extension, not the crypto one if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) { - return extractRelevantExtension(path.substring(0,dotPosition)); + return extractRelevantExtension(filename.substring(0,dotPosition)); } else { return extension; } diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index dc070164..f8fb0bf4 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -107,10 +107,6 @@ public class MucOptions { } - public interface OnJoinListener extends OnEventListener { - - } - public class User { private Role role = Role.NONE; private Affiliation affiliation = Affiliation.NONE; @@ -215,7 +211,6 @@ public class MucOptions { private boolean isOnline = false; private int error = ERROR_UNKNOWN; private OnRenameListener onRenameListener = null; - private OnJoinListener onJoinListener = null; private User self = new User(); private String subject = null; private String password = null; @@ -317,9 +312,6 @@ public class MucOptions { onRenameListener.onSuccess(); } mNickChangingInProgress = false; - } else if (this.onJoinListener != null) { - this.onJoinListener.onSuccess(); - this.onJoinListener = null; } } else { addUser(user); @@ -328,14 +320,11 @@ public class MucOptions { Element signed = packet.findChild("x", "jabber:x:signed"); if (signed != null) { Element status = packet.findChild("status"); - String msg; - if (status != null) { - msg = status.getContent(); - } else { - msg = ""; + String msg = status == null ? "" : status.getContent(); + long keyId = pgp.fetchKeyId(account, msg, signed.getContent()); + if (keyId != 0) { + user.setPgpKeyId(keyId); } - user.setPgpKeyId(pgp.fetchKeyId(account, msg, - signed.getContent())); } } } @@ -381,10 +370,6 @@ public class MucOptions { private void setError(int error) { this.isOnline = false; this.error = error; - if (onJoinListener != null) { - onJoinListener.onFailure(); - onJoinListener = null; - } } private List getStatusCodes(Element x) { @@ -438,10 +423,6 @@ public class MucOptions { this.onRenameListener = listener; } - public void setOnJoinListener(OnJoinListener listener) { - this.onJoinListener = listener; - } - public void setOffline() { this.users.clear(); this.error = 0; -- cgit v1.2.3 From fd6ed5b98984fa09f98b78cbe3e782a497c62c19 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 1 Nov 2015 14:50:06 +0100 Subject: detect server identity and added muc-workaround for slack --- src/main/java/eu/siacs/conversations/entities/Account.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index abf0a2a5..b02db812 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -59,6 +59,14 @@ public class Account extends AbstractEntity { return displayName; } + public XmppConnection.Identity getServerIdentity() { + if (xmppConnection == null) { + return XmppConnection.Identity.UNKNOWN; + } else { + return xmppConnection.getServerIdentity(); + } + } + public static enum State { DISABLED, OFFLINE, -- cgit v1.2.3 From 60211a315ee8cf83a6b87836c30abc28e4dec272 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 26 Nov 2015 17:44:29 +0100 Subject: hide subject edit button if not editable by user --- .../siacs/conversations/entities/MucOptions.java | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index f8fb0bf4..13a5bb9f 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -9,6 +9,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.forms.Data; +import eu.siacs.conversations.xmpp.forms.Field; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; @@ -207,6 +209,7 @@ public class MucOptions { private Account account; private List users = new CopyOnWriteArrayList<>(); private List features = new ArrayList<>(); + private Data form = new Data(); private Conversation conversation; private boolean isOnline = false; private int error = ERROR_UNKNOWN; @@ -226,12 +229,22 @@ public class MucOptions { this.features.addAll(features); } + public void updateFormData(Data form) { + this.form = form; + } + public boolean hasFeature(String feature) { return this.features.contains(feature); } public boolean canInvite() { - return !membersOnly() || self.getAffiliation().ranks(Affiliation.ADMIN); + Field field = this.form.getFieldByName("muc#roomconfig_allowinvites"); + return !membersOnly() || self.getRole().ranks(Role.MODERATOR) || (field != null && "1".equals(field.getValue())); + } + + public boolean canChangeSubject() { + Field field = this.form.getFieldByName("muc#roomconfig_changesubject"); + return self.getRole().ranks(Role.MODERATOR) || (field != null && "1".equals(field.getValue())); } public boolean participating() { @@ -472,11 +485,12 @@ public class MucOptions { ids.add(user.getPgpKeyId()); } } - long[] primitivLongArray = new long[ids.size()]; + ids.add(account.getPgpId()); + long[] primitiveLongArray = new long[ids.size()]; for (int i = 0; i < ids.size(); ++i) { - primitivLongArray[i] = ids.get(i); + primitiveLongArray[i] = ids.get(i); } - return primitivLongArray; + return primitiveLongArray; } public boolean pgpKeysInUse() { -- cgit v1.2.3 From f0b1761ec3826b72fe3b20032b532dc5b1adfc1c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 28 Nov 2015 20:11:38 +0100 Subject: initial tor support --- .../eu/siacs/conversations/entities/Account.java | 50 ++++++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index b02db812..3aa1675f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -2,6 +2,8 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; +import android.os.Bundle; +import android.os.Parcelable; import android.os.SystemClock; import eu.siacs.conversations.crypto.PgpDecryptionService; @@ -13,6 +15,7 @@ import org.json.JSONObject; import java.security.PublicKey; import java.security.interfaces.DSAPublicKey; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -39,6 +42,8 @@ public class Account extends AbstractEntity { public static final String KEYS = "keys"; public static final String AVATAR = "avatar"; public static final String DISPLAY_NAME = "display_name"; + public static final String HOSTNAME = "hostname"; + public static final String PORT = "port"; public static final String PINNED_MECHANISM_KEY = "pinned_mechanism"; @@ -67,7 +72,20 @@ public class Account extends AbstractEntity { } } - public static enum State { + public ArrayList getHostnamePortBundles() { + ArrayList values = new ArrayList<>(); + Bundle hostPort = new Bundle(); + if (hostname != null && !hostname.isEmpty()) { + hostPort.putString("name", hostname); + } else { + hostPort.putString("name", getServer().toString()); + } + hostPort.putInt("port", port); + values.add(hostPort); + return values; + } + + public enum State { DISABLED, OFFLINE, CONNECTING, @@ -147,6 +165,8 @@ public class Account extends AbstractEntity { protected JSONObject keys = new JSONObject(); protected String avatar; protected String displayName = null; + protected String hostname = null; + protected int port = 5222; protected boolean online = false; private OtrService mOtrService = null; private AxolotlService axolotlService = null; @@ -164,12 +184,12 @@ public class Account extends AbstractEntity { public Account(final Jid jid, final String password) { this(java.util.UUID.randomUUID().toString(), jid, - password, 0, null, "", null, null); + password, 0, null, "", null, null, null, 5222); } public Account(final String uuid, final Jid jid, final String password, final int options, final String rosterVersion, final String keys, - final String avatar, String displayName) { + final String avatar, String displayName, String hostname, int port) { this.uuid = uuid; this.jid = jid; if (jid.isBareJid()) { @@ -185,6 +205,8 @@ public class Account extends AbstractEntity { } this.avatar = avatar; this.displayName = displayName; + this.hostname = hostname; + this.port = port; } public static Account fromCursor(final Cursor cursor) { @@ -201,7 +223,9 @@ public class Account extends AbstractEntity { cursor.getString(cursor.getColumnIndex(ROSTERVERSION)), cursor.getString(cursor.getColumnIndex(KEYS)), cursor.getString(cursor.getColumnIndex(AVATAR)), - cursor.getString(cursor.getColumnIndex(DISPLAY_NAME))); + cursor.getString(cursor.getColumnIndex(DISPLAY_NAME)), + cursor.getString(cursor.getColumnIndex(HOSTNAME)), + cursor.getInt(cursor.getColumnIndex(PORT))); } public boolean isOptionSet(final int option) { @@ -236,6 +260,22 @@ public class Account extends AbstractEntity { this.password = password; } + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public String getHostname() { + return this.hostname == null ? "" : this.hostname; + } + + public void setPort(int port) { + this.port = port; + } + + public int getPort() { + return this.port; + } + public State getStatus() { if (isOptionSet(OPTION_DISABLED)) { return State.DISABLED; @@ -314,6 +354,8 @@ public class Account extends AbstractEntity { values.put(ROSTERVERSION, rosterVersion); values.put(AVATAR, avatar); values.put(DISPLAY_NAME, displayName); + values.put(HOSTNAME, hostname); + values.put(PORT, port); return values; } -- cgit v1.2.3 From ebccb67a7208042ca8362ae326b6b75369d61d12 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 29 Nov 2015 15:44:45 +0100 Subject: do socks5 connect manually --- .../eu/siacs/conversations/entities/Account.java | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 3aa1675f..062c0d25 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -2,8 +2,6 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; -import android.os.Bundle; -import android.os.Parcelable; import android.os.SystemClock; import eu.siacs.conversations.crypto.PgpDecryptionService; @@ -15,7 +13,6 @@ import org.json.JSONObject; import java.security.PublicKey; import java.security.interfaces.DSAPublicKey; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -72,19 +69,6 @@ public class Account extends AbstractEntity { } } - public ArrayList getHostnamePortBundles() { - ArrayList values = new ArrayList<>(); - Bundle hostPort = new Bundle(); - if (hostname != null && !hostname.isEmpty()) { - hostPort.putString("name", hostname); - } else { - hostPort.putString("name", getServer().toString()); - } - hostPort.putInt("port", port); - values.add(hostPort); - return values; - } - public enum State { DISABLED, OFFLINE, @@ -268,6 +252,10 @@ public class Account extends AbstractEntity { return this.hostname == null ? "" : this.hostname; } + public boolean isOnion() { + return getServer().toString().toLowerCase().endsWith(".onion"); + } + public void setPort(int port) { this.port = port; } -- cgit v1.2.3 From 2225b0b6d5586d608b15d4e1ac13faa99b8971bf Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 30 Nov 2015 16:01:48 +0100 Subject: add error state for unavailable tor network --- src/main/java/eu/siacs/conversations/entities/Account.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 062c0d25..75e6b2a0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -83,7 +83,7 @@ public class Account extends AbstractEntity { REGISTRATION_NOT_SUPPORTED(true), SECURITY_ERROR(true), INCOMPATIBLE_SERVER(true), - DNS_TIMEOUT(true); + TOR_NOT_AVAILABLE(true); private final boolean isError; @@ -127,8 +127,8 @@ public class Account extends AbstractEntity { return R.string.account_status_security_error; case INCOMPATIBLE_SERVER: return R.string.account_status_incompatible_server; - case DNS_TIMEOUT: - return R.string.account_status_dns_timeout; + case TOR_NOT_AVAILABLE: + return R.string.account_status_tor_unavailable; default: return R.string.account_status_unknown; } -- cgit v1.2.3 From dc8967d8fc09a5b7e515bb5005726d677a08c86b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Dec 2015 22:41:58 +0100 Subject: introduced build-time paranoia mode that disables unencrypted chats and forces TOR --- .../java/eu/siacs/conversations/entities/Conversation.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 473ef0fe..e93d5564 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -612,9 +612,16 @@ public class Conversation extends AbstractEntity implements Blockable { if (next == -1) { int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); if (outgoing == Message.ENCRYPTION_NONE) { - return this.getMostRecentlyUsedIncomingEncryption(); + next = this.getMostRecentlyUsedIncomingEncryption(); } else { - return outgoing; + next = outgoing; + } + } + if (Config.PARANOID_MODE && mode == MODE_SINGLE && next <= 0) { + if (getAccount().getAxolotlService().isContactAxolotlCapable(getContact())) { + return Message.ENCRYPTION_AXOLOTL; + } else { + return Message.ENCRYPTION_OTR; } } return next; -- cgit v1.2.3 From a3eb540f059f9123799c54d69201eba8a096e116 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Wed, 4 Nov 2015 20:56:45 -0600 Subject: Show status message when contact requests presence Remove presence when conversation closed --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 1eafa45f..b59b0b38 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -171,7 +171,7 @@ public class Message extends AbstractEntity { } public static Message createStatusMessage(Conversation conversation, String body) { - Message message = new Message(); + final Message message = new Message(); message.setType(Message.TYPE_STATUS); message.setConversation(conversation); message.setBody(body); -- cgit v1.2.3 From e5f154316cbfa1d701947fae8bc31239df37531a Mon Sep 17 00:00:00 2001 From: fiaxh Date: Wed, 2 Dec 2015 15:43:55 +0000 Subject: Unset all PGP signatures once ... so they will be redone to match the changed status. --- .../java/eu/siacs/conversations/entities/Account.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 75e6b2a0..64bbaa2b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -413,13 +413,13 @@ public class Account extends AbstractEntity { } public String getPgpSignature() { - if (keys.has(KEY_PGP_SIGNATURE)) { - try { + try { + if (keys.has(KEY_PGP_SIGNATURE) && !"null".equals(keys.getString(KEY_PGP_SIGNATURE))) { return keys.getString(KEY_PGP_SIGNATURE); - } catch (final JSONException e) { + } else { return null; } - } else { + } catch (final JSONException e) { return null; } } @@ -433,6 +433,15 @@ public class Account extends AbstractEntity { return true; } + public boolean unsetPgpSignature() { + try { + keys.put(KEY_PGP_SIGNATURE, JSONObject.NULL); + } catch (JSONException e) { + return false; + } + return true; + } + public long getPgpId() { if (keys.has(KEY_PGP_ID)) { try { -- cgit v1.2.3 From 6b592435cd7bc831f0aac1bb159229dae955fb9b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 3 Dec 2015 18:18:34 +0100 Subject: parse vcard avatars from muc presences --- .../siacs/conversations/entities/MucOptions.java | 277 +++++++++------------ 1 file changed, 122 insertions(+), 155 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 13a5bb9f..412f984f 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -4,20 +4,25 @@ import android.annotation.SuppressLint; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import eu.siacs.conversations.R; -import eu.siacs.conversations.crypto.PgpEngine; -import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.forms.Field; 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.pep.Avatar; @SuppressLint("DefaultLocale") public class MucOptions { + public Account getAccount() { + return this.conversation.getAccount(); + } + + public void setSelf(User user) { + this.self = user; + } + public enum Affiliation { OWNER("owner", 4, R.string.owner), ADMIN("admin", 3, R.string.admin), @@ -100,28 +105,31 @@ public class MucOptions { public static final String STATUS_CODE_LOST_MEMBERSHIP = "321"; private interface OnEventListener { - public void onSuccess(); + void onSuccess(); - public void onFailure(); + void onFailure(); } public interface OnRenameListener extends OnEventListener { } - public class User { + public static class User { private Role role = Role.NONE; private Affiliation affiliation = Affiliation.NONE; - private String name; private Jid jid; + private Jid fullJid; private long pgpKeyId = 0; + private Avatar avatar; + private MucOptions options; - public String getName() { - return name; + public User(MucOptions options, Jid from) { + this.options = options; + this.fullJid = from; } - public void setName(String user) { - this.name = user; + public String getName() { + return this.fullJid.getResourcepart(); } public void setJid(Jid jid) { @@ -162,7 +170,7 @@ public class MucOptions { return false; } else { User o = (User) other; - return name != null && name.equals(o.name) + return getName() != null && getName().equals(o.getName()) && jid != null && jid.equals(o.jid) && affiliation == o.affiliation && role == o.role; @@ -202,26 +210,43 @@ public class MucOptions { } public Contact getContact() { - return account.getRoster().getContactFromRoster(getJid()); + return getAccount().getRoster().getContactFromRoster(getJid()); + } + + public void setAvatar(Avatar avatar) { + this.avatar = avatar; + } + + public String getAvatar() { + return avatar == null ? null : avatar.getFilename(); + } + + public Account getAccount() { + return options.getAccount(); + } + + public Jid getFullJid() { + return fullJid; } } private Account account; - private List users = new CopyOnWriteArrayList<>(); + private final List users = new ArrayList<>(); private List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; private boolean isOnline = false; private int error = ERROR_UNKNOWN; - private OnRenameListener onRenameListener = null; - private User self = new User(); + public OnRenameListener onRenameListener = null; + private User self; private String subject = null; private String password = null; - private boolean mNickChangingInProgress = false; + public boolean mNickChangingInProgress = false; public MucOptions(Conversation conversation) { this.account = conversation.getAccount(); this.conversation = conversation; + this.self = new User(this,conversation.getJid()); } public void updateFeatures(ArrayList features) { @@ -273,135 +298,67 @@ public class MucOptions { } public void deleteUser(String name) { - for (int i = 0; i < users.size(); ++i) { - if (users.get(i).getName().equals(name)) { - users.remove(i); - return; + synchronized (this.users) { + for (int i = 0; i < users.size(); ++i) { + if (users.get(i).getName().equals(name)) { + users.remove(i); + return; + } } } } public void addUser(User user) { - for (int i = 0; i < users.size(); ++i) { - if (users.get(i).getName().equals(user.getName())) { - users.set(i, user); - return; + synchronized (this.users) { + for (int i = 0; i < users.size(); ++i) { + if (users.get(i).getName().equals(user.getName())) { + users.set(i, user); + return; + } } + users.add(user); } - users.add(user); } - public boolean isUserInRoom(String name) { - for (int i = 0; i < users.size(); ++i) { - if (users.get(i).getName().equals(name)) { - return true; - } + public User findUser(String name) { + if (name == null) { + return null; } - return false; - } - - public void processPacket(PresencePacket packet, PgpEngine pgp) { - final Jid from = packet.getFrom(); - if (!from.isBareJid()) { - final String name = from.getResourcepart(); - final String type = packet.getAttribute("type"); - final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user"); - final List codes = getStatusCodes(x); - if (type == null) { - User user = new User(); - if (x != null) { - Element item = x.findChild("item"); - if (item != null && name != null) { - user.setName(name); - user.setAffiliation(item.getAttribute("affiliation")); - user.setRole(item.getAttribute("role")); - user.setJid(item.getAttributeAsJid("jid")); - if (codes.contains(STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(this.conversation.getJid())) { - this.isOnline = true; - this.error = ERROR_NO_ERROR; - self = user; - if (mNickChangingInProgress) { - if (onRenameListener != null) { - onRenameListener.onSuccess(); - } - mNickChangingInProgress = false; - } - } else { - addUser(user); - } - if (pgp != null) { - Element signed = packet.findChild("x", "jabber:x:signed"); - if (signed != null) { - Element status = packet.findChild("status"); - String msg = status == null ? "" : status.getContent(); - long keyId = pgp.fetchKeyId(account, msg, signed.getContent()); - if (keyId != 0) { - user.setPgpKeyId(keyId); - } - } - } - } - } - } else if (type.equals("unavailable")) { - if (codes.contains(STATUS_CODE_SELF_PRESENCE) || - packet.getFrom().equals(this.conversation.getJid())) { - if (codes.contains(STATUS_CODE_CHANGED_NICK)) { - this.mNickChangingInProgress = true; - } else if (codes.contains(STATUS_CODE_KICKED)) { - setError(KICKED_FROM_ROOM); - } else if (codes.contains(STATUS_CODE_BANNED)) { - setError(ERROR_BANNED); - } else if (codes.contains(STATUS_CODE_LOST_MEMBERSHIP)) { - setError(ERROR_MEMBERS_ONLY); - } else { - setError(ERROR_UNKNOWN); - } - } else { - deleteUser(name); - } - } else if (type.equals("error")) { - Element error = packet.findChild("error"); - if (error != null && error.hasChild("conflict")) { - if (isOnline) { - if (onRenameListener != null) { - onRenameListener.onFailure(); - } - } else { - setError(ERROR_NICK_IN_USE); - } - } else if (error != null && error.hasChild("not-authorized")) { - setError(ERROR_PASSWORD_REQUIRED); - } else if (error != null && error.hasChild("forbidden")) { - setError(ERROR_BANNED); - } else if (error != null && error.hasChild("registration-required")) { - setError(ERROR_MEMBERS_ONLY); + synchronized (this.users) { + for (User user : users) { + if (user.getName().equals(name)) { + return user; } } } + return null; } - private void setError(int error) { - this.isOnline = false; + public boolean isUserInRoom(String name) { + return findUser(name) != null; + } + + public void setError(int error) { + this.isOnline = error == ERROR_NO_ERROR; this.error = error; } - private List getStatusCodes(Element x) { - List codes = new ArrayList<>(); - if (x != null) { - for (Element child : x.getChildren()) { - if (child.getName().equals("status")) { - String code = child.getAttribute("code"); - if (code != null) { - codes.add(code); - } - } - } + public ArrayList getUsers() { + synchronized (this.users) { + return new ArrayList(this.users); } - return codes; } - public List getUsers() { - return this.users; + public List getUsers(int max) { + synchronized (this.users) { + return new ArrayList<>(users.subList(0,Math.min(users.size(),5))); + } + } + + public int getUserCount() { + synchronized (this.users) { + return this.users.size(); + } } public String getProposedNick() { @@ -455,34 +412,38 @@ public class MucOptions { } public String createNameFromParticipants() { - if (users.size() >= 2) { - List names = new ArrayList(); - for (User user : users) { - Contact contact = user.getContact(); - if (contact != null && !contact.getDisplayName().isEmpty()) { - names.add(contact.getDisplayName().split("\\s+")[0]); - } else { - names.add(user.getName()); + synchronized (this.users) { + if (users.size() >= 2) { + List names = new ArrayList(); + for (User user : users) { + Contact contact = user.getContact(); + if (contact != null && !contact.getDisplayName().isEmpty()) { + names.add(contact.getDisplayName().split("\\s+")[0]); + } else { + names.add(user.getName()); + } } - } - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < names.size(); ++i) { - builder.append(names.get(i)); - if (i != names.size() - 1) { - builder.append(", "); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < names.size(); ++i) { + builder.append(names.get(i)); + if (i != names.size() - 1) { + builder.append(", "); + } } + return builder.toString(); + } else { + return null; } - return builder.toString(); - } else { - return null; } } public long[] getPgpKeyIds() { List ids = new ArrayList<>(); - for (User user : getUsers()) { - if (user.getPgpKeyId() != 0) { - ids.add(user.getPgpKeyId()); + synchronized (this.users) { + for (User user : this.users) { + if (user.getPgpKeyId() != 0) { + ids.add(user.getPgpKeyId()); + } } } ids.add(account.getPgpId()); @@ -494,18 +455,22 @@ public class MucOptions { } public boolean pgpKeysInUse() { - for (User user : getUsers()) { - if (user.getPgpKeyId() != 0) { - return true; + synchronized (this.users) { + for (User user : this.users) { + if (user.getPgpKeyId() != 0) { + return true; + } } } return false; } public boolean everybodyHasKeys() { - for (User user : getUsers()) { - if (user.getPgpKeyId() == 0) { - return false; + synchronized (this.users) { + for (User user : this.users) { + if (user.getPgpKeyId() == 0) { + return false; + } } } return true; @@ -520,9 +485,11 @@ public class MucOptions { } public Jid getTrueCounterpart(String counterpart) { - for (User user : this.getUsers()) { - if (user.getName().equals(counterpart)) { - return user.getJid(); + synchronized (this.users) { + for (User user : this.users) { + if (user.getName().equals(counterpart)) { + return user.getJid(); + } } } return null; -- cgit v1.2.3 From 242887447c09846f8b4eaeb8a29406e5135ec906 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Dec 2015 14:07:16 +0100 Subject: use proposed nick as default nick in mucoptions --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 412f984f..92254b90 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -246,7 +246,7 @@ public class MucOptions { public MucOptions(Conversation conversation) { this.account = conversation.getAccount(); this.conversation = conversation; - this.self = new User(this,conversation.getJid()); + this.self = new User(this,createJoinJid(getProposedNick())); } public void updateFeatures(ArrayList features) { -- cgit v1.2.3 From 3e3cb047be7f63233f766a022e9cf9ba8827094d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Dec 2015 15:34:45 +0100 Subject: rely on message id if message id is uuid and pgp encryption was used to deduplicate messages. fixes #1357 --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index b59b0b38..4a49d1b3 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -361,7 +361,9 @@ public class Message extends AbstractEntity { if (message.getRemoteMsgId() != null) { return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) && this.counterpart.equals(message.getCounterpart()) - && body.equals(otherBody); + && (body.equals(otherBody) + ||(message.getEncryption() == Message.ENCRYPTION_PGP + && message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ; } else { return this.remoteMsgId == null && this.counterpart.equals(message.getCounterpart()) -- cgit v1.2.3 From cd9a29718bcf961cdae2bb88ad65066e7347bfb5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Dec 2015 21:36:48 +0100 Subject: properly clear muc user avatar caches --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 92254b90..853a8408 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -213,8 +213,13 @@ public class MucOptions { return getAccount().getRoster().getContactFromRoster(getJid()); } - public void setAvatar(Avatar avatar) { - this.avatar = avatar; + public boolean setAvatar(Avatar avatar) { + if (this.avatar != null && this.avatar.equals(avatar)) { + return false; + } else { + this.avatar = avatar; + return true; + } } public String getAvatar() { -- cgit v1.2.3 From 11e58607c93f152aad82cfe7951355e03274bf47 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 9 Dec 2015 10:30:26 +0100 Subject: when no avatar found show avatar of contact and not the muc user in conferences --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 853a8408..014a4c98 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -302,15 +302,15 @@ public class MucOptions { return hasFeature("muc_moderated"); } - public void deleteUser(String name) { + public User deleteUser(String name) { synchronized (this.users) { for (int i = 0; i < users.size(); ++i) { if (users.get(i).getName().equals(name)) { - users.remove(i); - return; + return users.remove(i); } } } + return null; } public void addUser(User user) { -- cgit v1.2.3 From 293e820a5857ffff5301babc43fc08120a35385c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 11 Dec 2015 13:52:04 +0100 Subject: get rid of lastMessageTransmitted in favor of db query --- .../siacs/conversations/entities/Conversation.java | 30 +++++----------------- 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index e93d5564..8b7aa894 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -46,7 +46,6 @@ public class Conversation extends AbstractEntity implements Blockable { public static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption"; public static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; public static final String ATTRIBUTE_MUTED_TILL = "muted_till"; - public static final String ATTRIBUTE_LAST_MESSAGE_TRANSMITTED = "last_message_transmitted"; private String name; private String contactUuid; @@ -693,33 +692,16 @@ public class Conversation extends AbstractEntity implements Blockable { } } - public void resetLastMessageTransmitted() { - this.setAttribute(ATTRIBUTE_LAST_MESSAGE_TRANSMITTED,String.valueOf(-1)); - } - - public boolean setLastMessageTransmitted(long value) { - long before = getLastMessageTransmitted(); - if (value - before > 1000) { - this.setAttribute(ATTRIBUTE_LAST_MESSAGE_TRANSMITTED, String.valueOf(value)); - return true; - } else { - return false; - } - } - public long getLastMessageTransmitted() { - long timestamp = getLongAttribute(ATTRIBUTE_LAST_MESSAGE_TRANSMITTED,0); - if (timestamp == 0) { - synchronized (this.messages) { - for(int i = this.messages.size() - 1; i >= 0; --i) { - Message message = this.messages.get(i); - if (message.getStatus() == Message.STATUS_RECEIVED) { - return message.getTimeSent(); - } + synchronized (this.messages) { + for(int i = this.messages.size() - 1; i >= 0; --i) { + Message message = this.messages.get(i); + if (message.getStatus() == Message.STATUS_RECEIVED || message.isCarbon()) { + return message.getTimeSent(); } } } - return timestamp; + return 0; } public void setMutedTill(long value) { -- cgit v1.2.3 From b2c278c91bc2a733dcb807d7eb7f0d3e7145d9c2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 11 Dec 2015 19:28:44 +0100 Subject: set bookmark name to room subject if no subject has been set before --- src/main/java/eu/siacs/conversations/entities/Bookmark.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index 0210da24..acb4bf1a 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -138,6 +138,16 @@ public class Bookmark extends Element implements ListItem { return this.getAttribute("name"); } + public boolean setBookmarkName(String name) { + String before = getBookmarkName(); + if (name != null && !name.equals(before)) { + this.setAttribute("name", name); + return true; + } else { + return false; + } + } + public void unregisterConversation() { if (this.mJoinedConversation != null) { this.mJoinedConversation.deregisterWithBookmark(); -- cgit v1.2.3 From f6b22dad2032453bd2e1157488b142af1a86d413 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 14 Dec 2015 10:54:55 +0100 Subject: splite PARANOIA_MODE into three different options --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 8b7aa894..a085f0c0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -616,7 +616,7 @@ public class Conversation extends AbstractEntity implements Blockable { next = outgoing; } } - if (Config.PARANOID_MODE && mode == MODE_SINGLE && next <= 0) { + if (Config.FORCE_ENCRYPTION && mode == MODE_SINGLE && next <= 0) { if (getAccount().getAxolotlService().isContactAxolotlCapable(getContact())) { return Message.ENCRYPTION_AXOLOTL; } else { -- cgit v1.2.3 From f05f97251c9a3129db315009cd24759fb2ecd7c0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 19 Dec 2015 12:43:09 +0100 Subject: prefer server name over address book name when x509 verification is being used --- src/main/java/eu/siacs/conversations/entities/Contact.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index f924c05a..ecba70a7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -104,10 +105,12 @@ public class Contact implements ListItem, Blockable { } public String getDisplayName() { - if (this.systemName != null) { + if (this.systemName != null && !Config.X509_VERIFICATION) { return this.systemName; } else if (this.serverName != null) { return this.serverName; + } else if (this.systemName != null) { + return this.systemName; } else if (this.presenceName != null) { return this.presenceName; } else if (jid.hasLocalpart()) { -- cgit v1.2.3 From e8bf5cada4dcbd65bbd7f51ebd7233dbfaad1881 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 19 Dec 2015 12:44:12 +0100 Subject: only offer plain and omemo encryption when x509 verification is enabled --- .../java/eu/siacs/conversations/entities/Conversation.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index a085f0c0..962ad13b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -20,6 +20,7 @@ import java.util.Iterator; import java.util.List; import eu.siacs.conversations.Config; +import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -607,6 +608,14 @@ public class Conversation extends AbstractEntity implements Blockable { } public int getNextEncryption() { + final AxolotlService axolotlService = getAccount().getAxolotlService(); + if (Config.X509_VERIFICATION && mode == MODE_SINGLE) { + if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { + return Message.ENCRYPTION_AXOLOTL; + } else { + return Message.ENCRYPTION_NONE; + } + } int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1); if (next == -1) { int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); @@ -617,7 +626,7 @@ public class Conversation extends AbstractEntity implements Blockable { } } if (Config.FORCE_ENCRYPTION && mode == MODE_SINGLE && next <= 0) { - if (getAccount().getAxolotlService().isContactAxolotlCapable(getContact())) { + if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { return Message.ENCRYPTION_AXOLOTL; } else { return Message.ENCRYPTION_OTR; -- cgit v1.2.3 From ade89beb9647f753ebe7382b1b07bcfb3b688798 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 19 Dec 2015 13:07:38 +0100 Subject: use presence name not server name when verification is being used --- src/main/java/eu/siacs/conversations/entities/Contact.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index ecba70a7..c2d8b278 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -105,12 +105,12 @@ public class Contact implements ListItem, Blockable { } public String getDisplayName() { - if (this.systemName != null && !Config.X509_VERIFICATION) { + if (this.presenceName != null && Config.X509_VERIFICATION) { + return this.presenceName; + } else if (this.systemName != null) { return this.systemName; } else if (this.serverName != null) { return this.serverName; - } else if (this.systemName != null) { - return this.systemName; } else if (this.presenceName != null) { return this.presenceName; } else if (jid.hasLocalpart()) { -- cgit v1.2.3 From bcf99db3df27c196caba823b08fb55cf196dc9c8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 27 Dec 2015 17:29:19 +0100 Subject: fixed stuck at omemo encryption when x509 verification is being used --- .../java/eu/siacs/conversations/entities/Conversation.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 962ad13b..7793cc23 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -609,15 +609,15 @@ public class Conversation extends AbstractEntity implements Blockable { public int getNextEncryption() { final AxolotlService axolotlService = getAccount().getAxolotlService(); - if (Config.X509_VERIFICATION && mode == MODE_SINGLE) { - if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { - return Message.ENCRYPTION_AXOLOTL; - } else { - return Message.ENCRYPTION_NONE; - } - } int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1); if (next == -1) { + if (Config.X509_VERIFICATION && mode == MODE_SINGLE) { + if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { + return Message.ENCRYPTION_AXOLOTL; + } else { + return Message.ENCRYPTION_NONE; + } + } int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); if (outgoing == Message.ENCRYPTION_NONE) { next = this.getMostRecentlyUsedIncomingEncryption(); -- cgit v1.2.3 From fdb6b0e30d7cc5a90e4bad181ddc89acf4a2e4fa Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 4 Jan 2016 15:33:11 +0100 Subject: only report error after third unsuccesful attempt to connect --- src/main/java/eu/siacs/conversations/entities/Account.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 64bbaa2b..46865a6f 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -281,7 +281,7 @@ public class Account extends AbstractEntity { } public boolean hasErrorStatus() { - return getXmppConnection() != null && getStatus().isError() && getXmppConnection().getAttempt() >= 2; + return getXmppConnection() != null && getStatus().isError() && getXmppConnection().getAttempt() >= 3; } public String getResource() { -- cgit v1.2.3 From 62d0eebe5cfa07bf17dff7f0476428ae649d53ff Mon Sep 17 00:00:00 2001 From: fiaxh Date: Tue, 5 Jan 2016 20:07:29 +0100 Subject: Correct uuid check according to RFC 4122 --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 4a49d1b3..c5831e7e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -363,7 +363,7 @@ public class Message extends AbstractEntity { && this.counterpart.equals(message.getCounterpart()) && (body.equals(otherBody) ||(message.getEncryption() == Message.ENCRYPTION_PGP - && message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ; + && message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ; } else { return this.remoteMsgId == null && this.counterpart.equals(message.getCounterpart()) -- cgit v1.2.3 From c59eb75a59d2fbddea2a42e7d2435e7312f5c759 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 6 Jan 2016 12:59:13 +0100 Subject: avoid duplicate messages when sending files to mucs. fixes #1635 --- .../java/eu/siacs/conversations/entities/Conversation.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 7793cc23..f34641ab 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -693,8 +693,16 @@ public class Conversation extends AbstractEntity implements Blockable { synchronized (this.messages) { for (int i = this.messages.size() - 1; i >= 0; --i) { Message message = this.messages.get(i); - if ((message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_SEND) && message.getBody() != null && message.getBody().equals(body)) { - return message; + if (message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_SEND) { + String otherBody; + if (message.hasFileOnRemoteHost()) { + otherBody = message.getFileParams().url.toString(); + } else { + otherBody = message.body; + } + if (otherBody != null && otherBody.equals(body)) { + return message; + } } } return null; -- cgit v1.2.3 From a3e136b5504641f9782b9d94e35311dad19fbc1d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 8 Jan 2016 21:30:46 +0100 Subject: show per conference notification settings in details activity --- .../eu/siacs/conversations/entities/Conversation.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f34641ab..43012976 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -47,6 +47,7 @@ public class Conversation extends AbstractEntity implements Blockable { public static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption"; public static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; public static final String ATTRIBUTE_MUTED_TILL = "muted_till"; + public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify"; private String name; private String contactUuid; @@ -546,7 +547,7 @@ public class Conversation extends AbstractEntity implements Blockable { /** * short for is Private and Non-anonymous */ - public boolean isPnNA() { + private boolean isPnNA() { return mode == MODE_SINGLE || (getMucOptions().membersOnly() && getMucOptions().nonanonymous()); } @@ -729,6 +730,10 @@ public class Conversation extends AbstractEntity implements Blockable { return System.currentTimeMillis() < this.getLongAttribute(ATTRIBUTE_MUTED_TILL, 0); } + public boolean alwaysNotify() { + return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY,isPnNA()); + } + public boolean setAttribute(String key, String value) { try { this.attributes.put(key, value); @@ -772,6 +777,15 @@ public class Conversation extends AbstractEntity implements Blockable { } } + public boolean getBooleanAttribute(String key, boolean defaultValue) { + String value = this.getAttribute(key); + if (value == null) { + return defaultValue; + } else { + return Boolean.parseBoolean(value); + } + } + public void add(Message message) { message.setConversation(this); synchronized (this.messages) { -- cgit v1.2.3 From 6acb80a83ad6561dea5e14de6d2c514748be303f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 8 Jan 2016 22:07:23 +0100 Subject: added Config.java variable to change the default notification behaviour to always --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 43012976..dea9d661 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -731,7 +731,7 @@ public class Conversation extends AbstractEntity implements Blockable { } public boolean alwaysNotify() { - return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY,isPnNA()); + return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY,Config.ALWAYS_NOTIFY_BY_DEFAULT || isPnNA()); } public boolean setAttribute(String key, String value) { -- cgit v1.2.3 From 41ae4af1b812f76d1ba13d7c1f99e0f6ec80705b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 16 Jan 2016 18:57:47 +0100 Subject: made constructor private in Account entity --- src/main/java/eu/siacs/conversations/entities/Account.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 46865a6f..4abfc801 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -162,16 +162,12 @@ public class Account extends AbstractEntity { private List bookmarks = new CopyOnWriteArrayList<>(); private final Collection blocklist = new CopyOnWriteArraySet<>(); - public Account() { - this.uuid = "0"; - } - public Account(final Jid jid, final String password) { this(java.util.UUID.randomUUID().toString(), jid, password, 0, null, "", null, null, null, 5222); } - public Account(final String uuid, final Jid jid, + private Account(final String uuid, final Jid jid, final String password, final int options, final String rosterVersion, final String keys, final String avatar, String displayName, String hostname, int port) { this.uuid = uuid; -- cgit v1.2.3 From 40005cec1b1a864c529ead082a6e41a1471c874c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 22 Jan 2016 11:20:31 +0100 Subject: added config variable to allow non-tls connections --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index dea9d661..22607fc6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -626,7 +626,7 @@ public class Conversation extends AbstractEntity implements Blockable { next = outgoing; } } - if (Config.FORCE_ENCRYPTION && mode == MODE_SINGLE && next <= 0) { + if (Config.FORCE_E2E_ENCRYPTION && mode == MODE_SINGLE && next <= 0) { if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { return Message.ENCRYPTION_AXOLOTL; } else { -- cgit v1.2.3 From 28ebf927fb6cadc64a4f138cb84bac91c9903fdf Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Jan 2016 12:09:31 +0100 Subject: try to make in-valid-session detection work for pgp --- src/main/java/eu/siacs/conversations/entities/Message.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index c5831e7e..f3d891e8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -743,13 +743,20 @@ public class Message extends AbstractEntity { } public boolean isValidInSession() { - int pastEncryption = this.getPreviousEncryption(); - int futureEncryption = this.getNextEncryption(); + int pastEncryption = getCleanedEncryption(this.getPreviousEncryption()); + int futureEncryption = getCleanedEncryption(this.getNextEncryption()); boolean inUnencryptedSession = pastEncryption == ENCRYPTION_NONE || futureEncryption == ENCRYPTION_NONE || pastEncryption != futureEncryption; - return inUnencryptedSession || this.getEncryption() == pastEncryption; + return inUnencryptedSession || getCleanedEncryption(this.getEncryption()) == pastEncryption; + } + + private static int getCleanedEncryption(int encryption) { + if (encryption == ENCRYPTION_DECRYPTED || encryption == ENCRYPTION_DECRYPTION_FAILED) { + return ENCRYPTION_PGP; + } + return encryption; } } -- cgit v1.2.3 From a3e11415ec06945bea88b49c99a5662773c8bf17 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 1 Feb 2016 12:11:40 +0100 Subject: refactored user handling in conferences. show try again button when conference has errors --- .../siacs/conversations/entities/MucOptions.java | 141 +++++++++------------ 1 file changed, 57 insertions(+), 84 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/entities') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 014a4c98..7f4ded11 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -3,7 +3,10 @@ package eu.siacs.conversations.entities; import android.annotation.SuppressLint; import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import eu.siacs.conversations.R; import eu.siacs.conversations.xmpp.forms.Data; @@ -64,7 +67,7 @@ public class MucOptions { PARTICIPANT("participant", R.string.participant,2), NONE("none", R.string.no_role,0); - private Role(String string, int resId, int rank) { + Role(String string, int resId, int rank) { this.string = string; this.resId = resId; this.rank = rank; @@ -94,6 +97,7 @@ public class MucOptions { public static final int ERROR_PASSWORD_REQUIRED = 3; public static final int ERROR_BANNED = 4; public static final int ERROR_MEMBERS_ONLY = 5; + public static final int ERROR_NO_RESPONSE = 6; public static final int KICKED_FROM_ROOM = 9; @@ -236,12 +240,12 @@ public class MucOptions { } private Account account; - private final List users = new ArrayList<>(); + private final Map users = Collections.synchronizedMap(new LinkedHashMap()); private List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; private boolean isOnline = false; - private int error = ERROR_UNKNOWN; + private int error = ERROR_NO_RESPONSE; public OnRenameListener onRenameListener = null; private User self; private String subject = null; @@ -303,40 +307,15 @@ public class MucOptions { } public User deleteUser(String name) { - synchronized (this.users) { - for (int i = 0; i < users.size(); ++i) { - if (users.get(i).getName().equals(name)) { - return users.remove(i); - } - } - } - return null; + return this.users.remove(name); } public void addUser(User user) { - synchronized (this.users) { - for (int i = 0; i < users.size(); ++i) { - if (users.get(i).getName().equals(user.getName())) { - users.set(i, user); - return; - } - } - users.add(user); - } + this.users.put(user.getName(), user); } public User findUser(String name) { - if (name == null) { - return null; - } - synchronized (this.users) { - for (User user : users) { - if (user.getName().equals(name)) { - return user; - } - } - } - return null; + return this.users.get(name); } public boolean isUserInRoom(String name) { @@ -344,26 +323,34 @@ public class MucOptions { } public void setError(int error) { - this.isOnline = error == ERROR_NO_ERROR; + this.isOnline = isOnline && error == ERROR_NO_ERROR; this.error = error; } + public void setOnline() { + this.isOnline = true; + } + public ArrayList getUsers() { - synchronized (this.users) { - return new ArrayList(this.users); - } + return new ArrayList<>(users.values()); } public List getUsers(int max) { - synchronized (this.users) { - return new ArrayList<>(users.subList(0,Math.min(users.size(),5))); + ArrayList users = new ArrayList<>(); + int i = 1; + for(User user : this.users.values()) { + users.add(user); + if (i >= max) { + break; + } else { + ++i; + } } + return users; } public int getUserCount() { - synchronized (this.users) { - return this.users.size(); - } + return this.users.size(); } public String getProposedNick() { @@ -400,7 +387,7 @@ public class MucOptions { public void setOffline() { this.users.clear(); - this.error = 0; + this.error = ERROR_NO_RESPONSE; this.isOnline = false; } @@ -417,38 +404,34 @@ public class MucOptions { } public String createNameFromParticipants() { - synchronized (this.users) { - if (users.size() >= 2) { - List names = new ArrayList(); - for (User user : users) { - Contact contact = user.getContact(); - if (contact != null && !contact.getDisplayName().isEmpty()) { - names.add(contact.getDisplayName().split("\\s+")[0]); - } else { - names.add(user.getName()); - } + if (users.size() >= 2) { + List names = new ArrayList<>(); + for (User user : getUsers(5)) { + Contact contact = user.getContact(); + if (contact != null && !contact.getDisplayName().isEmpty()) { + names.add(contact.getDisplayName().split("\\s+")[0]); + } else { + names.add(user.getName()); } - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < names.size(); ++i) { - builder.append(names.get(i)); - if (i != names.size() - 1) { - builder.append(", "); - } + } + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < names.size(); ++i) { + builder.append(names.get(i)); + if (i != names.size() - 1) { + builder.append(", "); } - return builder.toString(); - } else { - return null; } + return builder.toString(); + } else { + return null; } } public long[] getPgpKeyIds() { List ids = new ArrayList<>(); - synchronized (this.users) { - for (User user : this.users) { - if (user.getPgpKeyId() != 0) { - ids.add(user.getPgpKeyId()); - } + for (User user : this.users.values()) { + if (user.getPgpKeyId() != 0) { + ids.add(user.getPgpKeyId()); } } ids.add(account.getPgpId()); @@ -460,22 +443,18 @@ public class MucOptions { } public boolean pgpKeysInUse() { - synchronized (this.users) { - for (User user : this.users) { - if (user.getPgpKeyId() != 0) { - return true; - } + for (User user : this.users.values()) { + if (user.getPgpKeyId() != 0) { + return true; } } return false; } public boolean everybodyHasKeys() { - synchronized (this.users) { - for (User user : this.users) { - if (user.getPgpKeyId() == 0) { - return false; - } + for (User user : this.users.values()) { + if (user.getPgpKeyId() == 0) { + return false; } } return true; @@ -489,15 +468,9 @@ public class MucOptions { } } - public Jid getTrueCounterpart(String counterpart) { - synchronized (this.users) { - for (User user : this.users) { - if (user.getName().equals(counterpart)) { - return user.getJid(); - } - } - } - return null; + public Jid getTrueCounterpart(String name) { + User user = findUser(name); + return user == null ? null : user.getJid(); } public String getPassword() { -- cgit v1.2.3