From a88c2d48c0ac3562fcc957b20a76fca97b93bf32 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Tue, 23 Feb 2016 23:57:51 +0100 Subject: No possibility of multiple invocation of log export --- src/main/java/eu/siacs/conversations/services/ExportLogsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java index 76983a90..87e65931 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java @@ -45,9 +45,9 @@ public class ExportLogsService extends Service { new Thread(new Runnable() { @Override public void run() { - running.set(false); export(); stopForeground(true); + running.set(false); stopSelf(); } }).start(); -- cgit v1.2.3 From e1a2f248afcc9fd884015da78decd5c0c8c83552 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Tue, 23 Feb 2016 23:58:42 +0100 Subject: Request WRITE_EXTERNAL_STORAGE for ExportLogsPreference in >= M --- .../conversations/ui/ExportLogsPreference.java | 7 ++++++ .../siacs/conversations/ui/SettingsActivity.java | 26 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java b/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java index a4e178bd..bedb4172 100644 --- a/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java +++ b/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java @@ -1,7 +1,10 @@ package eu.siacs.conversations.ui; +import android.Manifest; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; import android.preference.Preference; import android.util.AttributeSet; @@ -22,6 +25,10 @@ public class ExportLogsPreference extends Preference { } protected void onClick() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && getContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + return; + } final Intent startIntent = new Intent(getContext(), ExportLogsService.class); getContext().startService(startIntent); super.onClick(); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 07c328b9..c028d0d6 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -3,8 +3,10 @@ package eu.siacs.conversations.ui; import android.app.AlertDialog; import android.app.FragmentManager; import android.content.DialogInterface; +import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; @@ -25,10 +27,13 @@ import de.duenndns.ssl.MemorizingTrustManager; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.services.ExportLogsService; import eu.siacs.conversations.xmpp.XmppConnection; public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener { + + public static final int REQUEST_WRITE_LOGS = 0xbf8701; private SettingsFragment mSettingsFragment; @Override @@ -130,6 +135,15 @@ public class SettingsActivity extends XmppActivity implements return true; } }); + + final Preference exportLogsPreference = mSettingsFragment.findPreference("export_logs"); + exportLogsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + hasStoragePermission(REQUEST_WRITE_LOGS); + return true; + } + }); } @Override @@ -179,6 +193,18 @@ public class SettingsActivity extends XmppActivity implements } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (grantResults.length > 0) + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (requestCode == REQUEST_WRITE_LOGS) { + getApplicationContext().startService(new Intent(getApplicationContext(), ExportLogsService.class)); + } + } else { + Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); + } + } + private void displayToast(final String msg) { runOnUiThread(new Runnable() { @Override -- cgit v1.2.3 From 60ab03afb119a61503f101da91f54f15124f9373 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 27 Feb 2016 10:25:31 +0100 Subject: changed single_account config into more simple lock_settings --- src/main/java/eu/siacs/conversations/Config.java | 2 +- .../siacs/conversations/ui/ConferenceDetailsActivity.java | 2 +- .../eu/siacs/conversations/ui/ContactDetailsActivity.java | 2 +- .../eu/siacs/conversations/ui/ConversationActivity.java | 2 +- .../eu/siacs/conversations/ui/EditAccountActivity.java | 9 ++++++++- .../eu/siacs/conversations/ui/ManageAccountActivity.java | 4 ++-- .../siacs/conversations/ui/StartConversationActivity.java | 2 +- src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 14 ++++++++++++++ 8 files changed, 29 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index caadef80..30951223 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -45,7 +45,7 @@ public final class Config { 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 SINGLE_ACCOUNT = false; //set to true to allow only one account + 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 diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index a83ca8ba..adbb0953 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -333,7 +333,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.muc_details, menu); - return true; + return super.onCreateOptionsMenu(menu); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 64653acd..4165b4be 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -297,7 +297,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd edit.setVisible(false); delete.setVisible(false); } - return true; + return super.onCreateOptionsMenu(menu); } private void populateView() { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 7b2565c3..55a12710 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -420,7 +420,7 @@ public class ConversationActivity extends XmppActivity } } } - return true; + return super.onCreateOptionsMenu(menu); } protected void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 266ae840..b6f1b430 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -499,7 +499,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate clearDevices.setVisible(false); mamPrefs.setVisible(false); } - return true; + return super.onCreateOptionsMenu(menu); } @Override @@ -621,6 +621,13 @@ 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); this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(72))); diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index 1fc1924d..feac2c62 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -155,9 +155,9 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda addAccount.setVisible(false); addAccountWithCertificate.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); } else { - addAccount.setVisible(!Config.SINGLE_ACCOUNT); + addAccount.setVisible(!Config.LOCK_SETTINGS); } - addAccountWithCertificate.setVisible(!Config.SINGLE_ACCOUNT); + 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 48baf914..256f68c6 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -533,7 +533,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU mSearchEditText.append(mInitialJid); filter(mInitialJid); } - return true; + return super.onCreateOptionsMenu(menu); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 003b802c..38b26819 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -42,6 +42,7 @@ 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; @@ -377,6 +378,19 @@ 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 showBatteryOptimizationWarning() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); -- cgit v1.2.3 From 24a9ac290846c4facdf1d00f471dcaf34eea2be7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 27 Feb 2016 15:41:34 +0100 Subject: always search offline contacts as well. fixes #1653 --- src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 256f68c6..7d650e5b 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -740,6 +740,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU Presence.Status s = p == null ? Presence.Status.OFFLINE : p.getStatus(); if (contact.showInRoster() && contact.match(needle) && (!this.mHideOfflineContacts + || (needle != null && !needle.trim().isEmpty()) || s.compareTo(Presence.Status.OFFLINE) < 0)) { this.contacts.add(contact); } -- cgit v1.2.3 From 4ba41540fd3e6efa6b176716c292378df4e9b724 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 28 Feb 2016 20:45:50 +0100 Subject: made hashtable in roster store jids instead of strings --- .../java/eu/siacs/conversations/entities/Roster.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/entities/Roster.java b/src/main/java/eu/siacs/conversations/entities/Roster.java index 628a31d1..d3ad9181 100644 --- a/src/main/java/eu/siacs/conversations/entities/Roster.java +++ b/src/main/java/eu/siacs/conversations/entities/Roster.java @@ -9,7 +9,7 @@ import eu.siacs.conversations.xmpp.jid.Jid; public class Roster { final Account account; - final HashMap contacts = new HashMap<>(); + final HashMap contacts = new HashMap<>(); private String version = null; public Roster(Account account) { @@ -21,7 +21,7 @@ public class Roster { return null; } synchronized (this.contacts) { - Contact contact = contacts.get(jid.toBareJid().toString()); + Contact contact = contacts.get(jid.toBareJid()); if (contact != null && contact.showInRoster()) { return contact; } else { @@ -32,15 +32,13 @@ public class Roster { public Contact getContact(final Jid jid) { synchronized (this.contacts) { - final Jid bareJid = jid.toBareJid(); - if (contacts.containsKey(bareJid.toString())) { - return contacts.get(bareJid.toString()); - } else { - Contact contact = new Contact(bareJid); + if (!contacts.containsKey(jid.toBareJid())) { + Contact contact = new Contact(jid.toBareJid()); contact.setAccount(account); - contacts.put(bareJid.toString(), contact); + contacts.put(contact.getJid().toBareJid(), contact); return contact; } + return contacts.get(jid.toBareJid()); } } @@ -80,7 +78,7 @@ public class Roster { contact.setAccount(account); contact.setOption(Contact.Options.IN_ROSTER); synchronized (this.contacts) { - contacts.put(contact.getJid().toBareJid().toString(), contact); + contacts.put(contact.getJid().toBareJid(), contact); } } -- cgit v1.2.3 From 199ae3a4d8253fb00cdef5556763a46a319a2d46 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 28 Feb 2016 23:10:50 +0100 Subject: rename purge keys positive button to 'purge keys' --- src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 38b26819..5682f785 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -799,7 +799,7 @@ public abstract class XmppActivity extends Activity { + "\n\n" + CryptoHelper.prettifyFingerprint(fingerprint.substring(2)) + "\n\n" + getString(R.string.purge_key_desc_part2)); builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.accept), + builder.setPositiveButton(getString(R.string.purge_key), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { -- cgit v1.2.3 From 9e0466d1e643c07d1c3de088ddf2e5655899a50c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 29 Feb 2016 13:18:07 +0100 Subject: refactored omemo to take multiple recipients --- .../crypto/axolotl/AxolotlService.java | 154 ++++++++++++-------- .../siacs/conversations/entities/Conversation.java | 20 +-- .../siacs/conversations/entities/MucOptions.java | 11 ++ .../siacs/conversations/generator/IqGenerator.java | 7 + .../siacs/conversations/parser/MessageParser.java | 14 +- .../siacs/conversations/parser/PresenceParser.java | 8 +- .../services/XmppConnectionService.java | 40 +++++- .../conversations/ui/ConversationActivity.java | 21 +-- .../siacs/conversations/ui/TrustKeysActivity.java | 156 ++++++++++++--------- .../xmpp/jingle/JingleConnection.java | 2 +- src/main/res/layout/activity_trust_keys.xml | 29 +--- src/main/res/layout/keys_card.xml | 31 ++++ 12 files changed, 320 insertions(+), 173 deletions(-) create mode 100644 src/main/res/layout/keys_card.xml (limited to 'src') 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 949975aa..8658dfe2 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -81,13 +81,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - public boolean fetchMapHasErrors(Contact contact) { - Jid jid = contact.getJid().toBareJid(); - if (deviceIds.get(jid) != null) { - for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); - if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { - return true; + public boolean fetchMapHasErrors(List jids) { + for(Jid jid : jids) { + if (deviceIds.get(jid) != null) { + for (Integer foreignId : this.deviceIds.get(jid)) { + AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { + return true; + } } } } @@ -242,12 +243,29 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toString(), trust); } - public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Contact contact) { - return axolotlStore.getContactKeysWithTrust(contact.getJid().toBareJid().toString(), trust); + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Jid jid) { + return axolotlStore.getContactKeysWithTrust(jid.toBareJid().toString(), trust); + } + + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, List jids) { + Set keys = new HashSet<>(); + for(Jid jid : jids) { + keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toString(), trust)); + } + return keys; } - public long getNumTrustedKeys(Contact contact) { - return axolotlStore.getContactNumTrustedKeys(contact.getJid().toBareJid().toString()); + public long getNumTrustedKeys(Jid jid) { + return axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toString()); + } + + public boolean anyTargetHasNoTrustedKeys(List jids) { + for(Jid jid : jids) { + if (axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toString()) == 0) { + return true; + } + } + return false; } private AxolotlAddress getAddressForJid(Jid jid) { @@ -259,11 +277,19 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return new HashSet<>(this.sessions.getAll(ownAddress).values()); } - private Set findSessionsforContact(Contact contact) { + private Set findSessionsForContact(Contact contact) { AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); return new HashSet<>(this.sessions.getAll(contactAddress).values()); } + private Set findSessionsForConversation(Conversation conversation) { + HashSet sessions = new HashSet<>(); + for(Jid jid : getCryptoTargets(conversation)) { + sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values()); + } + return sessions; + } + public Set getFingerprintsForOwnSessions() { Set fingerprints = new HashSet<>(); for (XmppAxolotlSession session : findOwnSessions()) { @@ -274,15 +300,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public Set getFingerprintsForContact(final Contact contact) { Set fingerprints = new HashSet<>(); - for (XmppAxolotlSession session : findSessionsforContact(contact)) { + for (XmppAxolotlSession session : findSessionsForContact(contact)) { fingerprints.add(session.getFingerprint()); } return fingerprints; } - private boolean hasAny(Contact contact) { - AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); - return sessions.hasAny(contactAddress); + private boolean hasAny(Jid jid) { + return sessions.hasAny(getAddressForJid(jid)); } public boolean isPepBroken() { @@ -594,10 +619,25 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { }); } - public boolean isContactAxolotlCapable(Contact contact) { - Jid jid = contact.getJid().toBareJid(); - return hasAny(contact) || - (deviceIds.containsKey(jid) && !deviceIds.get(jid).isEmpty()); + public boolean isConversationAxolotlCapable(Conversation conversation) { + final List jids = getCryptoTargets(conversation); + for(Jid jid : jids) { + if (!hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty())) { + return false; + } + } + return jids.size() > 0; + } + + public List getCryptoTargets(Conversation conversation) { + final List jids; + if (conversation.getMode() == Conversation.MODE_SINGLE) { + jids = Arrays.asList(conversation.getJid().toBareJid()); + } else { + jids = conversation.getMucOptions().getMembers(); + jids.remove(account.getJid().toBareJid()); + } + return jids; } public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) { @@ -753,33 +793,31 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public Set findDevicesWithoutSession(final Conversation conversation) { - return findDevicesWithoutSession(conversation.getContact().getJid().toBareJid()); - } - - public Set findDevicesWithoutSession(final Jid contactJid) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + contactJid); Set addresses = new HashSet<>(); - if (deviceIds.get(contactJid) != null) { - for (Integer foreignId : this.deviceIds.get(contactJid)) { - AxolotlAddress address = new AxolotlAddress(contactJid.toString(), foreignId); - if (sessions.get(address) == null) { - IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); - if (identityKey != null) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already have session for " + address.toString() + ", adding to cache..."); - XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey); - sessions.put(address, session); - } else { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Found device " + contactJid + ":" + foreignId); - if (fetchStatusMap.get(address) != FetchStatus.ERROR) { - addresses.add(address); + for(Jid jid : getCryptoTargets(conversation)) { + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid); + if (deviceIds.get(jid) != null) { + for (Integer foreignId : this.deviceIds.get(jid)) { + AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + if (sessions.get(address) == null) { + IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); + if (identityKey != null) { + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already have session for " + address.toString() + ", adding to cache..."); + XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey); + sessions.put(address, session); } else { - Log.d(Config.LOGTAG,getLogprefix(account)+"skipping over "+address+" because it's broken"); + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Found device " + jid + ":" + foreignId); + if (fetchStatusMap.get(address) != FetchStatus.ERROR) { + addresses.add(address); + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "skipping over " + address + " because it's broken"); + } } } } + } else { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Have no target devices in PEP!"); } - } else { - Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Have no target devices in PEP!"); } if (deviceIds.get(account.getJid().toBareJid()) != null) { for (Integer ownId : this.deviceIds.get(account.getJid().toBareJid())) { @@ -827,7 +865,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public boolean trustedSessionVerified(final Conversation conversation) { - Set sessions = findSessionsforContact(conversation.getContact()); + Set sessions = findSessionsForConversation(conversation); sessions.addAll(findOwnSessions()); boolean verified = false; for(XmppAxolotlSession session : sessions) { @@ -842,26 +880,32 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return verified; } - public boolean hasPendingKeyFetches(Account account, Contact contact) { + public boolean hasPendingKeyFetches(Account account, List jids) { AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0); - AxolotlAddress foreignAddress = new AxolotlAddress(contact.getJid().toBareJid().toString(), 0); - return fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING) - || fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING); - + if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)) { + return true; + } + for(Jid jid : jids) { + AxolotlAddress foreignAddress = new AxolotlAddress(jid.toBareJid().toString(), 0); + if (fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING)) { + return true; + } + } + return false; } @Nullable - private XmppAxolotlMessage buildHeader(Contact contact) { + private XmppAxolotlMessage buildHeader(Conversation conversation) { final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage( - contact.getJid().toBareJid(), getOwnDeviceId()); + account.getJid().toBareJid(), getOwnDeviceId()); - Set contactSessions = findSessionsforContact(contact); + Set remoteSessions = findSessionsForConversation(conversation); Set ownSessions = findOwnSessions(); - if (contactSessions.isEmpty()) { + if (remoteSessions.isEmpty()) { return null; } Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl foreign keyElements..."); - for (XmppAxolotlSession session : contactSessions) { + for (XmppAxolotlSession session : remoteSessions) { Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString()); axolotlMessage.addDevice(session); } @@ -876,7 +920,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { @Nullable public XmppAxolotlMessage encrypt(Message message) { - XmppAxolotlMessage axolotlMessage = buildHeader(message.getContact()); + XmppAxolotlMessage axolotlMessage = buildHeader(message.getConversation()); if (axolotlMessage != null) { final String content; @@ -913,11 +957,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { }); } - public void prepareKeyTransportMessage(final Contact contact, final OnMessageCreatedCallback onMessageCreatedCallback) { + public void prepareKeyTransportMessage(final Conversation conversation, final OnMessageCreatedCallback onMessageCreatedCallback) { executor.execute(new Runnable() { @Override public void run() { - XmppAxolotlMessage axolotlMessage = buildHeader(contact); + XmppAxolotlMessage axolotlMessage = buildHeader(conversation); onMessageCreatedCallback.run(axolotlMessage); } }); diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 796b36f9..f05b3f91 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -659,8 +659,8 @@ 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 && mode == MODE_SINGLE) { - if (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact())) { + if (Config.X509_VERIFICATION) { + if (axolotlService != null && axolotlService.isConversationAxolotlCapable(this)) { return Message.ENCRYPTION_AXOLOTL; } else { return Message.ENCRYPTION_NONE; @@ -673,16 +673,20 @@ public class Conversation extends AbstractEntity implements Blockable { next = outgoing; } } - if (!Config.supportUnencrypted() - && (mode == MODE_SINGLE || Config.supportOpenPgpOnly()) - && next <= 0) { - if (Config.supportOmemo() && (axolotlService != null && axolotlService.isContactAxolotlCapable(getContact()) || !Config.multipleEncryptionChoices())) { + + if (!Config.supportUnencrypted() && next <= 0) { + if (Config.supportOmemo() + && (axolotlService != null && axolotlService.isConversationAxolotlCapable(this) || !Config.multipleEncryptionChoices())) { return Message.ENCRYPTION_AXOLOTL; - } else if (Config.supportOtr()) { + } else if (Config.supportOtr() && mode == MODE_SINGLE) { return Message.ENCRYPTION_OTR; - } else if (Config.supportOpenPgp()) { + } else if (Config.supportOpenPgp() + && (mode == MODE_SINGLE) || !Config.multipleEncryptionChoices()) { return Message.ENCRYPTION_PGP; } + } else if (next == Message.ENCRYPTION_AXOLOTL + && (!Config.supportOmemo() || axolotlService == null || !axolotlService.isConversationAxolotlCapable(this))) { + next = Message.ENCRYPTION_NONE; } return next; } diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 3567c14f..059573c6 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -4,9 +4,11 @@ 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; import eu.siacs.conversations.xmpp.forms.Data; @@ -245,6 +247,7 @@ public class MucOptions { private Account account; private final Map users = Collections.synchronizedMap(new LinkedHashMap()); + private final Set members = Collections.synchronizedSet(new HashSet()); private List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; @@ -501,4 +504,12 @@ public class MucOptions { public Conversation getConversation() { return this.conversation; } + + public void putMember(Jid jid) { + members.add(jid); + } + + public List getMembers() { + return new ArrayList<>(members); + } } diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index 4395a546..a3b0f650 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -335,4 +335,11 @@ public class IqGenerator extends AbstractGenerator { enable.addChild(data); return packet; } + + public IqPacket queryAffiliation(Conversation conversation, String affiliation) { + IqPacket packet = new IqPacket(IqPacket.TYPE.GET); + packet.setTo(conversation.getJid().toBareJid()); + packet.query("http://jabber.org/protocol/muc#admin").addChild("item").setAttribute("affiliation",affiliation); + return packet; + } } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index aa9d7f6c..fd2d070c 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -103,7 +103,7 @@ public class MessageParser extends AbstractParser implements } } - private Message parseAxolotlChat(Element axolotlMessage, Jid from, String id, Conversation conversation, int status) { + private Message parseAxolotlChat(Element axolotlMessage, Jid from, Conversation conversation, int status) { Message finishedMessage = null; AxolotlService service = conversation.getAccount().getAxolotlService(); XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid()); @@ -357,7 +357,17 @@ public class MessageParser extends AbstractParser implements } else if (pgpEncrypted != null && Config.supportOpenPgp()) { message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status); } else if (axolotlEncrypted != null && Config.supportOmemo()) { - message = parseAxolotlChat(axolotlEncrypted, from, remoteMsgId, conversation, status); + Jid origin; + if (conversation.getMode() == Conversation.MODE_MULTI) { + origin = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart()); + if (origin == null) { + Log.d(Config.LOGTAG,"axolotl message in non anonymous conference received"); + return; + } + } else { + origin = from; + } + message = parseAxolotlChat(axolotlEncrypted, origin, conversation, status); if (message == null) { return; } diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 63d28c97..c2782d23 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -64,10 +64,14 @@ public class PresenceParser extends AbstractParser implements Element item = x.findChild("item"); if (item != null && !from.isBareJid()) { mucOptions.setError(MucOptions.Error.NONE); - MucOptions.User user = new MucOptions.User(mucOptions,from); + MucOptions.User user = new MucOptions.User(mucOptions, from); user.setAffiliation(item.getAttribute("affiliation")); user.setRole(item.getAttribute("role")); - user.setJid(item.getAttributeAsJid("jid")); + Jid real = item.getAttributeAsJid("jid"); + if (real != null) { + user.setJid(real); + mucOptions.putMember(real.toBareJid()); + } if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) { mucOptions.setOnline(); mucOptions.setSelf(user); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index dde8ad28..0518f992 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1784,6 +1784,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Account account = conversation.getAccount(); final String nick = conversation.getMucOptions().getProposedNick(); final Jid joinJid = conversation.getMucOptions().createJoinJid(nick); + final MucOptions mucOptions = conversation.getMucOptions(); Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString()); PresencePacket packet = new PresencePacket(); packet.setFrom(conversation.getAccount().getJid()); @@ -1793,7 +1794,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa x.addChild("password").setContent(conversation.getMucOptions().getPassword()); } - if (conversation.getMucOptions().mamSupport()) { + if (mucOptions.mamSupport()) { // Use MAM instead of the limited muc history to get history x.addChild("history").setAttribute("maxchars", "0"); } else { @@ -1812,9 +1813,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa conversation.setContactJid(joinJid); databaseBackend.updateConversation(conversation); } - if (conversation.getMucOptions().mamSupport()) { + + if (mucOptions.mamSupport()) { getMessageArchiveService().catchupMUC(conversation); } + if (mucOptions.membersOnly() && mucOptions.nonanonymous()) { + fetchConferenceMembers(conversation); + } sendUnsentMessages(conversation); } @@ -1838,6 +1843,37 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } + private void fetchConferenceMembers(final Conversation conversation) { + final Account account = conversation.getAccount(); + final String[] affiliations = {"member","admin","owner"}; + OnIqPacketReceived callback = new OnIqPacketReceived() { + + private int i = 0; + + @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) { + for(Element child : query.getChildren()) { + if ("item".equals(child.getName())) { + conversation.getMucOptions().putMember(child.getAttributeAsJid("jid")); + } + } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not request affiliation "+affiliations[i]+" in "+conversation.getJid().toBareJid()); + } + ++i; + if (i >= affiliations.length) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": retrieved members for "+conversation.getJid().toBareJid()+": "+conversation.getMucOptions().getMembers()); + } + } + }; + for(String affiliation : affiliations) { + sendIqPacket(account, mIqGenerator.queryAffiliation(conversation, affiliation), callback); + } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": fetching members for "+conversation.getName()); + } + public void providePasswordForMuc(Conversation conversation, String password) { if (conversation.getMode() == Conversation.MODE_MULTI) { conversation.getMucOptions().setPassword(password); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 55a12710..e4ffb3e4 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -408,7 +408,7 @@ public class ConversationActivity extends XmppActivity menuContactDetails.setVisible(false); menuAttach.setVisible(getSelectedConversation().getAccount().httpUploadAvailable() && getSelectedConversation().getMucOptions().participating()); menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); - menuSecure.setVisible(Config.supportOpenPgp() && Config.multipleEncryptionChoices()); //only if pgp is supported we have a choice + menuSecure.setVisible((Config.supportOpenPgp() || Config.supportOmemo()) && Config.multipleEncryptionChoices()); //only if pgp is supported we have a choice } else { menuMucDetails.setVisible(false); menuSecure.setVisible(Config.multipleEncryptionChoices()); @@ -856,8 +856,8 @@ public class ConversationActivity extends XmppActivity axolotl.setVisible(Config.supportOmemo()); if (conversation.getMode() == Conversation.MODE_MULTI) { otr.setVisible(false); - axolotl.setVisible(false); - } else if (!conversation.getAccount().getAxolotlService().isContactAxolotlCapable(conversation.getContact())) { + } + if (!conversation.getAccount().getAxolotlService().isConversationAxolotlCapable(conversation)) { axolotl.setEnabled(false); } switch (conversation.getNextEncryption()) { @@ -1530,18 +1530,21 @@ public class ConversationActivity extends XmppActivity protected boolean trustKeysIfNeeded(int requestCode, int attachmentChoice) { AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService(); - Contact contact = mSelectedConversation.getContact(); + final List targets = axolotlService.getCryptoTargets(mSelectedConversation); boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty(); - boolean hasUndecidedContact = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED,contact).isEmpty(); + boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty(); boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty(); - boolean hasNoTrustedKeys = axolotlService.getNumTrustedKeys(mSelectedConversation.getContact()) == 0; - if(hasUndecidedOwn || hasUndecidedContact || hasPendingKeys || hasNoTrustedKeys) { + boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets); + if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys) { axolotlService.createSessionsIfNeeded(mSelectedConversation); Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class); - intent.putExtra("contact", mSelectedConversation.getContact().getJid().toBareJid().toString()); + String[] contacts = new String[targets.size()]; + for(int i = 0; i < contacts.length; ++i) { + contacts[i] = targets.get(i).toString(); + } + intent.putExtra("contacts", contacts); intent.putExtra(EXTRA_ACCOUNT, mSelectedConversation.getAccount().getJid().toBareJid().toString()); intent.putExtra("choice", attachmentChoice); - intent.putExtra("has_no_trusted", hasNoTrustedKeys); startActivityForResult(intent, requestCode); return true; } else { diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index eec30798..8919ac79 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -12,7 +12,9 @@ import android.widget.Toast; import org.whispersystems.libaxolotl.IdentityKey; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -20,32 +22,28 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated { private Jid accountJid; - private Jid contactJid; + private List contactJids; - private Contact contact; private Account mAccount; private TextView keyErrorMessage; private LinearLayout keyErrorMessageCard; private TextView ownKeysTitle; private LinearLayout ownKeys; private LinearLayout ownKeysCard; - private TextView foreignKeysTitle; private LinearLayout foreignKeys; - private LinearLayout foreignKeysCard; private Button mSaveButton; private Button mCancelButton; private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS; private final Map ownKeysToTrust = new HashMap<>(); - private final Map foreignKeysToTrust = new HashMap<>(); + private final Map> foreignKeysToTrust = new HashMap<>(); private final OnClickListener mSaveButtonListener = new OnClickListener() { @Override @@ -69,15 +67,6 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate populateView(); } - @Override - protected String getShareableUri() { - if (contact != null) { - return contact.getShareableUri(); - } else { - return ""; - } - } - @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -86,9 +75,13 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate this.accountJid = Jid.fromString(getIntent().getExtras().getString(EXTRA_ACCOUNT)); } catch (final InvalidJidException ignored) { } - try { - this.contactJid = Jid.fromString(getIntent().getExtras().getString("contact")); - } catch (final InvalidJidException ignored) { + this.contactJids = new ArrayList<>(); + for(String jid : getIntent().getStringArrayExtra("contacts")) { + try { + this.contactJids.add(Jid.fromString(jid)); + } catch (InvalidJidException e) { + e.printStackTrace(); + } } keyErrorMessageCard = (LinearLayout) findViewById(R.id.key_error_message_card); @@ -96,9 +89,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate ownKeysTitle = (TextView) findViewById(R.id.own_keys_title); ownKeys = (LinearLayout) findViewById(R.id.own_keys_details); ownKeysCard = (LinearLayout) findViewById(R.id.own_keys_card); - foreignKeysTitle = (TextView) findViewById(R.id.foreign_keys_title); - foreignKeys = (LinearLayout) findViewById(R.id.foreign_keys_details); - foreignKeysCard = (LinearLayout) findViewById(R.id.foreign_keys_card); + foreignKeys = (LinearLayout) findViewById(R.id.foreign_keys); mCancelButton = (Button) findViewById(R.id.cancel_button); mCancelButton.setOnClickListener(mCancelButtonListener); mSaveButton = (Button) findViewById(R.id.save_button); @@ -119,7 +110,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate boolean hasForeignKeys = false; for(final String fingerprint : ownKeysToTrust.keySet()) { hasOwnKeys = true; - addFingerprintRowWithListeners(ownKeys, contact.getAccount(), fingerprint, false, + addFingerprintRowWithListeners(ownKeys, mAccount, fingerprint, false, XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)), false, new CompoundButton.OnCheckedChangeListener() { @Override @@ -132,30 +123,36 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate null ); } - for(final String fingerprint : foreignKeysToTrust.keySet()) { - hasForeignKeys = true; - addFingerprintRowWithListeners(foreignKeys, contact.getAccount(), fingerprint, false, - XmppAxolotlSession.Trust.fromBoolean(foreignKeysToTrust.get(fingerprint)), false, - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - foreignKeysToTrust.put(fingerprint, isChecked); - lockOrUnlockAsNeeded(); - } - }, - null, - null - ); - } - if(hasOwnKeys) { - ownKeysTitle.setText(accountJid.toString()); - ownKeysCard.setVisibility(View.VISIBLE); - } - if(hasForeignKeys) { - foreignKeysTitle.setText(contactJid.toString()); - foreignKeysCard.setVisibility(View.VISIBLE); + synchronized (this.foreignKeysToTrust) { + for (Map.Entry> entry : foreignKeysToTrust.entrySet()) { + final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false); + final TextView header = (TextView) layout.findViewById(R.id.foreign_keys_title); + final LinearLayout keysContainer = (LinearLayout) layout.findViewById(R.id.foreign_keys_details); + header.setText(entry.getKey().toString()); + final Map fingerprints = entry.getValue(); + for (final String fingerprint : fingerprints.keySet()) { + hasForeignKeys = true; + addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false, + XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false, + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + fingerprints.put(fingerprint, isChecked); + lockOrUnlockAsNeeded(); + } + }, + null, + null + ); + } + foreignKeys.addView(layout); + } } + + ownKeysTitle.setText(accountJid.toString()); + ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE); + foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE); if(hasPendingKeyFetches()) { setFetching(); lock(); @@ -163,13 +160,15 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate if (!hasForeignKeys && hasNoOtherTrustedKeys()) { keyErrorMessageCard.setVisibility(View.VISIBLE); if (lastFetchReport == AxolotlService.FetchStatus.ERROR - || contact.getAccount().getAxolotlService().fetchMapHasErrors(contact)) { + || mAccount.getAxolotlService().fetchMapHasErrors(contactJids)) { keyErrorMessage.setText(R.string.error_no_keys_to_trust_server_error); } else { keyErrorMessage.setText(R.string.error_no_keys_to_trust); } - ownKeys.removeAllViews(); ownKeysCard.setVisibility(View.GONE); - foreignKeys.removeAllViews(); foreignKeysCard.setVisibility(View.GONE); + ownKeys.removeAllViews(); + ownKeysCard.setVisibility(View.GONE); + foreignKeys.removeAllViews(); + foreignKeys.setVisibility(View.GONE); } lockOrUnlockAsNeeded(); setDone(); @@ -178,45 +177,56 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate private boolean reloadFingerprints() { ownKeysToTrust.clear(); - foreignKeysToTrust.clear(); AxolotlService service = this.mAccount.getAxolotlService(); Set ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED); - Set foreignKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, contact); - if (hasNoOtherTrustedKeys() && ownKeysSet.size() == 0) { - foreignKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, contact)); - } for(final IdentityKey identityKey : ownKeysSet) { if(!ownKeysToTrust.containsKey(identityKey)) { ownKeysToTrust.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); } } - for(final IdentityKey identityKey : foreignKeysSet) { - if(!foreignKeysToTrust.containsKey(identityKey)) { - foreignKeysToTrust.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); + synchronized (this.foreignKeysToTrust) { + foreignKeysToTrust.clear(); + for (Jid jid : contactJids) { + Set foreignKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, jid); + if (hasNoOtherTrustedKeys(jid) && ownKeysSet.size() == 0) { + foreignKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, jid)); + } + Map foreignFingerprints = new HashMap<>(); + for (final IdentityKey identityKey : foreignKeysSet) { + if (!foreignFingerprints.containsKey(identityKey)) { + foreignFingerprints.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); + } + } + if (foreignFingerprints.size() > 0) { + foreignKeysToTrust.put(jid, foreignFingerprints); + } } } - return ownKeysSet.size() + foreignKeysSet.size() > 0; + return ownKeysSet.size() + foreignKeysToTrust.size() > 0; } @Override public void onBackendConnected() { - if ((accountJid != null) && (contactJid != null)) { + if (accountJid != null) { this.mAccount = xmppConnectionService.findAccountByJid(accountJid); if (this.mAccount == null) { return; } - this.contact = this.mAccount.getRoster().getContact(contactJid); reloadFingerprints(); populateView(); } } private boolean hasNoOtherTrustedKeys() { + return mAccount == null || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids); + } + + private boolean hasNoOtherTrustedKeys(Jid contact) { return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0; } private boolean hasPendingKeyFetches() { - return mAccount != null && contact != null && mAccount.getAxolotlService().hasPendingKeyFetches(mAccount,contact); + return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(mAccount, contactJids); } @@ -262,14 +272,18 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate private void commitTrusts() { for(final String fingerprint :ownKeysToTrust.keySet()) { - contact.getAccount().getAxolotlService().setFingerprintTrust( + mAccount.getAxolotlService().setFingerprintTrust( fingerprint, XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint))); } - for(final String fingerprint:foreignKeysToTrust.keySet()) { - contact.getAccount().getAxolotlService().setFingerprintTrust( - fingerprint, - XmppAxolotlSession.Trust.fromBoolean(foreignKeysToTrust.get(fingerprint))); + synchronized (this.foreignKeysToTrust) { + for (Map value : foreignKeysToTrust.values()) { + for (final String fingerprint : value.keySet()) { + mAccount.getAxolotlService().setFingerprintTrust( + fingerprint, + XmppAxolotlSession.Trust.fromBoolean(value.get(fingerprint))); + } + } } } @@ -284,11 +298,17 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate } private void lockOrUnlockAsNeeded() { - if (hasNoOtherTrustedKeys() && !foreignKeysToTrust.values().contains(true)){ - lock(); - } else { - unlock(); + synchronized (this.foreignKeysToTrust) { + for (Jid jid : contactJids) { + Map fingerprints = foreignKeysToTrust.get(jid); + if (hasNoOtherTrustedKeys(jid) && (fingerprints == null || !fingerprints.values().contains(true))) { + lock(); + return; + } + } } + unlock(); + } private void setDone() { 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 56582f97..a8e081a7 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -218,7 +218,7 @@ public class JingleConnection implements Transferable { public void init(final Message message) { if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) { Conversation conversation = message.getConversation(); - conversation.getAccount().getAxolotlService().prepareKeyTransportMessage(conversation.getContact(), new OnMessageCreatedCallback() { + conversation.getAccount().getAxolotlService().prepareKeyTransportMessage(conversation, new OnMessageCreatedCallback() { @Override public void run(XmppAxolotlMessage xmppAxolotlMessage) { if (xmppAxolotlMessage != null) { diff --git a/src/main/res/layout/activity_trust_keys.xml b/src/main/res/layout/activity_trust_keys.xml index 6f8a1bc9..d7bb7628 100644 --- a/src/main/res/layout/activity_trust_keys.xml +++ b/src/main/res/layout/activity_trust_keys.xml @@ -80,34 +80,11 @@ - - - - - + android:visibility="gone" + android:orientation="vertical"> diff --git a/src/main/res/layout/keys_card.xml b/src/main/res/layout/keys_card.xml new file mode 100644 index 00000000..7a502816 --- /dev/null +++ b/src/main/res/layout/keys_card.xml @@ -0,0 +1,31 @@ + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 134c75ae01eee45882d17a4d2fc721f4ccf3ca80 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 29 Feb 2016 16:32:24 +0100 Subject: use correct jid when leaving a conference. fixes #1732 --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 2 +- .../eu/siacs/conversations/services/XmppConnectionService.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 059573c6..4fe26743 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -248,7 +248,7 @@ public class MucOptions { private Account account; private final Map users = Collections.synchronizedMap(new LinkedHashMap()); private final Set members = Collections.synchronizedSet(new HashSet()); - private List features = new ArrayList<>(); + private final List features = new ArrayList<>(); private Data form = new Data(); private Conversation conversation; private boolean isOnline = false; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 0518f992..85eb479f 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1782,9 +1782,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private void join(Conversation conversation) { Account account = conversation.getAccount(); - final String nick = conversation.getMucOptions().getProposedNick(); - final Jid joinJid = conversation.getMucOptions().createJoinJid(nick); 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()); @@ -1947,7 +1946,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa account.pendingConferenceLeaves.remove(conversation); if (account.getStatus() == Account.State.ONLINE || now) { PresencePacket packet = new PresencePacket(); - packet.setTo(conversation.getJid()); + packet.setTo(conversation.getMucOptions().getSelf().getFullJid()); packet.setFrom(conversation.getAccount().getJid()); packet.setAttribute("type", "unavailable"); sendPresencePacket(conversation.getAccount(), packet); @@ -2047,9 +2046,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE.RESULT) { + Element query = packet.findChild("query","http://jabber.org/protocol/disco#info"); + if (packet.getType() == IqPacket.TYPE.RESULT && query != null) { ArrayList features = new ArrayList<>(); - Element query = packet.query(); for (Element child : query.getChildren()) { if (child != null && child.getName().equals("feature")) { String var = child.getAttribute("var"); @@ -2066,6 +2065,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (callback != null) { callback.onConferenceConfigurationFetched(conversation); } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": fetched muc configuration for "+conversation.getJid().toBareJid()+" - "+features.toString()); updateConversationUi(); } else if (packet.getType() == IqPacket.TYPE.ERROR) { if (callback != null) { -- cgit v1.2.3 From df7b399e04c9a5c6e20b0f0096bbe3b240ff2488 Mon Sep 17 00:00:00 2001 From: Tarun Date: Mon, 29 Feb 2016 23:35:50 +0530 Subject: Fix Issue #1634 : Shows XMPP URI as links. Shows XMPP URI as links, other than Web URL's and Email Addresses. Also performs respective actions on clicking XMPP URI. --- .../java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') 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 f6496b21..9339809c 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -17,6 +17,7 @@ import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; +import android.text.util.Linkify; import android.util.DisplayMetrics; import android.util.Patterns; import android.view.View; @@ -34,6 +35,7 @@ import java.lang.ref.WeakReference; import java.util.List; import java.util.concurrent.RejectedExecutionException; import java.util.regex.Matcher; +import java.util.regex.Pattern; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; @@ -53,6 +55,11 @@ public class MessageAdapter extends ArrayAdapter { private static final int SENT = 0; private static final int RECEIVED = 1; private static final int STATUS = 2; + private static final Pattern XMPP_PATTERN = Pattern + .compile("xmpp\\:(?:(?:[" + + Patterns.GOOD_IRI_CHAR + + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])" + + "|(?:\\%[a-fA-F0-9]{2}))+"); private ConversationActivity activity; @@ -349,6 +356,9 @@ public class MessageAdapter extends ArrayAdapter { urlCount++; } viewHolder.messageBody.setTextIsSelectable(urlCount <= 1); + viewHolder.messageBody.setAutoLinkMask(0); + Linkify.addLinks(viewHolder.messageBody, Linkify.WEB_URLS); + Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); } else { viewHolder.messageBody.setText(""); viewHolder.messageBody.setTextIsSelectable(false); -- cgit v1.2.3 From 198dc2c6b444671ec71deb10fbbaaced6e03dced Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Mar 2016 11:26:59 +0100 Subject: let users confirm each member in a conference even if that contact is already trusted --- .../crypto/axolotl/AxolotlService.java | 2 +- .../siacs/conversations/entities/Conversation.java | 72 +++++++++++++++++++--- .../conversations/ui/ConversationActivity.java | 4 +- .../siacs/conversations/ui/TrustKeysActivity.java | 50 ++++++++++----- src/main/res/layout/keys_card.xml | 60 ++++++++++-------- src/main/res/values/strings.xml | 1 + 6 files changed, 137 insertions(+), 52 deletions(-) (limited to 'src') 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 8658dfe2..cc5c2491 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -284,7 +284,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private Set findSessionsForConversation(Conversation conversation) { HashSet sessions = new HashSet<>(); - for(Jid jid : getCryptoTargets(conversation)) { + for(Jid jid : conversation.getAcceptedCryptoTargets()) { sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values()); } return sessions; diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f05b3f91..0252ea74 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -9,11 +9,13 @@ import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionStatus; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.security.interfaces.DSAPublicKey; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; @@ -48,6 +50,7 @@ public class Conversation extends AbstractEntity implements Blockable { public static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; public static final String ATTRIBUTE_MUTED_TILL = "muted_till"; public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify"; + public static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets"; private String name; private String contactUuid; @@ -313,6 +316,18 @@ public class Conversation extends AbstractEntity implements Blockable { return getLongAttribute("last_clear_history", 0); } + public List getAcceptedCryptoTargets() { + if (mode == MODE_SINGLE) { + return Arrays.asList(getJid().toBareJid()); + } else { + return getJidListAttribute(ATTRIBUTE_CRYPTO_TARGETS); + } + } + + public void setAcceptedCryptoTargets(List acceptedTargets) { + setAttribute(ATTRIBUTE_CRYPTO_TARGETS, acceptedTargets); + } + public void setCorrectingMessage(Message correctingMessage) { this.correctingMessage = correctingMessage; } @@ -794,20 +809,59 @@ public class Conversation extends AbstractEntity implements Blockable { } public boolean setAttribute(String key, String value) { - try { - this.attributes.put(key, value); - return true; - } catch (JSONException e) { - return false; + synchronized (this.attributes) { + try { + this.attributes.put(key, value); + return true; + } catch (JSONException e) { + return false; + } + } + } + + public boolean setAttribute(String key, List jids) { + JSONArray array = new JSONArray(); + for(Jid jid : jids) { + array.put(jid.toBareJid().toString()); + } + synchronized (this.attributes) { + try { + this.attributes.put(key, array); + return true; + } catch (JSONException e) { + e.printStackTrace(); + return false; + } } } public String getAttribute(String key) { - try { - return this.attributes.getString(key); - } catch (JSONException e) { - return null; + synchronized (this.attributes) { + try { + return this.attributes.getString(key); + } catch (JSONException e) { + return null; + } + } + } + + public List getJidListAttribute(String key) { + ArrayList list = new ArrayList<>(); + synchronized (this.attributes) { + try { + JSONArray array = this.attributes.getJSONArray(key); + for (int i = 0; i < array.length(); ++i) { + try { + list.add(Jid.fromString(array.getString(i))); + } catch (InvalidJidException e) { + //ignored + } + } + } catch (JSONException e) { + //ignored + } } + return list; } public int getIntAttribute(String key, int defaultValue) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index e4ffb3e4..eac53124 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1531,11 +1531,12 @@ public class ConversationActivity extends XmppActivity protected boolean trustKeysIfNeeded(int requestCode, int attachmentChoice) { AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService(); final List targets = axolotlService.getCryptoTargets(mSelectedConversation); + boolean hasUnaccepted = !mSelectedConversation.getAcceptedCryptoTargets().containsAll(targets); boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty(); boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty(); boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty(); boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets); - if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys) { + if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys || hasUnaccepted) { axolotlService.createSessionsIfNeeded(mSelectedConversation); Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class); String[] contacts = new String[targets.size()]; @@ -1545,6 +1546,7 @@ public class ConversationActivity extends XmppActivity intent.putExtra("contacts", contacts); intent.putExtra(EXTRA_ACCOUNT, mSelectedConversation.getAccount().getJid().toBareJid().toString()); intent.putExtra("choice", attachmentChoice); + intent.putExtra("conversation",mSelectedConversation.getUuid()); startActivityForResult(intent, requestCode); return true; } else { diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index 8919ac79..9bccca78 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -10,6 +10,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import android.util.Log; + import org.whispersystems.libaxolotl.IdentityKey; import java.util.ArrayList; @@ -18,19 +20,21 @@ import java.util.List; import java.util.Map; import java.util.Set; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated { - private Jid accountJid; private List contactJids; private Account mAccount; + private Conversation mConversation; private TextView keyErrorMessage; private LinearLayout keyErrorMessageCard; private TextView ownKeysTitle; @@ -71,10 +75,6 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_trust_keys); - try { - this.accountJid = Jid.fromString(getIntent().getExtras().getString(EXTRA_ACCOUNT)); - } catch (final InvalidJidException ignored) { - } this.contactJids = new ArrayList<>(); for(String jid : getIntent().getStringArrayExtra("contacts")) { try { @@ -126,13 +126,15 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate synchronized (this.foreignKeysToTrust) { for (Map.Entry> entry : foreignKeysToTrust.entrySet()) { + hasForeignKeys = true; final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false); + final Jid jid = entry.getKey(); final TextView header = (TextView) layout.findViewById(R.id.foreign_keys_title); final LinearLayout keysContainer = (LinearLayout) layout.findViewById(R.id.foreign_keys_details); - header.setText(entry.getKey().toString()); + final TextView informNoKeys = (TextView) layout.findViewById(R.id.no_keys_to_accept); + header.setText(jid.toString()); final Map fingerprints = entry.getValue(); for (final String fingerprint : fingerprints.keySet()) { - hasForeignKeys = true; addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false, XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false, new CompoundButton.OnCheckedChangeListener() { @@ -146,11 +148,17 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate null ); } + if (fingerprints.size() == 0) { + informNoKeys.setVisibility(View.VISIBLE); + informNoKeys.setText(getString(R.string.no_keys_just_confirm,mAccount.getRoster().getContact(jid).getDisplayName())); + } else { + informNoKeys.setVisibility(View.GONE); + } foreignKeys.addView(layout); } } - ownKeysTitle.setText(accountJid.toString()); + ownKeysTitle.setText(mAccount.getJid().toBareJid().toString()); ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE); foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE); if(hasPendingKeyFetches()) { @@ -176,6 +184,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate } private boolean reloadFingerprints() { + List acceptedTargets = mConversation == null ? new ArrayList() : mConversation.getAcceptedCryptoTargets(); ownKeysToTrust.clear(); AxolotlService service = this.mAccount.getAxolotlService(); Set ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED); @@ -197,7 +206,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate foreignFingerprints.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); } } - if (foreignFingerprints.size() > 0) { + if (foreignFingerprints.size() > 0 || !acceptedTargets.contains(jid)) { foreignKeysToTrust.put(jid, foreignFingerprints); } } @@ -207,11 +216,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate @Override public void onBackendConnected() { - if (accountJid != null) { - this.mAccount = xmppConnectionService.findAccountByJid(accountJid); - if (this.mAccount == null) { - return; - } + Intent intent = getIntent(); + this.mAccount = extractAccount(intent); + if (this.mAccount != null && intent != null) { + String uuid = intent.getStringExtra("conversation"); + this.mConversation = xmppConnectionService.findConversationByUuid(uuid); reloadFingerprints(); populateView(); } @@ -276,8 +285,14 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate fingerprint, XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint))); } + List acceptedTargets = mConversation == null ? new ArrayList() : mConversation.getAcceptedCryptoTargets(); synchronized (this.foreignKeysToTrust) { - for (Map value : foreignKeysToTrust.values()) { + for (Map.Entry> entry : foreignKeysToTrust.entrySet()) { + Jid jid = entry.getKey(); + Map value = entry.getValue(); + if (!acceptedTargets.contains(jid)) { + acceptedTargets.add(jid); + } for (final String fingerprint : value.keySet()) { mAccount.getAxolotlService().setFingerprintTrust( fingerprint, @@ -285,6 +300,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate } } } + if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) { + Log.d(Config.LOGTAG,"commiting accepted crypto targets: "+acceptedTargets); + mConversation.setAcceptedCryptoTargets(acceptedTargets); + //xmppConnectionService.updateConversation(mConversation); + } } private void unlock() { diff --git a/src/main/res/layout/keys_card.xml b/src/main/res/layout/keys_card.xml index 7a502816..d3271d1b 100644 --- a/src/main/res/layout/keys_card.xml +++ b/src/main/res/layout/keys_card.xml @@ -1,31 +1,39 @@ - + - + - - + + + \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index a25c1a84..69609f88 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -599,4 +599,5 @@ This field is required Correct message Send corrected message + You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference. -- cgit v1.2.3 From fd246f7e5aa6fa1012c22fa33cd87915260a10cb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Mar 2016 12:22:20 +0100 Subject: properly persist accepted crypto targets --- src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index 9bccca78..cc4ba7b2 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -10,8 +10,6 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; -import android.util.Log; - import org.whispersystems.libaxolotl.IdentityKey; import java.util.ArrayList; @@ -20,7 +18,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; @@ -301,9 +298,8 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate } } if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) { - Log.d(Config.LOGTAG,"commiting accepted crypto targets: "+acceptedTargets); mConversation.setAcceptedCryptoTargets(acceptedTargets); - //xmppConnectionService.updateConversation(mConversation); + xmppConnectionService.updateConversation(mConversation); } } -- cgit v1.2.3 From 15a1873d97b49293d025be09d9b135c6871a6da5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Mar 2016 18:58:33 +0100 Subject: removed unused config variable --- src/main/java/eu/siacs/conversations/Config.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 30951223..e39cd654 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -22,10 +22,6 @@ public final class Config { return (ENCRYPTION_MASK & OPENPGP) != 0; } - public static boolean supportOpenPgpOnly() { - return supportOpenPgp() && !multipleEncryptionChoices(); - } - public static boolean supportOtr() { return (ENCRYPTION_MASK & OTR) != 0; } -- cgit v1.2.3 From aaf64732b0e04d0b95407c5420da08c8c1752ec6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Mar 2016 19:00:18 +0100 Subject: expert option to treat vibrate as silent mode for XA. fixes #1530 --- .../conversations/services/XmppConnectionService.java | 10 +++++++++- .../java/eu/siacs/conversations/ui/SettingsActivity.java | 15 +++++++++------ src/main/res/values/strings.xml | 2 ++ src/main/res/xml/preferences.xml | 6 ++++++ 4 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 85eb479f..07a7e10b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -611,6 +611,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return getPreferences().getBoolean("xa_on_silent_mode", false); } + private boolean treatVibrateAsSilent() { + return getPreferences().getBoolean("treat_vibrate_as_silent", false); + } + private boolean awayWhenScreenOff() { return getPreferences().getBoolean("away_when_screen_off", false); } @@ -645,7 +649,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private boolean isPhoneSilenced() { AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - return audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT; + if (treatVibrateAsSilent()) { + return audioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; + } else { + return audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT; + } } private void resetAllAttemptCounts(boolean reallyAll) { diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index c028d0d6..750a7421 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -21,6 +21,7 @@ import java.security.KeyStoreException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Locale; import de.duenndns.ssl.MemorizingTrustManager; @@ -154,8 +155,13 @@ public class SettingsActivity extends XmppActivity implements } @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, - String name) { + public void onSharedPreferenceChanged(SharedPreferences preferences, String name) { + final List resendPresence = Arrays.asList( + "confirm_messages", + "xa_on_silent_mode", + "away_when_screen_off", + "allow_message_correction", + "treat_vibrate_as_silent"); if (name.equals("resource")) { String resource = preferences.getString("resource", "mobile") .toLowerCase(Locale.US); @@ -174,10 +180,7 @@ public class SettingsActivity extends XmppActivity implements } } else if (name.equals("keep_foreground_service")) { xmppConnectionService.toggleForegroundService(); - } else if (name.equals("confirm_messages") - || name.equals("xa_on_silent_mode") - || name.equals("away_when_screen_off") - || name.equals("allow_message_correction")) { + } else if (resendPresence.contains(name)) { if (xmppConnectionServiceBound) { if (name.equals("away_when_screen_off")) { xmppConnectionService.toggleScreenEventReceiver(); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 69609f88..6a36233c 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -536,6 +536,8 @@ Marks your resource as away when the screen is turned off Not available in silent mode Marks your resource as not available when device is in silent mode + Treat vibrate as silent mode + Marks your resource as not available when device is on vibrate Extended connection settings Show hostname and port settings when setting up an account xmpp.example.com diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index 35799573..f505baf7 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -189,6 +189,12 @@ android:key="xa_on_silent_mode" android:summary="@string/pref_xa_on_silent_mode_summary" android:title="@string/pref_xa_on_silent_mode"/> + Date: Thu, 3 Mar 2016 11:14:59 +0100 Subject: don't break with srcoll events on empty message lists --- .../java/eu/siacs/conversations/ui/ConversationFragment.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 15e4b985..09d98e83 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -123,7 +123,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private int getIndexOf(String uuid, List messages) { if (uuid == null) { - return 0; + return messages.size() - 1; } for(int i = 0; i < messages.size(); ++i) { if (uuid.equals(messages.get(i).getUuid())) { @@ -164,7 +164,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa @Override public void run() { final int oldPosition = messagesView.getFirstVisiblePosition(); - Message message = messageList.get(oldPosition); + final Message message; + if (oldPosition < messageList.size()) { + message = messageList.get(oldPosition); + } else { + message = null; + } String uuid = message != null ? message.getUuid() : null; View v = messagesView.getChildAt(0); final int pxOffset = (v == null) ? 0 : v.getTop(); -- cgit v1.2.3 From 4cb2d0ca932de2bb387c5f843ad6df608b04c03b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 3 Mar 2016 13:31:59 +0100 Subject: avoid unnecessary disconnect. prevent NetworkOnMainThreadException --- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 07a7e10b..cc269b67 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2554,9 +2554,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private void reconnectAccount(final Account account, final boolean force, final boolean interactive) { synchronized (account) { XmppConnection connection = account.getXmppConnection(); - if (connection != null) { - disconnect(account, force); - } else { + if (connection == null) { connection = createConnection(account); account.setXmppConnection(connection); } @@ -2570,6 +2568,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } if (!force) { + disconnect(account, false); try { Log.d(Config.LOGTAG, "wait for disconnect"); Thread.sleep(500); //sleep wait for disconnect @@ -2582,6 +2581,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa thread.start(); scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode()); } else { + disconnect(account, force); account.getRoster().clearPresences(); connection.resetEverything(); } -- cgit v1.2.3 From bc5f64bffe3deb260824f6eae33238c10ab71244 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 3 Mar 2016 13:33:02 +0100 Subject: moved avatarfetcher reset code to bind --- .../conversations/services/XmppConnectionService.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index cc269b67..ecf5504b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -254,6 +254,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onBind(final Account account) { + synchronized (mInProgressAvatarFetches) { + for (Iterator iterator = mInProgressAvatarFetches.iterator(); iterator.hasNext(); ) { + final String KEY = iterator.next(); + if (KEY.startsWith(account.getJid().toBareJid() + "_")) { + iterator.remove(); + } + } + } account.getRoster().clearPresences(); mJingleConnectionManager.cancelInTransmission(); fetchRosterFromServer(account); @@ -2559,14 +2567,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa account.setXmppConnection(connection); } if (!account.isOptionSet(Account.OPTION_DISABLED)) { - synchronized (this.mInProgressAvatarFetches) { - for (Iterator iterator = this.mInProgressAvatarFetches.iterator(); iterator.hasNext(); ) { - final String KEY = iterator.next(); - if (KEY.startsWith(account.getJid().toBareJid() + "_")) { - iterator.remove(); - } - } - } if (!force) { disconnect(account, false); try { -- cgit v1.2.3 From 07263370d9e4b03635baf7ac446813610bc0b98f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Mar 2016 11:24:40 +0100 Subject: allow to copy original url even while downloading. fixes #1743 --- .../eu/siacs/conversations/ui/ConversationFragment.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 09d98e83..9ef950c4 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -53,6 +53,7 @@ import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.TransferablePlaceholder; +import eu.siacs.conversations.http.HttpDownloadConnection; import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected; @@ -520,6 +521,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private void populateContextMenu(ContextMenu menu) { final Message m = this.selectedMessage; + final Transferable t = m.getTransferable(); Message relevantForCorrection = m; while(relevantForCorrection.mergeable(relevantForCorrection.next())) { relevantForCorrection = relevantForCorrection.next(); @@ -536,7 +538,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa MenuItem downloadFile = menu.findItem(R.id.download_file); MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); if ((m.getType() == Message.TYPE_TEXT || m.getType() == Message.TYPE_PRIVATE) - && m.getTransferable() == null + && t == null && !GeoHelper.isGeoUri(m.getBody()) && m.treatAsDownloadable() != Message.Decision.MUST) { copyText.setVisible(true); @@ -550,7 +552,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } if ((m.getType() != Message.TYPE_TEXT && m.getType() != Message.TYPE_PRIVATE - && m.getTransferable() == null) + && t == null) || (GeoHelper.isGeoUri(m.getBody()))) { shareWith.setVisible(true); } @@ -559,15 +561,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } if (m.hasFileOnRemoteHost() || GeoHelper.isGeoUri(m.getBody()) - || m.treatAsDownloadable() == Message.Decision.MUST) { + || m.treatAsDownloadable() == Message.Decision.MUST + || (t != null && t instanceof HttpDownloadConnection)) { copyUrl.setVisible(true); } - if ((m.getType() == Message.TYPE_TEXT && m.getTransferable() == null && m.treatAsDownloadable() != Message.Decision.NEVER) - || (m.isFileOrImage() && m.getTransferable() instanceof TransferablePlaceholder && m.hasFileOnRemoteHost())){ + if ((m.getType() == Message.TYPE_TEXT && t == null && m.treatAsDownloadable() != Message.Decision.NEVER) + || (m.isFileOrImage() && t instanceof TransferablePlaceholder && m.hasFileOnRemoteHost())){ downloadFile.setVisible(true); downloadFile.setTitle(activity.getString(R.string.download_x_file,UIHelper.getFileDescriptionString(activity, m))); } - if ((m.getTransferable() != null && !(m.getTransferable() instanceof TransferablePlaceholder)) + if ((t != null && !(t instanceof TransferablePlaceholder)) || (m.isFileOrImage() && (m.getStatus() == Message.STATUS_WAITING || m.getStatus() == Message.STATUS_OFFERED))) { cancelTransmission.setVisible(true); -- cgit v1.2.3 From 89eea3636f50596adf0a8f673226f0f4063a2e8f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Mar 2016 11:24:53 +0100 Subject: add a few more know file extensions --- src/main/java/eu/siacs/conversations/entities/Message.java | 6 +++--- src/main/java/eu/siacs/conversations/entities/Transferable.java | 9 ++++++--- .../java/eu/siacs/conversations/http/HttpDownloadConnection.java | 2 +- .../eu/siacs/conversations/xmpp/jingle/JingleConnection.java | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 3dfbd787..cd2d3443 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -576,7 +576,7 @@ public class Message extends AbstractEntity { if (dotPosition != -1) { String extension = filename.substring(dotPosition + 1); // we want the real file extension, not the crypto one - if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) { + if (Transferable.VALID_CRYPTO_EXTENSIONS.contains(extension)) { return extractRelevantExtension(filename.substring(0,dotPosition)); } else { return extension; @@ -624,8 +624,8 @@ public class Message extends AbstractEntity { } else { return Decision.NEVER; } - } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension) - || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) { + } else if (Transferable.VALID_IMAGE_EXTENSIONS.contains(extension) + || Transferable.WELL_KNOWN_EXTENSIONS.contains(extension)) { return Decision.SHOULD; } else { return Decision.NEVER; diff --git a/src/main/java/eu/siacs/conversations/entities/Transferable.java b/src/main/java/eu/siacs/conversations/entities/Transferable.java index 016c81bd..5a47c451 100644 --- a/src/main/java/eu/siacs/conversations/entities/Transferable.java +++ b/src/main/java/eu/siacs/conversations/entities/Transferable.java @@ -1,10 +1,13 @@ package eu.siacs.conversations.entities; +import java.util.Arrays; +import java.util.List; + public interface Transferable { - String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; - String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; - String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a","mp4"}; + List VALID_IMAGE_EXTENSIONS = Arrays.asList("webp", "jpeg", "jpg", "png", "jpe"); + List VALID_CRYPTO_EXTENSIONS = Arrays.asList("pgp", "gpg", "otr"); + List WELL_KNOWN_EXTENSIONS = Arrays.asList("pdf","m4a","mp4","3gp","aac","amr","mp3"); int STATUS_UNKNOWN = 0x200; int STATUS_CHECKING = 0x201; diff --git a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java index 455a0b14..84a44715 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java @@ -89,7 +89,7 @@ public class HttpDownloadConnection implements Transferable { this.message.setEncryption(Message.ENCRYPTION_NONE); } String extension; - if (Arrays.asList(VALID_CRYPTO_EXTENSIONS).contains(lastPart)) { + if (VALID_CRYPTO_EXTENSIONS.contains(lastPart)) { extension = secondToLast; } else { extension = lastPart; 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 a8e081a7..dcb13c23 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -322,14 +322,14 @@ public class JingleConnection implements Transferable { String[] filename = fileNameElement.getContent() .toLowerCase(Locale.US).toLowerCase().split("\\."); String extension = filename[filename.length - 1]; - if (Arrays.asList(VALID_IMAGE_EXTENSIONS).contains(extension)) { + if (VALID_IMAGE_EXTENSIONS.contains(extension)) { message.setType(Message.TYPE_IMAGE); message.setRelativeFilePath(message.getUuid()+"."+extension); - } else if (Arrays.asList(VALID_CRYPTO_EXTENSIONS).contains( + } else if (VALID_CRYPTO_EXTENSIONS.contains( filename[filename.length - 1])) { if (filename.length == 3) { extension = filename[filename.length - 2]; - if (Arrays.asList(VALID_IMAGE_EXTENSIONS).contains(extension)) { + if (VALID_IMAGE_EXTENSIONS.contains(extension)) { message.setType(Message.TYPE_IMAGE); message.setRelativeFilePath(message.getUuid()+"."+extension); } else { -- cgit v1.2.3 From aa24a0f779c82c555e3f3f6f76485301c9757c89 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Mar 2016 14:32:38 +0100 Subject: don't automatically crop avatar --- .../ui/PublishProfilePictureActivity.java | 62 +++++++++++++-------- src/main/res/drawable-hdpi/ic_crop_white_24dp.png | Bin 0 -> 302 bytes src/main/res/drawable-mdpi/ic_crop_white_24dp.png | Bin 0 -> 214 bytes src/main/res/drawable-xhdpi/ic_crop_white_24dp.png | Bin 0 -> 272 bytes .../res/drawable-xxhdpi/ic_crop_white_24dp.png | Bin 0 -> 326 bytes .../res/drawable-xxxhdpi/ic_crop_white_24dp.png | Bin 0 -> 394 bytes src/main/res/menu/publish_avatar.xml | 8 +++ src/main/res/values/strings.xml | 1 + 8 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 src/main/res/drawable-hdpi/ic_crop_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_crop_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_crop_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png create mode 100644 src/main/res/menu/publish_avatar.xml (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index a457bf96..ee70ee43 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -7,6 +7,8 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; @@ -27,13 +29,12 @@ import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.utils.ExifHelper; import eu.siacs.conversations.utils.FileUtils; import eu.siacs.conversations.utils.PhoneHelper; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; public class PublishProfilePictureActivity extends XmppActivity { - private static final int REQUEST_CHOOSE_FILE = 0xac23; + private static final int REQUEST_CHOOSE_FILE_AND_CROP = 0xac23; + private static final int REQUEST_CHOOSE_FILE = 0xac24; private ImageView avatar; private TextView accountTextView; private TextView hintOrWarning; @@ -138,7 +139,7 @@ public class PublishProfilePictureActivity extends XmppActivity { @Override public void onClick(View v) { if (hasStoragePermission(REQUEST_CHOOSE_FILE)) { - chooseAvatar(); + chooseAvatar(false); } } @@ -146,32 +147,52 @@ public class PublishProfilePictureActivity extends XmppActivity { this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext()); } - private void chooseAvatar() { + private void chooseAvatar(boolean crop) { Intent attachFileIntent = new Intent(); attachFileIntent.setType("image/*"); attachFileIntent.setAction(Intent.ACTION_GET_CONTENT); Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file)); - startActivityForResult(chooser, REQUEST_CHOOSE_FILE); + startActivityForResult(chooser, crop ? REQUEST_CHOOSE_FILE_AND_CROP : REQUEST_CHOOSE_FILE); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { if (grantResults.length > 0) if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (requestCode == REQUEST_CHOOSE_FILE) { - chooseAvatar(); + if (requestCode == REQUEST_CHOOSE_FILE_AND_CROP) { + chooseAvatar(true); + } else if (requestCode == REQUEST_CHOOSE_FILE) { + chooseAvatar(false); } } else { Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); } } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.publish_avatar, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + if (item.getItemId() == R.id.action_crop_image) { + if (hasStoragePermission(REQUEST_CHOOSE_FILE_AND_CROP)) { + chooseAvatar(true); + } + return true; + } else { + return onOptionsItemSelected(item); + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { - case REQUEST_CHOOSE_FILE: + case REQUEST_CHOOSE_FILE_AND_CROP: Uri source = data.getData(); String original = FileUtils.getPath(this, source); if (original != null) { @@ -181,9 +202,17 @@ public class PublishProfilePictureActivity extends XmppActivity { final int size = getPixel(192); Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this); break; + case REQUEST_CHOOSE_FILE: + this.avatarUri = data.getData(); + if (xmppConnectionServiceBound) { + loadImageIntoPreview(this.avatarUri); + } + break; case Crop.REQUEST_CROP: this.avatarUri = Uri.fromFile(new File(getCacheDir(), "croppedAvatar")); - loadImageIntoPreview(this.avatarUri); + if (xmppConnectionServiceBound) { + loadImageIntoPreview(this.avatarUri); + } break; } } else { @@ -248,21 +277,10 @@ public class PublishProfilePictureActivity extends XmppActivity { } } - private Bitmap loadScaledBitmap(Uri uri, int reqSize) throws FileNotFoundException { - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); - int rotation = ExifHelper.getOrientation(getContentResolver().openInputStream(uri)); - options.inSampleSize = FileBackend.calcSampleSize(options, reqSize); - options.inJustDecodeBounds = false; - Bitmap bm = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); - return FileBackend.rotate(bm,rotation); - } - protected void loadImageIntoPreview(Uri uri) { Bitmap bm = null; try { - bm = loadScaledBitmap(uri, getPixel(192)); + bm = xmppConnectionService.getFileBackend().cropCenterSquare(uri, getPixel(192)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/res/drawable-hdpi/ic_crop_white_24dp.png b/src/main/res/drawable-hdpi/ic_crop_white_24dp.png new file mode 100644 index 00000000..6cbb87ce Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_crop_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_crop_white_24dp.png b/src/main/res/drawable-mdpi/ic_crop_white_24dp.png new file mode 100644 index 00000000..d606c072 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_crop_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png new file mode 100644 index 00000000..983af77f Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png new file mode 100644 index 00000000..8c9eecb9 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png new file mode 100644 index 00000000..35d5434a Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png differ diff --git a/src/main/res/menu/publish_avatar.xml b/src/main/res/menu/publish_avatar.xml new file mode 100644 index 00000000..1bffb296 --- /dev/null +++ b/src/main/res/menu/publish_avatar.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 6a36233c..7368d0dc 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -602,4 +602,5 @@ Correct message Send corrected message You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference. + Select image and crop -- cgit v1.2.3 From 09d87965fbd77d5c3e463a168c56e4c9bac9fc2e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Mar 2016 20:09:21 +0100 Subject: mark oob messages and always display download button --- .../java/eu/siacs/conversations/entities/Message.java | 18 +++++++++++++++--- .../eu/siacs/conversations/parser/MessageParser.java | 6 +++++- .../conversations/persistance/DatabaseBackend.java | 7 ++++++- .../java/eu/siacs/conversations/utils/UIHelper.java | 5 ++++- 4 files changed, 30 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index cd2d3443..be9d3d92 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -52,6 +52,7 @@ public class Message extends AbstractEntity { public static final String STATUS = "status"; public static final String TYPE = "type"; public static final String CARBON = "carbon"; + public static final String OOB = "oob"; public static final String EDITED = "edited"; public static final String REMOTE_MSG_ID = "remoteMsgId"; public static final String SERVER_MSG_ID = "serverMsgId"; @@ -72,6 +73,7 @@ public class Message extends AbstractEntity { protected int status; protected int type; protected boolean carbon = false; + protected boolean oob = false; protected String edited = null; protected String relativeFilePath; protected boolean read = true; @@ -107,7 +109,8 @@ public class Message extends AbstractEntity { null, null, true, - null); + null, + false); this.conversation = conversation; } @@ -116,7 +119,7 @@ public class Message extends AbstractEntity { final int encryption, final int status, final int type, final boolean carbon, final String remoteMsgId, final String relativeFilePath, final String serverMsgId, final String fingerprint, final boolean read, - final String edited) { + final String edited, final boolean oob) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -133,6 +136,7 @@ public class Message extends AbstractEntity { this.axolotlFingerprint = fingerprint; this.read = read; this.edited = edited; + this.oob = oob; } public static Message fromCursor(Cursor cursor) { @@ -173,7 +177,8 @@ public class Message extends AbstractEntity { cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), cursor.getString(cursor.getColumnIndex(FINGERPRINT)), cursor.getInt(cursor.getColumnIndex(READ)) > 0, - cursor.getString(cursor.getColumnIndex(EDITED))); + cursor.getString(cursor.getColumnIndex(EDITED)), + cursor.getInt(cursor.getColumnIndex(OOB)) > 0); } public static Message createStatusMessage(Conversation conversation, String body) { @@ -219,6 +224,7 @@ public class Message extends AbstractEntity { values.put(FINGERPRINT, axolotlFingerprint); values.put(READ,read ? 1 : 0); values.put(EDITED, edited); + values.put(OOB, oob ? 1 : 0); return values; } @@ -554,6 +560,10 @@ public class Message extends AbstractEntity { return edited; } + public void setOob(boolean isOob) { + this.oob = isOob; + } + public enum Decision { MUST, SHOULD, @@ -610,6 +620,8 @@ public class Message extends AbstractEntity { URL url = new URL(body); if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { return Decision.NEVER; + } else if (oob) { + return Decision.MUST; } String extension = extractRelevantExtension(url); if (extension == null) { diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index fd2d070c..9470dab8 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -6,6 +6,7 @@ import android.util.Pair; import net.java.otr4j.session.Session; import net.java.otr4j.session.SessionStatus; +import java.net.URL; import java.util.ArrayList; import java.util.Set; import java.util.UUID; @@ -290,7 +291,9 @@ public class MessageParser extends AbstractParser implements final String body = packet.getBody(); final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user"); final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted"); - final Element replaceElement = packet.findChild("replace","urn:xmpp:message-correct:0"); + final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0"); + final Element oob = packet.findChild("x", "jabber:x:oob"); + final boolean isOob = oob!= null && body != null && body.equals(oob.findChildContent("url")); final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id"); final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); int status; @@ -384,6 +387,7 @@ public class MessageParser extends AbstractParser implements message.setServerMsgId(serverMsgId); message.setCarbon(isCarbon); message.setTime(timestamp); + 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()); diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index dcba4f74..b975a001 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -51,7 +51,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private static DatabaseBackend instance = null; private static final String DATABASE_NAME = "history"; - private static final int DATABASE_VERSION = 24; + private static final int DATABASE_VERSION = 25; private static String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -163,6 +163,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + Message.CARBON + " INTEGER, " + Message.EDITED + " TEXT, " + Message.READ + " NUMBER DEFAULT 1, " + + Message.OOB + " INTEGER, " + Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY(" + Message.CONVERSATION + ") REFERENCES " + Conversation.TABLENAME + "(" + Conversation.UUID @@ -375,6 +376,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (oldVersion < 24 && newVersion >= 24) { db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.EDITED + " TEXT"); } + + if (oldVersion < 25 && newVersion >= 25) { + db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.OOB + " INTEGER"); + } } public static synchronized DatabaseBackend getInstance(Context context) { diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 5e8af085..8cae8117 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -187,10 +187,13 @@ public class UIHelper { UIHelper.getMessageDisplayName(message) + " "), false); } else if (GeoHelper.isGeoUri(message.getBody())) { if (message.getStatus() == Message.STATUS_RECEIVED) { - return new Pair<>(context.getString(R.string.received_location),true); + return new Pair<>(context.getString(R.string.received_location), true); } else { return new Pair<>(context.getString(R.string.location), true); } + } else if (message.treatAsDownloadable() == Message.Decision.MUST) { + return new Pair<>(context.getString(R.string.x_file_offered_for_download, + getFileDescriptionString(context,message)),true); } else{ return new Pair<>(message.getBody().trim(), false); } -- cgit v1.2.3 From e9b4a2a021576a06671e63bb23b8daad6bda82bb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 4 Mar 2016 21:30:34 +0100 Subject: show host in file size checker --- .../eu/siacs/conversations/ui/adapter/MessageAdapter.java | 15 ++++++++++++++- src/main/res/values/strings.xml | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') 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 f6496b21..54dd7f02 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -31,6 +31,7 @@ import android.widget.TextView; import android.widget.Toast; import java.lang.ref.WeakReference; +import java.net.URL; import java.util.List; import java.util.concurrent.RejectedExecutionException; import java.util.regex.Matcher; @@ -625,7 +626,19 @@ public class MessageAdapter extends ArrayAdapter { } else if (message.bodyIsHeart()) { displayHeartMessage(viewHolder, message.getBody().trim()); } else if (message.treatAsDownloadable() == Message.Decision.MUST) { - displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message))); + try { + URL url = new URL(message.getBody()); + displayDownloadableMessage(viewHolder, + message, + activity.getString(R.string.check_x_filesize_on_host, + UIHelper.getFileDescriptionString(activity, message), + url.getHost())); + } catch (Exception e) { + displayDownloadableMessage(viewHolder, + message, + activity.getString(R.string.check_x_filesize, + UIHelper.getFileDescriptionString(activity, message))); + } } else { displayTextMessage(viewHolder, message, darkBackground); } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 7368d0dc..9657ea24 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -344,6 +344,7 @@ Checking %s on HTTP host You are not connected. Try again later Check %s size + Check %1$s size on %2$s Message options Copy text Copy original URL -- cgit v1.2.3 From 86fff5839aaf618367f3c50a2ad4274c16802aeb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 6 Mar 2016 12:16:29 +0100 Subject: warn in conversations when account is disabled --- .../eu/siacs/conversations/ui/ConversationFragment.java | 15 ++++++++++++++- src/main/res/values/strings.xml | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 9ef950c4..1665090c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -777,6 +777,17 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } + private OnClickListener mEnableAccountListener = new OnClickListener() { + @Override + public void onClick(View v) { + final Account account = conversation == null ? null : conversation.getAccount(); + if (account != null) { + account.setOption(Account.OPTION_DISABLED, false); + activity.xmppConnectionService.updateAccount(account); + } + } + }; + private OnClickListener mUnblockClickListener = new OnClickListener() { @Override public void onClick(final View v) { @@ -822,7 +833,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa final Account account = conversation.getAccount(); final Contact contact = conversation.getContact(); final int mode = conversation.getMode(); - if (conversation.isBlocked()) { + if (account.getStatus() == Account.State.DISABLED) { + showSnackbar(R.string.this_account_is_disabled, R.string.enable, this.mEnableAccountListener); + } else if (conversation.isBlocked()) { showSnackbar(R.string.contact_blocked, R.string.unblock, this.mUnblockClickListener); } else if (!contact.showInRoster() && contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { showSnackbar(R.string.contact_added_you, R.string.add_back, this.mAddBackClickListener); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 9657ea24..f0f2cc3e 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -604,4 +604,5 @@ Send corrected message You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference. Select image and crop + You have disabled this account -- cgit v1.2.3 From e6a9829dd2b275f80231b19930fbb75b209f4c2e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 6 Mar 2016 15:53:49 +0100 Subject: don't show opt-out of battery optimization dialog when push is enabled --- .../eu/siacs/conversations/ui/ConversationActivity.java | 14 +++++++++++++- .../eu/siacs/conversations/ui/EditAccountActivity.java | 5 +++-- src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index eac53124..aee923f6 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1353,7 +1353,9 @@ public class ConversationActivity extends XmppActivity } private void openBatteryOptimizationDialogIfNeeded() { - if (showBatteryOptimizationWarning() && getPreferences().getBoolean("show_battery_optimization", true)) { + if (hasAccountWithoutPush() + && isOptimizingBattery() + && getPreferences().getBoolean("show_battery_optimization", true)) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.battery_optimizations_enabled); builder.setMessage(R.string.battery_optimizations_enabled_dialog); @@ -1378,6 +1380,16 @@ public class ConversationActivity extends XmppActivity } } + private boolean hasAccountWithoutPush() { + for(Account account : xmppConnectionService.getAccounts()) { + if (account.getStatus() != Account.State.DISABLED + && !xmppConnectionService.getPushManagementService().available(account)) { + return true; + } + } + return false; + } + private void attachLocationToConversation(Conversation conversation, Uri uri) { if (conversation == null) { return; diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index b6f1b430..ed80a509 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -641,11 +641,12 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mRegisterNew.setChecked(false); } if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) { + Features features = this.mAccount.getXmppConnection().getFeatures(); this.mStats.setVisibility(View.VISIBLE); - this.mBatteryOptimizations.setVisibility(showBatteryOptimizationWarning() ? View.VISIBLE : View.GONE); + boolean showOptimizingWarning = !xmppConnectionService.getPushManagementService().available(mAccount) && isOptimizingBattery(); + this.mBatteryOptimizations.setVisibility(showOptimizingWarning ? View.VISIBLE : View.GONE); this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection() .getLastSessionEstablished())); - Features features = this.mAccount.getXmppConnection().getFeatures(); if (features.rosterVersioning()) { this.mServerInfoRosterVersion.setText(R.string.server_info_available); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 5682f785..baf40b22 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -391,7 +391,7 @@ public abstract class XmppActivity extends Activity { return super.onCreateOptionsMenu(menu); } - protected boolean showBatteryOptimizationWarning() { + protected boolean isOptimizingBattery() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); return !pm.isIgnoringBatteryOptimizations(getPackageName()); -- cgit v1.2.3 From 24aefa109c1f4d673e826c83720233651a850467 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 6 Mar 2016 21:35:59 +0100 Subject: pulled translations from transifex --- src/main/res/values-ar/strings.xml | 1 - src/main/res/values-bg/strings.xml | 14 +++++++--- src/main/res/values-ca/strings.xml | 1 - src/main/res/values-cs/strings.xml | 8 +++--- src/main/res/values-de/strings.xml | 24 +++++++++++------ src/main/res/values-el/strings.xml | 1 - src/main/res/values-es/strings.xml | 14 +++++++--- src/main/res/values-eu/strings.xml | 8 +++--- src/main/res/values-fr/strings.xml | 22 ++++++++++----- src/main/res/values-id/strings.xml | 42 ++++++++++++++++++++++++++--- src/main/res/values-it/strings.xml | 34 +++++++++++++++++++++-- src/main/res/values-iw/strings.xml | 2 -- src/main/res/values-ja/strings.xml | 8 +++--- src/main/res/values-ko/strings.xml | 2 -- src/main/res/values-nb-rNO/strings.xml | 2 -- src/main/res/values-nl/strings.xml | 14 +++++++--- src/main/res/values-pl/strings.xml | 33 +++++++++++++++++++++-- src/main/res/values-pt-rBR/strings.xml | 8 +++--- src/main/res/values-pt/strings.xml | 1 - src/main/res/values-ro-rRO/strings.xml | 16 ++++++++--- src/main/res/values-ru/strings.xml | 2 -- src/main/res/values-sk/strings.xml | 1 - src/main/res/values-sr/strings.xml | 49 +++++++++++++++++++++++++++------- src/main/res/values-sv/strings.xml | 16 ++++++++--- src/main/res/values-tr-rTR/strings.xml | 14 +++++++--- src/main/res/values-vi/strings.xml | 2 -- src/main/res/values-zh-rCN/strings.xml | 14 +++++++--- src/main/res/values-zh-rTW/strings.xml | 1 - 28 files changed, 272 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml index 2e59983c..e3a71f69 100644 --- a/src/main/res/values-ar/strings.xml +++ b/src/main/res/values-ar/strings.xml @@ -176,7 +176,6 @@ موجوده بالمفضلة سابقا انت تعديل موضوع الغرفة - الغرفة غير متاحه .. تأكد من عنوان الغرفة غادر جهة اتصال أضافتك نشر diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index 4f2a548c..b7589244 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -96,7 +96,6 @@ Conversations не може да шифрова съобщенията Ви, тъй като Вашият контакт не обявява публичния си ключ.\n\nМоля, помолете го/я да инсталира и настрои OpenPGP. Не са открити OpenPGP ключове Conversations не може да шифрова съобщенията Ви, тъй като Вашите контакти не обявяват публичните си ключове.\n\nМоля, помолете го да инсталират и настроят OpenPGP. - Получено е шифровано съобщение. Докоснете, за да го дешифровате. Общи XMPP ресурс Името, с което се определя този клиент @@ -240,8 +239,7 @@ Вече съществува такава отметка Вие Редактиране на темата на беседата - Беседата не е открита - Беше получена непозната грешка + Присъединяване към беседата… Напускане Контактът е добавен във Вашия списък от контакти Добавяне обратно @@ -308,10 +306,13 @@ Достъпът Ви до тази беседа беше забранен Тази беседа е само за членове Бяхте изритан от тази конференция + Беседата приключи + Вече не участвате в тази беседа използвайки профила %s Проверяване на %s на HTTP сървъра Не сте свързани. Опитайте отново по-късно Проверете размера на %s + Проверете размера на %1$s на %2$s Настройки за съобщенята Копиране на текста Копиране на оригиналния адрес @@ -490,6 +491,8 @@ Потребителско име Потребителско име Това не е правилно потребителско име + Име на беседата + Това не е правилно име на беседа Неуспешно сваляне: Сървърът не е открит Неуспешно сваляне: Файлът не е открит Неуспешно сваляне: Неуспешна връзка със сървъра @@ -502,6 +505,8 @@ Преминава в състояние „отсъстващ“ когато екранът бъде изключен Недостъпен, в тих режим Преминава в състояние „недостъпен“ когато устройството е в тих режим + Тих режим при режим на вибриране + Преминава в състояние „недостъпен“ когато устройството е в режим на вибриране. Разширени настройки за връзката Показване на настройките за сървър и порт при установка на профил xmpp.example.com @@ -565,4 +570,7 @@ Това поле е задължително Поправяне на съобщението Изпращане на поправеното съобщение + Вие вече имате доверие на този контакт. Избирайки „готово“, Вие просто потвърждавате, че %s е част от тази беседа. + Изберете изображение и изрежете + Вие сте деактивирали този профил diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index 6f48ab63..1c06d9ab 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -211,7 +211,6 @@ Aquesta llista de favorits ja existeix Tu Editar el tema de la sala - Sala no trobada Sortir Afegir un contacte a la llista de contactes Afegir nou diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 10730490..8979f86f 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -96,7 +96,6 @@ Není možné zašifrovat zprávu v aplikaci Konverzace, protože druhá strana neoznamuje svůj veřejný klíč.\n\nPožádejte svůj kontakt ať si nastaví OpenPGP. Nebyly nalezeny žádné OpenPGP klíče Není možné zašifrovat zprávy v aplikaci Konverzace, protože kontakty neoznamují svůj veřejný klíč.\n\nPožádejte své kontakty ať si nastaví OpenPGP. - Obdržena šifrovaná zpráva. Dešifrovat dotykem. Obecné XMPP zdroj Jméno se kterým se tento klient identifikuje @@ -240,8 +239,7 @@ Tato záložka již existuje Upravit jméno konference - Konference nenalezena - Došlo k neznámé chybě + Připojování ke konferenci... Odejít Kontakt přidán do seznamu Opět přidat @@ -308,6 +306,8 @@ Vstup do konference byl zakázán Tato konference je pouze pro členy Vykopli tě z této konference + Konference byla ukončena + Již nejste v této konferenci za použití účtu %s Ověřuji %s na HTTP hostiteli Bez připojení. Zkus znovu později @@ -492,6 +492,8 @@ Uživatelské jméno Uživatelské jméno Toto není platné uživatelské jméno + Jméno konferenc + Toto není platné jméno konference Stahování selhalo: Server nenalezen Stahování selhalo: Soubor nenalezen Stahování selhalo: Nelze se připojit k hostu diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 0968a5f7..454c8791 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -96,7 +96,6 @@ Conversations ist nicht in der Lage, deine Nachrichten zu verschlüsseln, weil dein Kontakt seinen oder ihren Schlüssel nicht preisgibt.\n\nBitte sag deinem Kontakt, er oder sie möge OpenPGP einrichten. Keine OpenPGP-Schlüssel gefunden Conversations ist nicht in der Lage, deine Nachrichten zu verschlüsseln, weil deine Kontakte ihre Schlüssel nicht preisgeben.\n\nBitte sage deinen Kontakten, sie mögen OpenPGP einrichten. - Verschlüsselte Nachricht erhalten. Antippen zum Entschlüsseln. Allgemeines XMPP-Ressource Der Name, mit dem sich der Client selbst identifiziert @@ -160,7 +159,7 @@ Vorübergehend abschalten Avatar veröffentlichen Öffentlichen OpenPGP-Schlüssel veröffentlichen - Anschalten + Aktivieren Bist du dir sicher? Wenn du dein Konto löschst, gehen alle Gesprächsverläufe verloren Sprache aufzeichnen @@ -217,7 +216,7 @@ Andere Geräte OMEMO-Fingerabdruck vertrauen Schlüssel werden abgerufen … - Erledigt + Fertig Überprüfen Entschlüsseln Konferenzen @@ -240,8 +239,7 @@ Die Konferenz befindet sich bereits auf deiner Kontaktliste Du Konferenz-Thema bearbeiten - Konferenz nicht gefunden - Unbekannter Fehler + Konferenz wird betreten… Verlassen Der Kontakt hat dich zur Kontaktliste hinzugefügt Auch hinzufügen @@ -301,17 +299,20 @@ Sonstiges Konferenz-Name Konferenz-Thema statt Raum-JID als Namen verwenden - Unterhaltung automatisch beitreten + Konferenzen automatisch beitreten Autojoin-Flag in Konferenzlesezeichen beachten OTR-Fingerabdruck in die Zwischenablage kopiert! OMEMO-Fingerabdruck in die Zwischenablage kopiert! Du wurdest von der Konferenz ausgeschlossen Die Konferenz ist nur für Mitglieder Du wurdest aus der Konferenz geworfen + Konferenz wurde geschlossen + Du bist nicht länger in dieser Konferenz Verwendetes Konto: %s %s auf HTTP-Host wird überprüft Nicht verbunden, bitte später versuchen %s-Größe prüfen + %1$s-Größe auf %2$s prüfen Nachrichtenoptionen Text kopieren Original-URL kopieren @@ -400,7 +401,7 @@ Aktuelles Passwort Neues Passwort Das Passwort darf nicht leer sein - Alle Konten anschalten + Alle Konten aktiveren Alle Konten abschalten Aktion durchführen mit Keine Zugehörigkeit @@ -490,6 +491,8 @@ Benutzername Benutzername Ungültiger Benutzername + Konferenz-Name + Dies ist kein gültiger Konferenz-Name Download fehlgeschlagen: Server nicht gefunden Download fehlgeschlagen: Datei nicht gefunden Download fehlgeschlagen: keine Verbindung zum Host @@ -501,7 +504,9 @@ Abwesend bei abgeschaltetem Bildschirm Setzt deinen Status auf \"abwesend\", solange dein Bildschirm abgeschaltet ist Nicht verfügbar bei Stummschaltung - Setzt deinen Status auf \"nicht verfügbar\", solange dein Telefon lautlos ist + Setzt deinen Status auf \"nicht verfügbar\", solange dein Gerät lautlos ist + Behandle Vibration als Stumm + Setze deinen Status auf \"nicht verfügbar\" solange dein Gerät auf \"vibrieren\" ist. Erweiterte Verbindungs-Optionen Hostname- und Port-Optionen bei Kontoeinrichtung anzeigen xmpp.domain.de @@ -565,4 +570,7 @@ Dieses Feld ist erforderlich Nachricht korrigieren Korrigierte Nachricht senden + Du vertraust diesem Kontakt bereits. In dem du \'Fertig\' auswählst bestätigst Du, dass %s Teil dieser Konferenz ist. + Bild auswählen und zuschneiden + Du hast diesen Account deaktiviert diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 0bdc6a5e..804a2146 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -211,7 +211,6 @@ Αυτός ο σελιδοδείκτης υπάρχει ήδη Εσείς Επεξεργασία θέματος συνδιάσκεψης - Η συνδιάσκεψη δεν βρέθηκε Έξοδος Η επαφή σας πρόσθεσε στην λίστα επαφών Προσθήκη επίσης diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 84df1850..f630f7ca 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -96,7 +96,6 @@ Conversations no ha podido cifrar tus mensajes porque tu contacto no está anunciando su clave publica.\n\nPor favor, pide a tu contacto que configure OpenPGP. Claves OpenPGP no encontradas Conversations no ha podido cifrar tus mensajes porque tus contactos no están anunciando su clave publica.\n\nPor favor, pide a tus contactos que configuren OpenPGP. - Mensaje cifrado recibido. Pulsa para descifrar. General Recurso El nombre que identifica el cliente que estás utilizando @@ -240,8 +239,7 @@ Este marcador ya existe Editar asunto de la conversación - Conversación no encontrada - Error desconocido + Uniéndose a conversación... Salir El contacto te ha añadido a su lista de contactos Añadir contacto @@ -308,10 +306,13 @@ Tu entrada a esta conversación ha sido prohibida Esta conversación es solo para miembros Has sido expulsado de esta conversación + La conversación ha sido cerrada + Ya no estás dentro de esta conversación Usando cuenta %s Comprobando %s en servidor HTTP No estás conectado. Inténtalo más tarde Comprobar tamaño de %s + Comprobar tamaño de %1$s en %2$s Opciones de mensaje Copiar texto Copiar URL original @@ -490,6 +491,8 @@ Usuario Usuario Esto no es un usuario válido + Nombre de la conversación + Nombre de conversación no válido Error al descargar: Servidor no encontrado Error al descargar: Archivo no encontrado Error al descargar: No se ha podido conectar con el servidor @@ -502,6 +505,8 @@ Cambia tu estado a ausente cuando la pantalla está apagada No disponible en modo silencio Cambia tu estado a no disponible cuando el dispositivo está en modo silencio + Modo vibración como modo silencio + Cambia tu estado a no disponible cuando el dispositivo está en modo vibración Opciones de conexión Mostrar el hostname y el puerto cuando se está creando una cuenta xmpp.ejemplo.com @@ -565,4 +570,7 @@ Este campo es requerido Corregir mensaje Enviar mensaje corregido + Ya confías en este contacto. Seleccionando \'hecho\', estás confirmando que %s es parte de esta conversación. + Seleccionar imagen y recortar + Has deshabilitado esta cuenta diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index ea91da79..27bbf42f 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -96,7 +96,6 @@ Conversations ez da zure mezuak enkriptatzeko gai zure kontaktua bere gako publikoa jakinarazten ez dagoelako.\n\nMesedez eskatu ezaiozu zure kontaktuari openPGP konfigura dezan. Ez da OpenPGP gakorik aurkitu Conversations ez da zure mezuak enkriptatzeko gai zure kontaktuak haien gako publikoa jakinarazten ez daudelako.\n\nMesedez eskatu ezaiezu zure kontakuei OpenPGP konfigura dezaten. - Enkriptatutako mezua jaso da. Ukitu desenkriptatzeko. Orokorrak XMPP baliabidea Bezero honek bere burua aurkezteko erabiltzen duen izena @@ -240,8 +239,7 @@ Laster-marka hau existitzen da dagoeneko Zu Konferentziaren gaia editatu - Konferentzia ez da aurkitu - Akats ezezaguna jaso da + Konferentziara batzen... Alde egin Kontaktuak bere zerrendara gehitu zaitu Bera gehitu @@ -308,6 +306,8 @@ Konferentzia honetara sartzea debekatuta duzu Konferentzia hau kideentzat da soilik Konferentzia honetatik kanporatua izan zara + Konferentzia itzali egin da + Ez zaude dagoeneko konferentzia honetan %s kontua erabiltzen %s egiaztatzen HTTP ostalarian Ez zaude konektatuta. Saiatu beranduago berriz @@ -490,6 +490,8 @@ Erabiltzaile izena Erabiltzaile izena Hau ez da erabiltzaile izen baliodun bat + Konferentziaren izena + Hau ez da konferentzia batentzako izen balioduna Deskargak huts egin du: zerbitzaria ez da aurkitu Deskargak huts egin du: fitxategia ez da aurkitu Deskargak huts egin du: ezin izan da ostalarira konektatu diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index 4105dad3..488a4b58 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -79,8 +79,8 @@ Choisir le status de présence Envoyer un message non chiffré Envoyer un message chiffré avec OTR - Envoyé un message chiffré avec OMEMO - Envoyé un message chiffré avec \\OMEMO + Envoyer un message chiffré avec OMEMO + Envoyer un message chiffré avec \\OMEMO Envoyer un message chiffré avec OpenPGP Votre identifiant a été changé Envoyer en clair @@ -96,7 +96,6 @@ Conversations ne peut pas chiffrer vos messages car votre contact n\'a pas communiqué sa clef publique.\n\nDemandez-lui de configurer OpenPGP. Aucune clef OpenPGP n\'a été trouvée. Conversations ne peut pas chiffrer votre message car vos contacts ne communiquent pas leur clef publique.\n\nDemandez-leur de configurer OpenPGP. - Message chiffré reçu. Appuyez pour déchiffrer. Général Ressource XMPP Nom utilisé par ce client pour s\'identifier @@ -171,7 +170,7 @@ Mot de passe Confirmer le mot de passe Les deux mots de passe ne correspondent pas. - Cet identifiant n\'est pas valide. + Cet identifiant n\'est pas valide Plus de mémoire disponible. L\'image est trop volumineuse. Voulez-vous ajouter %s à votre carnet d\'adresses ? En ligne @@ -240,8 +239,7 @@ Le favori existe déjà Vous Modifier le sujet de la conférence - Impossible de trouver la conférence - Erreur inconnue reçue + Connexion à la conférence... Partir Votre correspondant vous a ajouté dans sa liste de contacts Ré-ajouter @@ -308,10 +306,13 @@ Vous êtes banni de cette conférence Cette conférence est réservée aux membres Vous avez été éjecté de cette conférence + La conférence a été fermée + Vous n\'êtes plus dans cette conférence avec le compte %s Vérification de %s sur l\'hôte HTTP Vous n\'êtes pas connecté. Essayez plus tard. Vérification de la taille de %s + Vérification de la taille de %1$s sur %2$s Options du message Copier le texte Copier l\'URL @@ -489,7 +490,9 @@ %s a quitté la conférence ! Identifiant Identifiant - Ce n\'est pas un identifiant valide + Cet identifiant n\'est pas valide + Nom de la conférence + Ce nom de conférence n\'est pas valide Échec du téléchargement : impossible de trouver le serveur Échec du téléchargement : impossible de trouver le fichier Échec du téléchargement : impossible de se connecter à l\'hôte @@ -502,6 +505,8 @@ Marquer cette ressource comme absente quand l\'écran est éteint. Indisponible en mode silencieux Marque cette ressource comme indisponible quand l\'appareil est en mode silencieux + Indisponible en mode vibreur + Marque cette ressource comme indisponible quand l\'appareil est en mode vibreur Paramètres de connexioin avancés Montrer le nom d\'hôte et le port lors du paramétrage d\'un compte xmpp.example.com @@ -565,4 +570,7 @@ Ce champ est requis Corriger le message Envoyer le message corrigé + Vous faites déjà confiance à ce contact. En sélectionnant « Terminé » vous confirmerez seulement que %s est membre de cette conférence. + Sélectionner et découper une image + Vous avez désactivé ce compte diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml index eae96d30..3b5d10ff 100644 --- a/src/main/res/values-id/strings.xml +++ b/src/main/res/values-id/strings.xml @@ -27,7 +27,9 @@ %d min lalu Percakapan belum dibaca mengirim... - Nick ini sudah digunakan + Mendekripsi pesan. Mohon tunggu… + Pesan terenkripsi OpenPGP + Nickname ini sudah digunakan Administrator Pemilik Moderator @@ -73,6 +75,7 @@ Apakah Anda ingin menghapus semua pesan dalam Percakapan ini\n\nPeringatan:ini tidak akan mempengaruhi pesan yang disimpan pada perangkat atau server lain. Hapus pesan Pilih kehadiran untuk kontak + Kirim pesan tak-terenkripsi Kirim pesan terenskripsi OTR Kirim pesan terenskripsi OpenPGP Nick kamu telah dirubah @@ -82,6 +85,7 @@ Conversations menggunakan app pihak ke-3 bernama OpenKeychain untuk mengenkripsi dan menerjemahkan pesan dan mengorganisir kunci anda.\n\nOpenKeychain berlisensi GPLv3 dan tersedia fi F-Droid dan Google play.\n\n(Silahkan mulai ulang Conversations setelah menginstall.) Mulai ulang Pasang + Harap install OpenKeychain menawarkan... menunggu... Tidak ada kunci OpenPGP ditemukan @@ -93,6 +97,7 @@ Identifikasi nama klien ini dengan Terima berkas Otomatis menerima berkas lebih kecil dari... + Notif Notifikasi Notifikasikan jika pesan baru tiba Getar @@ -101,13 +106,15 @@ mainkan suara saat menerima notifikasi Tenggang waktu pemberitahuan Nonaktifkan pemberitahuan untuk waktu yang singkat setelah salinan diterima + Lanjutan Jangan kirim laporan kerusakan Dengan mengirimkan kesalahan Anda membantu pengembangan Aplikasi Conversations Konfirmasi Pesan Biarkan kontak Anda tahu kapan Anda telah menerima dan membaca pesan + UI OpenKeychain melaporkan kesalahan I/O Error menerjemahkan berkas - Menerima + Terima Sebuah kesalahan terjadi Memberikan perubahan kehadiran Terlebih dahulu meminta dan berlangganan kehadiran untuk kontak Anda buat @@ -141,6 +148,7 @@ Server tidak cocok OTR OpenPGP + OMEMO Ubah akun Hapus akun Sementara dimatikan @@ -213,7 +221,6 @@ Bookmark ini sudah ada Anda Ubah subjek conference - Conference tidak ditemukan Tinggalkan Kontak ditambahkan ke daftar anda Tambah kembali @@ -399,6 +406,7 @@ Menawarkan %s Sembunyikan Offline Nonaktifkan Akun + %s sedang mengetik… %s telah berhenti mengetik Notifikasi ketik pesan Biarkan kontak Anda tahu ketika Anda sedang menulis pesan baru @@ -434,7 +442,35 @@ Username Username Username ini tidak valid + Nama Conference Unduhan gagal: Server tidak ditemukan Unduh gagal: Berkas tidak ditemukan Unduhan gagal: Tidak dapat terhubung ke host + Gunakan latar putih + Tor network tidak tersedia + Rusak + Kehadiran + xmpp.example.com + Koneksi + Hubungkan via Tor + Hostname + Port + Informasi Sertifikat + Subjek + Nama Umum + Organisasi + SHA-1 + (Tidak tersedia) + Tidak ada sertifikat ditemukan + Kompres Gambar + Rubah ukuran dan kompres gambar + Selalu + Secara otomatis + Pengoptimalan baterai diaktifkan + Non-aktifkan + Area yang dipilih terlalu besar + (Tidak ada akun aktif) + Bagian ini wajib diisi + Perbaiki pesan + Kirim perbaikan pesan diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 5554efc4..a512575b 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -96,12 +96,12 @@ Conversations non è in grado di cifrare i tuoi messaggi perché il contatto non sta annunciando la sua chiave pubblica.\n\nPer favore chiedi al tuo contatto di configurare OpenPGP. Nessuna chiave OpenPGP trovata Conversations non è in grado di cifrare i tuoi messaggi perché i contatti non stanno annunciando la propria chiave pubblica.\n\nPer favore chiedi ai tuoi contatti di configurare OpenPGP. - Messaggio cifrato ricevuto. Tocca per decifrare. Generale Risorsa XMPP Il nome con il quale questo client si identifica Accetta i file Accetta automaticamente i file più piccoli di… + Notifiche Notifiche Notifica quando arriva un nuovo messaggio Vibra @@ -110,10 +110,12 @@ Riproduci una suoneria con la notifica Periodo tra notifiche Disabilita le notifiche per un breve lasso di tempo dopo che un messaggio è stato ricevuto + Avanzate Non inviare mai segnalazioni di errore Se scegli di inviare una segnalazione dell’errore aiuterai lo sviluppo di Conversations Conferma Messaggi Fai sapere ai tuoi contatti quando hai ricevuto il messaggio e l’hai letto + Interfaccia Utente OpenKeychain ha riportato un errore Errore di I/O nel decifrare il file Accetta @@ -188,6 +190,7 @@ XEP-0198: Stream Management XEP-0163: PEP (Avatars / OMEMO) XEP-0363: HTTP File Upload + XEP-0357: Push disponibile non disponibile Annuncio chiave pubblica non effettuato @@ -236,7 +239,7 @@ Questo segnalibro esiste già Tu Modifica soggetto conferenza - Conferenza non trovata + Entro in conferenza... Abbandona Il contatto ti ha aggiunto alla sua lista contatti Add back @@ -271,10 +274,14 @@ Sei sicuro di voler eliminare questa impronta? Ignora Attenzione: Inviando questo messaggio senza aggiornamenti della presenza reciproci potrebbe causare problemi inaspettati.\n\nVai nei dettagli del contatto per verificare le tue sottoscrizioni alla presenza. + Sicurezza Forza cifratura end-to-end Manda sempre messaggi cifrati (ad eccezione delle conferenze) + Permetti correzione del messaggio + Consenti ai tuoi contatti di modificare retroattivamente i loro messaggi Non salvare i messaggi cifrati Attenzione: Questo potrebbe comportare la perdita di messaggi + Impostazioni esperto Fai attenzione con queste impostazioni Info su Conversations Informazioni sulla licenza @@ -292,11 +299,15 @@ Altro Nome della conferenza Usa il soggetto della stanza al posto del JID per identificare le conferenze + Entra automaticamente in conferenza + Rispetta l\'opzione di entrata automatica nei segnalibri di conferenze Impronta OTR copiata! Fingerprint OMEMO copiata negli appunti| Sei stato bandito da questa conferenza Questa conferenza è solo per membri Sei stato buttato fuori dalla conferenza + La conferenza è stata chiusa + Non sei più in questa conferenza usando l’utente %s Controllo %s su host HTTP Non sei connesso. Riprova più tardi @@ -422,6 +433,7 @@ 2 ore 8 ore Fino a nuovo avviso + Input Invio spedisce Il tasto invio spedisce il messaggio Mostra il tasto invio @@ -478,6 +490,8 @@ Utente Utente Questo non è un nome utente valido + Nome conferenza + Questo non è un nome di conferenza valido Download fallito: Server non trovato Download fallito: File non trovato Download fallito: Impossibile connettersi all\'host @@ -485,13 +499,21 @@ Mostra i messaggi ricevuti con testo nero su sfondo bianco Rete Tor non disponibile Rotto + Presenza \"Non disponibile\" a schermo spento Imposta la tua risorsa come non disponibile quando lo schermo è spento Non disponibile in modalità silenzioso Imposta la tua risorsa come non disponibile quando il dispositivo è in modalità silenziosa + Impostazioni estese di connessione + Mostra nome host e impostazioni della porta quando configuri un account + xmpp.esempio.it Aggiungi account con certificato Impossibile analizzare il certificato Lasciare vuoto per autenticarsi con certificato + Preferenze di archiviazione + Preferenze di archiviazione lato server + Raccolta preferenze di archiviazione. Attendere prego... + Impossibile raccogliere le preferenze di archiviazione Testo captcha Captcha richiest inserire il testo dall\'immagine @@ -501,6 +523,7 @@ Errore ricezione chiave OMEMO! Chiave OMEMO verificata con certificato! Il tuo dispositivo non supporta la selezione di certificati utente! + Connessione Connettiti via Tor Indirizza tutte le connessioni attraverso la rete Tor. Richiede Orbot Nome host @@ -513,6 +536,7 @@ %d messaggio %d messaggi + Carica altri messaggi Condividi file con %s Immagine condivisa con %s Conversations necessita di accesso alla memoria esterna @@ -523,6 +547,7 @@ Emittente Nome comune Organizzazione + SHA-1 (Non disponibile) Nessun certificato trovato Notifica per tutti i messaggi @@ -530,6 +555,7 @@ Notifiche disabilitate Notifiche in pausa Comprimi immagini + Ridimensiona e comprimi immagini Sempre Automaticamente Ottimizzazioni batteria abilitate @@ -537,4 +563,8 @@ Il tuo dispositivo sta facendo delle ingenti ottimizzazioni della batteria per Conversations che potrebbero portare ritardi alle notifiche o anche perdita di messaggi.\n\nTi verrà ora chiesto di disabilitarle. Disabilita L\'area selezionata è troppo grande + (Nessun account attivo) + Questo campo è obbligatorio + Correggi messaggio + Invia messaggio corretto diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml index 2495360e..5b640ff2 100644 --- a/src/main/res/values-iw/strings.xml +++ b/src/main/res/values-iw/strings.xml @@ -94,7 +94,6 @@ Conversations אינה מסוגלת להצפין את הודעותיך משום שאיש הקשר שלך אינו מכריז על המפתח הפומבי שלו או שלה.\n\nאנא בקש מאיש הקשר שלך להגדיר את OpenPGP. לא נמצאו מפתחות OpenPGP Conversations אינה מסוגלת להצפין את הודעותיך משום שאנשי הקשר שלך אינם מכריזים על המפתח הפומבי שלהם.\n\nאנא בקש מאנשי הקשר שלך לארגן OpenPGP. - הודעה מוצפנת תנקבלה. גע כדי לפענח צופן. כללי משאב XMPP השם שבעזרתו לקוח זה מזהה את עצמו @@ -228,7 +227,6 @@ סימנייה זו כבר קיימת אני ערוך נושא ועידה - ועידה לא נמצאה עזוב איש קשר הוסיף אותך אל רשימת קשר הוסף בחזרה diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml index b77c30b5..54611dc5 100644 --- a/src/main/res/values-ja/strings.xml +++ b/src/main/res/values-ja/strings.xml @@ -96,7 +96,6 @@ 連絡先が公開鍵を通知しないため、Conversations はあなたのメッセージを暗号化することができません。\n\n連絡先に OpenPGP をセットアップするように依頼してください。 OpenPGP の鍵はありません 連絡先が公開鍵を通知しないため、Conversations はあなたのメッセージを暗号化することができません。\n\n連絡先に OpenPGP をセットアップするように依頼してください。 - 暗号化されたメッセージを受信しました。タッチすると復号化します。 全般 XMPP リソース 自分自身を識別するこのクライアントの名前 @@ -240,8 +239,7 @@ このブックマークはすでに存在します あなた 会議の件名を編集 - 会議が見つかりません - 不明なエラーを受け取りました + 会議に参加中… 退出 連絡先があなたを連絡先リストに追加しました 戻りを追加 @@ -308,6 +306,8 @@ あなたはこの会議から禁止されています この会議はメンバーのみです あなたはこの会議からキックされました + 会議は停止しました + あなたはもうこの会議に参加していません アカウント %s を使用 HTTP ホストの %s を確認中 接続されていません。後でもう一度お試しください @@ -488,6 +488,8 @@ ユーザー名 ユーザー名 これは有効なユーザー名ではありません + 会議名 + これは有効な会議名ではありません ダウンロードに失敗しました: サーバーが見つかりません ダウンロードに失敗しました: ファイルが見つかりません ダウンロードに失敗しました: ホストに接続できませんでした diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml index 0931f7f6..311d3fdd 100644 --- a/src/main/res/values-ko/strings.xml +++ b/src/main/res/values-ko/strings.xml @@ -96,7 +96,6 @@ 당신의 연락처가 그들의 공개 키를 선언하지 않고 있기 때문에 Conversations는 당신의 메세지를 암호화할 수 없습니다. OpenPGP를 설정하도록 당신의 연락처에게 물어보세요. OpenPGP 키가 발견되지 않음 당신의 연락처가 그들의 공개 키를 선언하지 않고 있기 때문에 Conversations는 당신의 메세지를 암호화할 수 없습니다. OpenPGP를 설정하도록 당신의 연락처에게 물어보세요. - 암호화된 메세지가 도착했습니다. 터치하여 복호화하세요. 일반 XMPP 자원 이 클라이언트가 자신을 알아보는 이름 @@ -236,7 +235,6 @@ 즐겨찾기가 이미 존재합니다 당신 회의 제목 편집 - 회의를 찾을 수 없습니다 퇴장 연락처가 당신을 연락처 목록에 추가했습니다 Add back diff --git a/src/main/res/values-nb-rNO/strings.xml b/src/main/res/values-nb-rNO/strings.xml index 19b46aac..b78c1fba 100644 --- a/src/main/res/values-nb-rNO/strings.xml +++ b/src/main/res/values-nb-rNO/strings.xml @@ -96,7 +96,6 @@ Conversations kan ikke kryptere din melding fordi din kontakt ikke annonserer sin offentlige nøkkel.\n\nSpør din kontakt om å sette opp OpenPGP. Ingen OpenPGP-nøkler funnet Conversations kan ikke kryptere din melding fordi dine kontakter ikke annonserer sine offentlige nøkkler.\n\nSpør din kontakt om å sette opp OpenPGP. - Kryptert melding mottatt. Trykk for å dekryptere. Generelt XMPP-ressurs Navnet denne klienten identifiserer seg med @@ -236,7 +235,6 @@ Dette bokmerket finnes allerede Deg Rediger temaet for konferansen - Fant ikke konferansen Forlat Kontakt la deg til i sin liste Gjengjeld tjenesten diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 76a8b950..9431e8cf 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -96,7 +96,6 @@ Conversations kan je berichten niet versleutelen omdat je contact geen publieke sleutel heeft ingesteld.\n\nVraag je contact om OpenPGP te configureren. Geen OpenPGP-sleutels gevonden Conversations kan je berichten niet versleutelen omdat je contacten geen publieke sleutel hebben ingesteld.\n\nVraag je contacten om OpenPGP te configureren. - Versleuteld bericht ontvangen. Raak aan om te ontsleutelen. Algemeen XMPP-bron De naam waarmee deze cliënt zich identificeert @@ -240,8 +239,7 @@ Deze bladwijzer bestaat al Jij Onderwerp van groepsgesprek bewerken - Groepsgesprek niet gevonden - Onbekende fout ontvangen + Deelnemen aan groepsgesprek… Verlaten Contact heeft je toegevoegd aan zijn/haar contacten Contact toevoegen aan eigen contacten @@ -308,10 +306,13 @@ Je bent verbannen uit dit groepsgesprek Dit groepsgesprek is enkel voor leden Je bent uit dit groepsgesprek geschopt + Het groepsgesprek is uitgeschakeld + Je neemt niet langer deel aan dit groepsgesprek met account %s %s op HTTP-host nakijken Je bent niet verbonden. Probeer later opnieuw Bestandsgrootte van %s controleren + Bestandsgrootte van %1$s op %2$s controleren Berichtopties Tekst kopiëren Oorspronkelijke URL kopiëren @@ -490,6 +491,8 @@ Gebruikersnaam Gebruikersnaam Dit is geen geldige gebruikersnaam + Groepsgespreksnaam + Dit is geen geldige groepsgespreksnaam Downloaden mislukt: server niet gevonden Downloaden mislukt: bestand niet gevonden Downloaden mislukt: kon geen verbinding maken met host @@ -502,6 +505,8 @@ Stelt je bron in als even weg wanneer het scherm uitgeschakeld is Niet beschikbaar in stille modus Stelt je bron in als niet beschikbaar wanneer je apparaat in stille modus staat + Trillen behandelen als stille modus + Stelt je bron in als niet beschikbaar wanneer je apparaat in trilmodus staat Uitgebreide verbindingsinstellingen Toon hostnaam- en poortinstellingen bij instellen van een account xmpp.voorbeeld.be @@ -565,4 +570,7 @@ Dit veld is vereist Bericht verbeteren Verbeterd bericht sturen + Je vertrouwt dit contact al. Door \'klaar\' te kiezen bevestig je enkel dat %s deel uitmaakt van dit groepsgesprek. + Afbeelding kiezen en bijsnijden + Je hebt deze account uitgeschakeld diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 2a9e3135..15bd0955 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -96,12 +96,12 @@ Conversations nie może zaszyfrować wiadomości, ponieważ kontakt nie udostępnia klucza publicznego.\n\nZasugeruj rozmówcy instalację OpenPGP. Nie znaleziono kluczy OpenPGP Conversations nie może zaszyfrować wiadomości, ponieważ kontakty nie udostępniają kluczy publicznych.\n\nZasugeruj rozmówcom instalację OpenPGP. - Odebrano zaszyfrowaną wiadomość. Dotknij by odszyfrować Główne Zasób XMPP Nazwa identyfikująca urządzenie Akceptuj pliki Automatycznie akceptuj pliki mniejsze niż... + Powiadomienie Powiadomienia Powiadamiaj, gdy nadejdzie wiadomość Wibracje @@ -110,10 +110,12 @@ Odtwórz dźwięk z powiadomieniem Opóźnienie powiadomień Wyłącz powiadomienia przez krótki czas po otrzymaniu kopii wiadomości + Zaawansowane Nie wysyłaj raportów awarii Wysyłając ślady stosu pomagasz rozwijać Conversations Potwierdzenia wiadomości Powiadamiaj kontakty o otrzymaniu lub przeczytaniu wiadomości + UI Wystąpił błąd OpenKeychain Błąd podczas deszyfrowania pliku Akceptuj @@ -188,6 +190,7 @@ XEP-0198: Stream Management XEP-0163: PEP (Awatary / OMEMO) XEP-0363: Przesyłanie plików przez HTTP + XEP-0357: Push dostępny niedostępny Brak informacji o kluczu publicznym @@ -236,7 +239,7 @@ Zakładka już istnieje Ty Edytuj temat konferencji - Nie znaleziono konferencji + Dołączenie do konferencji... Opuść pokój Kontakt został dodany do listy Dodaj ponownie @@ -271,10 +274,14 @@ Czy na pewno chcesz usunąć odcisk klucza? Ignoruj Uwaga: Wysyłanie bez obustronnych powiadomień o obecności może powodować nieoczekiwane problemy.\n\nSprawdź subskrypcję powiadomień w szczegółach kontaktu. + Bezpieczeństwo Wymuszaj szyfrowanie typu end-to-end Szyfruj wszystkie wiadomości (poza konferencjami) + Pozwól na poprawianie wiadomości + Pozwól swoim kontaktom poprawiać wiadomości Nie zapisuj zaszyfrowanych wiadomości Uwaga: Może powodować utratę wiadomości + Ustawienia zaawansowane Modyfikuj ustawienia ostrożnie O Conversations Informacje o kompilacji i licencji @@ -292,11 +299,15 @@ Inne opcje Nazwa konferencji Nazywaj konferencję tematem zamiast Jabber ID + Automatycznie dołączaj do konferencji + Respektuj flagi autodołączania i zakładkach konferencji Odcisk klucza OTR został skopiowany do schowka Odcisk klucza OMEMO został skopiowany do schowka! Zbanowano cię w konferencji To jest zamknięty pokój Wyrzucono cię z konferencji + Konferencję zamknięto + Nie uczestniczysz już w tej konferencji używając konta %s Sprawdzanie %s na hoście HTTP Brak połączenia. Spróbuj ponownie później @@ -480,6 +491,8 @@ Nazwa użytkownika Nazwa użytkownika Błędna nazwa użytkownika + Nazwa konferencji + Nie jest to poprawna nazwa konferencji Pobieranie nieudane: Nie odnaleziono serwera Pobieranie nieudane: Nie odnaleziono pliku Pobieranie nieudane: Nie można połączyć z hostem @@ -487,13 +500,21 @@ Pokazuj otrzymane wiadomości jako czarny tekst na białym tle Sieć TOR jest niedostepna Zepsute + Obecność Status \"Oddalony\" gdy wyświetlacz jest wyłączony Oznacza Twój zasób jako \"Oddalony\", gdy wyświetlacz jest wyłączony Niedostepne w trybie cichym Oznacza Twój zasób jako \"Nieobecny\" gdy urządzenie jest w trybie cichym + Rozszerzone ustawienia połączenia + Pokaż nazwę hosta i ustawienia portu przy dodawaniu konta + xmpp.examle.com Dodaj konto za pomocą certyfikatu Nie mogę odczytać certyfikatu Pozostaw puste by autoryzować za pomocą certyfikatu + Preferencje archiwizacji + Preferencje archiwizacji po stronie serwera + Pobieranie preferencji archiwizacji. Proszę czekać... + Nie można pobrać preferencji archiwizacji Captcha Captcha wymagana przepisz tekst z obrazka @@ -503,6 +524,7 @@ Błąd pobierania klucza OMEMO! Zweryfikowano klucz OMEMO z certyfikatem Twoje urządzenie nie wspiera wyboru certyfikatów klienckich + Połączenie Połącz przez sieć TOR Tuneluj wszystkie połączenia przez sieć TOR. Wymaga zainstalowania aplikacji \"Orbot\" Nazwa hosta @@ -516,6 +538,7 @@ %d wiadomości %d wiadomości + Załaduj wiecej wiadomości Dzielony plik z %s Dzielony obraz z %s Conversations potrzebuje dostęp do zewnętrznego magazynu @@ -526,6 +549,7 @@ Wystawca Nazwa Organizacja + SHA-1 (Niedostępne) Nie znaleziono certyfikatu Powiadom o wszystkich wiadomościach @@ -533,6 +557,7 @@ Powiadomienia wyłączone Powiadomienia wstrzymane Kompresuj obrazki + Zmień rozmiar i kompresuj obrazki Zawsze Automatycznie Optymalizacje zużycia baterii włączone @@ -540,4 +565,8 @@ Twoje urządzenie wykonuje poważnie optymalizacje zużycia baterii przez Conversations, które mogą powodować opóźnienie powiadomień lub nawet utratę wiadomości.\nZostaniesz teraz poproszony o ich wyłączenie Wyłącz Zaznaczony obszar jest zbyt duży + (Brak aktywynych kont) + To pole jest wymagane + Popraw wiadomość + Wyślij poprawioną wiadomość diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml index 368e17fa..19d25d5d 100644 --- a/src/main/res/values-pt-rBR/strings.xml +++ b/src/main/res/values-pt-rBR/strings.xml @@ -96,7 +96,6 @@ O Conversations não conseguiu criptografar suas mensagens porque o seu contato não está anunciando a chave pública dele(a).\n\nPor favor, solicite ao seu contato para configurar o OpenPGP. Não foi encontrada nenhuma chave OpenPGP O Conversations não conseguiu criptografar suas mensagens porque os seus contatos não estão anunciando a chave pública deles(as).\n\nPor favor, solicite aos seus contatos que configurem o OpenPGP. - Foi recebida uma mensagem criptografada. Toque para descriptografar. Geral Recurso XMPP O nome pelo qual esse cliente se identifica @@ -240,8 +239,7 @@ Esse favorito já existe Você Editar o assunto da conferência - A conferência não foi encontrada - Foi recebido um erro desconhecido + Entrando na conferência... Sair O contato foi adicionado à sua lista de contatos Adicionar novamente @@ -308,6 +306,8 @@ Você foi banido dessa conferência Essa conferência é restrita a seus membros Você foi expulso dessa conferência + A conferência foi encerrada + Você não está mais participando dessa conferência usando a conta %s Verificando %s no host HTTP Você não está conectado. Tente novamente mais tarde. @@ -490,6 +490,8 @@ Nome de usuário Nome de usuário Esse não é um nome de usuário válido + Nome da conferência + Esse nome de conferência não é válido Não foi possível fazer o download: servidor não encontrado Não foi possível fazer o download: arquivo não encontrado Não foi possível fazer o download: não foi possível conectar ao host diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml index 30265948..4164ca71 100644 --- a/src/main/res/values-pt/strings.xml +++ b/src/main/res/values-pt/strings.xml @@ -195,7 +195,6 @@ O favorito já existe Você Editar o assunto da conferência - Conferência não encontrada Sair Contato adicionado à sua lista de contato Adicionar novamente diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index afcf90e0..35a60872 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -96,7 +96,6 @@ Conversations nu a putut sa cripteze mesajele tale din cauza contactului care nu isi anunta cheia publica.\n\nRoaga contactul sa isi configureze OpenPGP. Nu am gasit chei OpenPGP Conversations nu poate cripta mesajele tale pentru contactele tale care nu isi anunta cheia publica.\n\nTe rog cere contactelor sa configureze OpenPGP. - Ai primit mesaj criptat. Apasa aici pentru a-l decripta. General Nume client XMPP Numele cu care acest client se identifica @@ -240,8 +239,7 @@ Acest semn de carte exista Tu Editeaza titlul conferintei - Conferinta nu a fost gasita - A fost primita o eroare necunoscuta + Alatura-te conferintei Paraseste Contactul a fost adaugat in lista Adauga inapoi @@ -308,10 +306,13 @@ Ti-a fost interzis accesul la aceasta conferinta Aceasta conferinta este rezervata membrilor Ai fost dat afara din conferinta + Conferinta a fost inchisa + Nu mai participi la aceasta conferinta folosind cont %s Verifica %s pe gazda HTTP Nu esti conectat. Incearca din nou mai tarziu. Verifica marimea %s + Verifica marimea %1$s pe %2$s Optiuni mesaje Copiaza text Copiaza URL original @@ -492,6 +493,8 @@ Nume utilizator Nume utilizator Acesta nu este un nume de utilizator valabil + Titlu conferinta + Acesta nu este un nume de conferinta valabil Descarcarea a esuat: Serverul nu a fost gasit Descarcare esuata: Fisierul nu a fost gasit Descarcarea a esuat. Nu s-a putut realiza conexiunea cu gazda. @@ -501,9 +504,11 @@ Deteriorat Setari de prezenta Plecat cand ecranul este oprit - Marcheaza clientul drept plecat cand ecranul este oprit + Declara clientul drept plecat cand ecranul este oprit Indisponibil in mod silentios Declara clientul drept indisponibil atunci cand dispozitivul este in mod silentios + Trateaza modul vibratie ca silentios + Declara clientul drept indisponibil atunci cand dispozitivul este in mod vibratie Optiuni avansate conexiune Arata optiunea de setare a numelui de gazda si a portului atunci cand se configureaza un cont xmpp.example.com @@ -569,4 +574,7 @@ Emitent Acest camp este obligatoriu Corectie mesaj Trimite text corectat + Deja ai incredere in acest contact. Selectand \'gata\' doar confirmi ca %s ia parte la conferinta. + Selecteaza imaginea si decupeaza + Ai dezactivat acest cont diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 01cdbcdd..5ed84b7b 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -96,7 +96,6 @@ Conversations не может зашифровать сообщение, потому что удаленный пользователь не анонсирует свой открытый ключ.\n\nПожалуйста, попросите удаленного пользователя тоже установить OpenPGP. Нет OpenPGP ключей Conversations не может зашифровать сообщения, потому что удаленные пользователи не анонсируют свои открытые ключи.\n\nПожалуйста, попросите удаленных пользователей тоже установить OpenPGP. - Получено зашифрованное сообщение. Нажмите, чтобы расшифровать. Общие Название ресурса Имя которым Conversations идентифицирует себя @@ -236,7 +235,6 @@ Такая закладка уже существует Вы Редактировать тему конференции - Конференция не найдена Покинуть Собеседник добавил вас в список контактов Добавить в ответ diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml index ce99da94..414fdf69 100644 --- a/src/main/res/values-sk/strings.xml +++ b/src/main/res/values-sk/strings.xml @@ -224,7 +224,6 @@ Táto záložka už existuje Ty Upraviť meno skupinovej konverzácie - Skupinová konverzácia sa nenašla Odísť Kontakt pridaný do zoznamu Znova pridať diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index 2be86f05..bf816ba2 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -62,8 +62,8 @@ Слањем контратрага помажете текући развој Конверзације\nУпозорење: Ово ће да искористи ваш ИксМПП налог за слање контратрага програмеру. Пошаљи одмах Не питај више - Не могу да се повежем са налогом - Не могу да се повежем са више налога + Не могох да се повежем са налогом + Не могох да се повежем са више налога Тапните овде да бисте управљали вашим налозима Приложи фајл Контакт није на вашем списку контаката. Желите ли да га додате? @@ -96,12 +96,12 @@ Конверзација није могла да шифрује ваше поруке јер ваш контакт не објављује свој јавни кључ.\n\nЗамолите вашег контакта да постави ОпенПГП. Нема ОпенПГП кључева Конверзација није могла да шифрује ваше поруке јер ваши контакти не објављују свој јавни кључ.\n\nЗамолите ваше контакте да поставе ОпенПГП. - Примљена је шифрована порука. Тапните за дешифровање. Опште ИксМПП ресурс Име са којим се овај клијент идентификује Прихватај фајлове Аутоматски прихватај фајлове мање од… + Обавештење Обавештења Обавести кад стигне нова порука Вибрирај @@ -110,10 +110,12 @@ Звуци обавештења Период одгоде обавештења Искључи обавештења на кратко по примању карбон копије + Напредно Никад не шаљи извештаје о паду Слањем контратрага помажете текући развој Конверзације Потврди поруке Обзнаните контакту кад примите и прочитате поруку + Сучеље Отворени кључарник је пријавио грешку У/И грешка дешифровања фајла Прихвати @@ -188,6 +190,7 @@ XEP-0198: менаџмент тока XEP-0163: PEP (аватари/ОМЕМО) XEP-0363: ХТТП отпремање фајлова + XEP-0357: „push“ доступан недоступан Недостају објаве јавног кључа @@ -236,8 +239,7 @@ Овај обележивач већ постоји Ви Уреди предмет групног ћаскања - Групно ћаскање није нађено - Примљена је непозната грешка + Придружујем се групном ћаскању… Напусти Контакт вас је додао на списак контаката Додај га @@ -272,10 +274,14 @@ Желите ли заиста да обришете овај отисак? Занемари Упозорење: Слање овога без узајамних ажурирања присутности би могло да узрокује неочекиване проблеме.\n\nИдите на детаље контакта да бисте проверили претплате на присутности. + Безбедност Присили крај-на-крај шифровање Увек шифруј поруке (осим за групна ћаскања) + Дозволи исправљање порука + Дозвољава вашим контактима да ретроактивно уређују њихове поруке Не успремај шифроване поруке Упозорење: Ово може да доведе до губитка порука + Поставке за стручњаке Будите пажљиви са овим О Конверзацији Подаци о издању и лиценци @@ -293,15 +299,20 @@ Остало Назив групног ћаскања Предмет собе уместо ЈИД-а идентификује групно ћаскање + Аутоматски ме придружуј групним ћаскањима + Поштовање опције аутоматског придруживања у обележивачу групног ћаскања ОТР отисак копиран на клипборд! ОМЕМО отисак копиран на клипборд! Забрањени сте на овом групном ћаскању Ово групно ћаскање је само за чланове Шутнути сте из овог групног ћаскања + Групно ћаскање је угашено + Више нисте у овом групном ћаскању преко налога %s Проверавам %s на ХТТП домаћину Нисте повезани. Покушајте поново касније Провери величину %s + Провери величину %1$s na %2$s Опције поруке Копирај текст Копирај изворни УРЛ @@ -423,6 +434,7 @@ 2 сата 8 сати до даљњег + Унос Ентер шаље Користи Ентер тастер за слање порука Прикажи Ентер тастер @@ -481,6 +493,8 @@ Корисничко име Корисничко име Ово није исправно корисничко име + Назив групног ћаскања + Ово није исправан назив за групно ћаскање Преузимање није успело: сервер није нађен Преузимање није успело: фајл није нађен Преузимање није успело: не могу да се повежем са домаћином @@ -488,14 +502,23 @@ Приказ примљених порука црним текстом на белој позадини Тор мрежа недоступна Оштећен + Присутност Одсутан кад је екран искључен - Означава ваш ресурс одсутним кад је екран искључен - Недоступан у тихом режиму - Означава ваш ресурс недоступним кад је уређај у тихом режиму + Означавање вашег ресурса одсутним кад је екран искључен + Недоступан у нечујном режиму + Означавање вашег ресурса недоступним кад је уређај у нечујном режиму + Вибрација је нечујни режим + Означавање вашег ресурса недоступним кад је уређај у режиму вибрирања + Проширене поставке повезивања + Приказ домаћина и порта у поставкама налога xmpp.primer.com Додај налог сертификатом - Не могу да рашчланим сертификат + Не могох да рашчланим сертификат Оставите празно за аутентификацију сертификатом + Поставке архивисања + Серверске поставке архивисања + Добављам поставке архивисања, сачекајте… + Не могох да добавим поставке архивисања Текст стопке Потребна стопка унесите текст са слике @@ -505,6 +528,7 @@ Грешка добављања ОМЕМО кључа! Оверен ОМЕМО кључ помоћу сертификата! Ваш уређај не подржава избор сертификата клијента! + Повезивање Повежи се преко Тора Тунеловање свих веза кроз Тор мрежу. Захтева Орбот Име домаћина @@ -529,6 +553,7 @@ Издавач Заједничко име Организација + СХА-1 (није доступно) Сертификат није нађен Обавештења за све поруке @@ -536,6 +561,7 @@ Обавештења искључена Обавештења паузирана Компресуј слике + Промена величине и компресовање слика увек аутоматски Оптимизација батерије је укључена @@ -545,4 +571,9 @@ Назначена површина је превелика (Нема активираних налога) Ово поље је захтевано + Исправи поруку + Пошаљи исправљену поруку + Већ се поуздате у овог контакта. Избором „Готово“ само потврђујете да је %s део овог групног ћаскања. + Изабери слику и опсеци + Искључили сте овај налог diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index c1feeaab..ee6a46ae 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -96,7 +96,6 @@ Conversations kan inte kryptera ditt meddelande eftersom din kontakt inte annonserar sin publika nyckel.\n\nBe din kontakt att sätta upp OpenPGP. Inga OpenPGP-nycklar funna Conversations kan inte kryptera ditt meddelande eftersom din kontakt inte annonserar sin publika nyckel.\n\nBe din kontakt att sätta upp OpenPGP. - Krypterat meddelande mottaget. Tryck för att avkryptera. Generellt XMPP-resurs Namnet klienten identifierar sig med @@ -240,8 +239,7 @@ Detta bokmärke finns redan Du Ändra konferensämne - Konferens hittades inte - Mottog okänt fel + Går med i konferens... Lämna Kontakten lade till dig i sin kontaktlista Addera tillbaka @@ -308,10 +306,13 @@ Du är bannlyst från denna konferens Medlemsskap krävs för denna konferens Du har blivit utsparkad från denna konferens + Konferensen stängdes ner + Du är inte längre med i denna konferens använder konto %s Kontrollerar %s på webbserver Du är inte ansluten. Försök igen senare - Kontrollera storleken på %s + Kontrollera filstorleken på %s + Kontrollera filstorlek för %1$s på %2$s Meddelandealternativ Kopiera text Kopiera orginal-URL @@ -490,6 +491,8 @@ Användarnamn Användarnamn Inte ett giltigt användanamn + Konferensnamn + Detta är inte ett giltigt konferensnamn Nerladdning gick fel: Server hittades inte Nerladdning gick fel: Filen hittades inte Nerladdningen gick fel: Kunder inte ansluta till server @@ -502,6 +505,8 @@ Sätter din tillgänglighet till borta när skrämen är av Status ej tillgänglig i tyst läge Sätter din tillgänglighet till ej tillgänglig när enheten är i tyst läge + Hantera vibrationsläge som tyst läge + Sätter din tillgänglighet till ej tillgänglig när enheten är i vibratorläge Utökade anslutningsinställningar Visa val av servernamn och port vid inställning av konto xmpp.example.com @@ -565,4 +570,7 @@ Detta fält måste fyllas i Korrigera meddelanden Skicka korrigerat meddelande + Du litar redan på denna kontakt. Genom att välja \'klar\' bekräftar du att %s är med i denna konferens. + Välj bild och beskär + Du har deaktiverat detta konto diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index 2a674290..2d434f03 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -96,7 +96,6 @@ Kişi ortak anahtarını yayınlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\nLütfen kişiden OpenPGP’yi ayarlamasını isteyin. Herhangi bir OpenPGP anahtarı bulunamadı Kişiler ortak anahtarlarını yayınlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\nLütfen kişilerden OpenPGP’yi ayarlamalarını isteyin. - Şifreli ileti alındı. Deşifre etmek için dokunun. Genel XMPP kaynağı İstemci kimliği @@ -240,8 +239,7 @@ Bu yer imi zaten mevcut Siz Grup sohbet konusunu düzenle - Grup sohbet bulunamadı - Bilinmeyen hata alındı + Grup sohbete katiliyor Ayrıl Kişi sizi listesine ekledi Siz de ekleyin @@ -308,10 +306,13 @@ Grup sohbetinden atıldınız Bu grup sohbet sadece üyelere açıktır Grup sohbetinden atıldınız + Grup sohbet sona erdi + Artık bu grup sohbet içerisinde değilsiniz. %s hesabını kullanarak HTTP sunucusundaki %s \'leri kontrol ediyor Bağlı değilsiniz. Daha sonra yeniden deneyin %s boyutunu kontrol edin + %2$s üzerindeki %1$s boyutunu kontrol edin İleti seçenekleri Metni kopyala Orijinal URL\'i kopyala @@ -488,6 +489,8 @@ Kullanıcı adı Kullanıcı adı Kullanıcı adı geçerli değil + Grup sohbet ismi + Bu grup sohbet adı geçerli değil İndirme başarısız: Sunucu bulunamadı İndirme başarısız: Dosya bulunamadı İndirme başarısız: Sunucuya bağlanılamadı @@ -500,6 +503,8 @@ Ekran kapandığında çevrimiçi durum bildiriminizi uzakta olarak değiştirir Sessiz moddayken erişilemez Telefonunuz sessizdeyken, durum bildiriminizi müsait değil olarak değiştirir + titreş modunu sessiz mod olarak değerlendir + cihazınız titreşim modundaysa durum bildiriminizi müsahit değil olarak değiştirir Genişletilmiş bağlantı seçenekleri Hesap oluştururken sunucu adıyla port seçeneğini göster xmpp.ornek.com @@ -562,4 +567,7 @@ Bu alan zorunludur ileti düzelt Düzeltilmiş iletiyi gönder + Bu kişiye zaten güveniyor durumdasınız. \"tamam\" seçeneğini işaretleyerek, sadece %s \'in bu grup sohbete katılabileceğini teyid ediyorsunuz. + Resmi seçip kırpın + Bu hesabı devre dışı bıraktınız diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 2d7511d6..935e6fa3 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -96,7 +96,6 @@ Conversations không thể mã hoá tin nhắn vì liên hệ của bạn không thông báo khoá công cộng của anh/chị ấy.\n\nHãy yêu cầu liên hệ đó cài đặt OpenPGP. Không tìm thấy các khoá OpenPGP Conversations không thể mã hoá tin nhắn vì các liên hệ của bạn không thông báo khoá công cộng của họ.\n\nHãy yêu cầu họ cài đặt OpenPGP. - Đã nhận tin nhắn được mã hoá. Chạm để giải mã. Tổng quan Ứng dụng XMPP Tên của máy trạm này được tự đặt là @@ -236,7 +235,6 @@ Đã có đánh dấu này rồi Bạn Chỉnh sửa tiêu đề diễn đàn - Không tìm thấy diễn đàn Rời khỏi Liên hệ đã thêm bạn vào danh bạ Thêm họ vào diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 5ed64ed5..8c770537 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -96,7 +96,6 @@ Conversations 无法加密信息,因为联系人未提供他/她的公钥。\n\n请通知联系人设置 OpenPGP。 未找到 OpenPGP 密钥 因您的联系人未公布公钥,Conversations未能成功加密您的信息.\n\n请通知联系人设置OpenPGP. - 接收到加密消息。轻触以解密。 常规 XMPP 资源 客户端标识名称 @@ -240,8 +239,7 @@ 该书签已存在 编辑讨论组主题 - 讨论组未找到 - 收到未知错误 + 加入讨论组… 离开 联系人已添加你到联系人列表 反向添加 @@ -308,10 +306,13 @@ 你被此讨论组屏蔽 此讨论组只允许成员加入 你被从此讨论组踢出 + 讨论组已被关闭 + 你已不属于此讨论组 用账户 %s 正在 HTTP 服务器中检查 %s 你没有连接。请稍后重试 检查 %s 大小 + 在 %2$s 上检查 %1$s 的大小 消息选项 拷贝文本 拷贝原始URL @@ -488,6 +489,8 @@ 用户名 用户名 该用户名无效 + 讨论组名称 + 该讨论组名称无效 下载失败:未找到服务器 下载失败:未找到文件 下载失败:无法连接到服务器 @@ -500,6 +503,8 @@ 当屏幕关闭时将标记您的资源为离开状态 静音模式时不可用 当设备进入静音模式时把资源标识改为不可用 + 静音模式开启振动 + 当设备进入振动模式时把资源标识改为不可用 高级边接设置 注册账户时显示主机名和端口 xmpp.example.com @@ -564,4 +569,7 @@ 必填 更正消息 发送更正后的消息 + 你已信任此联系人。选择“完成”表示 %s 将成为此讨论组的一部分。 + 选择照片并裁剪 + 你已经禁用了此账户 diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index ce80073b..952035f3 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -186,7 +186,6 @@ 該書籤已存在 編輯群組主題 - 群組未找到 離開 聯絡人已新增你到聯絡人列表 新增為聯絡人 -- cgit v1.2.3 From 48f3922fe652fea8d7b97afe90868d5d4ab290f7 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Tue, 8 Mar 2016 12:55:03 +0100 Subject: Fixed merge issue with AxolotlService (differentiation between impl and interface) --- .../crypto/axolotl/AxolotlService.java | 34 ++-- .../crypto/axolotl/AxolotlServiceImpl.java | 189 ++++++++++++--------- .../crypto/axolotl/AxolotlServiceStub.java | 81 +++++---- 3 files changed, 171 insertions(+), 133 deletions(-) (limited to 'src') 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 d8287aff..e490ac64 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -9,6 +9,7 @@ import org.whispersystems.libaxolotl.state.PreKeyRecord; import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; import java.security.cert.X509Certificate; +import java.util.List; import java.util.Set; import eu.siacs.conversations.entities.Account; @@ -30,6 +31,8 @@ public interface AxolotlService extends OnAdvancedStreamFeaturesLoaded { String PEP_BUNDLES = PEP_PREFIX + ".bundles"; String PEP_VERIFICATION = PEP_PREFIX + ".verification"; + int NUM_KEYS_TO_PUBLISH = 100; + enum FetchStatus { PENDING, SUCCESS, @@ -38,15 +41,10 @@ public interface AxolotlService extends OnAdvancedStreamFeaturesLoaded { ERROR } - boolean fetchMapHasErrors(Contact contact); - String getOwnFingerprint(); Set getKeysWithTrust(XmppAxolotlSession.Trust trust); - Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Contact contact); - - long getNumTrustedKeys(Contact contact); Set getFingerprintsForOwnSessions(); @@ -77,8 +75,6 @@ public interface AxolotlService extends OnAdvancedStreamFeaturesLoaded { void publishBundlesIfNeeded(boolean announce, boolean wipe); - boolean isContactAxolotlCapable(Contact contact); - XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint); X509Certificate getFingerprintCertificate(String fingerprint); @@ -87,24 +83,36 @@ public interface AxolotlService extends OnAdvancedStreamFeaturesLoaded { Set findDevicesWithoutSession(Conversation conversation); - Set findDevicesWithoutSession(Jid contactJid); - boolean createSessionsIfNeeded(Conversation conversation); boolean trustedSessionVerified(Conversation conversation); - boolean hasPendingKeyFetches(Account account, Contact contact); - @Nullable XmppAxolotlMessage encrypt(Message message); void preparePayloadMessage(Message message, boolean delay); - void prepareKeyTransportMessage(Contact contact, OnMessageCreatedCallback onMessageCreatedCallback); - XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message); XmppAxolotlMessage.XmppAxolotlPlaintextMessage processReceivingPayloadMessage(XmppAxolotlMessage message); XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message); + + boolean fetchMapHasErrors(List jids); + + Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Jid jid); + + Set getKeysWithTrust(XmppAxolotlSession.Trust trust, List jids); + + long getNumTrustedKeys(Jid jid); + + boolean anyTargetHasNoTrustedKeys(List jids); + + boolean isConversationAxolotlCapable(Conversation conversation); + + List getCryptoTargets(Conversation conversation); + + boolean hasPendingKeyFetches(Account account, List jids); + + void prepareKeyTransportMessage(Conversation conversation, OnMessageCreatedCallback onMessageCreatedCallback); } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceImpl.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceImpl.java index 27d50dbb..73974652 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceImpl.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceImpl.java @@ -51,7 +51,6 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class AxolotlServiceImpl implements AxolotlService { - public static final int NUM_KEYS_TO_PUBLISH = 100; public static final int publishTriesThreshold = 3; private final Account account; @@ -75,13 +74,14 @@ public class AxolotlServiceImpl implements AxolotlService { } @Override - public boolean fetchMapHasErrors(Contact contact) { - Jid jid = contact.getJid().toBareJid(); - if (deviceIds.get(jid) != null) { - for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); - if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { - return true; + public boolean fetchMapHasErrors(List jids) { + for(Jid jid : jids) { + if (deviceIds.get(jid) != null) { + for (Integer foreignId : this.deviceIds.get(jid)) { + AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { + return true; + } } } } @@ -220,24 +220,41 @@ public class AxolotlServiceImpl implements AxolotlService { this.executor = new SerialSingleThreadExecutor(); } - @Override public String getOwnFingerprint() { return axolotlStore.getIdentityKeyPair().getPublicKey().getFingerprint().replaceAll("\\s", ""); } - @Override public Set getKeysWithTrust(XmppAxolotlSession.Trust trust) { return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toString(), trust); } @Override - public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Contact contact) { - return axolotlStore.getContactKeysWithTrust(contact.getJid().toBareJid().toString(), trust); + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Jid jid) { + return axolotlStore.getContactKeysWithTrust(jid.toBareJid().toString(), trust); + } + + @Override + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, List jids) { + Set keys = new HashSet<>(); + for(Jid jid : jids) { + keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toString(), trust)); + } + return keys; + } + + @Override + public long getNumTrustedKeys(Jid jid) { + return axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toString()); } @Override - public long getNumTrustedKeys(Contact contact) { - return axolotlStore.getContactNumTrustedKeys(contact.getJid().toBareJid().toString()); + public boolean anyTargetHasNoTrustedKeys(List jids) { + for(Jid jid : jids) { + if (axolotlStore.getContactNumTrustedKeys(jid.toBareJid().toString()) == 0) { + return true; + } + } + return false; } private AxolotlAddress getAddressForJid(Jid jid) { @@ -249,12 +266,19 @@ public class AxolotlServiceImpl implements AxolotlService { return new HashSet<>(this.sessions.getAll(ownAddress).values()); } - private Set findSessionsforContact(Contact contact) { + private Set findSessionsForContact(Contact contact) { AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); return new HashSet<>(this.sessions.getAll(contactAddress).values()); } - @Override + private Set findSessionsForConversation(Conversation conversation) { + HashSet sessions = new HashSet<>(); + for(Jid jid : conversation.getAcceptedCryptoTargets()) { + sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values()); + } + return sessions; + } + public Set getFingerprintsForOwnSessions() { Set fingerprints = new HashSet<>(); for (XmppAxolotlSession session : findOwnSessions()) { @@ -263,26 +287,22 @@ public class AxolotlServiceImpl implements AxolotlService { return fingerprints; } - @Override public Set getFingerprintsForContact(final Contact contact) { Set fingerprints = new HashSet<>(); - for (XmppAxolotlSession session : findSessionsforContact(contact)) { + for (XmppAxolotlSession session : findSessionsForContact(contact)) { fingerprints.add(session.getFingerprint()); } return fingerprints; } - private boolean hasAny(Contact contact) { - AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); - return sessions.hasAny(contactAddress); + private boolean hasAny(Jid jid) { + return sessions.hasAny(getAddressForJid(jid)); } - @Override public boolean isPepBroken() { return this.pepBroken; } - @Override public void regenerateKeys(boolean wipeOther) { axolotlStore.regenerate(); sessions.clear(); @@ -290,19 +310,17 @@ public class AxolotlServiceImpl implements AxolotlService { publishBundlesIfNeeded(true, wipeOther); } - @Override public int getOwnDeviceId() { return axolotlStore.getLocalRegistrationId(); } - @Override public Set getOwnDeviceIds() { return this.deviceIds.get(account.getJid().toBareJid()); } private void setTrustOnSessions(final Jid jid, @NonNull final Set deviceIds, - final XmppAxolotlSession.Trust from, - final XmppAxolotlSession.Trust to) { + final XmppAxolotlSession.Trust from, + final XmppAxolotlSession.Trust to) { for (Integer deviceId : deviceIds) { AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toString(), deviceId); XmppAxolotlSession session = sessions.get(address); @@ -313,7 +331,6 @@ public class AxolotlServiceImpl implements AxolotlService { } } - @Override public void registerDevices(final Jid jid, @NonNull final Set deviceIds) { if (jid.toBareJid().equals(account.getJid().toBareJid())) { if (!deviceIds.isEmpty()) { @@ -356,7 +373,6 @@ public class AxolotlServiceImpl implements AxolotlService { mXmppConnectionService.keyStatusUpdated(null); } - @Override public void wipeOtherPepDevices() { if (pepBroken) { Log.d(Config.LOGTAG, getLogprefix(account) + "wipeOtherPepDevices called, but PEP is broken. Ignoring... "); @@ -374,12 +390,10 @@ public class AxolotlServiceImpl implements AxolotlService { }); } - @Override public void purgeKey(final String fingerprint) { axolotlStore.setFingerprintTrust(fingerprint.replaceAll("\\s", ""), XmppAxolotlSession.Trust.COMPROMISED); } - @Override public void publishOwnDeviceIdIfNeeded() { if (pepBroken) { Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... "); @@ -402,7 +416,6 @@ public class AxolotlServiceImpl implements AxolotlService { }); } - @Override public void publishOwnDeviceId(Set deviceIds) { Set deviceIdsCopy = new HashSet<>(deviceIds); if (!deviceIdsCopy.contains(getOwnDeviceId())) { @@ -432,7 +445,6 @@ public class AxolotlServiceImpl implements AxolotlService { } } - @Override public void publishDeviceVerificationAndBundle(final SignedPreKeyRecord signedPreKeyRecord, final Set preKeyRecords, final boolean announceAfter, @@ -458,7 +470,6 @@ public class AxolotlServiceImpl implements AxolotlService { } } - @Override public void publishBundlesIfNeeded(final boolean announce, final boolean wipe) { if (pepBroken) { Log.d(Config.LOGTAG, getLogprefix(account) + "publishBundlesIfNeeded called, but PEP is broken. Ignoring... "); @@ -598,23 +609,36 @@ public class AxolotlServiceImpl implements AxolotlService { } @Override - public boolean isContactAxolotlCapable(Contact contact) { - Jid jid = contact.getJid().toBareJid(); - return hasAny(contact) || - (deviceIds.containsKey(jid) && !deviceIds.get(jid).isEmpty()); + public boolean isConversationAxolotlCapable(Conversation conversation) { + final List jids = getCryptoTargets(conversation); + for(Jid jid : jids) { + if (!hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty())) { + return false; + } + } + return jids.size() > 0; } @Override + public List getCryptoTargets(Conversation conversation) { + final List jids; + if (conversation.getMode() == Conversation.MODE_SINGLE) { + jids = Arrays.asList(conversation.getJid().toBareJid()); + } else { + jids = conversation.getMucOptions().getMembers(); + jids.remove(account.getJid().toBareJid()); + } + return jids; + } + public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) { return axolotlStore.getFingerprintTrust(fingerprint); } - @Override public X509Certificate getFingerprintCertificate(String fingerprint) { return axolotlStore.getFingerprintCertificate(fingerprint); } - @Override public void setFingerprintTrust(String fingerprint, XmppAxolotlSession.Trust trust) { axolotlStore.setFingerprintTrust(fingerprint, trust); } @@ -759,36 +783,32 @@ public class AxolotlServiceImpl implements AxolotlService { } } - @Override public Set findDevicesWithoutSession(final Conversation conversation) { - return findDevicesWithoutSession(conversation.getContact().getJid().toBareJid()); - } - - @Override - public Set findDevicesWithoutSession(final Jid contactJid) { - Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Finding devices without session for " + contactJid); Set addresses = new HashSet<>(); - if (deviceIds.get(contactJid) != null) { - for (Integer foreignId : this.deviceIds.get(contactJid)) { - AxolotlAddress address = new AxolotlAddress(contactJid.toString(), foreignId); - if (sessions.get(address) == null) { - IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); - if (identityKey != null) { - Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Already have session for " + address.toString() + ", adding to cache..."); - XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey); - sessions.put(address, session); - } else { - Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Found device " + contactJid + ":" + foreignId); - if (fetchStatusMap.get(address) != FetchStatus.ERROR) { - addresses.add(address); + for(Jid jid : getCryptoTargets(conversation)) { + Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Finding devices without session for " + jid); + if (deviceIds.get(jid) != null) { + for (Integer foreignId : this.deviceIds.get(jid)) { + AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + if (sessions.get(address) == null) { + IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); + if (identityKey != null) { + Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Already have session for " + address.toString() + ", adding to cache..."); + XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, identityKey); + sessions.put(address, session); } else { - Log.d(Config.LOGTAG,getLogprefix(account)+"skipping over "+address+" because it's broken"); + Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Found device " + jid + ":" + foreignId); + if (fetchStatusMap.get(address) != FetchStatus.ERROR) { + addresses.add(address); + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "skipping over " + address + " because it's broken"); + } } } } + } else { + Log.w(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Have no target devices in PEP!"); } - } else { - Log.w(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Have no target devices in PEP!"); } if (deviceIds.get(account.getJid().toBareJid()) != null) { for (Integer ownId : this.deviceIds.get(account.getJid().toBareJid())) { @@ -814,7 +834,6 @@ public class AxolotlServiceImpl implements AxolotlService { return addresses; } - @Override public boolean createSessionsIfNeeded(final Conversation conversation) { Log.i(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Creating axolotl sessions if needed..."); boolean newSessions = false; @@ -836,9 +855,8 @@ public class AxolotlServiceImpl implements AxolotlService { return newSessions; } - @Override public boolean trustedSessionVerified(final Conversation conversation) { - Set sessions = findSessionsforContact(conversation.getContact()); + Set sessions = findSessionsForConversation(conversation); sessions.addAll(findOwnSessions()); boolean verified = false; for(XmppAxolotlSession session : sessions) { @@ -854,26 +872,32 @@ public class AxolotlServiceImpl implements AxolotlService { } @Override - public boolean hasPendingKeyFetches(Account account, Contact contact) { + public boolean hasPendingKeyFetches(Account account, List jids) { AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0); - AxolotlAddress foreignAddress = new AxolotlAddress(contact.getJid().toBareJid().toString(), 0); - return fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING) - || fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING); - + if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)) { + return true; + } + for(Jid jid : jids) { + AxolotlAddress foreignAddress = new AxolotlAddress(jid.toBareJid().toString(), 0); + if (fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING)) { + return true; + } + } + return false; } @Nullable - private XmppAxolotlMessage buildHeader(Contact contact) { + private XmppAxolotlMessage buildHeader(Conversation conversation) { final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage( - contact.getJid().toBareJid(), getOwnDeviceId()); + account.getJid().toBareJid(), getOwnDeviceId()); - Set contactSessions = findSessionsforContact(contact); + Set remoteSessions = findSessionsForConversation(conversation); Set ownSessions = findOwnSessions(); - if (contactSessions.isEmpty()) { + if (remoteSessions.isEmpty()) { return null; } Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Building axolotl foreign keyElements..."); - for (XmppAxolotlSession session : contactSessions) { + for (XmppAxolotlSession session : remoteSessions) { Log.v(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + session.getRemoteAddress().toString()); axolotlMessage.addDevice(session); } @@ -886,10 +910,9 @@ public class AxolotlServiceImpl implements AxolotlService { return axolotlMessage; } - @Override @Nullable public XmppAxolotlMessage encrypt(Message message) { - XmppAxolotlMessage axolotlMessage = buildHeader(message.getContact()); + XmppAxolotlMessage axolotlMessage = buildHeader(message.getConversation()); if (axolotlMessage != null) { final String content; @@ -909,7 +932,6 @@ public class AxolotlServiceImpl implements AxolotlService { return axolotlMessage; } - @Override public void preparePayloadMessage(final Message message, final boolean delay) { executor.execute(new Runnable() { @Override @@ -928,17 +950,16 @@ public class AxolotlServiceImpl implements AxolotlService { } @Override - public void prepareKeyTransportMessage(final Contact contact, final OnMessageCreatedCallback onMessageCreatedCallback) { + public void prepareKeyTransportMessage(final Conversation conversation, final OnMessageCreatedCallback onMessageCreatedCallback) { executor.execute(new Runnable() { @Override public void run() { - XmppAxolotlMessage axolotlMessage = buildHeader(contact); + XmppAxolotlMessage axolotlMessage = buildHeader(conversation); onMessageCreatedCallback.run(axolotlMessage); } }); } - @Override public XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message) { XmppAxolotlMessage axolotlMessage = messageCache.get(message.getUuid()); if (axolotlMessage != null) { @@ -971,7 +992,6 @@ public class AxolotlServiceImpl implements AxolotlService { return session; } - @Override public XmppAxolotlMessage.XmppAxolotlPlaintextMessage processReceivingPayloadMessage(XmppAxolotlMessage message) { XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = null; @@ -994,7 +1014,6 @@ public class AxolotlServiceImpl implements AxolotlService { return plaintextMessage; } - @Override public XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message) { XmppAxolotlMessage.XmppAxolotlKeyTransportMessage keyTransportMessage; @@ -1019,4 +1038,4 @@ public class AxolotlServiceImpl implements AxolotlService { } } } -} +} \ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceStub.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceStub.java index 42777b75..b0228d34 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceStub.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlServiceStub.java @@ -10,6 +10,7 @@ import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; import java.security.cert.X509Certificate; import java.util.Collections; +import java.util.List; import java.util.Set; import eu.siacs.conversations.entities.Account; @@ -23,11 +24,6 @@ import eu.siacs.conversations.xmpp.jid.Jid; */ public class AxolotlServiceStub implements AxolotlService { - @Override - public boolean fetchMapHasErrors(Contact contact) { - return false; - } - @Override public String getOwnFingerprint() { return null; @@ -38,16 +34,6 @@ public class AxolotlServiceStub implements AxolotlService { return Collections.emptySet(); } - @Override - public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Contact contact) { - return Collections.emptySet(); - } - - @Override - public long getNumTrustedKeys(Contact contact) { - return 0; - } - @Override public Set getFingerprintsForOwnSessions() { return Collections.emptySet(); @@ -113,11 +99,6 @@ public class AxolotlServiceStub implements AxolotlService { } - @Override - public boolean isContactAxolotlCapable(Contact contact) { - return false; - } - @Override public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) { return XmppAxolotlSession.Trust.TRUSTED; @@ -138,11 +119,6 @@ public class AxolotlServiceStub implements AxolotlService { return Collections.emptySet(); } - @Override - public Set findDevicesWithoutSession(Jid contactJid) { - return Collections.emptySet(); - } - @Override public boolean createSessionsIfNeeded(Conversation conversation) { return false; @@ -153,11 +129,6 @@ public class AxolotlServiceStub implements AxolotlService { return false; } - @Override - public boolean hasPendingKeyFetches(Account account, Contact contact) { - return false; - } - @Nullable @Override public XmppAxolotlMessage encrypt(Message message) { @@ -169,11 +140,6 @@ public class AxolotlServiceStub implements AxolotlService { } - @Override - public void prepareKeyTransportMessage(Contact contact, OnMessageCreatedCallback onMessageCreatedCallback) { - - } - @Override public XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message) { return null; @@ -189,6 +155,51 @@ public class AxolotlServiceStub implements AxolotlService { return null; } + @Override + public boolean fetchMapHasErrors(List jids) { + return false; + } + + @Override + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, Jid jid) { + return Collections.emptySet(); + } + + @Override + public Set getKeysWithTrust(XmppAxolotlSession.Trust trust, List jids) { + return Collections.emptySet(); + } + + @Override + public long getNumTrustedKeys(Jid jid) { + return 0; + } + + @Override + public boolean anyTargetHasNoTrustedKeys(List jids) { + return false; + } + + @Override + public boolean isConversationAxolotlCapable(Conversation conversation) { + return false; + } + + @Override + public List getCryptoTargets(Conversation conversation) { + return Collections.emptyList(); + } + + @Override + public boolean hasPendingKeyFetches(Account account, List jids) { + return false; + } + + @Override + public void prepareKeyTransportMessage(Conversation conversation, OnMessageCreatedCallback onMessageCreatedCallback) { + + } + @Override public void onAdvancedStreamFeaturesAvailable(Account account) { -- cgit v1.2.3 From d80e433e4286f4eef3bf416b83b40b31e5cdf0c9 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Tue, 8 Mar 2016 12:56:02 +0100 Subject: Use ImageUtil instead of old stupid generic FileBackend for cropCenterSquare --- .../java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index d36a4316..8c10adf2 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -281,7 +281,7 @@ public class PublishProfilePictureActivity extends XmppActivity { protected void loadImageIntoPreview(Uri uri) { Bitmap bm = null; try { - bm = FileBackend.cropCenterSquare(uri, getPixel(192)); + bm = ImageUtil.cropCenterSquare(uri, getPixel(192)); } catch (Exception e) { e.printStackTrace(); } -- cgit v1.2.3 From f051dd0bcdbd35d101420fb1f75f33a565a1e0f8 Mon Sep 17 00:00:00 2001 From: lookshe Date: Tue, 8 Mar 2016 20:34:18 +0100 Subject: Fixes FS#153 - Check if url, phone and email are linkified correctly --- .../conversations/ui/adapter/MessageAdapter.java | 37 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'src') 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 53611d37..36790041 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -330,15 +330,40 @@ public class MessageAdapter extends ArrayAdapter { } viewHolder.messageBody.setText(span); } - int urlCount = 0; - Matcher matcher = Patterns.WEB_URL.matcher(body); - while (matcher.find()) { - urlCount++; + int patternMatchCount = 0; + int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); + Matcher matcher = null; + + // first check if we have a match on XMPP_PATTERN so we do not have to check for EMAIL_ADDRESSES + matcher = XMPP_PATTERN.matcher(body); + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0 && matcher.find()) { + oldAutoLinkMask -= Linkify.EMAIL_ADDRESSES; } - viewHolder.messageBody.setTextIsSelectable(urlCount <= 1); + + // count matches for all patterns + if ((Linkify.WEB_URLS & oldAutoLinkMask) != 0) { + matcher = Patterns.WEB_URL.matcher(body); + while (matcher.find()) { + patternMatchCount++; + } + } + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0) { + matcher = Patterns.EMAIL_ADDRESS.matcher(body); + while (matcher.find()) { + patternMatchCount++; + } + } + if ((Linkify.PHONE_NUMBERS & oldAutoLinkMask) != 0) { + matcher = Patterns.PHONE.matcher(body); + while (matcher.find()) { + patternMatchCount++; + } + } + + viewHolder.messageBody.setTextIsSelectable(patternMatchCount <= 1); viewHolder.messageBody.setAutoLinkMask(0); - Linkify.addLinks(viewHolder.messageBody, Linkify.WEB_URLS); Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); + viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); } else { viewHolder.messageBody.setText(""); viewHolder.messageBody.setTextIsSelectable(false); -- cgit v1.2.3