From 1a073ca45455dcf46bb4d8bcaa962030a65c435a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 19 Apr 2016 18:03:24 +0200 Subject: added magic create welcome screen --- src/main/java/eu/siacs/conversations/Config.java | 1 + .../services/XmppConnectionService.java | 12 +++ .../conversations/ui/ConversationActivity.java | 13 ++- .../conversations/ui/EditAccountActivity.java | 4 +- .../conversations/ui/MagicCreateActivity.java | 113 +++++++++++++++++++++ .../eu/siacs/conversations/ui/WelcomeActivity.java | 37 +++++++ 6 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java create mode 100644 src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java (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 bfbf9a7f..2b12474c 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -38,6 +38,7 @@ public final class Config { public static final String DOMAIN_LOCK = null; //only allow account creation for this domain + public static final String MAGIC_CREATE_DOMAIN = null; public static final String CONFERENCE_DOMAIN_LOCK = null; //only allow conference creation for this domain public static final boolean LOCK_DOMAINS_IN_CONVERSATIONS = false; //only add contacts and conferences for own domains diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index dbfb818d..5040664a 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3217,6 +3217,18 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return mPushManagementService; } + public Account getPendingAccount() { + Account pending = null; + for(Account account : getAccounts()) { + if (account.isOptionSet(Account.OPTION_REGISTER)) { + pending = account; + } else { + return null; + } + } + return pending; + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); void onPreferencesFetchFailed(); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 920c07af..dbd3139f 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1125,6 +1125,8 @@ public class ConversationActivity extends XmppActivity if (mRedirected.compareAndSet(false, true)) { if (Config.X509_VERIFICATION) { startActivity(new Intent(this, ManageAccountActivity.class)); + } else if (Config.MAGIC_CREATE_DOMAIN != null) { + startActivity(new Intent(this, WelcomeActivity.class)); } else { startActivity(new Intent(this, EditAccountActivity.class)); } @@ -1132,9 +1134,14 @@ public class ConversationActivity extends XmppActivity } } else if (conversationList.size() <= 0) { if (mRedirected.compareAndSet(false, true)) { - Intent intent = new Intent(this, StartConversationActivity.class); - intent.putExtra("init", true); - startActivity(intent); + Account pendingAccount = xmppConnectionService.getPendingAccount(); + if (pendingAccount == null) { + Intent intent = new Intent(this, StartConversationActivity.class); + intent.putExtra("init", true); + startActivity(intent); + } else { + switchToAccount(pendingAccount, true); + } finish(); } } else if (getIntent() != null && VIEW_CONVERSATION.equals(getIntent().getType())) { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 48ccb9f0..b2c7f1a9 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -546,7 +546,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } updateAccountInformation(true); } - } else if (this.xmppConnectionService.getAccounts().size() == 0) { + } + if (this.xmppConnectionService.getAccounts().size() == 0 + || this.mAccount == xmppConnectionService.getPendingAccount()) { if (getActionBar() != null) { getActionBar().setDisplayHomeAsUpEnabled(false); getActionBar().setDisplayShowHomeEnabled(false); diff --git a/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java new file mode 100644 index 00000000..6b32bdc2 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java @@ -0,0 +1,113 @@ +package eu.siacs.conversations.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import java.security.SecureRandom; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; + +public class MagicCreateActivity extends XmppActivity implements TextWatcher { + + private TextView mFullJidDisplay; + private EditText mUsername; + private SecureRandom mRandom; + + private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456780+-/#$!?"; + private static final int PW_LENGTH = 10; + + @Override + protected void refreshUiReal() { + + } + + @Override + void onBackendConnected() { + + } + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.magic_create); + mFullJidDisplay = (TextView) findViewById(R.id.full_jid); + mUsername = (EditText) findViewById(R.id.username); + mRandom = new SecureRandom(); + Button next = (Button) findViewById(R.id.create_account); + next.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String username = mUsername.getText().toString(); + if (username.contains("@") || username.length() < 3) { + mUsername.setError(getString(R.string.invalid_username)); + mUsername.requestFocus(); + } else { + mUsername.setError(null); + try { + Jid jid = Jid.fromParts(username.toLowerCase(), Config.MAGIC_CREATE_DOMAIN, null); + Account account = xmppConnectionService.findAccountByJid(jid); + if (account == null) { + account = new Account(jid, createPassword()); + account.setOption(Account.OPTION_REGISTER, true); + account.setOption(Account.OPTION_DISABLED, true); + xmppConnectionService.createAccount(account); + } + Intent intent = new Intent(MagicCreateActivity.this, EditAccountActivity.class); + intent.putExtra("jid", account.getJid().toBareJid().toString()); + intent.putExtra("init", true); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } catch (InvalidJidException e) { + mUsername.setError(getString(R.string.invalid_username)); + mUsername.requestFocus(); + } + } + } + }); + mUsername.addTextChangedListener(this); + } + + private String createPassword() { + StringBuilder builder = new StringBuilder(PW_LENGTH); + for(int i = 0; i < PW_LENGTH; ++i) { + builder.append(CHARS.charAt(mRandom.nextInt(CHARS.length() - 1))); + } + return builder.toString(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (s.toString().trim().length() > 0) { + try { + mFullJidDisplay.setVisibility(View.VISIBLE); + Jid jid = Jid.fromParts(s.toString().toLowerCase(), Config.MAGIC_CREATE_DOMAIN, null); + mFullJidDisplay.setText(getString(R.string.your_full_jid_will_be, jid.toString())); + } catch (InvalidJidException e) { + mFullJidDisplay.setVisibility(View.INVISIBLE); + } + + } else { + mFullJidDisplay.setVisibility(View.INVISIBLE); + } + } +} diff --git a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java new file mode 100644 index 00000000..5818ffd5 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java @@ -0,0 +1,37 @@ +package eu.siacs.conversations.ui; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +import eu.siacs.conversations.R; + +public class WelcomeActivity extends Activity { + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.welcome); + final Button createAccount = (Button) findViewById(R.id.create_account); + createAccount.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(WelcomeActivity.this, MagicCreateActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + startActivity(intent); + } + }); + final Button useOwnProvider = (Button) findViewById(R.id.use_own_provider); + useOwnProvider.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(WelcomeActivity.this, EditAccountActivity.class)); + finish(); + } + }); + + } + +} -- cgit v1.2.3 From 1901abd05fc051b776e2bbb10295f936408a0843 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 22 Apr 2016 21:25:06 +0200 Subject: expert setting to manually change presence --- .../eu/siacs/conversations/entities/Account.java | 35 +++- .../eu/siacs/conversations/entities/Bookmark.java | 13 +- .../eu/siacs/conversations/entities/Contact.java | 30 ++-- .../eu/siacs/conversations/entities/ListItem.java | 6 +- .../eu/siacs/conversations/entities/Presence.java | 43 +++-- .../conversations/entities/PresenceTemplate.java | 55 ++++++ .../siacs/conversations/parser/PresenceParser.java | 3 +- .../conversations/persistance/DatabaseBackend.java | 44 ++++- .../services/XmppConnectionService.java | 40 ++++- .../siacs/conversations/ui/BlocklistActivity.java | 2 +- .../conversations/ui/ChooseContactActivity.java | 2 +- .../ui/ConferenceDetailsActivity.java | 11 -- .../conversations/ui/ContactDetailsActivity.java | 2 +- .../conversations/ui/ConversationFragment.java | 12 +- .../conversations/ui/EditAccountActivity.java | 14 +- .../conversations/ui/SetPresenceActivity.java | 200 +++++++++++++++++++++ .../siacs/conversations/ui/SettingsActivity.java | 6 +- .../ui/StartConversationActivity.java | 4 +- .../eu/siacs/conversations/ui/XmppActivity.java | 15 ++ .../conversations/ui/adapter/ListItemAdapter.java | 2 +- .../eu/siacs/conversations/utils/UIHelper.java | 17 ++ 21 files changed, 479 insertions(+), 77 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java create mode 100644 src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 2356ffb9..c172f0e7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -43,6 +43,8 @@ public class Account extends AbstractEntity { public static final String DISPLAY_NAME = "display_name"; public static final String HOSTNAME = "hostname"; public static final String PORT = "port"; + public static final String STATUS = "status"; + public static final String STATUS_MESSAGE = "status_message"; public static final String PINNED_MECHANISM_KEY = "pinned_mechanism"; @@ -168,15 +170,18 @@ public class Account extends AbstractEntity { private final Roster roster = new Roster(this); private List bookmarks = new CopyOnWriteArrayList<>(); private final Collection blocklist = new CopyOnWriteArraySet<>(); + private Presence.Status presenceStatus = Presence.Status.ONLINE; + private String presenceStatusMessage = null; public Account(final Jid jid, final String password) { this(java.util.UUID.randomUUID().toString(), jid, - password, 0, null, "", null, null, null, 5222); + password, 0, null, "", null, null, null, 5222, Presence.Status.ONLINE, null); } private Account(final String uuid, final Jid jid, - final String password, final int options, final String rosterVersion, final String keys, - final String avatar, String displayName, String hostname, int port) { + final String password, final int options, final String rosterVersion, final String keys, + final String avatar, String displayName, String hostname, int port, + final Presence.Status status, String statusMessage) { this.uuid = uuid; this.jid = jid; if (jid.isBareJid()) { @@ -194,6 +199,8 @@ public class Account extends AbstractEntity { this.displayName = displayName; this.hostname = hostname; this.port = port; + this.presenceStatus = status; + this.presenceStatusMessage = statusMessage; } public static Account fromCursor(final Cursor cursor) { @@ -212,7 +219,9 @@ public class Account extends AbstractEntity { cursor.getString(cursor.getColumnIndex(AVATAR)), cursor.getString(cursor.getColumnIndex(DISPLAY_NAME)), cursor.getString(cursor.getColumnIndex(HOSTNAME)), - cursor.getInt(cursor.getColumnIndex(PORT))); + cursor.getInt(cursor.getColumnIndex(PORT)), + Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS))), + cursor.getString(cursor.getColumnIndex(STATUS_MESSAGE))); } public boolean isOptionSet(final int option) { @@ -287,6 +296,22 @@ public class Account extends AbstractEntity { return getXmppConnection() != null && getStatus().isError() && getXmppConnection().getAttempt() >= 3; } + public void setPresenceStatus(Presence.Status status) { + this.presenceStatus = status; + } + + public Presence.Status getPresenceStatus() { + return this.presenceStatus; + } + + public void setPresenceStatusMessage(String message) { + this.presenceStatusMessage = message; + } + + public String getPresenceStatusMessage() { + return this.presenceStatusMessage; + } + public String getResource() { return jid.getResourcepart(); } @@ -347,6 +372,8 @@ public class Account extends AbstractEntity { values.put(DISPLAY_NAME, displayName); values.put(HOSTNAME, hostname); values.put(PORT, port); + values.put(STATUS, presenceStatus.toShowString()); + values.put(STATUS_MESSAGE, presenceStatusMessage); return values; } diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index 088dfd8a..8d97751c 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.entities; +import android.content.Context; + import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -76,7 +78,7 @@ public class Bookmark extends Element implements ListItem { } @Override - public List getTags() { + public List getTags(Context context) { ArrayList tags = new ArrayList(); for (Element element : getChildren()) { if (element.getName().equals("group") && element.getContent() != null) { @@ -114,7 +116,8 @@ public class Bookmark extends Element implements ListItem { } } - public boolean match(String needle) { + @Override + public boolean match(Context context, String needle) { if (needle == null) { return true; } @@ -122,12 +125,12 @@ public class Bookmark extends Element implements ListItem { final Jid jid = getJid(); return (jid != null && jid.toString().contains(needle)) || getDisplayName().toLowerCase(Locale.US).contains(needle) || - matchInTag(needle); + matchInTag(context, needle); } - private boolean matchInTag(String needle) { + private boolean matchInTag(Context context, String needle) { needle = needle.toLowerCase(Locale.US); - for (Tag tag : getTags()) { + for (Tag tag : getTags(context)) { if (tag.getName().toLowerCase(Locale.US).contains(needle)) { return true; } diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 691fc3e4..e608688b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; +import android.content.Context; import android.database.Cursor; import org.json.JSONArray; @@ -141,25 +142,14 @@ public class Contact implements ListItem, Blockable { } @Override - public List getTags() { + public List getTags(Context context) { final ArrayList tags = new ArrayList<>(); for (final String group : getGroups()) { tags.add(new Tag(group, UIHelper.getColorForName(group))); } - switch (getMostAvailableStatus()) { - case CHAT: - case ONLINE: - tags.add(new Tag("online", 0xff259b24)); - break; - case AWAY: - tags.add(new Tag("away", 0xffff9800)); - break; - case XA: - tags.add(new Tag("not available", 0xfff44336)); - break; - case DND: - tags.add(new Tag("dnd", 0xfff44336)); - break; + Presence.Status status = getMostAvailableStatus(); + if (status != Presence.Status.OFFLINE) { + tags.add(UIHelper.getTagForStatus(context, status)); } if (isBlocked()) { tags.add(new Tag("blocked", 0xff2e2f3b)); @@ -167,7 +157,7 @@ public class Contact implements ListItem, Blockable { return tags; } - public boolean match(String needle) { + public boolean match(Context context, String needle) { if (needle == null || needle.isEmpty()) { return true; } @@ -175,7 +165,7 @@ public class Contact implements ListItem, Blockable { String[] parts = needle.split("\\s+"); if (parts.length > 1) { for(int i = 0; i < parts.length; ++i) { - if (!match(parts[i])) { + if (!match(context, parts[i])) { return false; } } @@ -183,13 +173,13 @@ public class Contact implements ListItem, Blockable { } else { return jid.toString().contains(needle) || getDisplayName().toLowerCase(Locale.US).contains(needle) || - matchInTag(needle); + matchInTag(context, needle); } } - private boolean matchInTag(String needle) { + private boolean matchInTag(Context context, String needle) { needle = needle.toLowerCase(Locale.US); - for (Tag tag : getTags()) { + for (Tag tag : getTags(context)) { if (tag.getName().toLowerCase(Locale.US).contains(needle)) { return true; } diff --git a/src/main/java/eu/siacs/conversations/entities/ListItem.java b/src/main/java/eu/siacs/conversations/entities/ListItem.java index 22aedd4b..178df2d1 100644 --- a/src/main/java/eu/siacs/conversations/entities/ListItem.java +++ b/src/main/java/eu/siacs/conversations/entities/ListItem.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.entities; +import android.content.Context; + import java.util.List; import eu.siacs.conversations.xmpp.jid.Jid; @@ -11,7 +13,7 @@ public interface ListItem extends Comparable { Jid getJid(); - List getTags(); + List getTags(Context context); final class Tag { private final String name; @@ -31,5 +33,5 @@ public interface ListItem extends Comparable { } } - boolean match(final String needle); + boolean match(Context context, final String needle); } diff --git a/src/main/java/eu/siacs/conversations/entities/Presence.java b/src/main/java/eu/siacs/conversations/entities/Presence.java index 442f1bca..485adaa1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presence.java +++ b/src/main/java/eu/siacs/conversations/entities/Presence.java @@ -17,41 +17,46 @@ public class Presence implements Comparable { case XA: return "xa"; case DND: return "dnd"; } - return null; } + + public static Status fromShowString(String show) { + if (show == null) { + return ONLINE; + } else { + switch (show.toLowerCase(Locale.US)) { + case "away": + return AWAY; + case "xa": + return XA; + case "dnd": + return DND; + case "chat": + return CHAT; + default: + return ONLINE; + } + } + } } protected final Status status; protected ServiceDiscoveryResult disco; protected final String ver; protected final String hash; + protected final String message; - private Presence(Status status, String ver, String hash) { + private Presence(Status status, String ver, String hash, String message) { this.status = status; this.ver = ver; this.hash = hash; + this.message = message; } - public static Presence parse(String show, Element caps) { + public static Presence parse(String show, Element caps, String message) { final String hash = caps == null ? null : caps.getAttribute("hash"); final String ver = caps == null ? null : caps.getAttribute("ver"); - if (show == null) { - return new Presence(Status.ONLINE, ver, hash); - } else { - switch (show.toLowerCase(Locale.US)) { - case "away": - return new Presence(Status.AWAY, ver, hash); - case "xa": - return new Presence(Status.XA, ver, hash); - case "dnd": - return new Presence(Status.DND, ver, hash); - case "chat": - return new Presence(Status.CHAT, ver, hash); - default: - return new Presence(Status.ONLINE, ver, hash); - } - } + return new Presence(Status.fromShowString(show), ver, hash, message); } public int compareTo(Object other) { diff --git a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java new file mode 100644 index 00000000..dd45d7e4 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java @@ -0,0 +1,55 @@ +package eu.siacs.conversations.entities; + +import android.content.ContentValues; +import android.database.Cursor; + + +public class PresenceTemplate extends AbstractEntity { + + public static final String TABELNAME = "presence_templates"; + public static final String LAST_USED = "last_used"; + public static final String MESSAGE = "message"; + public static final String STATUS = "status"; + + private long lastUsed = 0; + private String statusMessage; + private Presence.Status status = Presence.Status.ONLINE; + + public PresenceTemplate(Presence.Status status, String statusMessage) { + this.status = status; + this.statusMessage = statusMessage; + this.lastUsed = System.currentTimeMillis(); + this.uuid = java.util.UUID.randomUUID().toString(); + } + + private PresenceTemplate() { + + } + + @Override + public ContentValues getContentValues() { + ContentValues values = new ContentValues(); + values.put(LAST_USED, lastUsed); + values.put(MESSAGE, statusMessage); + values.put(STATUS, status.toShowString()); + values.put(UUID, uuid); + return values; + } + + public static PresenceTemplate fromCursor(Cursor cursor) { + PresenceTemplate template = new PresenceTemplate(); + template.uuid = cursor.getString(cursor.getColumnIndex(UUID)); + template.lastUsed = cursor.getLong(cursor.getColumnIndex(LAST_USED)); + template.statusMessage = cursor.getString(cursor.getColumnIndex(MESSAGE)); + template.status = Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS))); + return template; + } + + public Presence.Status getStatus() { + return status; + } + + public String getStatusMessage() { + return statusMessage; + } +} diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index c2782d23..5c5ca6be 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -196,7 +196,8 @@ public class PresenceParser extends AbstractParser implements final String show = packet.findChildContent("show"); final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps"); - final Presence presence = Presence.parse(show, caps); + final String message = packet.findChildContent("status"); + final Presence presence = Presence.parse(show, caps, message); contact.updatePresence(resource, presence); if (presence.hasCaps() && Config.REQUEST_DISCO) { mXmppConnectionService.fetchCaps(account, from, presence); diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 04c53238..1ccc1e41 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -41,6 +41,7 @@ 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.PresenceTemplate; import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.entities.ServiceDiscoveryResult; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -51,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 = 25; + private static final int DATABASE_VERSION = 26; private static String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -73,6 +74,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { + "UNIQUE(" + ServiceDiscoveryResult.HASH + ", " + ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);"; + private static String CREATE_PRESENCE_TEMPLATES_STATEMENT = "CREATE TABLE " + + PresenceTemplate.TABELNAME + "(" + + PresenceTemplate.UUID + " TEXT, " + + PresenceTemplate.LAST_USED + " NUMBER," + + PresenceTemplate.MESSAGE + " TEXT," + + PresenceTemplate.STATUS + " TEXT," + + "UNIQUE("+PresenceTemplate.MESSAGE + "," +PresenceTemplate.STATUS+") ON CONFLICT REPLACE);"; + private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE " + SQLiteAxolotlStore.PREKEY_TABLENAME + "(" + SQLiteAxolotlStore.ACCOUNT + " TEXT, " @@ -175,6 +184,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { db.execSQL(CREATE_PREKEYS_STATEMENT); db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT); db.execSQL(CREATE_IDENTITIES_STATEMENT); + db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT); } @Override @@ -331,6 +341,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.HOSTNAME + " TEXT"); db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.PORT + " NUMBER DEFAULT 5222"); } + if (oldVersion < 26 && newVersion >= 26) { + db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS + " TEXT"); + db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS_MESSAGE + " TEXT"); + } /* Any migrations that alter the Account table need to happen BEFORE this migration, as it * depends on account de-serialization. */ @@ -380,6 +394,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (oldVersion < 25 && newVersion >= 25) { db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.OOB + " INTEGER"); } + + if (oldVersion < 26 && newVersion >= 26) { + db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT); + } } public static synchronized DatabaseBackend getInstance(Context context) { @@ -430,6 +448,30 @@ public class DatabaseBackend extends SQLiteOpenHelper { return result; } + public void insertPresenceTemplate(PresenceTemplate template) { + SQLiteDatabase db = this.getWritableDatabase(); + db.insert(PresenceTemplate.TABELNAME, null, template.getContentValues()); + } + + public List getPresenceTemplates() { + ArrayList templates = new ArrayList<>(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor = db.query(PresenceTemplate.TABELNAME,null,null,null,null,null,PresenceTemplate.LAST_USED+" desc"); + while (cursor.moveToNext()) { + templates.add(PresenceTemplate.fromCursor(cursor)); + } + cursor.close(); + return templates; + } + + public void deletePresenceTemplate(PresenceTemplate template) { + Log.d(Config.LOGTAG,"deleting presence template with uuid "+template.getUuid()); + SQLiteDatabase db = this.getWritableDatabase(); + String where = PresenceTemplate.UUID+"=?"; + String[] whereArgs = {template.getUuid()}; + db.delete(PresenceTemplate.TABELNAME,where,whereArgs); + } + public CopyOnWriteArrayList getConversations(int status) { CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 5040664a..4aee6079 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -73,6 +73,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.OnRenameListener; import eu.siacs.conversations.entities.Presence; +import eu.siacs.conversations.entities.PresenceTemplate; import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.entities.ServiceDiscoveryResult; import eu.siacs.conversations.entities.Transferable; @@ -629,6 +630,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return getPreferences().getBoolean("xa_on_silent_mode", false); } + private boolean manuallyChangePresence() { + return getPreferences().getBoolean("manually_change_presence", false); + } + private boolean treatVibrateAsSilent() { return getPreferences().getBoolean("treat_vibrate_as_silent", false); } @@ -762,7 +767,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void toggleScreenEventReceiver() { - if (awayWhenScreenOff()) { + if (awayWhenScreenOff() && !manuallyChangePresence()) { final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(this.mEventReceiver, filter); @@ -2998,7 +3003,17 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void sendPresence(final Account account) { - sendPresencePacket(account, mPresenceGenerator.selfPresence(account, getTargetPresence())); + PresencePacket packet; + if (manuallyChangePresence()) { + packet = mPresenceGenerator.selfPresence(account, account.getPresenceStatus()); + String message = account.getPresenceStatusMessage(); + if (message != null && !message.isEmpty()) { + packet.addChild(new Element("status").setContent(message)); + } + } else { + packet = mPresenceGenerator.selfPresence(account, getTargetPresence()); + } + sendPresencePacket(account, packet); } public void refreshAllPresences() { @@ -3229,6 +3244,27 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return pending; } + public void changeStatus(Account account, Presence.Status status, String statusMessage) { + databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + changeStatusReal(account, status, statusMessage); + } + + private void changeStatusReal(Account account, Presence.Status status, String statusMessage) { + account.setPresenceStatus(status); + account.setPresenceStatusMessage(statusMessage); + databaseBackend.updateAccount(account); + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + sendPresence(account); + } + } + + public void changeStatus(Presence.Status status, String statusMessage) { + databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + for(Account account : getAccounts()) { + changeStatusReal(account, status, statusMessage); + } + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); void onPreferencesFetchFailed(); diff --git a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java index 5a85c17b..abec8ed7 100644 --- a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java @@ -49,7 +49,7 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem if (account != null) { for (final Jid jid : account.getBlocklist()) { final Contact contact = account.getRoster().getContact(jid); - if (contact.match(needle) && contact.isBlocked()) { + if (contact.match(this, needle) && contact.isBlocked()) { getListItems().add(contact); } } diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java index c5357a5e..1698343b 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -144,7 +144,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity { for (final Contact contact : account.getRoster().getContacts()) { if (contact.showInRoster() && !filterContacts.contains(contact.getJid().toBareJid().toString()) - && contact.match(needle)) { + && contact.match(this, needle)) { getListItems().add(contact); } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index a2757070..d7420359 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -643,17 +643,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setListItemBackgroundOnView(View view) { - int sdk = android.os.Build.VERSION.SDK_INT; - if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) { - view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground)); - } else { - view.setBackground(getResources().getDrawable(R.drawable.greybackground)); - } - } - private void viewPgpKey(User user) { PgpEngine pgp = xmppConnectionService.getPgpEngine(); if (pgp != null) { diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index e4fc59fa..308bc742 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -439,7 +439,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd keys.setVisibility(View.GONE); } - List tagList = contact.getTags(); + List tagList = contact.getTags(this); if (tagList.size() == 0 || !this.showDynamicTags) { tags.setVisibility(View.GONE); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 095bf58f..23b68e3b 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -474,9 +474,15 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } else { Account account = message.getConversation().getAccount(); - Intent intent = new Intent(activity, EditAccountActivity.class); - intent.putExtra("jid", account.getJid().toBareJid().toString()); - intent.putExtra("fingerprint", message.getFingerprint()); + Intent intent; + if (activity.manuallyChangePresence()) { + intent = new Intent(activity, SetPresenceActivity.class); + intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT, account.getJid().toBareJid().toString()); + } else { + intent = new Intent(activity, EditAccountActivity.class); + intent.putExtra("jid", account.getJid().toBareJid().toString()); + intent.putExtra("fingerprint", message.getFingerprint()); + } startActivity(intent); } } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index b2c7f1a9..04824193 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -476,6 +476,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate 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); + final MenuItem changePresence = menu.findItem(R.id.action_change_presence); + + changePresence.setVisible(manuallyChangePresence()); renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null); @@ -536,8 +539,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate protected void onBackendConnected() { if (this.jidToEdit != null) { this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit); - this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); if (this.mAccount != null) { + this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); if (this.mAccount.getPrivateKeyAlias() != null) { this.mPassword.setHint(R.string.authenticate_with_certificate); if (this.mInitMode) { @@ -593,6 +596,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate case R.id.action_renew_certificate: renewCertificate(); break; + case R.id.action_change_presence: + changePresence(); + break; } return super.onOptionsItemSelected(item); } @@ -601,6 +607,12 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null); } + private void changePresence() { + Intent intent = new Intent(this, SetPresenceActivity.class); + intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT,mAccount.getJid().toBareJid().toString()); + startActivity(intent); + } + @Override public void alias(String alias) { if (alias != null) { diff --git a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java new file mode 100644 index 00000000..5fe9c5d8 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java @@ -0,0 +1,200 @@ +package eu.siacs.conversations.ui; + +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.Spinner; +import android.widget.TextView; + +import android.util.Log; + +import java.util.List; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.atomic.AtomicBoolean; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.entities.Presence; +import eu.siacs.conversations.entities.PresenceTemplate; +import eu.siacs.conversations.utils.UIHelper; + +public class SetPresenceActivity extends XmppActivity implements View.OnClickListener { + + //data + protected Account mAccount; + private List mTemplates; + + //UI Elements + protected ScrollView mScrollView; + protected EditText mStatusMessage; + protected Spinner mShowSpinner; + protected CheckBox mAllAccounts; + protected LinearLayout mTemplatesView; + + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_set_presence); + mScrollView = (ScrollView) findViewById(R.id.scroll_view); + mShowSpinner = (Spinner) findViewById(R.id.presence_show); + ArrayAdapter adapter = ArrayAdapter.createFromResource(this, + R.array.presence_show_options, + R.layout.simple_list_item); + mShowSpinner.setAdapter(adapter); + mShowSpinner.setSelection(1); + mStatusMessage = (EditText) findViewById(R.id.presence_status_message); + mAllAccounts = (CheckBox) findViewById(R.id.all_accounts); + mTemplatesView = (LinearLayout) findViewById(R.id.templates); + final Button changePresence = (Button) findViewById(R.id.change_presence); + changePresence.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + executeChangePresence(); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.change_presence, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + if (item.getItemId() == R.id.action_account_details) { + if (mAccount != null) { + switchToAccount(mAccount); + } + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + + private void executeChangePresence() { + Presence.Status status = getStatusFromSpinner(); + boolean allAccounts = mAllAccounts.isChecked(); + String statusMessage = mStatusMessage.getText().toString().trim(); + if (allAccounts) { + xmppConnectionService.changeStatus(status, statusMessage); + } else if (mAccount != null) { + xmppConnectionService.changeStatus(mAccount, status, statusMessage); + } + finish(); + } + + private Presence.Status getStatusFromSpinner() { + switch (mShowSpinner.getSelectedItemPosition()) { + case 0: + return Presence.Status.CHAT; + case 2: + return Presence.Status.AWAY; + case 3: + return Presence.Status.XA; + case 4: + return Presence.Status.DND; + default: + return Presence.Status.ONLINE; + } + } + + private void setStatusInSpinner(Presence.Status status) { + switch(status) { + case AWAY: + mShowSpinner.setSelection(2); + break; + case XA: + mShowSpinner.setSelection(3); + break; + case CHAT: + mShowSpinner.setSelection(0); + break; + case DND: + mShowSpinner.setSelection(4); + break; + default: + mShowSpinner.setSelection(1); + break; + } + } + + @Override + protected void refreshUiReal() { + + } + + @Override + void onBackendConnected() { + mAccount = extractAccount(getIntent()); + if (mAccount != null) { + setStatusInSpinner(mAccount.getPresenceStatus()); + String message = mAccount.getPresenceStatusMessage(); + if (mStatusMessage.getText().length() == 0 && message != null) { + mStatusMessage.append(message); + } + mTemplates = xmppConnectionService.databaseBackend.getPresenceTemplates(); + } + redrawTemplates(); + } + + private void redrawTemplates() { + if (mTemplates == null || mTemplates.size() == 0) { + mTemplatesView.setVisibility(View.GONE); + } else { + mTemplatesView.removeAllViews(); + mTemplatesView.setVisibility(View.VISIBLE); + LayoutInflater inflater = getLayoutInflater(); + for (PresenceTemplate template : mTemplates) { + View templateLayout = inflater.inflate(R.layout.presence_template, mTemplatesView, false); + templateLayout.setTag(template); + setListItemBackgroundOnView(templateLayout); + templateLayout.setOnClickListener(this); + TextView message = (TextView) templateLayout.findViewById(R.id.presence_status_message); + TextView status = (TextView) templateLayout.findViewById(R.id.status); + ImageButton button = (ImageButton) templateLayout.findViewById(R.id.delete_button); + button.setTag(template); + button.setOnClickListener(this); + ListItem.Tag tag = UIHelper.getTagForStatus(this, template.getStatus()); + status.setText(tag.getName()); + status.setBackgroundColor(tag.getColor()); + message.setText(template.getStatusMessage()); + mTemplatesView.addView(templateLayout); + } + } + } + + @Override + public void onClick(View v) { + PresenceTemplate template = (PresenceTemplate) v.getTag(); + if (template == null) { + return; + } + if (v.getId() == R.id.presence_template) { + setStatusInSpinner(template.getStatus()); + mStatusMessage.getEditableText().clear(); + mStatusMessage.getEditableText().append(template.getStatusMessage()); + new Handler().post(new Runnable() { + @Override + public void run() { + mScrollView.smoothScrollTo(0,0); + } + }); + } else if (v.getId() == R.id.delete_button) { + xmppConnectionService.databaseBackend.deletePresenceTemplate(template); + mTemplates.remove(template); + redrawTemplates(); + } + } +} diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 750a7421..6eef7eb3 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -161,7 +161,8 @@ public class SettingsActivity extends XmppActivity implements "xa_on_silent_mode", "away_when_screen_off", "allow_message_correction", - "treat_vibrate_as_silent"); + "treat_vibrate_as_silent", + "manually_change_presence"); if (name.equals("resource")) { String resource = preferences.getString("resource", "mobile") .toLowerCase(Locale.US); @@ -182,7 +183,8 @@ public class SettingsActivity extends XmppActivity implements xmppConnectionService.toggleForegroundService(); } else if (resendPresence.contains(name)) { if (xmppConnectionServiceBound) { - if (name.equals("away_when_screen_off")) { + if (name.equals("away_when_screen_off") + || name.equals("manually_change_presence")) { xmppConnectionService.toggleScreenEventReceiver(); } xmppConnectionService.refreshAllPresences(); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 7d650e5b..4a59da21 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -738,7 +738,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU for (Contact contact : account.getRoster().getContacts()) { Presence p = contact.getPresences().getMostAvailablePresence(); Presence.Status s = p == null ? Presence.Status.OFFLINE : p.getStatus(); - if (contact.showInRoster() && contact.match(needle) + if (contact.showInRoster() && contact.match(this, needle) && (!this.mHideOfflineContacts || (needle != null && !needle.trim().isEmpty()) || s.compareTo(Presence.Status.OFFLINE) < 0)) { @@ -756,7 +756,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU for (Account account : xmppConnectionService.getAccounts()) { if (account.getStatus() != Account.State.DISABLED) { for (Bookmark bookmark : account.getBookmarks()) { - if (bookmark.match(needle)) { + if (bookmark.match(this, needle)) { this.conferences.add(bookmark); } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 7d70b20f..17086b7e 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -536,6 +536,17 @@ public abstract class XmppActivity extends Activity { } } + @SuppressWarnings("deprecation") + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + protected void setListItemBackgroundOnView(View view) { + int sdk = android.os.Build.VERSION.SDK_INT; + if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) { + view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground)); + } else { + view.setBackground(getResources().getDrawable(R.drawable.greybackground)); + } + } + protected void choosePgpSignId(Account account) { xmppConnectionService.getPgpEngine().chooseKey(account, new UiCallback() { @Override @@ -1006,6 +1017,10 @@ public abstract class XmppActivity extends Activity { return getPreferences().getString("picture_compression", "auto").equals("never"); } + protected boolean manuallyChangePresence() { + return getPreferences().getBoolean("manually_change_presence", false); + } + protected void unregisterNdefPushMessageCallback() { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null && nfcAdapter.isEnabled()) { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index da8e3910..02c54b77 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -62,7 +62,7 @@ public class ListItemAdapter extends ArrayAdapter { ImageView picture = (ImageView) view.findViewById(R.id.contact_photo); LinearLayout tagLayout = (LinearLayout) view.findViewById(R.id.tags); - List tags = item.getTags(); + List tags = item.getTags(activity); if (tags.size() == 0 || !this.showDynamicTags) { tagLayout.setVisibility(View.GONE); } else { diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index add3d80c..5ab058d1 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -14,7 +14,9 @@ import java.util.Locale; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.xmpp.jid.Jid; @@ -267,4 +269,19 @@ public class UIHelper { body = body.replace("?","").replace("¿",""); return LOCATION_QUESTIONS.contains(body); } + + public static ListItem.Tag getTagForStatus(Context context, Presence.Status status) { + switch (status) { + case CHAT: + return new ListItem.Tag(context.getString(R.string.presence_chat), 0xff259b24); + case AWAY: + return new ListItem.Tag(context.getString(R.string.presence_away), 0xffff9800); + case XA: + return new ListItem.Tag(context.getString(R.string.presence_xa), 0xfff44336); + case DND: + return new ListItem.Tag(context.getString(R.string.presence_dnd), 0xfff44336); + default: + return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24); + } + } } -- cgit v1.2.3 From a9c17681077c82b7095aa62b10f4f78c7a467e60 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 23 Apr 2016 12:19:00 +0200 Subject: show status messages in contact details --- .../eu/siacs/conversations/entities/Presences.java | 14 +++++++++++++ .../conversations/ui/ContactDetailsActivity.java | 24 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 813eda7a..5fe10de0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -1,8 +1,10 @@ package eu.siacs.conversations.entities; +import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import eu.siacs.conversations.xml.Element; @@ -57,4 +59,16 @@ public class Presences { return presences.containsKey(presence); } } + + public List getStatusMessages() { + ArrayList messages = new ArrayList<>(); + synchronized (this.presences) { + for(Presence presence : this.presences.values()) { + if (presence.message != null && !presence.message.trim().isEmpty()) { + messages.add(presence.message.trim()); + } + } + } + return messages; + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 308bc742..b4a5277c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -42,6 +42,7 @@ import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; import eu.siacs.conversations.utils.CryptoHelper; @@ -107,6 +108,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd private TextView contactJidTv; private TextView accountJidTv; private TextView lastseen; + private TextView statusMessage; private CheckBox send; private CheckBox receive; private Button addContactButton; @@ -203,6 +205,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd contactJidTv = (TextView) findViewById(R.id.details_contactjid); accountJidTv = (TextView) findViewById(R.id.details_account); lastseen = (TextView) findViewById(R.id.details_lastseen); + statusMessage = (TextView) findViewById(R.id.status_message); send = (CheckBox) findViewById(R.id.details_send_presence); receive = (CheckBox) findViewById(R.id.details_receive_presence); badge = (QuickContactBadge) findViewById(R.id.details_contact_badge); @@ -310,6 +313,25 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd send.setOnCheckedChangeListener(null); receive.setOnCheckedChangeListener(null); + List statusMessages = contact.getPresences().getStatusMessages(); + if (statusMessages.size() == 0) { + statusMessage.setVisibility(View.GONE); + } else { + StringBuilder builder = new StringBuilder(); + statusMessage.setVisibility(View.VISIBLE); + int s = statusMessages.size(); + for(int i = 0; i < s; ++i) { + if (s > 1) { + builder.append("• "); + } + builder.append(statusMessages.get(i)); + if (i < s - 1) { + builder.append("\n"); + } + } + statusMessage.setText(builder); + } + if (contact.getOption(Contact.Options.FROM)) { send.setText(R.string.send_presence_updates); send.setChecked(true); @@ -342,13 +364,13 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd receive.setEnabled(false); send.setEnabled(false); } - send.setOnCheckedChangeListener(this.mOnSendCheckedChange); receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange); } else { addContactButton.setVisibility(View.VISIBLE); send.setVisibility(View.GONE); receive.setVisibility(View.GONE); + statusMessage.setVisibility(View.GONE); } if (contact.isBlocked() && !this.showDynamicTags) { -- cgit v1.2.3 From cd1fbf60ec920bbdb179c437a06db66a4de19483 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 23 Apr 2016 12:33:56 +0200 Subject: add change prescence to manage account context menu --- .../java/eu/siacs/conversations/ui/EditAccountActivity.java | 5 ++--- .../java/eu/siacs/conversations/ui/ManageAccountActivity.java | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) (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 04824193..d4b0172d 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -477,9 +477,6 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate); final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs); final MenuItem changePresence = menu.findItem(R.id.action_change_presence); - - changePresence.setVisible(manuallyChangePresence()); - renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null); if (mAccount != null && mAccount.isOnlineAndConnected()) { @@ -494,6 +491,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (otherDevices == null || otherDevices.isEmpty()) { clearDevices.setVisible(false); } + changePresence.setVisible(manuallyChangePresence()); } else { showQrCode.setVisible(false); showBlocklist.setVisible(false); @@ -501,6 +499,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate changePassword.setVisible(false); clearDevices.setVisible(false); mamPrefs.setVisible(false); + changePresence.setVisible(false); } return super.onCreateOptionsMenu(menu); } diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index feac2c62..e43db5d3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -121,9 +121,11 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda menu.findItem(R.id.mgmt_account_disable).setVisible(false); menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false); menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false); + menu.findItem(R.id.mgmt_account_change_presence).setVisible(false); } else { menu.findItem(R.id.mgmt_account_enable).setVisible(false); menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(Config.supportOpenPgp()); + menu.findItem(R.id.mgmt_account_change_presence).setVisible(manuallyChangePresence()); } menu.setHeaderTitle(this.selectedAccount.getJid().toBareJid().toString()); } @@ -187,6 +189,9 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda case R.id.mgmt_account_announce_pgp: publishOpenPGPPublicKey(selectedAccount); return true; + case R.id.mgmt_account_change_presence: + changePresence(selectedAccount); + return true; default: return super.onContextItemSelected(item); } @@ -235,6 +240,12 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda } } + private void changePresence(Account account) { + Intent intent = new Intent(this, SetPresenceActivity.class); + intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT,account.getJid().toBareJid().toString()); + startActivity(intent); + } + public void onClickTglAccountState(Account account, boolean enable) { if (enable) { enableAccount(account); -- cgit v1.2.3 From a363e0a5d8a6d90f6153c8526a38ec0055dc4141 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 23 Apr 2016 15:10:35 +0200 Subject: don't create templates for empty status messages --- .../eu/siacs/conversations/services/XmppConnectionService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 4aee6079..236877a5 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3245,7 +3245,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void changeStatus(Account account, Presence.Status status, String statusMessage) { - databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + if (!statusMessage.isEmpty()) { + databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + } changeStatusReal(account, status, statusMessage); } @@ -3259,7 +3261,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void changeStatus(Presence.Status status, String statusMessage) { - databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + if (!statusMessage.isEmpty()) { + databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); + } for(Account account : getAccounts()) { changeStatusReal(account, status, statusMessage); } -- cgit v1.2.3 From 59652ecaf2d249d2e0046614fa0f3a3063b4b604 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 25 Apr 2016 11:06:17 +0200 Subject: fixed table creation --- .../conversations/persistance/DatabaseBackend.java | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 1ccc1e41..dde385bd 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -144,13 +144,19 @@ public class DatabaseBackend extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { db.execSQL("PRAGMA foreign_keys=ON;"); - db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID - + " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT," - + Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT," + db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID+ " TEXT PRIMARY KEY," + + Account.USERNAME + " TEXT," + + Account.SERVER + " TEXT," + + Account.PASSWORD + " TEXT," + Account.DISPLAY_NAME + " TEXT, " - + Account.ROSTERVERSION + " TEXT," + Account.OPTIONS - + " NUMBER, " + Account.AVATAR + " TEXT, " + Account.KEYS - + " TEXT, " + Account.HOSTNAME + " TEXT, " + Account.PORT + " NUMBER DEFAULT 5222)"); + + Account.STATUS + " TEXT," + + Account.STATUS_MESSAGE + " TEXT," + + Account.ROSTERVERSION + " TEXT," + + Account.OPTIONS + " NUMBER, " + + Account.AVATAR + " TEXT, " + + Account.KEYS + " TEXT, " + + Account.HOSTNAME + " TEXT, " + + Account.PORT + " NUMBER DEFAULT 5222)"); db.execSQL("create table " + Conversation.TABLENAME + " (" + Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME + " TEXT, " + Conversation.CONTACT + " TEXT, " @@ -329,6 +335,8 @@ public class DatabaseBackend extends SQLiteOpenHelper { recreateAxolotlDb(db); db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.FINGERPRINT + " TEXT"); + } else if (oldVersion < 22 && newVersion >= 22) { + db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE); } if (oldVersion < 16 && newVersion >= 16) { db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " @@ -379,10 +387,6 @@ public class DatabaseBackend extends SQLiteOpenHelper { } } - if (oldVersion < 22 && newVersion >= 22) { - db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE); - } - if (oldVersion < 23 && newVersion >= 23) { db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT); } -- cgit v1.2.3 From 9c3e910dc4c5605e0edad5ca876fff085f2150cb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 26 Apr 2016 23:23:48 +0200 Subject: prevent user from accidentally changing password after using magic create --- .../eu/siacs/conversations/entities/Account.java | 1 + .../services/XmppConnectionService.java | 1 + .../conversations/ui/ChangePasswordActivity.java | 22 ++++++++- .../conversations/ui/EditAccountActivity.java | 57 +++++++++++++++++----- .../conversations/ui/MagicCreateActivity.java | 3 ++ 5 files changed, 71 insertions(+), 13 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index c172f0e7..2c0ec7ff 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -52,6 +52,7 @@ public class Account extends AbstractEntity { public static final int OPTION_DISABLED = 1; public static final int OPTION_REGISTER = 2; public static final int OPTION_USECOMPRESSION = 3; + public static final int OPTION_MAGIC_CREATE = 4; public final HashSet> inProgressDiscoFetches = new HashSet<>(); public boolean httpUploadAvailable(long filesize) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 236877a5..f3326991 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1513,6 +1513,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onIqPacketReceived(final Account account, final IqPacket packet) { if (packet.getType() == IqPacket.TYPE.RESULT) { account.setPassword(newPassword); + account.setOption(Account.OPTION_MAGIC_CREATE, false); databaseBackend.updateAccount(account); callback.onPasswordChangeSucceeded(); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java index ccb3a22e..d4ef4090 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java @@ -1,9 +1,11 @@ package eu.siacs.conversations.ui; +import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; +import android.widget.TextView; import android.widget.Toast; import eu.siacs.conversations.R; @@ -22,7 +24,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti final String currentPassword = mCurrentPassword.getText().toString(); final String newPassword = mNewPassword.getText().toString(); final String newPasswordConfirm = mNewPasswordConfirm.getText().toString(); - if (!currentPassword.equals(mAccount.getPassword())) { + if (!mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && !currentPassword.equals(mAccount.getPassword())) { mCurrentPassword.requestFocus(); mCurrentPassword.setError(getString(R.string.account_status_unauthorized)); } else if (!newPassword.equals(newPasswordConfirm)) { @@ -43,6 +45,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti } } }; + private TextView mCurrentPasswordLabel; private EditText mCurrentPassword; private EditText mNewPassword; private EditText mNewPasswordConfirm; @@ -51,7 +54,13 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti @Override void onBackendConnected() { this.mAccount = extractAccount(getIntent()); - + if (this.mAccount != null && this.mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) { + this.mCurrentPasswordLabel.setVisibility(View.GONE); + this.mCurrentPassword.setVisibility(View.GONE); + } else { + this.mCurrentPasswordLabel.setVisibility(View.VISIBLE); + this.mCurrentPassword.setVisibility(View.VISIBLE); + } } @Override @@ -67,11 +76,20 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti }); this.mChangePasswordButton = (Button) findViewById(R.id.right_button); this.mChangePasswordButton.setOnClickListener(this.mOnChangePasswordButtonClicked); + this.mCurrentPasswordLabel = (TextView) findViewById(R.id.current_password_label); this.mCurrentPassword = (EditText) findViewById(R.id.current_password); this.mNewPassword = (EditText) findViewById(R.id.new_password); this.mNewPasswordConfirm = (EditText) findViewById(R.id.new_password_confirm); } + @Override + protected void onStart() { + super.onStart(); + Intent intent = getIntent(); + String password = intent != null ? intent.getStringExtra("password") : ""; + this.mNewPassword.getEditableText().append(password); + } + @Override public void onPasswordChangeSucceeded() { runOnUiThread(new Runnable() { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index d4b0172d..d6ea50fb 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -33,6 +33,8 @@ import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; +import android.util.Log; + import java.util.Arrays; import java.util.List; import java.util.Set; @@ -109,6 +111,13 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate @Override public void onClick(final View v) { + final String password = mPassword.getText().toString(); + final String passwordConfirm = mPasswordConfirm.getText().toString(); + + if (!mInitMode && passwordChangedInMagicCreateMode()) { + gotoChangePassword(password); + return; + } if (mInitMode && mAccount != null) { mAccount.setOption(Account.OPTION_DISABLED, false); } @@ -173,8 +182,6 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate mAccountJid.requestFocus(); return; } - final String password = mPassword.getText().toString(); - final String passwordConfirm = mPasswordConfirm.getText().toString(); if (registerNewAccount) { if (!password.equals(passwordConfirm)) { mPasswordConfirm.setError(getString(R.string.passwords_do_not_match)); @@ -183,6 +190,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } } if (mAccount != null) { + if (mInitMode && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) { + mAccount.setOption(Account.OPTION_MAGIC_CREATE, mAccount.getPassword().contains(password)); + } mAccount.setJid(jid); mAccount.setPort(numericPort); mAccount.setHostname(hostname); @@ -330,7 +340,13 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } protected void updateSaveButton() { - if (accountInfoEdited() && !mInitMode) { + boolean accountInfoEdited = accountInfoEdited(); + + if (!mInitMode && passwordChangedInMagicCreateMode()) { + this.mSaveButton.setText(R.string.change_password); + this.mSaveButton.setEnabled(true); + this.mSaveButton.setTextColor(getPrimaryTextColor()); + } else if (accountInfoEdited && !mInitMode) { this.mSaveButton.setText(R.string.save); this.mSaveButton.setEnabled(true); this.mSaveButton.setTextColor(getPrimaryTextColor()); @@ -349,7 +365,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (!mInitMode) { if (mAccount != null && mAccount.isOnlineAndConnected()) { this.mSaveButton.setText(R.string.save); - if (!accountInfoEdited()) { + if (!accountInfoEdited) { this.mSaveButton.setEnabled(false); this.mSaveButton.setTextColor(getSecondaryTextColor()); } @@ -366,16 +382,28 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (this.mAccount == null) { return false; } + return jidEdited() || + !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) || + !this.mAccount.getHostname().equals(this.mHostname.getText().toString()) || + !String.valueOf(this.mAccount.getPort()).equals(this.mPort.getText().toString()); + } + + protected boolean jidEdited() { final String unmodified; if (Config.DOMAIN_LOCK != null) { unmodified = this.mAccount.getJid().getLocalpart(); } else { unmodified = this.mAccount.getJid().toBareJid().toString(); } - return !unmodified.equals(this.mAccountJid.getText().toString()) || - !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) || - !this.mAccount.getHostname().equals(this.mHostname.getText().toString()) || - !String.valueOf(this.mAccount.getPort()).equals(this.mPort.getText().toString()); + return !unmodified.equals(this.mAccountJid.getText().toString()); + } + + protected boolean passwordChangedInMagicCreateMode() { + return mAccount != null + && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) + && !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) + && !this.jidEdited() + && mAccount.isOnlineAndConnected(); } @Override @@ -582,9 +610,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate item.setChecked(!item.isChecked()); break; case R.id.action_change_password_on_server: - final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class); - changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString()); - startActivity(changePasswordIntent); + gotoChangePassword(null); break; case R.id.action_mam_prefs: editMamPrefs(); @@ -602,6 +628,15 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return super.onOptionsItemSelected(item); } + private void gotoChangePassword(String newPassword) { + final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class); + changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString()); + if (newPassword != null) { + changePasswordIntent.putExtra("password", newPassword); + } + startActivity(changePasswordIntent); + } + private void renewCertificate() { KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null); } diff --git a/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java index 6b32bdc2..1b16e565 100644 --- a/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java @@ -8,6 +8,7 @@ import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; import java.security.SecureRandom; @@ -60,12 +61,14 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher { account = new Account(jid, createPassword()); account.setOption(Account.OPTION_REGISTER, true); account.setOption(Account.OPTION_DISABLED, true); + account.setOption(Account.OPTION_MAGIC_CREATE, true); xmppConnectionService.createAccount(account); } Intent intent = new Intent(MagicCreateActivity.this, EditAccountActivity.class); intent.putExtra("jid", account.getJid().toBareJid().toString()); intent.putExtra("init", true); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + Toast.makeText(MagicCreateActivity.this, R.string.secure_password_generated, Toast.LENGTH_SHORT).show(); startActivity(intent); } catch (InvalidJidException e) { mUsername.setError(getString(R.string.invalid_username)); -- cgit v1.2.3 From ebcb13c8ebdb9f0e1de8ea2c9b4c491f1d8ae308 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 27 Apr 2016 10:35:08 +0200 Subject: made it possible to go back to welcome screen from edit account --- .../java/eu/siacs/conversations/ui/EditAccountActivity.java | 10 +++++++--- src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) (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 d6ea50fb..9dd79ccf 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -315,9 +315,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate public void run() { final Intent intent; final XmppConnection connection = mAccount.getXmppConnection(); + final boolean wasFirstAccount = xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1; if (avatar != null || (connection != null && !connection.getFeatures().pep())) { intent = new Intent(getApplicationContext(), StartConversationActivity.class); - if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) { + if (wasFirstAccount) { intent.putExtra("init", true); } } else { @@ -325,6 +326,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toBareJid().toString()); intent.putExtra("setup", true); } + if (wasFirstAccount) { + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + } startActivity(intent); finish(); } @@ -577,8 +581,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate updateAccountInformation(true); } } - if (this.xmppConnectionService.getAccounts().size() == 0 - || this.mAccount == xmppConnectionService.getPendingAccount()) { + if ((Config.MAGIC_CREATE_DOMAIN == null && this.xmppConnectionService.getAccounts().size() == 0) + || (this.mAccount != null && this.mAccount == xmppConnectionService.getPendingAccount())) { if (getActionBar() != null) { getActionBar().setDisplayHomeAsUpEnabled(false); getActionBar().setDisplayShowHomeEnabled(false); diff --git a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java index 5818ffd5..78f0f609 100644 --- a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java @@ -28,7 +28,6 @@ public class WelcomeActivity extends Activity { @Override public void onClick(View v) { startActivity(new Intent(WelcomeActivity.this, EditAccountActivity.class)); - finish(); } }); -- cgit v1.2.3 From 29616d02a8e97a9044daec286bdfa7c862108fa4 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 27 Apr 2016 16:43:02 +0200 Subject: removed unused config variables --- src/main/java/eu/siacs/conversations/Config.java | 6 ------ .../java/eu/siacs/conversations/entities/Bookmark.java | 4 +--- .../java/eu/siacs/conversations/entities/Contact.java | 4 +--- .../conversations/ui/ConferenceDetailsActivity.java | 6 +----- .../eu/siacs/conversations/ui/EditAccountActivity.java | 6 ------ .../java/eu/siacs/conversations/ui/EnterJidDialog.java | 17 +++++------------ .../siacs/conversations/ui/ManageAccountActivity.java | 3 --- .../conversations/ui/StartConversationActivity.java | 17 +++++------------ .../java/eu/siacs/conversations/ui/XmppActivity.java | 13 ------------- src/main/java/eu/siacs/conversations/utils/Xmlns.java | 2 +- 10 files changed, 14 insertions(+), 64 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 2b12474c..1c83d05a 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -39,10 +39,6 @@ public final class Config { public static final String DOMAIN_LOCK = null; //only allow account creation for this domain public static final String MAGIC_CREATE_DOMAIN = null; - public static final String CONFERENCE_DOMAIN_LOCK = null; //only allow conference creation for this domain - public static final boolean LOCK_DOMAINS_IN_CONVERSATIONS = false; //only add contacts and conferences for own domains - - public static final boolean LOCK_SETTINGS = false; //set to true to disallow account and settings editing public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox public static final boolean ALLOW_NON_TLS_CONNECTIONS = false; //very dangerous. you should have a good reason to set this to true @@ -51,8 +47,6 @@ public final class Config { public static final boolean SHOW_CONNECTED_ACCOUNTS = false; //show number of connected accounts in foreground notification public static final boolean SHOW_DISABLE_FOREGROUND = true; //if set to true the foreground notification has a button to disable it - public static final boolean LEGACY_NAMESPACE_HTTP_UPLOAD = false; - public static final int PING_MAX_INTERVAL = 300; public static final int PING_MIN_INTERVAL = 30; public static final int PING_TIMEOUT = 15; diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index 8d97751c..fd6a5dab 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -63,9 +63,7 @@ public class Bookmark extends Element implements ListItem { @Override public String getDisplayJid() { Jid jid = getJid(); - if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && jid != null && jid.getDomainpart().equals(Config.CONFERENCE_DOMAIN_LOCK)) { - return jid.getLocalpart(); - } else if (jid != null) { + if (jid != null) { return jid.toString(); } else { return null; diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index e608688b..8721d9c4 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -124,9 +124,7 @@ public class Contact implements ListItem, Blockable { @Override public String getDisplayJid() { - if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && jid != null && jid.getDomainpart().equals(Config.DOMAIN_LOCK)) { - return jid.getLocalpart(); - } else if (jid != null) { + if (jid != null) { return jid.toString(); } else { return null; diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index d7420359..c806a03e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -528,11 +528,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers mAccountJid.setText(getString(R.string.using_account, account)); mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48))); setTitle(mConversation.getName()); - if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && mConversation.getJid().getDomainpart().equals(Config.CONFERENCE_DOMAIN_LOCK)) { - mFullJid.setText(mConversation.getJid().getLocalpart()); - } else { - mFullJid.setText(mConversation.getJid().toBareJid().toString()); - } + mFullJid.setText(mConversation.getJid().toBareJid().toString()); mYourNick.setText(mucOptions.getActualNick()); mRoleAffiliaton = (TextView) findViewById(R.id.muc_role); if (mucOptions.online()) { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 9dd79ccf..7cb243db 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -674,12 +674,6 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mNamePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE); } - mPassword.setEnabled(!Config.LOCK_SETTINGS); - mAccountJid.setEnabled(!Config.LOCK_SETTINGS); - mHostname.setEnabled(!Config.LOCK_SETTINGS); - mPort.setEnabled(!Config.LOCK_SETTINGS); - mPasswordConfirm.setEnabled(!Config.LOCK_SETTINGS); - mRegisterNew.setEnabled(!Config.LOCK_SETTINGS); if (!mInitMode) { this.mAvatar.setVisibility(View.VISIBLE); diff --git a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java index a6b3c73c..89000a68 100644 --- a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java +++ b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java @@ -43,17 +43,14 @@ public class EnterJidDialog { final String title, final String positiveButton, final String prefilledJid, final String account, boolean allowEditJid ) { - final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(title); View dialogView = LayoutInflater.from(context).inflate(R.layout.enter_jid_dialog, null); final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id); - jabberIdDesc.setText(lock ? R.string.username : R.string.account_settings_jabber_id); + jabberIdDesc.setText(R.string.account_settings_jabber_id); final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid); - if (!lock) { - jid.setAdapter(new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, knownHosts)); - } + jid.setAdapter(new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, knownHosts)); if (prefilledJid != null) { jid.append(prefilledJid); if (!allowEditJid) { @@ -64,7 +61,7 @@ public class EnterJidDialog { } } - jid.setHint(Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null ? R.string.username_hint : R.string.account_settings_example_jabber_id); + jid.setHint(R.string.account_settings_example_jabber_id); if (account == null) { StartConversationActivity.populateAccountSpinner(context, activatedAccounts, spinner); @@ -100,13 +97,9 @@ public class EnterJidDialog { } final Jid contactJid; try { - if (lock) { - contactJid = Jid.fromParts(jid.getText().toString(), Config.DOMAIN_LOCK, null); - } else { - contactJid = Jid.fromString(jid.getText().toString()); - } + contactJid = Jid.fromString(jid.getText().toString()); } catch (final InvalidJidException e) { - jid.setError(context.getString(lock ? R.string.invalid_username : R.string.invalid_jid)); + jid.setError(context.getString(R.string.invalid_jid)); return; } diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index e43db5d3..4b870279 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -156,10 +156,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda if (Config.X509_VERIFICATION) { addAccount.setVisible(false); addAccountWithCertificate.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - } else { - addAccount.setVisible(!Config.LOCK_SETTINGS); } - addAccountWithCertificate.setVisible(!Config.LOCK_SETTINGS); if (!accountsLeftToEnable()) { enableAll.setVisible(false); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 4a59da21..558a9672 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -390,13 +390,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU final View dialogView = getLayoutInflater().inflate(R.layout.join_conference_dialog, null); final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid); - final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.CONFERENCE_DOMAIN_LOCK != null; final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id); - jabberIdDesc.setText(lock ? R.string.conference_name : R.string.conference_address); - jid.setHint(lock ? R.string.conference_name : R.string.conference_address_example); - if (!lock) { - jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts)); - } + jabberIdDesc.setText(R.string.conference_address); + jid.setHint(R.string.conference_address_example); + jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts)); if (prefilledJid != null) { jid.append(prefilledJid); } @@ -422,13 +419,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU } final Jid conferenceJid; try { - if (lock) { - conferenceJid = Jid.fromParts(jid.getText().toString(),Config.CONFERENCE_DOMAIN_LOCK, null); - } else { - conferenceJid = Jid.fromString(jid.getText().toString()); - } + conferenceJid = Jid.fromString(jid.getText().toString()); } catch (final InvalidJidException e) { - jid.setError(getString(lock ? R.string.invalid_conference_name : R.string.invalid_jid)); + jid.setError(getString(R.string.invalid_jid)); return; } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 17086b7e..b89b5560 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -378,19 +378,6 @@ public abstract class XmppActivity extends Activity { } } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - final MenuItem menuSettings = menu.findItem(R.id.action_settings); - final MenuItem menuManageAccounts = menu.findItem(R.id.action_accounts); - if (menuSettings != null) { - menuSettings.setVisible(!Config.LOCK_SETTINGS); - } - if (menuManageAccounts != null) { - menuManageAccounts.setVisible(!Config.LOCK_SETTINGS); - } - return super.onCreateOptionsMenu(menu); - } - protected boolean isOptimizingBattery() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); diff --git a/src/main/java/eu/siacs/conversations/utils/Xmlns.java b/src/main/java/eu/siacs/conversations/utils/Xmlns.java index a19ec791..ad30b3e6 100644 --- a/src/main/java/eu/siacs/conversations/utils/Xmlns.java +++ b/src/main/java/eu/siacs/conversations/utils/Xmlns.java @@ -7,5 +7,5 @@ public final class Xmlns { public static final String ROSTER = "jabber:iq:roster"; public static final String REGISTER = "jabber:iq:register"; public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; - public static final String HTTP_UPLOAD = Config.LEGACY_NAMESPACE_HTTP_UPLOAD ? "eu:siacs:conversations:http:upload" : "urn:xmpp:http:upload"; + public static final String HTTP_UPLOAD = "urn:xmpp:http:upload"; } -- cgit v1.2.3 From 5021b9a5dd2b8ba00682285a6b407641c970236e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 28 Apr 2016 19:02:20 +0200 Subject: don't request disco from self --- src/main/java/eu/siacs/conversations/Config.java | 2 -- src/main/java/eu/siacs/conversations/parser/PresenceParser.java | 2 +- 2 files changed, 1 insertion(+), 3 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 1c83d05a..c6d1f0b8 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -89,8 +89,6 @@ public final class Config { public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; - public static final boolean REQUEST_DISCO = true; - public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; public static final int MAM_MAX_MESSAGES = 500; diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 5c5ca6be..e6cfa38f 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -199,7 +199,7 @@ public class PresenceParser extends AbstractParser implements final String message = packet.findChildContent("status"); final Presence presence = Presence.parse(show, caps, message); contact.updatePresence(resource, presence); - if (presence.hasCaps() && Config.REQUEST_DISCO) { + if (presence.hasCaps() && !from.equals(account.getJid())) { mXmppConnectionService.fetchCaps(account, from, presence); } -- cgit v1.2.3 From 51753a1d3910d902c67febb649e7d60ab8423f61 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 28 Apr 2016 20:13:58 +0200 Subject: cleaned up captcha dialog --- .../conversations/ui/EditAccountActivity.java | 92 ++++++++++------------ 1 file changed, 41 insertions(+), 51 deletions(-) (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 7cb243db..b6341275 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -892,65 +892,55 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } @Override - public void onCaptchaRequested(final Account account, final String id, final Data data, - final Bitmap captcha) { - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - final ImageView view = new ImageView(this); - final LinearLayout layout = new LinearLayout(this); - final EditText input = new EditText(this); - - view.setImageBitmap(captcha); - view.setScaleType(ImageView.ScaleType.FIT_CENTER); - - input.setHint(getString(R.string.captcha_hint)); - - layout.setOrientation(LinearLayout.VERTICAL); - layout.addView(view); - layout.addView(input); + public void onCaptchaRequested(final Account account, final String id, final Data data, final Bitmap captcha) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) { + mCaptchaDialog.dismiss(); + } + final AlertDialog.Builder builder = new AlertDialog.Builder(EditAccountActivity.this); + final View view = getLayoutInflater().inflate(R.layout.captcha, null); + final ImageView imageView = (ImageView) view.findViewById(R.id.captcha); + final EditText input = (EditText) view.findViewById(R.id.input); + imageView.setImageBitmap(captcha); - builder.setTitle(getString(R.string.captcha_required)); - builder.setView(layout); + builder.setTitle(getString(R.string.captcha_required)); + builder.setView(view); - builder.setPositiveButton(getString(R.string.ok), - new DialogInterface.OnClickListener() { + builder.setPositiveButton(getString(R.string.ok), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String rc = input.getText().toString(); + data.put("username", account.getUsername()); + data.put("password", account.getPassword()); + data.put("ocr", rc); + data.submit(); + + if (xmppConnectionServiceBound) { + xmppConnectionService.sendCreateAccountWithCaptchaPacket( + account, id, data); + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - String rc = input.getText().toString(); - data.put("username", account.getUsername()); - data.put("password", account.getPassword()); - data.put("ocr", rc); - data.submit(); - - if (xmppConnectionServiceBound) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket( - account, id, data); + if (xmppConnectionService != null) { + xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); } } }); - builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (xmppConnectionService != null) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); - } - } - }); - - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - if (xmppConnectionService != null) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); - } - } - }); - runOnUiThread(new Runnable() { - @Override - public void run() { - if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) { - mCaptchaDialog.dismiss(); - } + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + if (xmppConnectionService != null) { + xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); + } + } + }); mCaptchaDialog = builder.create(); mCaptchaDialog.show(); } -- cgit v1.2.3 From 1d2e2f71c21f275fe2aa9676aaf932ee2abe8bad Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 28 Apr 2016 20:14:53 +0200 Subject: cancel potential tasks when receiving image preview from cache --- src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index b89b5560..bb901613 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -1146,6 +1146,9 @@ public abstract class XmppActivity extends Activity { @Override protected Bitmap doInBackground(Message... params) { + if (isCancelled()) { + return null; + } message = params[0]; try { return xmppConnectionService.getFileBackend().getThumbnail( @@ -1157,7 +1160,7 @@ public abstract class XmppActivity extends Activity { @Override protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { + if (bitmap != null && !isCancelled()) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); @@ -1176,6 +1179,7 @@ public abstract class XmppActivity extends Activity { bm = null; } if (bm != null) { + cancelPotentialWork(message, imageView); imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else { @@ -1189,13 +1193,13 @@ public abstract class XmppActivity extends Activity { try { task.execute(message); } catch (final RejectedExecutionException ignored) { + ignored.printStackTrace(); } } } } - public static boolean cancelPotentialWork(Message message, - ImageView imageView) { + public static boolean cancelPotentialWork(Message message, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) { -- cgit v1.2.3 From 252d015b711ca165695c18436f18352053ede3a5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 28 Apr 2016 20:15:28 +0200 Subject: synchronize around thumbnail cache to avoid loading images twice --- .../conversations/persistance/FileBackend.java | 33 ++++++++++++++-------- 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 30609214..c63ce870 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -20,6 +20,7 @@ import android.system.StructStat; import android.util.Base64; import android.util.Base64OutputStream; import android.util.Log; +import android.util.LruCache; import android.webkit.MimeTypeMap; import java.io.ByteArrayOutputStream; @@ -344,20 +345,28 @@ public class FileBackend { } } - public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) - throws FileNotFoundException { - Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(message.getUuid()); + public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException { + final String uuid = message.getUuid(); + final LruCache cache = mXmppConnectionService.getBitmapCache(); + Log.d(Config.LOGTAG,"get thumbnail for "+uuid+" cacheOnly="+Boolean.toString(cacheOnly)); + Bitmap thumbnail = cache.get(uuid); if ((thumbnail == null) && (!cacheOnly)) { - File file = getFile(message); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = calcSampleSize(file, size); - Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options); - if (fullsize == null) { - throw new FileNotFoundException(); + synchronized (cache) { + thumbnail = cache.get(uuid); + if (thumbnail != null) { + return thumbnail; + } + File file = getFile(message); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(file, size); + Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), options); + if (fullsize == null) { + throw new FileNotFoundException(); + } + thumbnail = resize(fullsize, size); + thumbnail = rotate(thumbnail, getRotation(file)); + this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail); } - thumbnail = resize(fullsize, size); - thumbnail = rotate(thumbnail, getRotation(file)); - this.mXmppConnectionService.getBitmapCache().put(message.getUuid(),thumbnail); } return thumbnail; } -- cgit v1.2.3 From 6d9ca2591575a5e04d554a168e45413a628f6540 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Apr 2016 13:24:26 +0200 Subject: catch rare NPE when determining max http size --- src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java index 4ed015f4..9a7414ef 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java @@ -27,6 +27,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.adapter.ConversationAdapter; +import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -264,6 +265,8 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer private void share(final Conversation conversation) { final Account account = conversation.getAccount(); + final XmppConnection connection = account.getXmppConnection(); + final long max = connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize(); mListView.setEnabled(false); if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) { if (share.uuid == null) { @@ -275,9 +278,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer return; } if (share.uris.size() != 0) { - final long max = account.getXmppConnection() - .getFeatures() - .getMaxHttpUploadSize(); OnPresenceSelected callback = new OnPresenceSelected() { @Override public void onPresenceSelected() { -- cgit v1.2.3 From c7882b7225bc9615aa69066c3182014992ad24d1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Apr 2016 13:48:30 +0200 Subject: port all android drop down list items to our own --- .../java/eu/siacs/conversations/ui/EditAccountActivity.java | 2 +- src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java | 6 +++--- .../eu/siacs/conversations/ui/StartConversationActivity.java | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) (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 b6341275..3d7eb1cc 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -593,7 +593,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } if (Config.DOMAIN_LOCK == null) { final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this, - android.R.layout.simple_list_item_1, + R.layout.simple_list_item, xmppConnectionService.getKnownHosts()); this.mAccountJid.setAdapter(mKnownHostsAdapter); } diff --git a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java index 89000a68..f77d9c0a 100644 --- a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java +++ b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java @@ -50,7 +50,7 @@ public class EnterJidDialog { jabberIdDesc.setText(R.string.account_settings_jabber_id); final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid); - jid.setAdapter(new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, knownHosts)); + jid.setAdapter(new KnownHostsAdapter(context, R.layout.simple_list_item, knownHosts)); if (prefilledJid != null) { jid.append(prefilledJid); if (!allowEditJid) { @@ -67,10 +67,10 @@ public class EnterJidDialog { StartConversationActivity.populateAccountSpinner(context, activatedAccounts, spinner); } else { ArrayAdapter adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, + R.layout.simple_list_item, new String[] { account }); spinner.setEnabled(false); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + adapter.setDropDownViewResource(R.layout.simple_list_item); spinner.setAdapter(adapter); } diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 558a9672..78c05e41 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -393,7 +393,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id); jabberIdDesc.setText(R.string.conference_address); jid.setHint(R.string.conference_address_example); - jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts)); + jid.setAdapter(new KnownHostsAdapter(this, R.layout.simple_list_item, mKnownConferenceHosts)); if (prefilledJid != null) { jid.append(prefilledJid); } @@ -487,16 +487,15 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU public static void populateAccountSpinner(Context context, List accounts, Spinner spinner) { if (accounts.size() > 0) { - ArrayAdapter adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, accounts); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + ArrayAdapter adapter = new ArrayAdapter<>(context, R.layout.simple_list_item, accounts); + adapter.setDropDownViewResource(R.layout.simple_list_item); spinner.setAdapter(adapter); spinner.setEnabled(true); } else { ArrayAdapter adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, + R.layout.simple_list_item, Arrays.asList(new String[]{context.getString(R.string.no_accounts)})); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + adapter.setDropDownViewResource(R.layout.simple_list_item); spinner.setAdapter(adapter); spinner.setEnabled(false); } -- cgit v1.2.3 From d5608cb4f3bd357e46513a38b8f3676049992dcc Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Apr 2016 13:58:37 +0200 Subject: catch ActivityNotFoundException when requesting battery op --- src/main/java/eu/siacs/conversations/ui/ConversationActivity.java | 7 ++++++- src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index dbd3139f..2c98e4e7 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -5,6 +5,7 @@ import android.app.ActionBar; import android.app.AlertDialog; import android.app.FragmentTransaction; import android.app.PendingIntent; +import android.content.ActivityNotFoundException; import android.content.ClipData; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -1392,7 +1393,11 @@ public class ConversationActivity extends XmppActivity Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); Uri uri = Uri.parse("package:" + getPackageName()); intent.setData(uri); - startActivityForResult(intent, REQUEST_BATTERY_OP); + try { + startActivityForResult(intent, REQUEST_BATTERY_OP); + } catch (ActivityNotFoundException e) { + Toast.makeText(ConversationActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show(); + } } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 3d7eb1cc..59ac7e1b 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.PendingIntent; +import android.content.ActivityNotFoundException; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -445,7 +446,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); Uri uri = Uri.parse("package:"+getPackageName()); intent.setData(uri); - startActivityForResult(intent,REQUEST_BATTERY_OP); + try { + startActivityForResult(intent, REQUEST_BATTERY_OP); + } catch (ActivityNotFoundException e) { + Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show(); + } } }); this.mSessionEst = (TextView) findViewById(R.id.session_est); -- cgit v1.2.3 From 936006173ce11111f10c0bddd66d28c439ca584e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Apr 2016 20:38:23 +0200 Subject: properly cancel avatar tasks --- .../java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java | 5 +++-- src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java | 5 +++-- src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index f5f48a26..34c9d7b3 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -126,12 +126,12 @@ public class ConversationAdapter extends ArrayAdapter { @Override protected Bitmap doInBackground(Conversation... params) { - return activity.avatarService().get(params[0], activity.getPixel(56)); + return activity.avatarService().get(params[0], activity.getPixel(56), isCancelled()); } @Override protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { + if (bitmap != null && !isCancelled()) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); @@ -145,6 +145,7 @@ public class ConversationAdapter extends ArrayAdapter { if (cancelPotentialWork(conversation, imageView)) { final Bitmap bm = activity.avatarService().get(conversation, activity.getPixel(56), true); if (bm != null) { + cancelPotentialWork(conversation, imageView); imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 02c54b77..c29b01bc 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -106,12 +106,12 @@ public class ListItemAdapter extends ArrayAdapter { @Override protected Bitmap doInBackground(ListItem... params) { - return activity.avatarService().get(params[0], activity.getPixel(48)); + return activity.avatarService().get(params[0], activity.getPixel(48), isCancelled()); } @Override protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { + if (bitmap != null && !isCancelled()) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); @@ -125,6 +125,7 @@ public class ListItemAdapter extends ArrayAdapter { if (cancelPotentialWork(item, imageView)) { final Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true); if (bm != null) { + cancelPotentialWork(item, imageView); imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 0268097f..10179d7e 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -754,7 +754,7 @@ public class MessageAdapter extends ArrayAdapter { @Override protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { + if (bitmap != null && !isCancelled()) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); @@ -768,6 +768,7 @@ public class MessageAdapter extends ArrayAdapter { if (cancelPotentialWork(message, imageView)) { final Bitmap bm = activity.avatarService().get(message, activity.getPixel(48), true); if (bm != null) { + cancelPotentialWork(message, imageView); imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else { -- cgit v1.2.3 From 98ecac0ffa8fdf8852cd24f99c19e8e1088110ad Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 30 Apr 2016 13:34:20 +0200 Subject: removed unnecessary logging --- src/main/java/eu/siacs/conversations/persistance/FileBackend.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index c63ce870..df510efe 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -348,7 +348,6 @@ public class FileBackend { public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException { final String uuid = message.getUuid(); final LruCache cache = mXmppConnectionService.getBitmapCache(); - Log.d(Config.LOGTAG,"get thumbnail for "+uuid+" cacheOnly="+Boolean.toString(cacheOnly)); Bitmap thumbnail = cache.get(uuid); if ((thumbnail == null) && (!cacheOnly)) { synchronized (cache) { -- cgit v1.2.3 From d23178acb994ffdfcc135a0e8e54a3c7deadeef0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 May 2016 10:37:28 +0200 Subject: show only username when registering account with magic create --- src/main/java/eu/siacs/conversations/Config.java | 2 +- .../conversations/ui/EditAccountActivity.java | 33 ++++++++++++++-------- 2 files changed, 22 insertions(+), 13 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 c6d1f0b8..dfb55d6b 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -38,7 +38,7 @@ public final class Config { public static final String DOMAIN_LOCK = null; //only allow account creation for this domain - public static final String MAGIC_CREATE_DOMAIN = null; + public static final String MAGIC_CREATE_DOMAIN = "conversations.im"; public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox public static final boolean ALLOW_NON_TLS_CONNECTIONS = false; //very dangerous. you should have a good reason to set this to true diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 59ac7e1b..41d12d89 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -102,6 +102,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate private Jid jidToEdit; private boolean mInitMode = false; + private boolean mUsernameMode = Config.DOMAIN_LOCK != null; private boolean mShowOptions = false; private Account mAccount; private String messageFingerprint; @@ -128,20 +129,20 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return; } final boolean registerNewAccount = mRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI; - if (Config.DOMAIN_LOCK != null && mAccountJid.getText().toString().contains("@")) { + if (mUsernameMode && mAccountJid.getText().toString().contains("@")) { mAccountJid.setError(getString(R.string.invalid_username)); mAccountJid.requestFocus(); return; } final Jid jid; try { - if (Config.DOMAIN_LOCK != null) { - jid = Jid.fromParts(mAccountJid.getText().toString(), Config.DOMAIN_LOCK, null); + if (mUsernameMode) { + jid = Jid.fromParts(mAccountJid.getText().toString(), getUserModeDomain(), null); } else { jid = Jid.fromString(mAccountJid.getText().toString()); } } catch (final InvalidJidException e) { - if (Config.DOMAIN_LOCK != null) { + if (mUsernameMode) { mAccountJid.setError(getString(R.string.invalid_username)); } else { mAccountJid.setError(getString(R.string.invalid_jid)); @@ -175,7 +176,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } if (jid.isDomainJid()) { - if (Config.DOMAIN_LOCK != null) { + if (mUsernameMode) { mAccountJid.setError(getString(R.string.invalid_username)); } else { mAccountJid.setError(getString(R.string.invalid_jid)); @@ -395,7 +396,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate protected boolean jidEdited() { final String unmodified; - if (Config.DOMAIN_LOCK != null) { + if (mUsernameMode) { unmodified = this.mAccount.getJid().getLocalpart(); } else { unmodified = this.mAccount.getJid().toBareJid().toString(); @@ -427,10 +428,6 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid); this.mAccountJid.addTextChangedListener(this.mTextWatcher); this.mAccountJidLabel = (TextView) findViewById(R.id.account_jid_label); - if (Config.DOMAIN_LOCK != null) { - this.mAccountJidLabel.setText(R.string.username); - this.mAccountJid.setHint(R.string.username_hint); - } this.mPassword = (EditText) findViewById(R.id.account_password); this.mPassword.addTextChangedListener(this.mTextWatcher); this.mPasswordConfirm = (EditText) findViewById(R.id.account_password_confirm); @@ -577,6 +574,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit); if (this.mAccount != null) { this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); + this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER); if (this.mAccount.getPrivateKeyAlias() != null) { this.mPassword.setHint(R.string.authenticate_with_certificate); if (this.mInitMode) { @@ -596,7 +594,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mCancelButton.setEnabled(false); this.mCancelButton.setTextColor(getSecondaryTextColor()); } - if (Config.DOMAIN_LOCK == null) { + if (mUsernameMode) { + this.mAccountJidLabel.setText(R.string.username); + this.mAccountJid.setHint(R.string.username_hint); + } else { final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this, R.layout.simple_list_item, xmppConnectionService.getKnownHosts()); @@ -606,6 +607,14 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate invalidateOptionsMenu(); } + private String getUserModeDomain() { + if (mAccount != null) { + return mAccount.getJid().getDomainpart(); + } else { + return Config.DOMAIN_LOCK; + } + } + @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { @@ -666,7 +675,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate private void updateAccountInformation(boolean init) { if (init) { this.mAccountJid.getEditableText().clear(); - if (Config.DOMAIN_LOCK != null) { + if (mUsernameMode) { this.mAccountJid.getEditableText().append(this.mAccount.getJid().getLocalpart()); } else { this.mAccountJid.getEditableText().append(this.mAccount.getJid().toBareJid().toString()); -- cgit v1.2.3 From 06a561743a32aa0773bacdc75bed0bfd3bee6357 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 May 2016 14:31:30 +0200 Subject: ping all accounts at the same time --- .../services/XmppConnectionService.java | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index f3326991..ec4b0463 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -51,6 +51,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -555,6 +556,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } this.wakeLock.acquire(); + boolean pingNow = false; + HashSet pingCandidates = new HashSet<>(); + for (Account account : accounts) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!hasInternetConnection()) { @@ -583,12 +587,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa int secs = (int) (pingTimeoutIn / 1000); this.scheduleWakeUpCall(secs, account.getUuid().hashCode()); } - } else if (msToNextPing <= 0) { - account.getXmppConnection().sendPing(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping"); - this.scheduleWakeUpCall(Config.PING_TIMEOUT, account.getUuid().hashCode()); } else { - this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); + pingCandidates.add(account); + if (msToNextPing <= 0) { + pingNow = true; + } else { + this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); + } } } else if (account.getStatus() == Account.State.OFFLINE) { reconnectAccount(account, true, interactive); @@ -617,6 +622,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } } + if (pingNow) { + for (Account account : pingCandidates) { + account.getXmppConnection().sendPing(); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping"); + this.scheduleWakeUpCall(Config.PING_TIMEOUT, account.getUuid().hashCode()); + } + } if (wakeLock.isHeld()) { try { wakeLock.release(); -- cgit v1.2.3 From cef2eb58a76ee11b277c3d861d57cb4684e81fef Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 3 May 2016 22:16:51 +0200 Subject: fixed presence template dedup for 'online' status --- src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java index dd45d7e4..3b3ce08d 100644 --- a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java +++ b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java @@ -28,10 +28,11 @@ public class PresenceTemplate extends AbstractEntity { @Override public ContentValues getContentValues() { + final String show = status.toShowString(); ContentValues values = new ContentValues(); values.put(LAST_USED, lastUsed); values.put(MESSAGE, statusMessage); - values.put(STATUS, status.toShowString()); + values.put(STATUS, show == null ? "" : show); values.put(UUID, uuid); return values; } -- cgit v1.2.3 From cf374ec4efca617037f81d21bca7fdc7c5d524d2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 3 May 2016 23:35:57 +0200 Subject: Renaming of variable Was probably just a copy/paste typo. --- .../conversations/crypto/axolotl/SQLiteAxolotlStore.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 3c8cb3c1..979a2845 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java @@ -125,15 +125,15 @@ public class SQLiteAxolotlStore implements AxolotlStore { } private int loadCurrentPreKeyId() { - String regIdString = this.account.getKey(JSONKEY_CURRENT_PREKEY_ID); - int reg_id; - if (regIdString != null) { - reg_id = Integer.valueOf(regIdString); + String prekeyIdString = this.account.getKey(JSONKEY_CURRENT_PREKEY_ID); + int prekey_id; + if (prekeyIdString != null) { + prekey_id = Integer.valueOf(prekeyIdString); } else { Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve current prekey id for account " + account.getJid()); - reg_id = 0; + prekey_id = 0; } - return reg_id; + return prekey_id; } public void regenerate() { -- cgit v1.2.3 From 7047d68165db137cb6acdf084c218a77e17e8e80 Mon Sep 17 00:00:00 2001 From: klemens Date: Wed, 4 May 2016 10:29:29 +0200 Subject: spelling fixes --- .../java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java | 2 +- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 2 +- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 2 +- .../java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java | 4 ++-- 4 files changed, 5 insertions(+), 5 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 a24e4530..86d23761 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -350,7 +350,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public void registerDevices(final Jid jid, @NonNull final Set deviceIds) { if (jid.toBareJid().equals(account.getJid().toBareJid())) { if (!deviceIds.isEmpty()) { - Log.d(Config.LOGTAG, getLogprefix(account) + "Received non-empty own device list. Resetting publish attemps and pepBroken status."); + Log.d(Config.LOGTAG, getLogprefix(account) + "Received non-empty own device list. Resetting publish attempts and pepBroken status."); pepBroken = false; numPublishTriesOnEmptyPep = 0; } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ec4b0463..5fd8a053 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2528,7 +2528,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa callback.success(avatar); } Log.d(Config.LOGTAG, account.getJid().toBareJid() - + ": succesfuly fetched pep avatar for " + avatar.owner); + + ": successfully fetched pep avatar for " + avatar.owner); return; } } else { diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 4dc5492e..c1e26a70 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -485,7 +485,7 @@ public class XmppConnection implements Runnable { if ("true".equals(enabled.getAttribute("resume"))) { this.streamId = enabled.getAttribute("id"); Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() - + ": stream managment(" + smVersion + + ": stream management(" + smVersion + ") enabled (resumable)"); } else { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index beed92fa..c9ee6bdc 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -266,7 +266,7 @@ public class JingleConnection implements Transferable { @Override public void established() { Log.d(Config.LOGTAG, - "succesfully connected to our own primary candidate"); + "successfully connected to our own primary candidate"); mergeCandidate(candidate); sendInitRequest(); } @@ -594,7 +594,7 @@ public class JingleConnection implements Transferable { this.connect(); } else { Log.d(Config.LOGTAG, - "ignoring because file is already in transmission or we havent sent our candidate yet"); + "ignoring because file is already in transmission or we haven't sent our candidate yet"); } return true; } else { -- cgit v1.2.3 From fb41a4ffaa8aa8d47955cbb75cc0ba97107517a3 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 May 2016 18:22:17 +0200 Subject: fixed npe when calling changepassword activity directly --- src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java index d4ef4090..750a1da3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java @@ -86,8 +86,10 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti protected void onStart() { super.onStart(); Intent intent = getIntent(); - String password = intent != null ? intent.getStringExtra("password") : ""; - this.mNewPassword.getEditableText().append(password); + String password = intent != null ? intent.getStringExtra("password") : null; + if (password != null) { + this.mNewPassword.getEditableText().append(password); + } } @Override -- cgit v1.2.3 From c27663c4566762d06ff1ed1c98ed943c01a172f4 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 May 2016 18:23:36 +0200 Subject: clear password field before setting new one --- src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java index 750a1da3..3fb75630 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java @@ -88,6 +88,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti Intent intent = getIntent(); String password = intent != null ? intent.getStringExtra("password") : null; if (password != null) { + this.mNewPassword.getEditableText().clear(); this.mNewPassword.getEditableText().append(password); } } -- cgit v1.2.3 From 12704fa640ba7ea028f247f2709202cb6a8ec7e1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 May 2016 09:58:35 +0200 Subject: refactor captcha response handling to avoid network on main thread exception --- .../siacs/conversations/generator/IqGenerator.java | 6 ++- .../services/XmppConnectionService.java | 5 ++- .../siacs/conversations/xmpp/XmppConnection.java | 49 ++++++++-------------- 3 files changed, 25 insertions(+), 35 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index b7911ef7..daacfe59 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -303,8 +303,10 @@ public class IqGenerator extends AbstractGenerator { register.setTo(account.getServer()); register.setId(id); - register.query("jabber:iq:register").addChild(data); - + Element query = register.query("jabber:iq:register"); + if (data != null) { + query.addChild(data); + } return register; } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 5fd8a053..ba9d7968 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3002,9 +3002,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void sendCreateAccountWithCaptchaPacket(Account account, String id, Data data) { - XmppConnection connection = account.getXmppConnection(); + final XmppConnection connection = account.getXmppConnection(); if (connection != null) { - connection.sendCaptchaRegistryRequest(id, data); + IqPacket request = mIqGenerator.generateCreateAccountWithCaptcha(account, id, data); + sendIqPacket(account, request, connection.registrationResponseListener); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index c1e26a70..687f07da 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -176,28 +176,24 @@ public class XmppConnection implements Runnable { }; private Identity mServerIdentity = Identity.UNKNOWN; - private OnIqPacketReceived createPacketReceiveHandler() { - return new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE.RESULT) { - account.setOption(Account.OPTION_REGISTER, - false); - forceCloseSocket(); - changeStatus(Account.State.REGISTRATION_SUCCESSFUL); - } else if (packet.hasChild("error") - && (packet.findChild("error") - .hasChild("conflict"))) { - forceCloseSocket(); - changeStatus(Account.State.REGISTRATION_CONFLICT); - } else { - forceCloseSocket(); - changeStatus(Account.State.REGISTRATION_FAILED); - Log.d(Config.LOGTAG, packet.toString()); - } + public final OnIqPacketReceived registrationResponseListener = new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT) { + account.setOption(Account.OPTION_REGISTER, false); + forceCloseSocket(); + changeStatus(Account.State.REGISTRATION_SUCCESSFUL); + } else if (packet.hasChild("error") + && (packet.findChild("error").hasChild("conflict"))) { + forceCloseSocket(); + changeStatus(Account.State.REGISTRATION_CONFLICT); + } else { + forceCloseSocket(); + changeStatus(Account.State.REGISTRATION_FAILED); + Log.d(Config.LOGTAG, packet.toString()); } - }; - } + } + }; public XmppConnection(final Account account, final XmppConnectionService service) { this.account = account; @@ -809,15 +805,6 @@ public class XmppConnection implements Runnable { return mechanisms; } - public void sendCaptchaRegistryRequest(String id, Data data) { - if (data == null) { - setAccountCreationFailed(""); - } else { - IqPacket request = getIqGenerator().generateCreateAccountWithCaptcha(account, id, data); - sendIqPacket(request, createPacketReceiveHandler()); - } - } - private void sendRegistryRequest() { final IqPacket register = new IqPacket(IqPacket.TYPE.GET); register.query("jabber:iq:register"); @@ -835,7 +822,7 @@ public class XmppConnection implements Runnable { final Element password = new Element("password").setContent(account.getPassword()); register.query("jabber:iq:register").addChild(username); register.query().addChild(password); - sendIqPacket(register, createPacketReceiveHandler()); + sendIqPacket(register, registrationResponseListener); } else if (packet.getType() == IqPacket.TYPE.RESULT && (packet.query().hasChild("x", "jabber:x:data"))) { final Data data = Data.parse(packet.query().findChild("x", "jabber:x:data")); -- cgit v1.2.3 From 6e0ec9b924173bd2afe3b87646e3b1f4e907b7c1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 May 2016 13:17:04 +0200 Subject: republish pgp signature when changing status --- .../eu/siacs/conversations/crypto/PgpEngine.java | 5 ++- .../eu/siacs/conversations/entities/Account.java | 4 +- .../services/XmppConnectionService.java | 10 ++--- .../conversations/ui/ConversationActivity.java | 6 +-- .../conversations/ui/ConversationFragment.java | 2 +- .../conversations/ui/ManageAccountActivity.java | 6 +-- .../conversations/ui/SetPresenceActivity.java | 45 ++++++++++++++++++++-- .../siacs/conversations/ui/SettingsActivity.java | 3 ++ .../eu/siacs/conversations/ui/XmppActivity.java | 39 +++++++++++++++---- 9 files changed, 95 insertions(+), 25 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java index 7ca5bea0..b7d5ac8c 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java @@ -2,6 +2,7 @@ package eu.siacs.conversations.crypto; import android.app.PendingIntent; import android.content.Intent; +import android.util.Log; import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.util.OpenPgpApi; @@ -16,6 +17,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URL; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; @@ -299,7 +301,7 @@ public class PgpEngine { public void generateSignature(final Account account, String status, final UiCallback callback) { - if (account.getPgpId() == -1) { + if (account.getPgpId() == 0) { return; } Intent params = new Intent(); @@ -308,6 +310,7 @@ public class PgpEngine { params.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, account.getPgpId()); InputStream is = new ByteArrayInputStream(status.getBytes()); final OutputStream os = new ByteArrayOutputStream(); + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": signing status message \""+status+"\""); api.executeApiAsync(params, is, os, new IOpenPgpCallback() { @Override diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 2c0ec7ff..1bcb15c0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -478,10 +478,10 @@ public class Account extends AbstractEntity { try { return keys.getLong(KEY_PGP_ID); } catch (JSONException e) { - return -1; + return 0; } } else { - return -1; + return 0; } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ba9d7968..7aac94b6 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3258,18 +3258,18 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return pending; } - public void changeStatus(Account account, Presence.Status status, String statusMessage) { + public void changeStatus(Account account, Presence.Status status, String statusMessage, boolean send) { if (!statusMessage.isEmpty()) { databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); } - changeStatusReal(account, status, statusMessage); + changeStatusReal(account, status, statusMessage, send); } - private void changeStatusReal(Account account, Presence.Status status, String statusMessage) { + private void changeStatusReal(Account account, Presence.Status status, String statusMessage, boolean send) { account.setPresenceStatus(status); account.setPresenceStatusMessage(statusMessage); databaseBackend.updateAccount(account); - if (!account.isOptionSet(Account.OPTION_DISABLED)) { + if (!account.isOptionSet(Account.OPTION_DISABLED) && send) { sendPresence(account); } } @@ -3279,7 +3279,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage)); } for(Account account : getAccounts()) { - changeStatusReal(account, status, statusMessage); + changeStatusReal(account, status, statusMessage, true); } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 2c98e4e7..eb9ccb6b 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -825,7 +825,7 @@ public class ConversationActivity extends XmppActivity conversation.setNextEncryption(Message.ENCRYPTION_PGP); item.setChecked(true); } else { - announcePgp(conversation.getAccount(), conversation); + announcePgp(conversation.getAccount(), conversation, onOpenPGPKeyPublished); } } else { showInstallPgpDialog(); @@ -1284,7 +1284,7 @@ public class ConversationActivity extends XmppActivity // associate selected PGP keyId with the account mSelectedConversation.getAccount().setPgpSignId(data.getExtras().getLong(OpenPgpApi.EXTRA_SIGN_KEY_ID)); // we need to announce the key as described in XEP-027 - announcePgp(mSelectedConversation.getAccount(), null); + announcePgp(mSelectedConversation.getAccount(), null, onOpenPGPKeyPublished); } else { choosePgpSignId(mSelectedConversation.getAccount()); } @@ -1294,7 +1294,7 @@ public class ConversationActivity extends XmppActivity } } else if (requestCode == REQUEST_ANNOUNCE_PGP) { if (xmppConnectionServiceBound) { - announcePgp(mSelectedConversation.getAccount(), mSelectedConversation); + announcePgp(mSelectedConversation.getAccount(), mSelectedConversation, onOpenPGPKeyPublished); this.mPostponedActivityResult = null; } else { this.mPostponedActivityResult = new Pair<>(requestCode, data); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 23b68e3b..0b4608ba 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1188,7 +1188,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa return; } if (conversation.getAccount().getPgpSignature() == null) { - activity.announcePgp(conversation.getAccount(), conversation); + activity.announcePgp(conversation.getAccount(), conversation, activity.onOpenPGPKeyPublished); return; } if (conversation.getMode() == Conversation.MODE_SINGLE) { diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index 4b870279..2d29c521 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -328,7 +328,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda private void publishOpenPGPPublicKey(Account account) { if (ManageAccountActivity.this.hasPgp()) { - choosePgpSignId(selectedAccount); + announcePgp(selectedAccount, null, onOpenPGPKeyPublished); } else { this.showInstallPgpDialog(); } @@ -360,12 +360,12 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda if (requestCode == REQUEST_CHOOSE_PGP_ID) { if (data.getExtras().containsKey(OpenPgpApi.EXTRA_SIGN_KEY_ID)) { selectedAccount.setPgpSignId(data.getExtras().getLong(OpenPgpApi.EXTRA_SIGN_KEY_ID)); - announcePgp(selectedAccount, null); + announcePgp(selectedAccount, null, onOpenPGPKeyPublished); } else { choosePgpSignId(selectedAccount); } } else if (requestCode == REQUEST_ANNOUNCE_PGP) { - announcePgp(selectedAccount, null); + announcePgp(selectedAccount, null, onOpenPGPKeyPublished); } this.mPostponedActivityResult = null; } else { diff --git a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java index 5fe9c5d8..effd30bf 100644 --- a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java @@ -1,7 +1,9 @@ package eu.siacs.conversations.ui; +import android.content.Intent; import android.os.Bundle; import android.os.Handler; +import android.util.Pair; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -18,6 +20,8 @@ import android.widget.TextView; import android.util.Log; +import org.openintents.openpgp.util.OpenPgpApi; + import java.util.List; import java.util.concurrent.RunnableFuture; import java.util.concurrent.atomic.AtomicBoolean; @@ -42,6 +46,14 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis protected Spinner mShowSpinner; protected CheckBox mAllAccounts; protected LinearLayout mTemplatesView; + private Pair mPostponedActivityResult; + + private Runnable onPresenceChanged = new Runnable() { + @Override + public void run() { + finish(); + } + }; protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -83,16 +95,37 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (xmppConnectionServiceBound && mAccount != null) { + if (requestCode == REQUEST_ANNOUNCE_PGP) { + announcePgp(mAccount, null, onPresenceChanged); + } + this.mPostponedActivityResult = null; + } else { + this.mPostponedActivityResult = new Pair<>(requestCode, data); + } + } + } + private void executeChangePresence() { Presence.Status status = getStatusFromSpinner(); boolean allAccounts = mAllAccounts.isChecked(); String statusMessage = mStatusMessage.getText().toString().trim(); - if (allAccounts) { + if (allAccounts && noAccountUsesPgp()) { xmppConnectionService.changeStatus(status, statusMessage); + finish(); } else if (mAccount != null) { - xmppConnectionService.changeStatus(mAccount, status, statusMessage); + if (mAccount.getPgpId() == 0) { + xmppConnectionService.changeStatus(mAccount, status, statusMessage, true); + finish(); + } else { + xmppConnectionService.changeStatus(mAccount, status, statusMessage, false); + announcePgp(mAccount, null, onPresenceChanged); + } } - finish(); } private Presence.Status getStatusFromSpinner() { @@ -145,6 +178,12 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis mStatusMessage.append(message); } mTemplates = xmppConnectionService.databaseBackend.getPresenceTemplates(); + if (this.mPostponedActivityResult != null) { + this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second); + } + boolean e = noAccountUsesPgp(); + mAllAccounts.setEnabled(e); + mAllAccounts.setTextColor(e ? getPrimaryTextColor() : getSecondaryTextColor()); } redrawTemplates(); } diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 6eef7eb3..cd843b25 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -187,6 +187,9 @@ public class SettingsActivity extends XmppActivity implements || name.equals("manually_change_presence")) { xmppConnectionService.toggleScreenEventReceiver(); } + if (name.equals("manually_change_presence") && !noAccountUsesPgp()) { + Toast.makeText(this, R.string.republish_pgp_keys, Toast.LENGTH_LONG).show(); + } xmppConnectionService.refreshAllPresences(); } } else if (name.equals("dont_trust_system_cas")) { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index bb901613..b58fa6c2 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -68,6 +68,7 @@ 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; @@ -118,6 +119,13 @@ public abstract class XmppActivity extends Activity { protected int mTheme; protected boolean mUsingEnterKey = false; + protected Runnable onOpenPGPKeyPublished = new Runnable() { + @Override + public void run() { + Toast.makeText(XmppActivity.this,R.string.openpgp_has_been_published, Toast.LENGTH_SHORT).show(); + } + }; + private long mLastUiRefresh = 0; private Handler mRefreshUiHandler = new Handler(); private Runnable mRefreshUiRunnable = new Runnable() { @@ -489,18 +497,23 @@ public abstract class XmppActivity extends Activity { startActivityForResult(intent, REQUEST_INVITE_TO_CONVERSATION); } - protected void announcePgp(Account account, final Conversation conversation) { - if (account.getPgpId() == -1) { + protected void announcePgp(Account account, final Conversation conversation, final Runnable onSuccess) { + if (account.getPgpId() == 0) { choosePgpSignId(account); } else { - xmppConnectionService.getPgpEngine().generateSignature(account, "", new UiCallback() { + String status = null; + if (manuallyChangePresence()) { + status = account.getPresenceStatusMessage(); + } + if (status == null) { + status = ""; + } + xmppConnectionService.getPgpEngine().generateSignature(account, status, new UiCallback() { @Override - public void userInputRequried(PendingIntent pi, - Account account) { + public void userInputRequried(PendingIntent pi, Account account) { try { - startIntentSenderForResult(pi.getIntentSender(), - REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); + startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); } catch (final SendIntentException ignored) { } } @@ -513,6 +526,9 @@ public abstract class XmppActivity extends Activity { conversation.setNextEncryption(Message.ENCRYPTION_PGP); xmppConnectionService.databaseBackend.updateConversation(conversation); } + if (onSuccess != null) { + runOnUiThread(onSuccess); + } } @Override @@ -523,6 +539,15 @@ public abstract class XmppActivity extends Activity { } } + protected boolean noAccountUsesPgp() { + for(Account account : xmppConnectionService.getAccounts()) { + if (account.getPgpId() != 0) { + return false; + } + } + return true; + } + @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) protected void setListItemBackgroundOnView(View view) { -- cgit v1.2.3 From 544e1dee656eb547d5b3a16f4929ed301ff6c540 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 5 May 2016 17:09:01 +0200 Subject: Remove copy of innerkey The line overwrites this.innerkey with the value that was already there. --- .../java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index cf950d6d..93a73677 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -158,7 +158,6 @@ public class XmppAxolotlMessage { IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); - this.innerKey = secretKey.getEncoded(); this.ciphertext = cipher.doFinal(plaintext.getBytes()); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException -- cgit v1.2.3 From 0157039e87f5843189641aab2e6f827dcd4d0051 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 May 2016 19:34:44 +0200 Subject: =?UTF-8?q?log=20more=20information=20about=20HTTP=E2=80=99s=20max?= =?UTF-8?q?=20upload=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/eu/siacs/conversations/persistance/FileBackend.java | 2 ++ src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index df510efe..db48c8b3 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -134,10 +134,12 @@ public class FileBackend { public static boolean allFilesUnderSize(Context context, List uris, long max) { if (max <= 0) { + Log.d(Config.LOGTAG,"server did not report max file size for http upload"); return true; //exception to be compatible with HTTP Upload < v0.2 } for(Uri uri : uris) { if (FileBackend.getFileSize(context, uri) > max) { + Log.d(Config.LOGTAG,"not all files are under "+max+" bytes. suggesting falling back to jingle"); return false; } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 687f07da..26139f8e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1555,7 +1555,12 @@ public class XmppConnection implements Runnable { if (items.size() > 0) { try { long maxsize = Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(Xmlns.HTTP_UPLOAD, "max-file-size")); - return filesize <= maxsize; + if(filesize <= maxsize) { + return true; + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": http upload is not available for files with size "+filesize+" (max is "+maxsize+")"); + return false; + } } catch (Exception e) { return true; } -- cgit v1.2.3 From a7cd05bd4e5e350a91361da18f5437ca7f64e1bd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 May 2016 20:22:47 +0200 Subject: report bind failure as account state --- .../java/eu/siacs/conversations/entities/Account.java | 5 ++++- .../eu/siacs/conversations/xmpp/XmppConnection.java | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 1bcb15c0..1a7798b2 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -93,7 +93,8 @@ public class Account extends AbstractEntity { REGISTRATION_NOT_SUPPORTED(true), SECURITY_ERROR(true), INCOMPATIBLE_SERVER(true), - TOR_NOT_AVAILABLE(true); + TOR_NOT_AVAILABLE(true), + BIND_FAILURE(true); private final boolean isError; @@ -139,6 +140,8 @@ public class Account extends AbstractEntity { return R.string.account_status_incompatible_server; case TOR_NOT_AVAILABLE: return R.string.account_status_tor_unavailable; + case BIND_FAILURE: + return R.string.account_status_bind_failure; default: return R.string.account_status_unknown; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 26139f8e..26610561 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -906,22 +906,23 @@ public class XmppConnection implements Runnable { if (jid != null && jid.getContent() != null) { try { account.setResource(Jid.fromString(jid.getContent()).getResourcepart()); + if (streamFeatures.hasChild("session")) { + sendStartSession(); + } else { + sendPostBindInitialization(); + } + return; } catch (final InvalidJidException e) { - // TODO: Handle the case where an external JID is technically invalid? - } - if (streamFeatures.hasChild("session")) { - sendStartSession(); - } else { - sendPostBindInitialization(); + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server reported invalid jid ("+jid.getContent()+") on bind"); } } else { Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure. (no jid)"); - disconnect(true); } } else { Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure (" + packet.toString()); - disconnect(true); } + forceCloseSocket(); + changeStatus(Account.State.BIND_FAILURE); } }); } -- cgit v1.2.3 From 76889b9c58b27438b4b73474b325483cb859a3e7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 May 2016 11:34:17 +0200 Subject: handle invalid base64 is SASl SCRAM response --- .../java/eu/siacs/conversations/crypto/sasl/ScramSha1.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java index 3a05446c..f40eec55 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java @@ -185,13 +185,17 @@ public class ScramSha1 extends SaslMechanism { state = State.RESPONSE_SENT; return Base64.encodeToString(clientFinalMessage.getBytes(), Base64.NO_WRAP); case RESPONSE_SENT: - final String clientCalculatedServerFinalMessage = "v=" + - Base64.encodeToString(serverSignature, Base64.NO_WRAP); - if (challenge == null || !clientCalculatedServerFinalMessage.equals(new String(Base64.decode(challenge, Base64.DEFAULT)))) { + try { + final String clientCalculatedServerFinalMessage = "v=" + + Base64.encodeToString(serverSignature, Base64.NO_WRAP); + if (!clientCalculatedServerFinalMessage.equals(new String(Base64.decode(challenge, Base64.DEFAULT)))) { + throw new Exception(); + }; + state = State.VALID_SERVER_RESPONSE; + return ""; + } catch(Exception e) { throw new AuthenticationException("Server final message does not match calculated final message"); } - state = State.VALID_SERVER_RESPONSE; - return ""; default: throw new InvalidStateException(state); } -- cgit v1.2.3 From fb7525e0b999d6aecffcd4d0501329e6080a5073 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 May 2016 11:34:45 +0200 Subject: catch all exceptions thrown by xml pull parser --- src/main/java/eu/siacs/conversations/xml/XmlReader.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/xml/XmlReader.java b/src/main/java/eu/siacs/conversations/xml/XmlReader.java index aeaaa593..b8aa3aa0 100644 --- a/src/main/java/eu/siacs/conversations/xml/XmlReader.java +++ b/src/main/java/eu/siacs/conversations/xml/XmlReader.java @@ -96,17 +96,8 @@ public class XmlReader { } catch (RuntimeException re) { } } - } catch (ArrayIndexOutOfBoundsException e) { - throw new IOException( - "xml parser mishandled ArrayIndexOufOfBounds", e); - } catch (StringIndexOutOfBoundsException e) { - throw new IOException( - "xml parser mishandled StringIndexOufOfBounds", e); - } catch (NullPointerException e) { - throw new IOException("xml parser mishandled NullPointerException", - e); - } catch (IndexOutOfBoundsException e) { - throw new IOException("xml parser mishandled IndexOutOfBound", e); + } catch (Exception e) { + throw new IOException("xml parser mishandled "+e.getClass().getName(), e); } return null; } -- cgit v1.2.3 From 6f3b8f64d17c84e7baac78b1efa72400859f67e6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 8 May 2016 21:45:18 +0200 Subject: check for h attribute in 'failed' nonza --- .../java/eu/siacs/conversations/xmpp/XmppConnection.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (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 26610561..36424482 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -537,12 +537,18 @@ public class XmppConnection implements Runnable { try { final int serverSequence = Integer.parseInt(ack.getAttribute("h")); acknowledgeStanzaUpTo(serverSequence); - } catch (NumberFormatException e) { + } catch (NumberFormatException | NullPointerException e) { Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server send ack without sequence number"); } } else if (nextTag.isStart("failed")) { - tagReader.readElement(nextTag); - Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": resumption failed"); + Element failed = tagReader.readElement(nextTag); + try { + final int serverCount = Integer.parseInt(failed.getAttribute("h")); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed but server acknowledged stanza #"+h); + acknowledgeStanzaUpTo(serverCount); + } catch (NumberFormatException | NullPointerException e) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed"); + } resetStreamId(); if (account.getStatus() != Account.State.ONLINE) { sendBindRequest(); -- cgit v1.2.3 From 488780d2ce2dfb471adc7a99310c29a5202ea6c0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 8 May 2016 21:53:45 +0200 Subject: fix logging wrong variable for failed resume --- 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 36424482..772bfd3d 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -544,7 +544,7 @@ public class XmppConnection implements Runnable { Element failed = tagReader.readElement(nextTag); try { final int serverCount = Integer.parseInt(failed.getAttribute("h")); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed but server acknowledged stanza #"+h); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed but server acknowledged stanza #"+serverCount); acknowledgeStanzaUpTo(serverCount); } catch (NumberFormatException | NullPointerException e) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed"); -- cgit v1.2.3 From 27b245ac3503f0b179098d8da3b5c95a76ea74bd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 09:41:30 +0200 Subject: do not show last-seen metric in UI --- src/main/java/eu/siacs/conversations/parser/AbstractParser.java | 8 ++------ src/main/java/eu/siacs/conversations/parser/MessageParser.java | 7 ++----- src/main/java/eu/siacs/conversations/parser/PresenceParser.java | 1 - .../eu/siacs/conversations/services/XmppConnectionService.java | 6 ++---- .../java/eu/siacs/conversations/ui/ContactDetailsActivity.java | 8 -------- 5 files changed, 6 insertions(+), 24 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 7d399073..73c717bf 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -48,16 +48,12 @@ public abstract class AbstractParser { return dateFormat.parse(timestamp); } - protected void updateLastseen(final AbstractStanza packet, final Account account, final boolean presenceOverwrite) { - updateLastseen(getTimestamp(packet), account, packet.getFrom(), presenceOverwrite); - } - - protected void updateLastseen(long timestamp, final Account account, final Jid from, final boolean presenceOverwrite) { + protected void updateLastseen(long timestamp, final Account account, final Jid from) { final String presence = from == null || from.isBareJid() ? "" : from.getResourcepart(); final Contact contact = account.getRoster().getContact(from); if (timestamp >= contact.lastseen.time) { contact.lastseen.time = timestamp; - if (!presence.isEmpty() && presenceOverwrite) { + if (!presence.isEmpty()) { contact.lastseen.presence = presence; } } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 21bdbdf6..3f5cfe24 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -395,14 +395,11 @@ public class MessageParser extends AbstractParser implements if (conversation.getMode() == Conversation.MODE_MULTI) { Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart()); message.setTrueCounterpart(trueCounterpart); - if (trueCounterpart != null) { - updateLastseen(timestamp, account, trueCounterpart, false); - } if (!isTypeGroupChat) { message.setType(Message.TYPE_PRIVATE); } } else { - updateLastseen(timestamp, account, packet.getFrom(), true); + updateLastseen(timestamp, account, from); } if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) { @@ -543,7 +540,7 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.markRead(conversation); } } else { - updateLastseen(timestamp, account, packet.getFrom(), true); + updateLastseen(timestamp, account, from); final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), displayed.getAttribute("id"), Message.STATUS_SEND_DISPLAYED); Message message = displayedMessage == null ? null : displayedMessage.prev(); while (message != null diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index e6cfa38f..c6b23459 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -211,7 +211,6 @@ public class PresenceParser extends AbstractParser implements contact.setPgpKeyId(pgp.fetchKeyId(account, msg, x.getContent())); } boolean online = sizeBefore < contact.getPresences().size(); - updateLastseen(packet, account, false); mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, online); } else if (type.equals("unavailable")) { if (from.isBareJid()) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 7aac94b6..320a3e10 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2817,17 +2817,15 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public boolean displayCaptchaRequest(Account account, String id, Data data, Bitmap captcha) { - boolean rc = false; if (mOnCaptchaRequested != null) { DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics(); Bitmap scaled = Bitmap.createScaledBitmap(captcha, (int) (captcha.getWidth() * metrics.scaledDensity), (int) (captcha.getHeight() * metrics.scaledDensity), false); mOnCaptchaRequested.onCaptchaRequested(account, id, data, scaled); - rc = true; + return true; } - - return rc; + return false; } public void updateBlocklistUi(final OnUpdateBlocklist.Status status) { diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index b4a5277c..76dc306d 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -107,7 +107,6 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd private Jid contactJid; private TextView contactJidTv; private TextView accountJidTv; - private TextView lastseen; private TextView statusMessage; private CheckBox send; private CheckBox receive; @@ -204,7 +203,6 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd contactJidTv = (TextView) findViewById(R.id.details_contactjid); accountJidTv = (TextView) findViewById(R.id.details_account); - lastseen = (TextView) findViewById(R.id.details_lastseen); statusMessage = (TextView) findViewById(R.id.status_message); send = (CheckBox) findViewById(R.id.details_send_presence); receive = (CheckBox) findViewById(R.id.details_receive_presence); @@ -373,12 +371,6 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd statusMessage.setVisibility(View.GONE); } - if (contact.isBlocked() && !this.showDynamicTags) { - lastseen.setText(R.string.contact_blocked); - } else { - lastseen.setText(UIHelper.lastseen(getApplicationContext(), contact.lastseen.time)); - } - if (contact.getPresences().size() > 1) { contactJidTv.setText(contact.getDisplayJid() + " (" + contact.getPresences().size() + ")"); -- cgit v1.2.3 From 549be9bb3df86dfd7aea819b8f64508ec55d9322 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 10:29:02 +0200 Subject: report host-account as account state in UI --- src/main/java/eu/siacs/conversations/entities/Account.java | 5 ++++- .../java/eu/siacs/conversations/xmpp/XmppConnection.java | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 1a7798b2..c6b655d0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -94,7 +94,8 @@ public class Account extends AbstractEntity { SECURITY_ERROR(true), INCOMPATIBLE_SERVER(true), TOR_NOT_AVAILABLE(true), - BIND_FAILURE(true); + BIND_FAILURE(true), + HOST_UNKNOWN(true); private final boolean isError; @@ -142,6 +143,8 @@ public class Account extends AbstractEntity { return R.string.account_status_tor_unavailable; case BIND_FAILURE: return R.string.account_status_bind_failure; + case HOST_UNKNOWN: + return R.string.account_status_host_unknown; default: return R.string.account_status_unknown; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 772bfd3d..57dc4ebf 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -880,6 +880,7 @@ public class XmppConnection implements Runnable { } public void resetEverything() { + resetAttemptCount(); resetStreamId(); clearIqCallbacks(); mStanzaQueue.clear(); @@ -1173,15 +1174,20 @@ public class XmppConnection implements Runnable { private void processStreamError(final Tag currentTag) throws XmlPullParserException, IOException { final Element streamError = tagReader.readElement(currentTag); - if (streamError != null && streamError.hasChild("conflict")) { + if (streamError == null) { + return; + } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString()); + if (streamError.hasChild("conflict")) { final String resource = account.getResource().split("\\.")[0]; account.setResource(resource + "." + nextRandomId()); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": switching resource due to conflict (" + account.getResource() + ")"); - } else if (streamError != null) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString()); + } else if (streamError.hasChild("host-unknown")) { + changeStatus(Account.State.HOST_UNKNOWN); } + forceCloseSocket(); } private void sendStartStream() throws IOException { -- cgit v1.2.3 From e542dd39233217b0e3cdc77628c3486e80d4581b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 10:32:25 +0200 Subject: always show download button when link is encrypted dont check for known mime type --- src/main/java/eu/siacs/conversations/entities/Message.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (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 f6a45533..225d0531 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -631,11 +631,7 @@ public class Message extends AbstractEntity { boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); if (encrypted) { - if (MimeUtils.guessMimeTypeFromExtension(extension) != null) { - return Decision.MUST; - } else { - return Decision.NEVER; - } + return Decision.MUST; } else if (Transferable.VALID_IMAGE_EXTENSIONS.contains(extension) || Transferable.WELL_KNOWN_EXTENSIONS.contains(extension)) { return Decision.SHOULD; -- cgit v1.2.3 From c37b5af2ca12beeb2fc7e4caabde79f2e0cd16aa Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 10:53:44 +0200 Subject: add lock domain and magic create domain to known hosts --- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 320a3e10..4a7a8d67 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2969,6 +2969,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } } + if(Config.DOMAIN_LOCK != null && !hosts.contains(Config.DOMAIN_LOCK)) { + hosts.add(Config.DOMAIN_LOCK); + } + if(Config.MAGIC_CREATE_DOMAIN != null && !hosts.contains(Config.MAGIC_CREATE_DOMAIN)) { + hosts.add(Config.MAGIC_CREATE_DOMAIN); + } return hosts; } -- cgit v1.2.3 From 8e3948e4954dd847f2d608b9c5018648ef09719b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 17:48:09 +0200 Subject: =?UTF-8?q?don=E2=80=99t=20let=20attempt=20count=20fall=20below=20?= =?UTF-8?q?zero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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 57dc4ebf..823fa0ce 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -355,7 +355,7 @@ public class XmppConnection implements Runnable { } catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage()); this.changeStatus(Account.State.OFFLINE); - this.attempt--; //don't count attempt when reconnecting instantly anyway + this.attempt = Math.max(0, this.attempt - 1); } finally { forceCloseSocket(); if (wakeLock.isHeld()) { -- cgit v1.2.3 From cc209afc517bdb37f8342457e89c6e2695962ffe Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 May 2016 18:11:13 +0200 Subject: stop processing PreKeyWhisperMessage if there is no PreKeyId fixes #1832 --- .../eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java index b713eb5f..b7d11ec0 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java @@ -168,6 +168,10 @@ public class XmppAxolotlSession { try { try { PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey); + if (!message.getPreKeyId().isPresent()) { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage did not contain a PreKeyId"); + break; + } Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId()); IdentityKey msgIdentityKey = message.getIdentityKey(); if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) { @@ -175,9 +179,7 @@ public class XmppAxolotlSession { } else { this.identityKey = msgIdentityKey; plaintext = cipher.decrypt(message); - if (message.getPreKeyId().isPresent()) { - preKeyId = message.getPreKeyId().get(); - } + preKeyId = message.getPreKeyId().get(); } } catch (InvalidMessageException | InvalidVersionException e) { Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received"); -- cgit v1.2.3 From 1bc92482e947abde8a9660baed57b463cd55f403 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 10:39:04 +0200 Subject: scroll to bottom after sending multi-line message --- .../java/eu/siacs/conversations/ui/ConversationFragment.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0b4608ba..1c1fcb75 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -10,6 +10,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender.SendIntentException; import android.os.Bundle; +import android.os.Handler; import android.support.annotation.Nullable; import android.text.InputType; import android.view.ContextMenu; @@ -956,10 +957,15 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } private void messageSent() { - int size = this.messageList.size(); - messagesView.setSelection(size - 1); mEditMessage.setText(""); updateChatMsgHint(); + new Handler().post(new Runnable() { + @Override + public void run() { + int size = messageList.size(); + messagesView.setSelection(size - 1); + } + }); } public void setFocusOnInputField() { -- cgit v1.2.3 From 09e20f6e01f53ff1d4c038a5ff0cbd3d7868130a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 11:30:44 +0200 Subject: check if pgpengine is still bound before using it --- src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java | 2 +- src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java | 2 +- src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java b/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java index 093a8963..f9fed914 100644 --- a/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java @@ -44,7 +44,7 @@ public class PresenceGenerator extends AbstractGenerator { } packet.setFrom(account.getJid()); String sig = account.getPgpSignature(); - if (sig != null) { + if (sig != null && mXmppConnectionService.getPgpEngine() != null) { packet.addChild("x", "jabber:x:signed").setContent(sig); } String capHash = getCapHash(); diff --git a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java index effd30bf..6d13e7ea 100644 --- a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java @@ -118,7 +118,7 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis xmppConnectionService.changeStatus(status, statusMessage); finish(); } else if (mAccount != null) { - if (mAccount.getPgpId() == 0) { + if (mAccount.getPgpId() == 0 && hasPgp()) { xmppConnectionService.changeStatus(mAccount, status, statusMessage, true); finish(); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index b58fa6c2..5ce74824 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -540,6 +540,9 @@ public abstract class XmppActivity extends Activity { } protected boolean noAccountUsesPgp() { + if (!hasPgp()) { + return true; + } for(Account account : xmppConnectionService.getAccounts()) { if (account.getPgpId() != 0) { return false; -- cgit v1.2.3 From 908aa19a36eaf80442da153cbac729d3fdb0aa31 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 14:20:11 +0200 Subject: make omemo default when all resources support it --- .../conversations/crypto/axolotl/AxolotlService.java | 1 + .../eu/siacs/conversations/entities/Conversation.java | 15 ++++++++------- .../java/eu/siacs/conversations/entities/Presence.java | 18 +++++++++++++----- .../eu/siacs/conversations/entities/Presences.java | 17 +++++++++++++++-- .../conversations/generator/AbstractGenerator.java | 2 +- 5 files changed, 38 insertions(+), 15 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 86d23761..ae1b3a03 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -53,6 +53,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public static final String PEP_PREFIX = "eu.siacs.conversations.axolotl"; public static final String PEP_DEVICE_LIST = PEP_PREFIX + ".devicelist"; + public static final String PEP_DEVICE_LIST_NOTIFY = PEP_DEVICE_LIST + "+notify"; public static final String PEP_BUNDLES = PEP_PREFIX + ".bundles"; public static final String PEP_VERIFICATION = PEP_PREFIX + ".verification"; diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index b1d597df..646bc2be 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -27,6 +27,7 @@ import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; + public class Conversation extends AbstractEntity implements Blockable { public static final String TABLENAME = "conversations"; @@ -678,12 +679,12 @@ public class Conversation extends AbstractEntity implements Blockable { final AxolotlService axolotlService = getAccount().getAxolotlService(); int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1); if (next == -1) { - if (Config.X509_VERIFICATION) { - if (axolotlService != null && axolotlService.isConversationAxolotlCapable(this)) { - return Message.ENCRYPTION_AXOLOTL; - } else { - return Message.ENCRYPTION_NONE; - } + if (Config.supportOmemo() + && axolotlService != null + && mode == MODE_SINGLE + && axolotlService.isConversationAxolotlCapable(this) + && getContact().getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY)) { + return Message.ENCRYPTION_AXOLOTL; } int outgoing = this.getMostRecentlyUsedOutgoingEncryption(); if (outgoing == Message.ENCRYPTION_NONE) { @@ -695,7 +696,7 @@ public class Conversation extends AbstractEntity implements Blockable { if (!Config.supportUnencrypted() && next <= 0) { if (Config.supportOmemo() - && (axolotlService != null && axolotlService.isConversationAxolotlCapable(this) || !Config.multipleEncryptionChoices())) { + && ((axolotlService != null && axolotlService.isConversationAxolotlCapable(this)) || !Config.multipleEncryptionChoices())) { return Message.ENCRYPTION_AXOLOTL; } else if (Config.supportOtr() && mode == MODE_SINGLE) { return Message.ENCRYPTION_OTR; diff --git a/src/main/java/eu/siacs/conversations/entities/Presence.java b/src/main/java/eu/siacs/conversations/entities/Presence.java index 485adaa1..e9f6d0d1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presence.java +++ b/src/main/java/eu/siacs/conversations/entities/Presence.java @@ -40,11 +40,11 @@ public class Presence implements Comparable { } } - protected final Status status; - protected ServiceDiscoveryResult disco; - protected final String ver; - protected final String hash; - protected final String message; + private final Status status; + private ServiceDiscoveryResult disco; + private final String ver; + private final String hash; + private final String message; private Presence(Status status, String ver, String hash, String message) { this.status = status; @@ -79,7 +79,15 @@ public class Presence implements Comparable { return this.hash; } + public String getMessage() { + return this.message; + } + public void setServiceDiscoveryResult(ServiceDiscoveryResult disco) { this.disco = disco; } + + public ServiceDiscoveryResult getServiceDiscoveryResult() { + return disco; + } } diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 5fe10de0..754175ab 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -64,11 +64,24 @@ public class Presences { ArrayList messages = new ArrayList<>(); synchronized (this.presences) { for(Presence presence : this.presences.values()) { - if (presence.message != null && !presence.message.trim().isEmpty()) { - messages.add(presence.message.trim()); + String message = presence.getMessage(); + if (message != null && !message.trim().isEmpty()) { + messages.add(message.trim()); } } } return messages; } + + public boolean allOrNonSupport(String namespace) { + synchronized (this.presences) { + for(Presence presence : this.presences.values()) { + ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult(); + if (disco == null || !disco.getFeatures().contains(namespace)) { + return false; + } + } + } + return true; + } } diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java index 05fa0b82..4be6c621 100644 --- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java @@ -33,7 +33,7 @@ public abstract class AbstractGenerator { "urn:xmpp:ping", "jabber:iq:version", "http://jabber.org/protocol/chatstates", - AxolotlService.PEP_DEVICE_LIST+"+notify"}; + AxolotlService.PEP_DEVICE_LIST_NOTIFY}; private final String[] MESSAGE_CONFIRMATION_FEATURES = { "urn:xmpp:chat-markers:0", "urn:xmpp:receipts" -- cgit v1.2.3 From 7113e21a433b04d82a161ea36625d3512a86f18a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 18:47:41 +0200 Subject: use 'phone' or 'tablet' as default resource --- .../java/eu/siacs/conversations/services/XmppConnectionService.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/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 4a7a8d67..7301c7aa 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -851,7 +851,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public XmppConnection createConnection(final Account account) { final SharedPreferences sharedPref = getPreferences(); - account.setResource(sharedPref.getString("resource", "mobile") + account.setResource(sharedPref.getString("resource", getString(R.string.default_resource)) .toLowerCase(Locale.getDefault())); final XmppConnection connection = new XmppConnection(account, this); connection.setOnMessagePacketReceivedListener(this.mMessageParser); -- cgit v1.2.3 From f4369b29ae0d4d3ad562ce6695af6aca8f7416ea Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 18:49:54 +0200 Subject: improve keyboard handling. fixes #1387 * start a new Conversations by pressing mod+space * automatically start searching when pressing keys in StartConversationsActivity * when hitting enter when number of search results == 1 open that conversation --- .../conversations/ui/ConversationActivity.java | 3 ++ .../ui/StartConversationActivity.java | 53 +++++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index eb9ccb6b..c7fa2d28 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -953,6 +953,9 @@ public class ConversationActivity extends XmppActivity if (modifier && key == KeyEvent.KEYCODE_TAB && isConversationsOverviewHideable()) { toggleConversationsOverview(); return true; + } else if (modifier && key == KeyEvent.KEYCODE_SPACE) { + startActivity(new Intent(this, StartConversationActivity.class)); + return true; } else if (modifier && key == downKey) { if (isConversationsOverviewHideable() && !isConversationsOverviewVisable()) { showConversationsOverview(); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 78c05e41..3ab6d1d2 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -91,7 +91,6 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU private List mKnownHosts; private List mKnownConferenceHosts; private Invite mPendingInvite = null; - private Menu mOptionsMenu; private EditText mSearchEditText; private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false); private final int REQUEST_SYNC_CONTACTS = 0x3b28cf; @@ -116,9 +115,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU @Override public boolean onMenuItemActionCollapse(MenuItem item) { - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), - InputMethodManager.HIDE_IMPLICIT_ONLY); + hideKeyboard(); mSearchEditText.setText(""); filter(null); return true; @@ -169,6 +166,28 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU int count) { } }; + + private TextView.OnEditorActionListener mSearchDone = new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (getActionBar().getSelectedNavigationIndex() == 0) { + if (contacts.size() == 1) { + openConversationForContact((Contact) contacts.get(0)); + } else { + hideKeyboard(); + mContactsListFragment.getListView().requestFocus(); + } + } else { + if (conferences.size() == 1) { + openConversationsForBookmark((Bookmark) conferences.get(0)); + } else { + hideKeyboard(); + mConferenceListFragment.getListView().requestFocus(); + } + } + return true; + } + }; private MenuItem mMenuSearchView; private ListItemAdapter.OnTagClickedListener mOnTagClickedListener = new ListItemAdapter.OnTagClickedListener() { @Override @@ -260,6 +279,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU protected void openConversationForContact(int position) { Contact contact = (Contact) contacts.get(position); + openConversationForContact(contact); + } + + protected void openConversationForContact(Contact contact) { Conversation conversation = xmppConnectionService .findOrCreateConversation(contact.getAccount(), contact.getJid(), false); @@ -277,6 +300,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU protected void openConversationForBookmark(int position) { Bookmark bookmark = (Bookmark) conferences.get(position); + openConversationsForBookmark(bookmark); + } + + protected void openConversationsForBookmark(Bookmark bookmark) { Jid jid = bookmark.getJid(); if (jid == null) { Toast.makeText(this,R.string.invalid_jid,Toast.LENGTH_SHORT).show(); @@ -503,7 +530,6 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU @Override public boolean onCreateOptionsMenu(Menu menu) { - this.mOptionsMenu = menu; getMenuInflater().inflate(R.menu.start_conversation, menu); MenuItem menuCreateContact = menu.findItem(R.id.action_create_contact); MenuItem menuCreateConference = menu.findItem(R.id.action_join_conference); @@ -515,6 +541,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU mSearchEditText = (EditText) mSearchView .findViewById(R.id.search_field); mSearchEditText.addTextChangedListener(mSearchTextWatcher); + mSearchEditText.setOnEditorActionListener(mSearchDone); if (getActionBar().getSelectedNavigationIndex() == 0) { menuCreateConference.setVisible(false); } else { @@ -554,12 +581,26 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_SEARCH && !event.isLongPress()) { - mOptionsMenu.findItem(R.id.action_search).expandActionView(); + openSearch(); return true; } + int c = event.getUnicodeChar(); + if (c > 32) { + if (mSearchEditText != null && !mSearchEditText.isFocused()) { + openSearch(); + mSearchEditText.append(Character.toString((char) c)); + return true; + } + } return super.onKeyUp(keyCode, event); } + private void openSearch() { + if (mMenuSearchView != null) { + mMenuSearchView.expandActionView(); + } + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) { -- cgit v1.2.3 From cbdb4136136726d572b8bc521fc910f4dc31f00f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 21:39:47 +0200 Subject: prefer IPv4 DNS servers some devices might have problems contacting the IPv6 DNS server while in sleep mode --- .../java/eu/siacs/conversations/utils/DNSHelper.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index 306d50c2..b96d3c25 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -12,6 +12,7 @@ import android.os.Parcelable; import android.util.Log; import java.io.IOException; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.SocketTimeoutException; import java.net.UnknownHostException; @@ -77,9 +78,9 @@ public class DNSHelper { LinkProperties linkProperties = connectivityManager.getLinkProperties(networks[i]); if (linkProperties != null) { if (hasDefaultRoute(linkProperties)) { - servers.addAll(0, linkProperties.getDnsServers()); + servers.addAll(0, getIPv4First(linkProperties.getDnsServers())); } else { - servers.addAll(linkProperties.getDnsServers()); + servers.addAll(getIPv4First(linkProperties.getDnsServers())); } } } @@ -89,6 +90,18 @@ public class DNSHelper { return servers.size() > 0 ? servers : getDnsServersPreLollipop(); } + private static List getIPv4First(List in) { + List out = new ArrayList<>(); + for(InetAddress addr : in) { + if (addr instanceof Inet4Address) { + out.add(0, addr); + } else { + out.add(addr); + } + } + return out; + } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static boolean hasDefaultRoute(LinkProperties linkProperties) { for(RouteInfo route: linkProperties.getRoutes()) { @@ -155,7 +168,7 @@ public class DNSHelper { public static Bundle queryDNS(String host, InetAddress dnsServer) { Bundle bundle = new Bundle(); try { - client.setTimeout(Config.PING_TIMEOUT * 1000); + client.setTimeout(Config.SOCKET_TIMEOUT * 1000); final String qname = "_xmpp-client._tcp." + host; final String tlsQname = "_xmpps-client._tcp." + host; Log.d(Config.LOGTAG, "using dns server: " + dnsServer.getHostAddress() + " to look up " + host); -- cgit v1.2.3 From 2014f388b1f5eef66c8f787dc6889b03ae461d08 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 21:54:42 +0200 Subject: interrupt XMPPConnection Thread in some cases the the DNS query might take too long (even though we specified a timeout) if that happens we need a secondary solution (besides killing the socket) to stop the thread --- src/main/java/eu/siacs/conversations/utils/DNSHelper.java | 7 ++++++- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index b96d3c25..2f588f49 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -51,14 +51,19 @@ public class DNSHelper { final String host = jid.getDomainpart(); final List servers = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDnsServers(context) : getDnsServersPreLollipop(); Bundle b = new Bundle(); + boolean interrupted = false; for(InetAddress server : servers) { + if (Thread.currentThread().isInterrupted()) { + interrupted = true; + break; + } b = queryDNS(host, server); if (b.containsKey("values")) { return b; } } if (!b.containsKey("values")) { - Log.d(Config.LOGTAG,"all dns queries failed. provide fallback A record"); + Log.d(Config.LOGTAG,(interrupted ? "Thread interrupted during DNS query" :"all dns queries failed") + ". provide fallback A record"); ArrayList values = new ArrayList<>(); values.add(createNamePortBundle(host, 5222, false)); b.putParcelableArrayList("values",values); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 823fa0ce..3740097e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -280,6 +280,10 @@ public class XmppConnection implements Runnable { final Bundle result = DNSHelper.getSRVRecord(account.getServer(), mXmppConnectionService); final ArrayListvalues = result.getParcelableArrayList("values"); for(Iterator iterator = values.iterator(); iterator.hasNext();) { + if (Thread.currentThread().isInterrupted()) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": Thread was interrupted"); + return; + } final Bundle namePort = (Bundle) iterator.next(); try { String srvRecordServer; @@ -1334,7 +1338,12 @@ public class XmppConnection implements Runnable { } } + public void interrupt() { + Thread.currentThread().interrupt(); + } + public void disconnect(final boolean force) { + interrupt(); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": disconnecting force="+Boolean.valueOf(force)); if (force) { forceCloseSocket(); -- cgit v1.2.3 From b8c1bd2cbaf0ed3fe2ddf9525c6bd1fab1bc3e06 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 May 2016 21:57:07 +0200 Subject: reset attempt count when reconnecting because of timeout --- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 7301c7aa..977524d1 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -604,6 +604,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; if (timeout < 0) { Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting"); + account.getXmppConnection().resetAttemptCount(); reconnectAccount(account, true, interactive); } else if (discoTimeout < 0) { account.getXmppConnection().sendDiscoTimeout(); @@ -2652,6 +2653,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (connection == null) { connection = createConnection(account); account.setXmppConnection(connection); + } else { + connection.interrupt(); } if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!force) { -- cgit v1.2.3 From b756d61c45f5cd3a3c69dd93115ad558f41de216 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 May 2016 10:45:30 +0200 Subject: show presence of other resources as template --- .../eu/siacs/conversations/entities/Account.java | 4 ++++ .../conversations/entities/PresenceTemplate.java | 20 ++++++++++++++++++++ .../eu/siacs/conversations/entities/Presences.java | 11 +++++++++++ .../services/XmppConnectionService.java | 10 ++++++++++ .../siacs/conversations/ui/SetPresenceActivity.java | 4 ++-- .../eu/siacs/conversations/xmpp/XmppConnection.java | 6 ++---- 6 files changed, 49 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index c6b655d0..1cdf0d67 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -79,6 +79,10 @@ public class Account extends AbstractEntity { } } + public Contact getSelfContact() { + return getRoster().getContact(jid); + } + public enum State { DISABLED, OFFLINE, diff --git a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java index 3b3ce08d..c268b24c 100644 --- a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java +++ b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java @@ -53,4 +53,24 @@ public class PresenceTemplate extends AbstractEntity { public String getStatusMessage() { return statusMessage; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PresenceTemplate template = (PresenceTemplate) o; + + if (statusMessage != null ? !statusMessage.equals(template.statusMessage) : template.statusMessage != null) + return false; + return status == template.status; + + } + + @Override + public int hashCode() { + int result = statusMessage != null ? statusMessage.hashCode() : 0; + result = 31 * result + status.hashCode(); + return result; + } } diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 754175ab..7630fd93 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Map; import eu.siacs.conversations.xml.Element; @@ -54,6 +55,16 @@ public class Presences { } } + public List asTemplates() { + synchronized (this.presences) { + ArrayList templates = new ArrayList<>(presences.size()); + for(Presence p : presences.values()) { + templates.add(new PresenceTemplate(p.getStatus(),p.getMessage())); + } + return templates; + } + } + public boolean has(String presence) { synchronized (this.presences) { return presences.containsKey(presence); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 977524d1..807aa4f9 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3290,6 +3290,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } + public List getPresenceTemplates(Account account) { + List templates = databaseBackend.getPresenceTemplates(); + for(PresenceTemplate template : account.getSelfContact().getPresences().asTemplates()) { + if (!templates.contains(template)) { + templates.add(0, template); + } + } + return templates; + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); void onPreferencesFetchFailed(); diff --git a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java index 6d13e7ea..0962d209 100644 --- a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java @@ -118,7 +118,7 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis xmppConnectionService.changeStatus(status, statusMessage); finish(); } else if (mAccount != null) { - if (mAccount.getPgpId() == 0 && hasPgp()) { + if (mAccount.getPgpId() == 0 || !hasPgp()) { xmppConnectionService.changeStatus(mAccount, status, statusMessage, true); finish(); } else { @@ -177,7 +177,7 @@ public class SetPresenceActivity extends XmppActivity implements View.OnClickLis if (mStatusMessage.getText().length() == 0 && message != null) { mStatusMessage.append(message); } - mTemplates = xmppConnectionService.databaseBackend.getPresenceTemplates(); + mTemplates = xmppConnectionService.getPresenceTemplates(mAccount); if (this.mPostponedActivityResult != null) { this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 3740097e..cc3647e6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1315,10 +1315,8 @@ public class XmppConnection implements Runnable { } socket.close(); Log.d(Config.LOGTAG,account.getJid().toBareJid()+": closed tcp without closing stream"); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); + } catch (IOException | InterruptedException e) { + return; } } }).start(); -- cgit v1.2.3 From aced9d2697b02416d194695f23ad2d3c579fcf5d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 May 2016 11:20:27 +0200 Subject: do not process self presence we don't want our own resource show up in the self contact --- src/main/java/eu/siacs/conversations/parser/PresenceParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index c6b23459..aea9002a 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -171,7 +171,7 @@ public class PresenceParser extends AbstractParser implements public void parseContactPresence(final PresencePacket packet, final Account account) { final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); final Jid from = packet.getFrom(); - if (from == null) { + if (from == null || from.equals(account.getJid())) { return; } final String type = packet.getAttribute("type"); @@ -199,7 +199,7 @@ public class PresenceParser extends AbstractParser implements final String message = packet.findChildContent("status"); final Presence presence = Presence.parse(show, caps, message); contact.updatePresence(resource, presence); - if (presence.hasCaps() && !from.equals(account.getJid())) { + if (presence.hasCaps()) { mXmppConnectionService.fetchCaps(account, from, presence); } -- cgit v1.2.3 From e41a9483bdc1aa772b9f69695cb96643effb1827 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 May 2016 11:47:29 +0200 Subject: only default to omemo when all our devices support it --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 1 + 1 file changed, 1 insertion(+) (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 646bc2be..9d814046 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -683,6 +683,7 @@ public class Conversation extends AbstractEntity implements Blockable { && axolotlService != null && mode == MODE_SINGLE && axolotlService.isConversationAxolotlCapable(this) + && getAccount().getSelfContact().getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY) && getContact().getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY)) { return Message.ENCRYPTION_AXOLOTL; } -- cgit v1.2.3 From 6a28b5a9fa9baa7cbbad596ebf135f3841b5d63b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 May 2016 11:57:02 +0200 Subject: don't show duplicate status message in contact details --- src/main/java/eu/siacs/conversations/entities/Presences.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 7630fd93..c8078331 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -75,9 +75,9 @@ public class Presences { ArrayList messages = new ArrayList<>(); synchronized (this.presences) { for(Presence presence : this.presences.values()) { - String message = presence.getMessage(); - if (message != null && !message.trim().isEmpty()) { - messages.add(message.trim()); + String message = presence.getMessage() == null ? null : presence.getMessage().trim(); + if (message != null && !message.isEmpty() && !messages.contains(message)) { + messages.add(message); } } } -- cgit v1.2.3 From 540f6f3d7a3ad2600f8dc0af238465742070f39e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 May 2016 09:54:49 +0200 Subject: send caps hash in muc join this prevents desktop clients from iq'ing use when they join --- .../eu/siacs/conversations/services/XmppConnectionService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 807aa4f9..aeb800bd 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1838,8 +1838,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final MucOptions mucOptions = conversation.getMucOptions(); final Jid joinJid = mucOptions.getSelf().getFullJid(); Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString()); - PresencePacket packet = new PresencePacket(); - packet.setFrom(conversation.getAccount().getJid()); + PresencePacket packet = mPresenceGenerator.selfPresence(account, Presence.Status.ONLINE); packet.setTo(joinJid); Element x = packet.addChild("x", "http://jabber.org/protocol/muc"); if (conversation.getMucOptions().getPassword() != null) { @@ -1853,10 +1852,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa // Fallback to muc history x.addChild("history").setAttribute("since", PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted())); } - String sig = account.getPgpSignature(); - if (sig != null) { - packet.addChild("x", "jabber:x:signed").setContent(sig); - } sendPresencePacket(account, packet); if (onConferenceJoined != null) { onConferenceJoined.onConferenceJoined(conversation); -- cgit v1.2.3 From a25912c32cced0683b59bea3095210d76a8d41a6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 May 2016 09:55:06 +0200 Subject: log incoming iq requests --- src/main/java/eu/siacs/conversations/Config.java | 1 + src/main/java/eu/siacs/conversations/parser/IqParser.java | 5 +++++ 2 files changed, 6 insertions(+) (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 dfb55d6b..1c196b21 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -77,6 +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 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/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 5903d511..afbc0412 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -268,6 +268,11 @@ 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)) { + 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)); + } + if (packet.getType() == IqPacket.TYPE.ERROR || packet.getType() == IqPacket.TYPE.TIMEOUT) { return; } else if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { -- cgit v1.2.3 From c9e9dc2ef23f12f5b8f09acf9a4acbf17a409764 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 May 2016 11:08:00 +0200 Subject: include name in locations received in MUCs --- .../java/eu/siacs/conversations/utils/GeoHelper.java | 18 +++++++++++------- .../java/eu/siacs/conversations/utils/UIHelper.java | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java index 74f91a98..9a93df38 100644 --- a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; @@ -54,13 +55,16 @@ public class GeoHelper { Intent locationPluginIntent = new Intent("eu.siacs.conversations.location.show"); locationPluginIntent.putExtra("latitude",latitude); locationPluginIntent.putExtra("longitude",longitude); - if (conversation.getMode() == Conversation.MODE_SINGLE) { - if (message.getStatus() == Message.STATUS_RECEIVED) { - locationPluginIntent.putExtra("name",conversation.getName()); - locationPluginIntent.putExtra("jid",message.getCounterpart().toString()); - } - else { - locationPluginIntent.putExtra("jid",conversation.getAccount().getJid().toString()); + if (message.getStatus() != Message.STATUS_RECEIVED) { + locationPluginIntent.putExtra("jid",conversation.getAccount().getJid().toString()); + locationPluginIntent.putExtra("name",conversation.getAccount().getJid().getLocalpart()); + } else { + Contact contact = message.getContact(); + if (contact != null) { + locationPluginIntent.putExtra("name", contact.getDisplayName()); + locationPluginIntent.putExtra("jid", contact.getJid().toString()); + } else { + locationPluginIntent.putExtra("name", UIHelper.getDisplayedMucCounterpart(message.getCounterpart())); } } intents.add(locationPluginIntent); diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 5ab058d1..6ca5370a 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -249,7 +249,7 @@ public class UIHelper { } } - private static String getDisplayedMucCounterpart(final Jid counterpart) { + public static String getDisplayedMucCounterpart(final Jid counterpart) { if (counterpart==null) { return ""; } else if (!counterpart.isBareJid()) { -- cgit v1.2.3 From cf5ca27a069b3f87b879c2b5c58bee3f0635b9a9 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 May 2016 12:35:31 +0200 Subject: escape HTML in OTR messages if other client is Pidgin --- .../eu/siacs/conversations/entities/Account.java | 2 +- .../siacs/conversations/parser/MessageParser.java | 43 ++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 1cdf0d67..a708b0ce 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -450,7 +450,7 @@ public class Account extends AbstractEntity { } public int countPresences() { - return this.getRoster().getContact(this.getJid().toBareJid()).getPresences().size(); + return this.getSelfContact().getPresences().size(); } public String getPgpSignature() { diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 3f5cfe24..69ac4c18 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.parser; +import android.text.Html; import android.util.Log; import android.util.Pair; @@ -7,6 +8,9 @@ import net.java.otr4j.session.Session; import net.java.otr4j.session.SessionStatus; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.UUID; @@ -20,6 +24,8 @@ 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.Presence; +import eu.siacs.conversations.entities.ServiceDiscoveryResult; import eu.siacs.conversations.http.HttpConnectionManager; import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.XmppConnectionService; @@ -31,8 +37,10 @@ import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; -public class MessageParser extends AbstractParser implements - OnMessagePacketReceived { +public class MessageParser extends AbstractParser implements OnMessagePacketReceived { + + private static final List CLIENTS_SENDING_HTML_IN_OTR = Arrays.asList(new String[]{"Pidgin","Adium"}); + public MessageParser(XmppConnectionService service) { super(service); } @@ -95,6 +103,11 @@ public class MessageParser extends AbstractParser implements conversation.setSymmetricKey(CryptoHelper.hexToBytes(key)); return null; } + if (clientMightSendHtml(conversation.getAccount(), from)) { + Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+": received OTR message from bad behaving client. escaping HTML…"); + body = Html.fromHtml(body).toString(); + } + final OtrService otrService = conversation.getAccount().getOtrService(); Message finishedMessage = new Message(conversation, body, Message.ENCRYPTION_OTR, Message.STATUS_RECEIVED); finishedMessage.setFingerprint(otrService.getFingerprint(otrSession.getRemotePublicKey())); @@ -107,6 +120,30 @@ public class MessageParser extends AbstractParser implements } } + private static boolean clientMightSendHtml(Account account, Jid from) { + String resource = from.getResourcepart(); + if (resource == null) { + return false; + } + Presence presence = account.getRoster().getContact(from).getPresences().getPresences().get(resource); + ServiceDiscoveryResult disco = presence == null ? null : presence.getServiceDiscoveryResult(); + if (disco == null) { + return false; + } + return hasIdentityKnowForSendingHtml(disco.getIdentities()); + } + + private static boolean hasIdentityKnowForSendingHtml(List identities) { + for(ServiceDiscoveryResult.Identity identity : identities) { + if (identity.getName() != null) { + if (CLIENTS_SENDING_HTML_IN_OTR.contains(identity.getName())) { + return true; + } + } + } + return false; + } + private Message parseAxolotlChat(Element axolotlMessage, Jid from, Conversation conversation, int status) { Message finishedMessage = null; AxolotlService service = conversation.getAccount().getAxolotlService(); @@ -311,7 +348,7 @@ public class MessageParser extends AbstractParser implements } boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT; - boolean isProperlyAddressed = (to != null ) && (!to.isBareJid() || account.countPresences() <= 1); + boolean isProperlyAddressed = (to != null ) && (!to.isBareJid() || account.countPresences() == 0); boolean isMucStatusMessage = from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status"); if (packet.fromAccount(account)) { status = Message.STATUS_SEND; -- cgit v1.2.3 From 6f1a4494eb89b0b5db8bbfa4718593b5c236e477 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 May 2016 12:35:51 +0200 Subject: use the same typo in both saving disco and reading disco --- .../java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (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 c4fc30ab..9accec95 100644 --- a/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java +++ b/src/main/java/eu/siacs/conversations/entities/ServiceDiscoveryResult.java @@ -53,6 +53,7 @@ public class ServiceDiscoveryResult { } public Identity(final JSONObject o) { + this( o.optString("category", null), o.optString("type", null), @@ -145,7 +146,7 @@ public class ServiceDiscoveryResult { this.hash = hash; this.ver = ver; - JSONArray identities = o.optJSONArray("identities"); + JSONArray identities = o.optJSONArray("identites"); if (identities != null) { for (int i = 0; i < identities.length(); i++) { this.identities.add(new Identity(identities.getJSONObject(i))); -- cgit v1.2.3 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 cc3647e6..66fd6527 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 ae1b3a03..327a1cc8 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 7681a3d4..a221c701 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 69ac4c18..f10798f3 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 aea9002a..1f1e92ee 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 bb8ec5f2..633758a5 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 aeb800bd..f88c0c9b 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 c806a03e..bca1c1ba 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 1c1fcb75..f1352780 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 5ce74824..e963ef4c 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 a221c701..50641f5a 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 1f1e92ee..c82c83d1 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 f88c0c9b..6b01261c 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 bca1c1ba..245dba15 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 50641f5a..e931f5fd 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 e963ef4c..858806e3 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 e931f5fd..8d7c5adb 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 73c717bf..cf9e10ff 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 f10798f3..642ea931 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 c82c83d1..2a912a45 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 6b01261c..e8a98cda 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 8d7c5adb..d26ecd7c 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 cf9e10ff..03f19ed8 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 245dba15..2e4b94e5 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 979a2845..4eb73313 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 225d0531..818ac1d6 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 9accec95..9ee1d180 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 dde385bd..f1155b07 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 e8a98cda..c3340486 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 8dabcb5b..c81c5a1f 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 9d814046..10b42b46 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 66fd6527..f75f027b 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 41d12d89..1ba7dd3d 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 d26ecd7c..44d16cf2 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 1c196b21..ababe495 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 327a1cc8..aac81443 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 afbc0412..189df4a7 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 642ea931..a3fd9916 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 From e1cf7b8cb641e5a30c0226404399beb46ff34dc5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 May 2016 08:54:29 +0200 Subject: refactore exceptionhandler to have one line file writer --- src/main/java/eu/siacs/conversations/utils/DNSHelper.java | 3 +++ .../eu/siacs/conversations/utils/ExceptionHandler.java | 14 +------------- .../java/eu/siacs/conversations/utils/ExceptionHelper.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index 2f588f49..ac64cf2e 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -47,7 +47,10 @@ public class DNSHelper { protected static Client client = new Client(); + protected static Context context; + public static Bundle getSRVRecord(final Jid jid, Context context) throws IOException { + DNSHelper.context = context; final String host = jid.getDomainpart(); final List servers = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDnsServers(context) : getDnsServersPreLollipop(); Bundle b = new Bundle(); diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java index 4e3ec236..efc83bcb 100644 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java +++ b/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java @@ -27,19 +27,7 @@ public class ExceptionHandler implements UncaughtExceptionHandler { ex.printStackTrace(printWriter); String stacktrace = result.toString(); printWriter.close(); - try { - OutputStream os = context.openFileOutput("stacktrace.txt", - Context.MODE_PRIVATE); - os.write(stacktrace.getBytes()); - os.flush(); - os.close(); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + ExceptionHelper.writeToStacktraceFile(context, stacktrace); this.defaultHandler.uncaughtException(thread, ex); } diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java index 8799b4a5..58d74b58 100644 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java @@ -14,8 +14,10 @@ import android.util.Log; import java.io.BufferedReader; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStream; import java.util.List; import eu.siacs.conversations.Config; @@ -118,4 +120,14 @@ public class ExceptionHelper { return false; } } + + public static void writeToStacktraceFile(Context context, String msg) { + try { + OutputStream os = context.openFileOutput("stacktrace.txt", Context.MODE_PRIVATE); + os.write(msg.getBytes()); + os.flush(); + os.close(); + } catch (IOException ignored) { + } + } } -- cgit v1.2.3 From 277e3d59c866f7eeb9546bdc6703fb095d794ca4 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 May 2016 09:25:37 +0200 Subject: update ui after affiliation changes --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 3 +++ .../java/eu/siacs/conversations/services/XmppConnectionService.java | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/main/java/eu/siacs/conversations') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index a3fd9916..31d13299 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -571,6 +571,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece +conversation.getJid().toBareJid()); if (!user.realJidMatchesAccount()) { conversation.getMucOptions().addUser(user); + mXmppConnectionService.getAvatarService().clear(conversation); + mXmppConnectionService.updateMucRosterUi(); + mXmppConnectionService.updateConversationUi(); } } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index c3340486..09e5d1a9 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1908,6 +1908,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa MucOptions.User user = AbstractParser.parseItem(conversation,child); if (!user.realJidMatchesAccount()) { conversation.getMucOptions().addUser(user); + getAvatarService().clear(conversation); + updateMucRosterUi(); + updateConversationUi(); } } } -- cgit v1.2.3 From a8420c9ad0d6c13e98aea77878644335d2dd2f8f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 May 2016 10:45:10 +0200 Subject: disable stanza logging --- src/main/java/eu/siacs/conversations/Config.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/Config.java b/src/main/java/eu/siacs/conversations/Config.java index ababe495..476e2ead 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 BACKGROUND_STANZA_LOGGING = true; + public static final boolean BACKGROUND_STANZA_LOGGING = false; 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; -- cgit v1.2.3