diff options
Diffstat (limited to 'src/main/java/eu/siacs')
11 files changed, 322 insertions, 193 deletions
diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 0d51b4a1..c56767af 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -44,7 +44,7 @@ public final class Config { public static final int REFRESH_UI_INTERVAL = 500; public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb - public static final boolean DISABLE_HTTP_UPLOAD = true; + public static final boolean DISABLE_HTTP_UPLOAD = false; public static final boolean DISABLE_STRING_PREP = false; // setting to true might increase startup performance public static final boolean EXTENDED_SM_LOGGING = true; // log stanza counts public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 1eafa45f..4a49d1b3 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); @@ -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()) diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 13a5bb9f..92254b90 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<User> users = new CopyOnWriteArrayList<>(); + private final List<User> users = new ArrayList<>(); private List<String> 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,createJoinJid(getProposedNick())); } public void updateFeatures(ArrayList<String> 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<String> 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<String> getStatusCodes(Element x) { - List<String> 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<User> getUsers() { + synchronized (this.users) { + return new ArrayList(this.users); } - return codes; } - public List<User> getUsers() { - return this.users; + public List<User> 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<String> names = new ArrayList<String>(); - 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<String> names = new ArrayList<String>(); + 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<Long> 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; diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index b4c648fe..3e923af1 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -169,7 +169,7 @@ public class MessageParser extends AbstractParser implements if ("urn:xmpp:avatar:metadata".equals(node)) { Avatar avatar = Avatar.parseMetadata(items); if (avatar != null) { - avatar.owner = from; + avatar.owner = from.toBareJid(); if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { if (account.getJid().toBareJid().equals(from)) { if (account.setAvatar(avatar.getFilename())) { diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index d83347d8..12ffd33f 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -1,11 +1,13 @@ package eu.siacs.conversations.parser; import java.util.ArrayList; +import java.util.List; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.generator.PresenceGenerator; @@ -24,19 +26,18 @@ public class PresenceParser extends AbstractParser implements } public void parseConferencePresence(PresencePacket packet, Account account) { - PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine(); final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().toBareJid()); if (conversation != null) { final MucOptions mucOptions = conversation.getMucOptions(); boolean before = mucOptions.online(); - int count = mucOptions.getUsers().size(); - final ArrayList<MucOptions.User> tileUserBefore = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); - mucOptions.processPacket(packet, mPgpEngine); - final ArrayList<MucOptions.User> tileUserAfter = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); + int count = mucOptions.getUserCount(); + final List<MucOptions.User> tileUserBefore = mucOptions.getUsers(5); + processConferencePresence(packet, mucOptions); + final List<MucOptions.User> tileUserAfter = mucOptions.getUsers(5); if (!tileUserAfter.equals(tileUserBefore)) { mXmppConnectionService.getAvatarService().clear(conversation); } - if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUsers().size())) { + if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUserCount())) { mXmppConnectionService.updateConversationUi(); } else if (mucOptions.online()) { mXmppConnectionService.updateMucRosterUi(); @@ -44,8 +45,109 @@ public class PresenceParser extends AbstractParser implements } } - public void parseContactPresence(PresencePacket packet, Account account) { - PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); + private void processConferencePresence(PresencePacket packet, MucOptions mucOptions) { + final Jid from = packet.getFrom(); + if (!from.isBareJid()) { + final String type = packet.getAttribute("type"); + final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user"); + Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); + final List<String> codes = getStatusCodes(x); + if (type == null) { + if (x != null) { + Element item = x.findChild("item"); + if (item != null && !from.isBareJid()) { + MucOptions.User user = new MucOptions.User(mucOptions,from); + user.setAffiliation(item.getAttribute("affiliation")); + user.setRole(item.getAttribute("role")); + user.setJid(item.getAttributeAsJid("jid")); + if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) { + mucOptions.setError(MucOptions.ERROR_NO_ERROR); + mucOptions.setSelf(user); + if (mucOptions.mNickChangingInProgress) { + if (mucOptions.onRenameListener != null) { + mucOptions.onRenameListener.onSuccess(); + } + mucOptions.mNickChangingInProgress = false; + } + } else { + mucOptions.addUser(user); + } + if (mXmppConnectionService.getPgpEngine() != 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 = mXmppConnectionService.getPgpEngine().fetchKeyId(mucOptions.getAccount(), msg, signed.getContent()); + if (keyId != 0) { + user.setPgpKeyId(keyId); + } + } + } + if (avatar != null) { + avatar.owner = from; + if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { + user.setAvatar(avatar); + } else { + mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar); + } + } + } + } + } else if (type.equals("unavailable")) { + if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || + packet.getFrom().equals(mucOptions.getConversation().getJid())) { + if (codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) { + mucOptions.mNickChangingInProgress = true; + } else if (codes.contains(MucOptions.STATUS_CODE_KICKED)) { + mucOptions.setError(MucOptions.KICKED_FROM_ROOM); + } else if (codes.contains(MucOptions.STATUS_CODE_BANNED)) { + mucOptions.setError(MucOptions.ERROR_BANNED); + } else if (codes.contains(MucOptions.STATUS_CODE_LOST_MEMBERSHIP)) { + mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY); + } else { + mucOptions.setError(MucOptions.ERROR_UNKNOWN); + } + } else if (!from.isBareJid()){ + mucOptions.deleteUser(from.getResourcepart()); + } + } else if (type.equals("error")) { + Element error = packet.findChild("error"); + if (error != null && error.hasChild("conflict")) { + if (mucOptions.online()) { + if (mucOptions.onRenameListener != null) { + mucOptions.onRenameListener.onFailure(); + } + } else { + mucOptions.setError(MucOptions.ERROR_NICK_IN_USE); + } + } else if (error != null && error.hasChild("not-authorized")) { + mucOptions.setError(MucOptions.ERROR_PASSWORD_REQUIRED); + } else if (error != null && error.hasChild("forbidden")) { + mucOptions.setError(MucOptions.ERROR_BANNED); + } else if (error != null && error.hasChild("registration-required")) { + mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY); + } + } + } + } + + private static List<String> getStatusCodes(Element x) { + List<String> 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); + } + } + } + } + return codes; + } + + public void parseContactPresence(final PresencePacket packet, final Account account) { + final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); final Jid from = packet.getFrom(); if (from == null) { return; @@ -93,6 +195,17 @@ public class PresenceParser extends AbstractParser implements mPresenceGenerator.sendPresenceUpdatesTo(contact)); } else { contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST); + final String statusMessage = packet.findChildContent("status"); + if (statusMessage != null && !statusMessage.isEmpty()) { + final Conversation conversation = mXmppConnectionService.findOrCreateConversation( + account, contact.getJid().toBareJid(), false); + conversation.add(new Message( + conversation, + statusMessage, + Message.ENCRYPTION_NONE, + Message.STATUS_RECEIVED + )); + } } } mXmppConnectionService.updateRosterUi(); diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 5db4abae..31d625cc 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -58,6 +58,22 @@ public class AvatarService { return avatar; } + public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) { + final String KEY = key(user, size); + Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); + if (avatar != null || cachedOnly) { + return avatar; + } + if (user.getAvatar() != null) { + avatar = mXmppConnectionService.getFileBackend().getAvatar(user.getAvatar(), size); + } + if (avatar == null) { + avatar = get(user.getName(), size, cachedOnly); + } + this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); + return avatar; + } + public void clear(Contact contact) { synchronized (this.sizes) { for (Integer size : sizes) { @@ -77,6 +93,16 @@ public class AvatarService { + contact.getJid() + "_" + String.valueOf(size); } + private String key(MucOptions.User user, int size) { + synchronized (this.sizes) { + if (!this.sizes.contains(size)) { + this.sizes.add(size); + } + } + return PREFIX_CONTACT + "_" + user.getAccount().getJid().toBareJid() + "_" + + user.getFullJid() + "_" + String.valueOf(size); + } + public Bitmap get(ListItem item, int size) { return get(item,size,false); } @@ -122,7 +148,7 @@ public class AvatarService { if (bitmap != null || cachedOnly) { return bitmap; } - final List<MucOptions.User> users = new ArrayList<>(mucOptions.getUsers()); + final List<MucOptions.User> users = mucOptions.getUsers(); int count = users.size(); bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); @@ -198,15 +224,20 @@ public class AvatarService { } public Bitmap get(Message message, int size, boolean cachedOnly) { + final Conversation conversation = message.getConversation(); if (message.getStatus() == Message.STATUS_RECEIVED) { - Contact contact = message.getContact(); - if (contact != null) { - return get(contact, size, cachedOnly); - } else { - return get(UIHelper.getMessageDisplayName(message), size, cachedOnly); + Contact c = message.getContact(); + if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null)) { + return get(c, size, cachedOnly); + } else if (message.getConversation().getMode() == Conversation.MODE_MULTI){ + MucOptions.User user = conversation.getMucOptions().findUser(message.getCounterpart().getResourcepart()); + if (user != null) { + return get(user,size,cachedOnly); + } } + return get(UIHelper.getMessageDisplayName(message), size, cachedOnly); } else { - return get(message.getConversation().getAccount(), size, cachedOnly); + return get(conversation.getAccount(), size, cachedOnly); } } @@ -290,6 +321,11 @@ public class AvatarService { if (drawTile(canvas, uri, left, top, right, bottom)) { return true; } + } else if (user.getAvatar() != null) { + Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(user.getAvatar()); + if (drawTile(canvas, uri, left, top, right, bottom)) { + return true; + } } String name = contact != null ? contact.getDisplayName() : user.getName(); drawTile(canvas, name, left, top, right, bottom); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index fff8a984..77606956 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1322,6 +1322,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa leaveMuc(conversation); } else { conversation.endOtrIfNeeded(); + if (conversation.getContact().getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { + Log.d(Config.LOGTAG, "Canceling presence request from " + conversation.getJid().toString()); + sendPresencePacket( + conversation.getAccount(), + mPresenceGenerator.stopPresenceUpdatesTo(conversation.getContact()) + ); + } } this.databaseBackend.updateConversation(conversation); this.conversations.remove(conversation); @@ -1713,9 +1720,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Account account = conversation.getAccount(); final String nick = conversation.getMucOptions().getProposedNick(); final Jid joinJid = conversation.getMucOptions().createJoinJid(nick); - if (joinJid == null) { - return; //safety net - } Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString()); PresencePacket packet = new PresencePacket(); packet.setFrom(conversation.getAccount().getJid()); @@ -2351,12 +2355,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (getFileBackend().save(avatar)) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": successfully fetched vCard avatar for " + avatar.owner); - Contact contact = account.getRoster() - .getContact(avatar.owner); - contact.setAvatar(avatar); - getAvatarService().clear(contact); - updateConversationUi(); - updateRosterUi(); + if (avatar.owner.isBareJid()) { + Contact contact = account.getRoster() + .getContact(avatar.owner); + contact.setAvatar(avatar); + getAvatarService().clear(contact); + updateConversationUi(); + updateRosterUi(); + } else { + Conversation conversation = find(account,avatar.owner.toBareJid()); + if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { + MucOptions.User user = conversation.getMucOptions().findUser(avatar.owner.getResourcepart()); + if (user != null) { + user.setAvatar(avatar); + } + } + } } } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index a2abbf52..adae7916 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -494,8 +494,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); membersView.removeAllViews(); - final ArrayList<User> users = new ArrayList<>(); - users.addAll(mConversation.getMucOptions().getUsers()); + final ArrayList<User> users = mucOptions.getUsers(); Collections.sort(users,new Comparator<User>() { @Override public int compare(User lhs, User rhs) { @@ -527,20 +526,17 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }); tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); } - Bitmap bm; Contact contact = user.getContact(); if (contact != null) { - bm = avatarService().get(contact, getPixel(48)); tvDisplayName.setText(contact.getDisplayName()); tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); } else { - bm = avatarService().get(user.getName(), getPixel(48)); tvDisplayName.setText(user.getName()); tvStatus.setText(getStatus(user)); } ImageView iv = (ImageView) view.findViewById(R.id.contact_photo); - iv.setImageBitmap(bm); + iv.setImageBitmap(avatarService().get(user, getPixel(48), false)); membersView.addView(view); if (mConversation.getMucOptions().canInvite()) { mInviteButton.setVisibility(View.VISIBLE); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0397ad24..94d16f33 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -365,7 +365,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa break; case Message.ENCRYPTION_AXOLOTL: AxolotlService axolotlService = conversation.getAccount().getAxolotlService(); - if (axolotlService.trustedSessionVerified(conversation)) { + if (axolotlService != null && axolotlService.trustedSessionVerified(conversation)) { mEditMessage.setHint(getString(R.string.send_omemo_x509_message)); } else { mEditMessage.setHint(getString(R.string.send_omemo_message)); diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 961d2cd6..fc8b36fe 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -491,7 +491,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } } } - this.mUseTor = getPreferences().getBoolean("use_tor", false); + this.mUseTor = Config.PARANOID_MODE || getPreferences().getBoolean("use_tor", false); this.mNamePort.setVisibility(mUseTor ? View.VISIBLE : View.GONE); } diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index f3c4f79a..e07df627 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -227,10 +227,11 @@ public class DNSHelper { } public static boolean isIp(final String server) { - return PATTERN_IPV4.matcher(server).matches() + return server != null && ( + PATTERN_IPV4.matcher(server).matches() || PATTERN_IPV6.matcher(server).matches() || PATTERN_IPV6_6HEX4DEC.matcher(server).matches() || PATTERN_IPV6_HEX4DECCOMPRESSED.matcher(server).matches() - || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches(); + || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches()); } } |