aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs')
-rw-r--r--src/main/java/eu/siacs/conversations/Config.java2
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Message.java6
-rw-r--r--src/main/java/eu/siacs/conversations/entities/MucOptions.java277
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java2
-rw-r--r--src/main/java/eu/siacs/conversations/parser/PresenceParser.java129
-rw-r--r--src/main/java/eu/siacs/conversations/services/AvatarService.java50
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java32
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java8
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java2
-rw-r--r--src/main/java/eu/siacs/conversations/utils/DNSHelper.java5
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());
}
}