From d7c5264ad0d74b043fd81e1120401b3b9bf91c66 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 16 May 2016 19:58:24 +0200 Subject: cap exponential backoff at 300s (10 attempts) --- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index cc3647e6e..66fd65272 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1422,7 +1422,7 @@ public class XmppConnection implements Runnable { } public int getTimeToNextAttempt() { - final int interval = (int) (25 * Math.pow(1.5, attempt)); + final int interval = Math.min((int) (25 * Math.pow(1.3, attempt)), 300); final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000); return interval - secondsSinceLast; } -- cgit v1.2.3 From 8d0693ed6a46ea45844f4d8319f5d051ec256756 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 16 May 2016 14:10:40 +0200 Subject: keep conference members in memory and show them in conference details --- .../crypto/axolotl/AxolotlService.java | 1 - .../siacs/conversations/entities/MucOptions.java | 174 +++++++++++++++------ .../siacs/conversations/parser/MessageParser.java | 4 +- .../siacs/conversations/parser/PresenceParser.java | 11 +- .../conversations/services/AvatarService.java | 2 +- .../services/XmppConnectionService.java | 26 ++- .../ui/ConferenceDetailsActivity.java | 37 +++-- .../conversations/ui/ConversationFragment.java | 22 ++- .../eu/siacs/conversations/ui/XmppActivity.java | 4 +- 9 files changed, 184 insertions(+), 97 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index ae1b3a03f..327a1cc84 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -643,7 +643,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { jids = Arrays.asList(conversation.getJid().toBareJid()); } else { jids = conversation.getMucOptions().getMembers(); - jids.remove(account.getJid().toBareJid()); } return jids; } diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 7681a3d42..a221c7011 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -5,9 +5,7 @@ import android.annotation.SuppressLint; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Set; import eu.siacs.conversations.R; @@ -28,6 +26,15 @@ public class MucOptions { this.self = user; } + public void changeAffiliation(Jid jid, Affiliation affiliation) { + User user = findUserByRealJid(jid); + if (user != null) { + users.remove(user); + user.affiliation = affiliation; + users.add(user); + } + } + public enum Affiliation { OWNER("owner", 4, R.string.owner), ADMIN("admin", 3, R.string.admin), @@ -127,7 +134,7 @@ public class MucOptions { public static class User { private Role role = Role.NONE; private Affiliation affiliation = Affiliation.NONE; - private Jid jid; + private Jid realJid; private Jid fullJid; private long pgpKeyId = 0; private Avatar avatar; @@ -139,15 +146,15 @@ public class MucOptions { } public String getName() { - return this.fullJid.getResourcepart(); + return fullJid == null ? null : fullJid.getResourcepart(); } - public void setJid(Jid jid) { - this.jid = jid; + public void setRealJid(Jid jid) { + this.realJid = jid != null ? jid.toBareJid() : null; } - public Jid getJid() { - return this.jid; + public Jid getRealJid() { + return this.realJid; } public Role getRole() { @@ -155,6 +162,10 @@ public class MucOptions { } public void setRole(String role) { + if (role == null) { + this.role = Role.NONE; + return; + } role = role.toLowerCase(); switch (role) { case "moderator": @@ -172,26 +183,15 @@ public class MucOptions { } } - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } else if (!(other instanceof User)) { - return false; - } else { - User o = (User) other; - return getName() != null && getName().equals(o.getName()) - && jid != null && jid.equals(o.jid) - && affiliation == o.affiliation - && role == o.role; - } - } - public Affiliation getAffiliation() { return this.affiliation; } public void setAffiliation(String affiliation) { + if (affiliation == null) { + this.affiliation = Affiliation.NONE; + return; + } affiliation = affiliation.toLowerCase(); switch (affiliation) { case "admin": @@ -220,7 +220,7 @@ public class MucOptions { } public Contact getContact() { - return getAccount().getRoster().getContactFromRoster(getJid()); + return getAccount().getRoster().getContactFromRoster(getRealJid()); } public boolean setAvatar(Avatar avatar) { @@ -243,11 +243,39 @@ public class MucOptions { public Jid getFullJid() { return fullJid; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + User user = (User) o; + + if (role != user.role) return false; + if (affiliation != user.affiliation) return false; + if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null) + return false; + return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null; + + } + + @Override + public int hashCode() { + int result = role != null ? role.hashCode() : 0; + result = 31 * result + (affiliation != null ? affiliation.hashCode() : 0); + result = 31 * result + (realJid != null ? realJid.hashCode() : 0); + result = 31 * result + (fullJid != null ? fullJid.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "[fulljid:"+String.valueOf(fullJid)+",realjid:"+String.valueOf(realJid)+",affiliation"+affiliation.toString()+"]"; + } } private Account account; - private final Map users = Collections.synchronizedMap(new LinkedHashMap()); - private final Set members = Collections.synchronizedSet(new HashSet()); + private final Set users = Collections.synchronizedSet(new HashSet()); private final List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; @@ -315,20 +343,66 @@ public class MucOptions { return hasFeature("muc_moderated"); } - public User deleteUser(String name) { - return this.users.remove(name); + public User deleteUser(Jid jid) { + User user = findUserByFullJid(jid); + if (user != null) { + users.remove(user); + if (user.affiliation.ranks(Affiliation.MEMBER)) { + user.role = Role.NONE; + user.avatar = null; + user.fullJid = null; + users.add(user); + } + } + return user; } public void addUser(User user) { - this.users.put(user.getName(), user); + User old; + if (user.fullJid == null && user.realJid != null) { + old = findUserByRealJid(user.realJid); + if (old != null) { + return; //don't add. user already exists + } + } else if (user.realJid != null) { + old = findUserByRealJid(user.realJid); + if (old != null && old.fullJid == null) { + users.remove(old); + } + } + old = findUserByFullJid(user.getFullJid()); + if (old != null) { + users.remove(old); + } + this.users.add(user); + } + + public User findUserByFullJid(Jid jid) { + if (jid == null) { + return null; + } + for(User user : users) { + if (jid.equals(user.getFullJid())) { + return user; + } + } + return null; } - public User findUser(String name) { - return this.users.get(name); + public User findUserByRealJid(Jid jid) { + if (jid == null) { + return null; + } + for(User user : users) { + if (jid.equals(user.getRealJid())) { + return user; + } + } + return null; } - public boolean isUserInRoom(String name) { - return findUser(name) != null; + public boolean isUserInRoom(Jid jid) { + return findUserByFullJid(jid) != null; } public void setError(Error error) { @@ -341,7 +415,7 @@ public class MucOptions { } public ArrayList getUsers() { - return new ArrayList<>(users.values()); + return new ArrayList<>(users); } public List getUsers(int max) { @@ -410,7 +484,7 @@ public class MucOptions { Contact contact = user.getContact(); if (contact != null && !contact.getDisplayName().isEmpty()) { names.add(contact.getDisplayName().split("\\s+")[0]); - } else { + } else if (user.getName() != null){ names.add(user.getName()); } } @@ -429,7 +503,7 @@ public class MucOptions { public long[] getPgpKeyIds() { List ids = new ArrayList<>(); - for (User user : this.users.values()) { + for (User user : this.users) { if (user.getPgpKeyId() != 0) { ids.add(user.getPgpKeyId()); } @@ -443,7 +517,7 @@ public class MucOptions { } public boolean pgpKeysInUse() { - for (User user : this.users.values()) { + for (User user : this.users) { if (user.getPgpKeyId() != 0) { return true; } @@ -452,7 +526,7 @@ public class MucOptions { } public boolean everybodyHasKeys() { - for (User user : this.users.values()) { + for (User user : this.users) { if (user.getPgpKeyId() == 0) { return false; } @@ -468,12 +542,12 @@ public class MucOptions { } } - public Jid getTrueCounterpart(String name) { - if (name.equals(getSelf().getName())) { + public Jid getTrueCounterpart(Jid jid) { + if (jid.equals(getSelf().getFullJid())) { return account.getJid().toBareJid(); } - User user = findUser(name); - return user == null ? null : user.getJid(); + User user = findUserByFullJid(jid); + return user == null ? null : user.getRealJid(); } public String getPassword() { @@ -499,11 +573,21 @@ public class MucOptions { return this.conversation; } - public void putMember(Jid jid) { - members.add(jid); + public void putMember(Jid fullJid, Jid realJid, String affiliation, String role) { + User user = new User(this, fullJid); + user.setRealJid(realJid); + user.setAffiliation(affiliation); + user.setRole(role); + addUser(user); } public List getMembers() { - return new ArrayList<>(members); + ArrayList members = new ArrayList<>(); + for(User user : users) { + if (user.affiliation.ranks(Affiliation.MEMBER) && user.getRealJid() != null) { + members.add(user.getRealJid()); + } + } + return members; } } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 69ac4c18d..f10798f37 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -402,7 +402,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } else if (axolotlEncrypted != null && Config.supportOmemo()) { Jid origin; if (conversation.getMode() == Conversation.MODE_MULTI) { - origin = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart()); + origin = conversation.getMucOptions().getTrueCounterpart(counterpart); if (origin == null) { Log.d(Config.LOGTAG,"axolotl message in non anonymous conference received"); return; @@ -430,7 +430,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece message.setOob(isOob); message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0"); if (conversation.getMode() == Conversation.MODE_MULTI) { - Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart()); + Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart); message.setTrueCounterpart(trueCounterpart); if (!isTypeGroupChat) { message.setType(Message.TYPE_PRIVATE); diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index aea9002ac..1f1e92ee4 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -14,15 +14,12 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presence; -import eu.siacs.conversations.entities.ServiceDiscoveryResult; import eu.siacs.conversations.generator.PresenceGenerator; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnPresencePacketReceived; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; -import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; public class PresenceParser extends AbstractParser implements @@ -67,11 +64,7 @@ public class PresenceParser extends AbstractParser implements MucOptions.User user = new MucOptions.User(mucOptions, from); user.setAffiliation(item.getAttribute("affiliation")); user.setRole(item.getAttribute("role")); - Jid real = item.getAttributeAsJid("jid"); - if (real != null) { - user.setJid(real); - mucOptions.putMember(real.toBareJid()); - } + user.setRealJid(item.getAttributeAsJid("jid")); if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) { mucOptions.setOnline(); mucOptions.setSelf(user); @@ -127,7 +120,7 @@ public class PresenceParser extends AbstractParser implements Log.d(Config.LOGTAG, "unknown error in conference: " + packet); } } else if (!from.isBareJid()){ - MucOptions.User user = mucOptions.deleteUser(from.getResourcepart()); + MucOptions.User user = mucOptions.deleteUser(from); if (user != null) { mXmppConnectionService.getAvatarService().clear(user); } diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index bb8ec5f29..633758a5b 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -246,7 +246,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { 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()); + MucOptions.User user = conversation.getMucOptions().findUserByFullJid(message.getCounterpart()); if (user != null) { return getImpl(user,size,cachedOnly); } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index aeb800bd8..f88c0c9bd 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1899,11 +1899,26 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(Account account, IqPacket packet) { + Element query = packet.query("http://jabber.org/protocol/muc#admin"); if (packet.getType() == IqPacket.TYPE.RESULT && query != null) { + final String local = conversation.getJid().getLocalpart(); + final String domain = conversation.getJid().getDomainpart(); for(Element child : query.getChildren()) { if ("item".equals(child.getName())) { - conversation.getMucOptions().putMember(child.getAttributeAsJid("jid")); + String affiliation = child.getAttribute("affiliation"); + String role = child.getAttribute("role"); + String nick = child.getAttribute("nick"); + Jid fullJid; + try { + fullJid = nick != null ? Jid.fromParts(local, domain, nick) : null; + } catch (InvalidJidException e) { + fullJid = null; + } + Jid realJid = child.getAttributeAsJid("jid"); + if (realJid != null && !realJid.equals(account.getJid().toBareJid())) { + conversation.getMucOptions().putMember(fullJid, realJid, affiliation, role); + } } } } else { @@ -2175,13 +2190,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - public void changeAffiliationInConference(final Conversation conference, Jid user, MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) { + public void changeAffiliationInConference(final Conversation conference, Jid user, final MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) { final Jid jid = user.toBareJid(); IqPacket request = this.mIqGenerator.changeAffiliation(conference, jid, affiliation.toString()); sendIqPacket(conference.getAccount(), request, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE.RESULT) { + conference.getMucOptions().changeAffiliation(jid, affiliation); callback.onAffiliationChangedSuccessful(jid); } else { callback.onAffiliationChangeFailed(jid, R.string.could_not_change_affiliation); @@ -2193,8 +2209,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void changeAffiliationsInConference(final Conversation conference, MucOptions.Affiliation before, MucOptions.Affiliation after) { List jids = new ArrayList<>(); for (MucOptions.User user : conference.getMucOptions().getUsers()) { - if (user.getAffiliation() == before && user.getJid() != null) { - jids.add(user.getJid()); + if (user.getAffiliation() == before && user.getRealJid() != null) { + jids.add(user.getRealJid()); } } IqPacket request = this.mIqGenerator.changeAffiliation(conference, jids, after.toString()); @@ -2574,7 +2590,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } 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()); + MucOptions.User user = conversation.getMucOptions().findUserByFullJid(avatar.owner); if (user != null) { if (user.setAvatar(avatar)) { getAvatarService().clear(user); diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index c806a03e4..bca1c1baa 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.ui; -import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.PendingIntent; import android.content.ActivityNotFoundException; @@ -8,7 +7,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender.SendIntentException; -import android.os.Build; import android.os.Bundle; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -365,13 +363,13 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers final Contact contact = user.getContact(); if (contact != null) { name = contact.getDisplayName(); - } else if (user.getJid() != null){ - name = user.getJid().toBareJid().toString(); + } else if (user.getRealJid() != null){ + name = user.getRealJid().toBareJid().toString(); } else { name = user.getName(); } menu.setHeaderTitle(name); - if (user.getJid() != null) { + if (user.getRealJid() != null) { MenuItem showContactDetails = menu.findItem(R.id.action_contact_details); MenuItem startConversation = menu.findItem(R.id.start_conversation); MenuItem giveMembership = menu.findItem(R.id.give_membership); @@ -424,22 +422,22 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers startConversation(mSelectedUser); return true; case R.id.give_admin_privileges: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this); + xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.ADMIN,this); return true; case R.id.give_membership: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this); + xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.MEMBER,this); return true; case R.id.remove_membership: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this); + xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.NONE,this); return true; case R.id.remove_admin_privileges: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this); + xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.MEMBER,this); return true; case R.id.remove_from_room: removeFromRoom(mSelectedUser); return true; case R.id.ban_from_conference: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this); + xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.OUTCAST,this); xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,this); return true; case R.id.send_private_message: @@ -452,7 +450,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers private void removeFromRoom(final User user) { if (mConversation.getMucOptions().membersOnly()) { - xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.NONE,this); + xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.NONE,this); xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); } else { AlertDialog.Builder builder = new AlertDialog.Builder(this); @@ -462,7 +460,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers builder.setPositiveButton(R.string.ban_now,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this); + xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this); xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); } }); @@ -471,8 +469,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } protected void startConversation(User user) { - if (user.getJid() != null) { - Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getJid().toBareJid(),false); + if (user.getRealJid() != null) { + Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getRealJid().toBareJid(),false); switchToConversation(conversation); } } @@ -577,8 +575,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers final ArrayList users = mucOptions.getUsers(); Collections.sort(users,new Comparator() { @Override - public int compare(User lhs, User rhs) { - return lhs.getName().compareToIgnoreCase(rhs.getName()); + public int compare(User l, User r) { + return l.getName() == null || r.getName() == null ? 0 : l.getName().compareToIgnoreCase(r.getName()); } }); for (final User user : users) { @@ -607,11 +605,12 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); } Contact contact = user.getContact(); + String name = user.getName(); if (contact != null) { tvDisplayName.setText(contact.getDisplayName()); - tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); + tvStatus.setText((name != null ? name+ " \u2022 " : "") + getStatus(user)); } else { - tvDisplayName.setText(user.getName()); + tvDisplayName.setText(name == null ? "" : name); tvStatus.setText(getStatus(user)); } @@ -657,7 +656,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void onAffiliationChangedSuccessful(Jid jid) { - + refreshUi(); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 1c1fcb75d..f1352780a 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -461,12 +461,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa public void onContactPictureClicked(Message message) { if (message.getStatus() <= Message.STATUS_RECEIVED) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - String user = message.getCounterpart().isBareJid() ? message.getCounterpart().toString() : message.getCounterpart().getResourcepart(); + Jid user = message.getCounterpart(); + if (user != null && !user.isBareJid()) { if (!message.getConversation().getMucOptions().isUserInRoom(user)) { - Toast.makeText(activity,activity.getString(R.string.user_has_left_conference,user),Toast.LENGTH_SHORT).show(); + Toast.makeText(activity,activity.getString(R.string.user_has_left_conference,user.getResourcepart()),Toast.LENGTH_SHORT).show(); } - highlightInConference(user); + highlightInConference(user.getResourcepart()); } } else { if (!message.getContact().isSelf()) { @@ -495,14 +495,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa public void onContactPictureLongClicked(Message message) { if (message.getStatus() <= Message.STATUS_RECEIVED) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - String user = message.getCounterpart().getResourcepart(); - if (user != null) { - if (message.getConversation().getMucOptions().isUserInRoom(user)) { - privateMessageWith(message.getCounterpart()); - } else { - Toast.makeText(activity, activity.getString(R.string.user_has_left_conference, user), Toast.LENGTH_SHORT).show(); - } + Jid user = message.getCounterpart(); + if (user != null && !user.isBareJid()) { + if (message.getConversation().getMucOptions().isUserInRoom(user)) { + privateMessageWith(user); + } else { + Toast.makeText(activity, activity.getString(R.string.user_has_left_conference, user.getResourcepart()), Toast.LENGTH_SHORT).show(); } } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 5ce74824a..e963ef4c7 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -42,7 +42,6 @@ import android.preference.PreferenceManager; import android.text.InputType; import android.util.DisplayMetrics; import android.util.Log; -import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -68,7 +67,6 @@ import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.RunnableFuture; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -481,7 +479,7 @@ public abstract class XmppActivity extends Activity { List contacts = new ArrayList<>(); if (conversation.getMode() == Conversation.MODE_MULTI) { for (MucOptions.User user : conversation.getMucOptions().getUsers()) { - Jid jid = user.getJid(); + Jid jid = user.getRealJid(); if (jid != null) { contacts.add(jid.toBareJid().toString()); } -- cgit v1.2.3 From fc5304c6feb302334d15be183d55663965a29de1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 16 May 2016 15:50:57 +0200 Subject: change affiliation for in memory users that are currently not joined in a conference --- .../java/eu/siacs/conversations/entities/MucOptions.java | 8 +++++--- .../java/eu/siacs/conversations/parser/PresenceParser.java | 4 +++- .../siacs/conversations/services/XmppConnectionService.java | 1 + .../eu/siacs/conversations/ui/ConferenceDetailsActivity.java | 12 +++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index a221c7011..50641f5a4 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -28,10 +28,12 @@ public class MucOptions { public void changeAffiliation(Jid jid, Affiliation affiliation) { User user = findUserByRealJid(jid); - if (user != null) { + if (user != null && user.getRole() == Role.NONE) { users.remove(user); - user.affiliation = affiliation; - users.add(user); + if (affiliation.ranks(Affiliation.MEMBER)) { + user.affiliation = affiliation; + users.add(user); + } } } diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 1f1e92ee4..c82c83d13 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -140,9 +140,11 @@ public class PresenceParser extends AbstractParser implements } else if (error != null && error.hasChild("forbidden")) { mucOptions.setError(MucOptions.Error.BANNED); } else if (error != null && error.hasChild("registration-required")) { - mucOptions.setError(MucOptions.Error.BANNED); + mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); } } + } else { + Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().toBareJid()+": "+packet); } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index f88c0c9bd..6b01261c8 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2198,6 +2198,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE.RESULT) { conference.getMucOptions().changeAffiliation(jid, affiliation); + getAvatarService().clear(conference); callback.onAffiliationChangedSuccessful(jid); } else { callback.onAffiliationChangeFailed(jid, R.string.could_not_change_affiliation); diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index bca1c1baa..245dba159 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -438,7 +438,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers return true; case R.id.ban_from_conference: xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.OUTCAST,this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,this); + if (mSelectedUser.getRole() != MucOptions.Role.NONE) { + xmppConnectionService.changeRoleInConference(mConversation, mSelectedUser.getName(), MucOptions.Role.NONE, this); + } return true; case R.id.send_private_message: privateMsgInMuc(mConversation,mSelectedUser.getName()); @@ -451,7 +453,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers private void removeFromRoom(final User user) { if (mConversation.getMucOptions().membersOnly()) { xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.NONE,this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); + if (user.getRole() != MucOptions.Role.NONE) { + xmppConnectionService.changeRoleInConference(mConversation, mSelectedUser.getName(), MucOptions.Role.NONE, ConferenceDetailsActivity.this); + } } else { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.ban_from_conference); @@ -461,7 +465,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void onClick(DialogInterface dialog, int which) { xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); + if (user.getRole() != MucOptions.Role.NONE) { + xmppConnectionService.changeRoleInConference(mConversation, mSelectedUser.getName(), MucOptions.Role.NONE, ConferenceDetailsActivity.this); + } } }); builder.create().show(); -- cgit v1.2.3 From 14952ba5e5ffbbbda2d0453157f03779ffbdaffb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 May 2016 10:43:48 +0200 Subject: offer offline members to be invited again --- .../eu/siacs/conversations/entities/MucOptions.java | 18 ++++++++++++++++-- .../java/eu/siacs/conversations/ui/XmppActivity.java | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 50641f5a4..e931f5fd2 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -349,7 +349,7 @@ public class MucOptions { User user = findUserByFullJid(jid); if (user != null) { users.remove(user); - if (user.affiliation.ranks(Affiliation.MEMBER)) { + if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null) { user.role = Role.NONE; user.avatar = null; user.fullJid = null; @@ -417,7 +417,21 @@ public class MucOptions { } public ArrayList getUsers() { - return new ArrayList<>(users); + return getUsers(true); + } + + public ArrayList getUsers(boolean includeOffline) { + if (includeOffline) { + return new ArrayList<>(users); + } else { + ArrayList onlineUsers = new ArrayList<>(); + for(User user : users) { + if(user.getRole().ranks(Role.PARTICIPANT)) { + onlineUsers.add(user); + } + } + return onlineUsers; + } } public List getUsers(int max) { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index e963ef4c7..858806e3e 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -478,7 +478,7 @@ public abstract class XmppActivity extends Activity { ChooseContactActivity.class); List contacts = new ArrayList<>(); if (conversation.getMode() == Conversation.MODE_MULTI) { - for (MucOptions.User user : conversation.getMucOptions().getUsers()) { + for (MucOptions.User user : conversation.getMucOptions().getUsers(false)) { Jid jid = user.getRealJid(); if (jid != null) { contacts.add(jid.toBareJid().toString()); -- cgit v1.2.3 From 61726f4994dffad0407bbc9dc539874ce9f79171 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 May 2016 14:25:58 +0200 Subject: refactored muc item parsing to also parse muc status messages --- .../siacs/conversations/entities/MucOptions.java | 12 ++++------- .../siacs/conversations/parser/AbstractParser.java | 23 ++++++++++++++++++++++ .../siacs/conversations/parser/MessageParser.java | 16 ++++++++++++--- .../siacs/conversations/parser/PresenceParser.java | 2 -- .../services/XmppConnectionService.java | 18 ++++------------- 5 files changed, 44 insertions(+), 27 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index e931f5fd2..8d7c5adbd 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -274,6 +274,10 @@ public class MucOptions { public String toString() { return "[fulljid:"+String.valueOf(fullJid)+",realjid:"+String.valueOf(realJid)+",affiliation"+affiliation.toString()+"]"; } + + public boolean realJidMatchesAccount() { + return realJid != null && realJid.equals(options.account.getJid().toBareJid()); + } } private Account account; @@ -589,14 +593,6 @@ public class MucOptions { return this.conversation; } - public void putMember(Jid fullJid, Jid realJid, String affiliation, String role) { - User user = new User(this, fullJid); - user.setRealJid(realJid); - user.setAffiliation(affiliation); - user.setRole(role); - addUser(user); - } - public List getMembers() { ArrayList members = new ArrayList<>(); for(User user : users) { diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 73c717bf2..cf9e10fff 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -8,8 +8,11 @@ import java.util.Locale; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; @@ -66,4 +69,24 @@ public abstract class AbstractParser { } return item.findChildContent("data", "urn:xmpp:avatar:data"); } + + public static MucOptions.User parseItem(Conversation conference, Element item) { + final String local = conference.getJid().getLocalpart(); + final String domain = conference.getJid().getDomainpart(); + String affiliation = item.getAttribute("affiliation"); + String role = item.getAttribute("role"); + String nick = item.getAttribute("nick"); + Jid fullJid; + try { + fullJid = nick != null ? Jid.fromParts(local, domain, nick) : null; + } catch (InvalidJidException e) { + fullJid = null; + } + Jid realJid = item.getAttributeAsJid("jid"); + MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid); + user.setRealJid(realJid); + user.setAffiliation(affiliation); + user.setRole(role); + return user; + } } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index f10798f37..642ea9313 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -533,8 +533,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } } else if (!packet.hasChild("body")){ //no body + Conversation conversation = mXmppConnectionService.find(account, from.toBareJid()); if (isTypeGroupChat) { - Conversation conversation = mXmppConnectionService.find(account, from.toBareJid()); if (packet.hasChild("subject")) { if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { conversation.setHasMessagesLeftOnServer(conversation.countMessages() > 0); @@ -550,14 +550,24 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece return; } } - - if (conversation != null && isMucStatusMessage) { + } + if (conversation != null && mucUserElement != null && from.isBareJid()) { + if (mucUserElement.hasChild("status")) { for (Element child : mucUserElement.getChildren()) { if (child.getName().equals("status") && MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED.equals(child.getAttribute("code"))) { mXmppConnectionService.fetchConferenceConfiguration(conversation); } } + } else if (mucUserElement.hasChild("item")) { + for(Element child : mucUserElement.getChildren()) { + if ("item".equals(child.getName())) { + MucOptions.User user = AbstractParser.parseItem(conversation,child); + if (!user.realJidMatchesAccount()) { + conversation.getMucOptions().addUser(user); + } + } + } } } } diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index c82c83d13..2a912a45a 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -143,8 +143,6 @@ public class PresenceParser extends AbstractParser implements mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); } } - } else { - Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().toBareJid()+": "+packet); } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 6b01261c8..e8a98cdaf 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -83,6 +83,7 @@ import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.generator.MessageGenerator; import eu.siacs.conversations.generator.PresenceGenerator; import eu.siacs.conversations.http.HttpConnectionManager; +import eu.siacs.conversations.parser.AbstractParser; import eu.siacs.conversations.parser.IqParser; import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.PresenceParser; @@ -1902,22 +1903,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Element query = packet.query("http://jabber.org/protocol/muc#admin"); if (packet.getType() == IqPacket.TYPE.RESULT && query != null) { - final String local = conversation.getJid().getLocalpart(); - final String domain = conversation.getJid().getDomainpart(); for(Element child : query.getChildren()) { if ("item".equals(child.getName())) { - String affiliation = child.getAttribute("affiliation"); - String role = child.getAttribute("role"); - String nick = child.getAttribute("nick"); - Jid fullJid; - try { - fullJid = nick != null ? Jid.fromParts(local, domain, nick) : null; - } catch (InvalidJidException e) { - fullJid = null; - } - Jid realJid = child.getAttributeAsJid("jid"); - if (realJid != null && !realJid.equals(account.getJid().toBareJid())) { - conversation.getMucOptions().putMember(fullJid, realJid, affiliation, role); + MucOptions.User user = AbstractParser.parseItem(conversation,child); + if (!user.realJidMatchesAccount()) { + conversation.getMucOptions().addUser(user); } } } -- cgit v1.2.3 From b478eca315661c50d76052aafcbbcc041790300f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 May 2016 15:01:56 +0200 Subject: improved ordering of muc participants --- .../siacs/conversations/entities/MucOptions.java | 25 ++++++++++++++++++++-- .../siacs/conversations/parser/AbstractParser.java | 2 +- .../ui/ConferenceDetailsActivity.java | 7 +----- 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 8d7c5adbd..d26ecd7c1 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -133,7 +133,7 @@ public class MucOptions { } - public static class User { + public static class User implements Comparable { private Role role = Role.NONE; private Affiliation affiliation = Affiliation.NONE; private Jid realJid; @@ -222,7 +222,13 @@ public class MucOptions { } public Contact getContact() { - return getAccount().getRoster().getContactFromRoster(getRealJid()); + if (fullJid != null) { + return getAccount().getRoster().getContactFromRoster(realJid); + } else if (realJid != null){ + return getAccount().getRoster().getContact(realJid); + } else { + return null; + } } public boolean setAvatar(Avatar avatar) { @@ -278,6 +284,21 @@ public class MucOptions { public boolean realJidMatchesAccount() { return realJid != null && realJid.equals(options.account.getJid().toBareJid()); } + + @Override + public int compareTo(User another) { + Contact ourContact = getContact(); + Contact anotherContact = another.getContact(); + if (ourContact != null && anotherContact != null) { + return ourContact.compareTo(anotherContact); + } else if (ourContact == null && anotherContact != null) { + return getName().compareToIgnoreCase(anotherContact.getDisplayName()); + } else if (ourContact != null) { + return ourContact.getDisplayName().compareToIgnoreCase(another.getName()); + } else { + return getName().compareToIgnoreCase(another.getName()); + } + } } private Account account; diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index cf9e10fff..03f19ed82 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -83,7 +83,7 @@ public abstract class AbstractParser { fullJid = null; } Jid realJid = item.getAttributeAsJid("jid"); - MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid); + MucOptions.User user = new MucOptions.User(conference.getMucOptions(), nick == null ? null : fullJid); user.setRealJid(realJid); user.setAffiliation(affiliation); user.setRole(role); diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 245dba159..2e4b94e58 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -579,12 +579,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); membersView.removeAllViews(); final ArrayList users = mucOptions.getUsers(); - Collections.sort(users,new Comparator() { - @Override - public int compare(User l, User r) { - return l.getName() == null || r.getName() == null ? 0 : l.getName().compareToIgnoreCase(r.getName()); - } - }); + Collections.sort(users); for (final User user : users) { View view = inflater.inflate(R.layout.contact, membersView,false); this.setListItemBackgroundOnView(view); -- cgit v1.2.3 From afa3883089ae8f827b1a6068db0a6efffb73485f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:39:47 +0200 Subject: synchronize around identity key generation --- .../conversations/crypto/axolotl/SQLiteAxolotlStore.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java index 979a2845d..4eb73313d 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java @@ -90,16 +90,18 @@ public class SQLiteAxolotlStore implements AxolotlStore { // -------------------------------------- private IdentityKeyPair loadIdentityKeyPair() { - IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account); + synchronized (mXmppConnectionService) { + IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account); - if (ownKey != null) { + if (ownKey != null) { + return ownKey; + } else { + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve own IdentityKeyPair"); + ownKey = generateIdentityKeyPair(); + mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownKey); + } return ownKey; - } else { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve own IdentityKeyPair"); - ownKey = generateIdentityKeyPair(); - mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownKey); } - return ownKey; } private int loadRegistrationId() { -- cgit v1.2.3 From 627bf18f8cfa72aee3f410f22245403ff6a98ed0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:40:03 +0200 Subject: don't NPE on rare race condition while fetching MAM --- src/main/java/eu/siacs/conversations/entities/Message.java | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 225d05315..818ac1d65 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -492,6 +492,9 @@ public class Message extends AbstractEntity { Message current = this; while(current.mergeable(current.next())) { current = current.next(); + if (current == null) { + break; + } body.append(MERGE_SEPARATOR); body.append(current.getBody().trim()); } @@ -507,6 +510,9 @@ public class Message extends AbstractEntity { Message current = this; while(current.mergeable(current.next())) { current = current.next(); + if (current == null) { + break; + } status = current.status; } return status; @@ -517,6 +523,9 @@ public class Message extends AbstractEntity { Message current = this; while(current.mergeable(current.next())) { current = current.next(); + if (current == null) { + break; + } time = current.timeSent; } return time; -- cgit v1.2.3 From 0eb8d4226ea8639b6a1e9a568863146423d4f0f8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:41:56 +0200 Subject: also save form elements in disco storage --- .../entities/ServiceDiscoveryResult.java | 58 +++++++++++++++++++++- .../conversations/persistance/DatabaseBackend.java | 6 ++- .../services/XmppConnectionService.java | 4 +- .../eu/siacs/conversations/xmpp/forms/Data.java | 2 +- 4 files changed, 64 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java b/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java index 9accec95d..9ee1d180e 100644 --- a/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java +++ b/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java @@ -146,7 +146,7 @@ public class ServiceDiscoveryResult { this.hash = hash; this.ver = ver; - JSONArray identities = o.optJSONArray("identites"); + JSONArray identities = o.optJSONArray("identities"); if (identities != null) { for (int i = 0; i < identities.length(); i++) { this.identities.add(new Identity(identities.getJSONObject(i))); @@ -158,6 +158,54 @@ public class ServiceDiscoveryResult { this.features.add(features.getString(i)); } } + JSONArray forms = o.optJSONArray("forms"); + if (forms != null) { + for(int i = 0; i < forms.length(); i++) { + this.forms.add(createFormFromJSONObject(forms.getJSONObject(i))); + } + } + } + + private static Data createFormFromJSONObject(JSONObject o) { + Data data = new Data(); + JSONArray names = o.names(); + for(int i = 0; i < names.length(); ++i) { + try { + String name = names.getString(i); + JSONArray jsonValues = o.getJSONArray(name); + ArrayList values = new ArrayList<>(jsonValues.length()); + for(int j = 0; j < jsonValues.length(); ++j) { + values.add(jsonValues.getString(j)); + } + data.put(name, values); + } catch (Exception e) { + e.printStackTrace(); + } + } + return data; + } + + private static JSONObject createJSONFromForm(Data data) { + JSONObject object = new JSONObject(); + for(Field field : data.getFields()) { + try { + JSONArray jsonValues = new JSONArray(); + for(String value : field.getValues()) { + jsonValues.put(value); + } + object.put(field.getFieldName(), jsonValues); + } catch(Exception e) { + e.printStackTrace(); + } + } + try { + JSONArray jsonValues = new JSONArray(); + jsonValues.put(data.getFormType()); + object.put(Data.FORM_TYPE, jsonValues); + } catch(Exception e) { + e.printStackTrace(); + } + return object; } public String getVer() { @@ -274,10 +322,16 @@ public class ServiceDiscoveryResult { for(Identity id : this.getIdentities()) { ids.put(id.toJSON()); } - o.put("identites", ids); + o.put("identities", ids); o.put("features", new JSONArray(this.getFeatures())); + JSONArray forms = new JSONArray(); + for(Data data : this.forms) { + forms.put(createJSONFromForm(data)); + } + o.put("forms", forms); + return o; } catch(JSONException e) { return null; diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index dde385bd9..f1155b07d 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -52,7 +52,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private static DatabaseBackend instance = null; private static final String DATABASE_NAME = "history"; - private static final int DATABASE_VERSION = 26; + private static final int DATABASE_VERSION = 27; private static String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -402,6 +402,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (oldVersion < 26 && newVersion >= 26) { db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT); } + + if (oldVersion < 27 && newVersion >= 27) { + db.execSQL("DELETE FROM "+ServiceDiscoveryResult.TABLENAME); + } } public static synchronized DatabaseBackend getInstance(Context context) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index e8a98cdaf..c3340486a 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1768,7 +1768,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - private boolean checkListeners() { + public boolean checkListeners() { return (this.mOnAccountUpdate == null && this.mOnConversationUpdate == null && this.mOnRosterUpdate == null @@ -3181,7 +3181,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - private ServiceDiscoveryResult getCachedServiceDiscoveryResult(Pair key) { + public ServiceDiscoveryResult getCachedServiceDiscoveryResult(Pair key) { ServiceDiscoveryResult result = discoCache.get(key); if (result != null) { return result; diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java index 8dabcb5be..c81c5a1f3 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java +++ b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java @@ -9,7 +9,7 @@ import eu.siacs.conversations.xml.Element; public class Data extends Element { - private static final String FORM_TYPE = "FORM_TYPE"; + public static final String FORM_TYPE = "FORM_TYPE"; public Data() { super("x"); -- cgit v1.2.3 From 70497318ddb8f4a441ef369e24041a3e4d4e1f1f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:42:57 +0200 Subject: remove unwanted 'use previous encryption' lookup --- .../siacs/conversations/entities/Conversation.java | 23 +--------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 9d814046a..10b42b460 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -641,23 +641,6 @@ public class Conversation extends AbstractEntity implements Blockable { return this.nextCounterpart; } - private int getMostRecentlyUsedOutgoingEncryption() { - synchronized (this.messages) { - for(int i = this.messages.size() -1; i >= 0; --i) { - 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) { - return Message.ENCRYPTION_PGP; - } else { - return e; - } - } - } - } - return Message.ENCRYPTION_NONE; - } - private int getMostRecentlyUsedIncomingEncryption() { synchronized (this.messages) { for(int i = this.messages.size() -1; i >= 0; --i) { @@ -686,12 +669,8 @@ public class Conversation extends AbstractEntity implements Blockable { && getAccount().getSelfContact().getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY) && getContact().getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY)) { return Message.ENCRYPTION_AXOLOTL; - } - int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); - if (outgoing == Message.ENCRYPTION_NONE) { - next = this.getMostRecentlyUsedIncomingEncryption(); } else { - next = outgoing; + next = this.getMostRecentlyUsedIncomingEncryption(); } } -- cgit v1.2.3 From 3f65b0e985db52a38b639ca8bbad9167b1cc8d1a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:44:16 +0200 Subject: access disco over caching mechanism instead of querying db --- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 66fd65272..f75f027b6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1027,7 +1027,7 @@ public class XmppConnection implements Runnable { final String ver = caps == null ? null : caps.getAttribute("ver"); ServiceDiscoveryResult discoveryResult = null; if (hash != null && ver != null) { - discoveryResult = mXmppConnectionService.databaseBackend.findDiscoveryResult(hash, ver); + discoveryResult = mXmppConnectionService.getCachedServiceDiscoveryResult(new Pair<>(hash, ver)); } if (discoveryResult == null) { sendServiceDiscoveryInfo(account.getServer()); -- cgit v1.2.3 From ef27055434489aa09b1d4b0597249a869a505639 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:46:19 +0200 Subject: show password dialog when account was magic created --- .../conversations/ui/EditAccountActivity.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 41d12d89a..1ba7dd3d0 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -507,6 +507,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate final MenuItem showBlocklist = menu.findItem(R.id.action_show_block_list); final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more); final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server); + final MenuItem showPassword = menu.findItem(R.id.action_show_password); final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices); final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate); final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs); @@ -535,6 +536,13 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate mamPrefs.setVisible(false); changePresence.setVisible(false); } + + if (mAccount != null) { + showPassword.setVisible(mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) + && !mAccount.isOptionSet(Account.OPTION_REGISTER)); + } else { + showPassword.setVisible(false); + } return super.onCreateOptionsMenu(menu); } @@ -642,6 +650,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate case R.id.action_change_presence: changePresence(); break; + case R.id.action_show_password: + showPassword(); + break; } return super.onOptionsItemSelected(item); } @@ -900,6 +911,17 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate xmppConnectionService.fetchMamPreferences(mAccount, this); } + private void showPassword() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + View view = getLayoutInflater().inflate(R.layout.dialog_show_password, null); + TextView password = (TextView) view.findViewById(R.id.password); + password.setText(mAccount.getPassword()); + builder.setTitle(R.string.password); + builder.setView(view); + builder.setPositiveButton(R.string.cancel, null); + builder.create().show(); + } + @Override public void onKeyStatusUpdated(AxolotlService.FetchStatus report) { refreshUi(); -- cgit v1.2.3 From 8d595c1fc2a083046a91919d9db29915d3dfeca6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:47:03 +0200 Subject: sync around individual calls instead of synchronizing entire object --- .../siacs/conversations/entities/MucOptions.java | 128 +++++++++++++-------- 1 file changed, 79 insertions(+), 49 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index d26ecd7c1..44d16cf23 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -28,11 +28,13 @@ public class MucOptions { public void changeAffiliation(Jid jid, Affiliation affiliation) { User user = findUserByRealJid(jid); - if (user != null && user.getRole() == Role.NONE) { - users.remove(user); - if (affiliation.ranks(Affiliation.MEMBER)) { - user.affiliation = affiliation; - users.add(user); + synchronized (users) { + if (user != null && user.getRole() == Role.NONE) { + users.remove(user); + if (affiliation.ranks(Affiliation.MEMBER)) { + user.affiliation = affiliation; + users.add(user); + } } } } @@ -155,10 +157,6 @@ public class MucOptions { this.realJid = jid != null ? jid.toBareJid() : null; } - public Jid getRealJid() { - return this.realJid; - } - public Role getRole() { return this.role; } @@ -299,10 +297,14 @@ public class MucOptions { return getName().compareToIgnoreCase(another.getName()); } } + + public Jid getRealJid() { + return realJid; + } } private Account account; - private final Set users = Collections.synchronizedSet(new HashSet()); + private final Set users = new HashSet<>(); private final List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; @@ -373,12 +375,14 @@ public class MucOptions { public User deleteUser(Jid jid) { User user = findUserByFullJid(jid); if (user != null) { - users.remove(user); - if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null) { - user.role = Role.NONE; - user.avatar = null; - user.fullJid = null; - users.add(user); + synchronized (users) { + users.remove(user); + if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null) { + user.role = Role.NONE; + user.avatar = null; + user.fullJid = null; + users.add(user); + } } } return user; @@ -389,28 +393,40 @@ public class MucOptions { if (user.fullJid == null && user.realJid != null) { old = findUserByRealJid(user.realJid); if (old != null) { - return; //don't add. user already exists + if (old.fullJid != null) { + return; //don't add. user already exists + } else { + synchronized (users) { + users.remove(old); + } + } } } else if (user.realJid != null) { old = findUserByRealJid(user.realJid); - if (old != null && old.fullJid == null) { - users.remove(old); + synchronized (users) { + if (old != null && old.fullJid == null) { + users.remove(old); + } } } old = findUserByFullJid(user.getFullJid()); - if (old != null) { - users.remove(old); + synchronized (this.users) { + if (old != null) { + users.remove(old); + } + this.users.add(user); } - this.users.add(user); } public User findUserByFullJid(Jid jid) { if (jid == null) { return null; } - for(User user : users) { - if (jid.equals(user.getFullJid())) { - return user; + synchronized (users) { + for (User user : users) { + if (jid.equals(user.getFullJid())) { + return user; + } } } return null; @@ -420,9 +436,11 @@ public class MucOptions { if (jid == null) { return null; } - for(User user : users) { - if (jid.equals(user.getRealJid())) { - return user; + synchronized (users) { + for (User user : users) { + if (jid.equals(user.realJid)) { + return user; + } } } return null; @@ -446,16 +464,18 @@ public class MucOptions { } public ArrayList getUsers(boolean includeOffline) { - if (includeOffline) { - return new ArrayList<>(users); - } else { - ArrayList onlineUsers = new ArrayList<>(); - for(User user : users) { - if(user.getRole().ranks(Role.PARTICIPANT)) { - onlineUsers.add(user); + synchronized (users) { + if (includeOffline) { + return new ArrayList<>(users); + } else { + ArrayList onlineUsers = new ArrayList<>(); + for (User user : users) { + if (user.getRole().ranks(Role.PARTICIPANT)) { + onlineUsers.add(user); + } } + return onlineUsers; } - return onlineUsers; } } @@ -465,7 +485,9 @@ public class MucOptions { } public int getUserCount() { - return this.users.size(); + synchronized (users) { + return users.size(); + } } public String getProposedNick() { @@ -501,7 +523,9 @@ public class MucOptions { } public void setOffline() { - this.users.clear(); + synchronized (users) { + this.users.clear(); + } this.error = Error.NO_RESPONSE; this.isOnline = false; } @@ -519,7 +543,7 @@ public class MucOptions { } public String createNameFromParticipants() { - if (users.size() >= 2) { + if (getUserCount() >= 2) { List names = new ArrayList<>(); for (User user : getUsers(5)) { Contact contact = user.getContact(); @@ -558,18 +582,22 @@ public class MucOptions { } public boolean pgpKeysInUse() { - for (User user : this.users) { - if (user.getPgpKeyId() != 0) { - return true; + synchronized (users) { + for (User user : users) { + if (user.getPgpKeyId() != 0) { + return true; + } } } return false; } public boolean everybodyHasKeys() { - for (User user : this.users) { - if (user.getPgpKeyId() == 0) { - return false; + synchronized (users) { + for (User user : users) { + if (user.getPgpKeyId() == 0) { + return false; + } } } return true; @@ -588,7 +616,7 @@ public class MucOptions { return account.getJid().toBareJid(); } User user = findUserByFullJid(jid); - return user == null ? null : user.getRealJid(); + return user == null ? null : user.realJid; } public String getPassword() { @@ -616,9 +644,11 @@ public class MucOptions { public List getMembers() { ArrayList members = new ArrayList<>(); - for(User user : users) { - if (user.affiliation.ranks(Affiliation.MEMBER) && user.getRealJid() != null) { - members.add(user.getRealJid()); + synchronized (users) { + for (User user : users) { + if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null) { + members.add(user.realJid); + } } } return members; -- cgit v1.2.3 From 9ce2cfa3d2e8aac80f8e73855a879baad78dad0d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 May 2016 10:47:27 +0200 Subject: resetting fetch status error when mutual subscription is reestablished --- src/main/java/eu/siacs/conversations/Config.java | 2 +- .../conversations/crypto/axolotl/AxolotlService.java | 18 ++++++++++++++++++ .../java/eu/siacs/conversations/parser/IqParser.java | 11 ++++++++++- .../eu/siacs/conversations/parser/MessageParser.java | 8 ++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 1c196b21a..ababe495f 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -77,7 +77,7 @@ public final class Config { 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 = false; // log stanza counts - public static final boolean EXTENDED_IQ_LOGGING = true; // log iq requests + public static final boolean BACKGROUND_STANZA_LOGGING = true; public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption public static final boolean ENCRYPT_ON_HTTP_UPLOADED = false; diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 327a1cc84..aac814433 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -216,6 +216,20 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private static class FetchStatusMap extends AxolotlAddressMap { + public void clearErrorFor(Jid jid) { + synchronized (MAP_LOCK) { + Map devices = this.map.get(jid.toBareJid().toString()); + if (devices == null) { + return; + } + for(Map.Entry entry : devices.entrySet()) { + if (entry.getValue() == FetchStatus.ERROR) { + Log.d(Config.LOGTAG,"resetting error for "+jid.toBareJid()+"("+entry.getKey()+")"); + entry.setValue(FetchStatus.TIMEOUT); + } + } + } + } } public static String getLogprefix(Account account) { @@ -320,6 +334,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { numPublishTriesOnEmptyPep = 0; } + public void clearErrorsInFetchStatusMap(Jid jid) { + fetchStatusMap.clearErrorFor(jid); + } + public void regenerateKeys(boolean wipeOther) { axolotlStore.regenerate(); sessions.clear(); diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index afbc04124..189df4a7b 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -54,6 +54,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { final String name = item.getAttribute("name"); final String subscription = item.getAttribute("subscription"); final Contact contact = account.getRoster().getContact(jid); + boolean bothPre = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM); if (!contact.getOption(Contact.Options.DIRTY_PUSH)) { contact.setServerName(name); contact.parseGroupsFromElement(item); @@ -69,6 +70,14 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { contact.parseSubscriptionFromElement(item); } } + boolean both = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM); + if ((both != bothPre) && both) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": gained mutual presence subscription with "+contact.getJid()); + AxolotlService axolotlService = account.getAxolotlService(); + if (axolotlService != null) { + axolotlService.clearErrorsInFetchStatusMap(contact.getJid()); + } + } mXmppConnectionService.getAvatarService().clear(contact); } } @@ -268,7 +277,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (Config.EXTENDED_IQ_LOGGING && (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET)) { + if (Config.BACKGROUND_STANZA_LOGGING && (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET)) { Element first = packet.getChildren().size() > 0 ? packet.getChildren().get(0) : null; Log.d(Config.LOGTAG,account.getJid().toBareJid()+": IQ request from "+packet.getFrom()+(first == null ? "" : " "+first)); } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 642ea9313..a3fd9916a 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -533,6 +533,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } } else if (!packet.hasChild("body")){ //no body + if (Config.BACKGROUND_STANZA_LOGGING && !mXmppConnectionService.checkListeners()) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": " + original); + } Conversation conversation = mXmppConnectionService.find(account, from.toBareJid()); if (isTypeGroupChat) { if (packet.hasChild("subject")) { @@ -563,6 +566,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece for(Element child : mucUserElement.getChildren()) { if ("item".equals(child.getName())) { MucOptions.User user = AbstractParser.parseItem(conversation,child); + Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for " + +user.getRealJid()+" to "+user.getAffiliation()+" in " + +conversation.getJid().toBareJid()); if (!user.realJidMatchesAccount()) { conversation.getMucOptions().addUser(user); } @@ -572,6 +578,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } + + Element received = packet.findChild("received", "urn:xmpp:chat-markers:0"); if (received == null) { received = packet.findChild("received", "urn:xmpp:receipts"); -- cgit v1.2.3