diff options
Diffstat (limited to 'src/main/java')
8 files changed, 122 insertions, 45 deletions
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 2ce62c9ad..77c9d9d7e 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -337,9 +337,10 @@ public class AxolotlService { } public void publishOwnDeviceId(Set<Integer> deviceIds) { - if (!deviceIds.contains(getOwnDeviceId())) { + Set<Integer> deviceIdsCopy = new HashSet<>(deviceIds); + if (!deviceIdsCopy.contains(getOwnDeviceId())) { Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist."); - if (deviceIds.isEmpty()) { + if (deviceIdsCopy.isEmpty()) { if (numPublishTriesOnEmptyPep >= publishTriesThreshold) { Log.w(Config.LOGTAG, getLogprefix(account) + "Own device publish attempt threshold exceeded, aborting..."); pepBroken = true; @@ -351,8 +352,8 @@ public class AxolotlService { } else { numPublishTriesOnEmptyPep = 0; } - deviceIds.add(getOwnDeviceId()); - IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); + deviceIdsCopy.add(getOwnDeviceId()); + IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIdsCopy); mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { @@ -490,7 +491,10 @@ public class AxolotlService { } private void buildSessionFromPEP(final AxolotlAddress address) { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new sesstion for " + address.getDeviceId()); + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new sesstion for " + address.toString()); + if (address.getDeviceId() == getOwnDeviceId()) { + throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!"); + } try { IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice( diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java index 190eb88a8..4d7793023 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java @@ -89,15 +89,14 @@ public class SQLiteAxolotlStore implements AxolotlStore { private IdentityKeyPair loadIdentityKeyPair() { String ownName = account.getJid().toBareJid().toString(); - IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account, - ownName); + IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account); if (ownKey != null) { return ownKey; } else { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve axolotl key for account " + ownName); + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve own IdentityKeyPair"); ownKey = generateIdentityKeyPair(); - mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownName, ownKey); + mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownKey); } return ownKey; } diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 0eff99cf7..bfb26446d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -506,17 +506,25 @@ public class Message extends AbstractEntity { private static String extractRelevantExtension(URL url) { String path = url.getPath(); + return extractRelevantExtension(path); + } + + private static String extractRelevantExtension(String path) { if (path == null || path.isEmpty()) { return null; } + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); - String[] extensionParts = filename.split("\\."); - if (extensionParts.length == 2) { - return extensionParts[extensionParts.length - 1]; - } else if (extensionParts.length == 3 && Arrays - .asList(Transferable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1])) { - return extensionParts[extensionParts.length -2]; + int dotPosition = filename.lastIndexOf("."); + + 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)) { + return extractRelevantExtension(path.substring(0,dotPosition)); + } else { + return extension; + } } return null; } diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 9fe47512b..d420c1cd8 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -42,7 +42,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private static DatabaseBackend instance = null; private static final String DATABASE_NAME = "history"; - private static final int DATABASE_VERSION = 16; + private static final int DATABASE_VERSION = 17; private static String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -301,6 +301,24 @@ public class DatabaseBackend extends SQLiteOpenHelper { db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.CARBON + " INTEGER"); } + if (oldVersion < 17 && newVersion >= 17) { + List<Account> accounts = getAccounts(db); + for (Account account : accounts) { + String ownDeviceIdString = account.getKey(SQLiteAxolotlStore.JSONKEY_REGISTRATION_ID); + if ( ownDeviceIdString == null ) { + continue; + } + int ownDeviceId = Integer.valueOf(ownDeviceIdString); + AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), ownDeviceId); + deleteSession(db, account, ownAddress); + IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account); + if (identityKeyPair != null) { + setIdentityKeyTrust(db, account, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), XmppAxolotlSession.Trust.TRUSTED); + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not load own identity key pair"); + } + } + } } public static synchronized DatabaseBackend getInstance(Context context) { @@ -414,8 +432,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public List<Account> getAccounts() { - List<Account> list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); + return getAccounts(db); + } + + private List<Account> getAccounts(SQLiteDatabase db) { + List<Account> list = new ArrayList<>(); Cursor cursor = db.query(Account.TABLENAME, null, null, null, null, null, null); while (cursor.moveToNext()) { @@ -602,8 +624,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public List<Integer> getSubDeviceSessions(Account account, AxolotlAddress contact) { - List<Integer> devices = new ArrayList<>(); final SQLiteDatabase db = this.getReadableDatabase(); + return getSubDeviceSessions(db, account, contact); + } + + private List<Integer> getSubDeviceSessions(SQLiteDatabase db, Account account, AxolotlAddress contact) { + List<Integer> devices = new ArrayList<>(); String[] columns = {SQLiteAxolotlStore.DEVICE_ID}; String[] selectionArgs = {account.getUuid(), contact.getName()}; @@ -642,6 +668,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { public void deleteSession(Account account, AxolotlAddress contact) { SQLiteDatabase db = this.getWritableDatabase(); + deleteSession(db, account, contact); + } + + private void deleteSession(SQLiteDatabase db, Account account, AxolotlAddress contact) { String[] args = {account.getUuid(), contact.getName(), Integer.toString(contact.getDeviceId())}; @@ -790,15 +820,24 @@ public class DatabaseBackend extends SQLiteOpenHelper { } private Cursor getIdentityKeyCursor(Account account, String name, boolean own) { - return getIdentityKeyCursor(account, name, own, null); + final SQLiteDatabase db = this.getReadableDatabase(); + return getIdentityKeyCursor(db, account, name, own); } - private Cursor getIdentityKeyCursor(Account account, String fingerprint) { - return getIdentityKeyCursor(account, null, null, fingerprint); + private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, boolean own) { + return getIdentityKeyCursor(db, account, name, own, null); } - private Cursor getIdentityKeyCursor(Account account, String name, Boolean own, String fingerprint) { + private Cursor getIdentityKeyCursor(Account account, String fingerprint) { final SQLiteDatabase db = this.getReadableDatabase(); + return getIdentityKeyCursor(db, account, fingerprint); + } + + private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String fingerprint) { + return getIdentityKeyCursor(db, account, null, null, fingerprint); + } + + private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, Boolean own, String fingerprint) { String[] columns = {SQLiteAxolotlStore.TRUSTED, SQLiteAxolotlStore.KEY}; ArrayList<String> selectionArgs = new ArrayList<>(4); @@ -825,9 +864,15 @@ public class DatabaseBackend extends SQLiteOpenHelper { return cursor; } - public IdentityKeyPair loadOwnIdentityKeyPair(Account account, String name) { + public IdentityKeyPair loadOwnIdentityKeyPair(Account account) { + SQLiteDatabase db = getReadableDatabase(); + return loadOwnIdentityKeyPair(db, account); + } + + private IdentityKeyPair loadOwnIdentityKeyPair(SQLiteDatabase db, Account account) { + String name = account.getJid().toBareJid().toString(); IdentityKeyPair identityKeyPair = null; - Cursor cursor = getIdentityKeyCursor(account, name, true); + Cursor cursor = getIdentityKeyCursor(db, account, name, true); if(cursor.getCount() != 0) { cursor.moveToFirst(); try { @@ -911,6 +956,10 @@ public class DatabaseBackend extends SQLiteOpenHelper { public boolean setIdentityKeyTrust(Account account, String fingerprint, XmppAxolotlSession.Trust trust) { SQLiteDatabase db = this.getWritableDatabase(); + return setIdentityKeyTrust(db, account, fingerprint, trust); + } + + private boolean setIdentityKeyTrust(SQLiteDatabase db, Account account, String fingerprint, XmppAxolotlSession.Trust trust) { String[] selectionArgs = { account.getUuid(), fingerprint @@ -928,8 +977,8 @@ public class DatabaseBackend extends SQLiteOpenHelper { storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT)); } - public void storeOwnIdentityKeyPair(Account account, String name, IdentityKeyPair identityKeyPair) { - storeIdentityKey(account, name, true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), XmppAxolotlSession.Trust.TRUSTED); + public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) { + storeIdentityKey(account, account.getJid().toBareJid().toString(), true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), XmppAxolotlSession.Trust.TRUSTED); } public void recreateAxolotlDb() { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index aaa46825d..071db609d 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -988,6 +988,7 @@ public class ConversationActivity extends XmppActivity } else { this.mConversationFragment.messageListAdapter.updatePreferences(); this.mConversationFragment.messagesView.invalidateViews(); + this.mConversationFragment.setupIme(); } if(!forbidProcessingPendings) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 3adbc8431..f25e338b4 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -232,7 +232,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (actionId == EditorInfo.IME_ACTION_SEND) { InputMethodManager imm = (InputMethodManager) v.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + if (imm.isFullscreenMode()) { + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + } sendMessage(); return true; } else { @@ -345,21 +347,24 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } - private void setupIme() { - if (((ConversationActivity) getActivity()).usingEnterKey()) { + public void setupIme() { + if (activity.usingEnterKey() && activity.enterIsSend()) { + mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE)); + mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); + } else if (activity.usingEnterKey()) { + mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); } else { + mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); } } @Override - public View onCreateView(final LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_conversation, container, false); view.setOnClickListener(null); mEditMessage = (EditMessage) view.findViewById(R.id.textinput); - setupIme(); mEditMessage.setOnClickListener(new OnClickListener() { @Override @@ -639,9 +644,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (conversation == null) { return; } - this.activity = (ConversationActivity) getActivity(); - + setupIme(); if (this.conversation != null) { final String msg = mEditMessage.getText().toString(); this.conversation.setNextMessage(msg); diff --git a/src/main/java/eu/siacs/conversations/ui/EditMessage.java b/src/main/java/eu/siacs/conversations/ui/EditMessage.java index a58cf2b8b..72975bb76 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditMessage.java +++ b/src/main/java/eu/siacs/conversations/ui/EditMessage.java @@ -36,7 +36,7 @@ public class EditMessage extends EditText { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_ENTER) { + if (keyCode == KeyEvent.KEYCODE_ENTER && !event.isShiftPressed()) { if (keyboardListener != null && keyboardListener.onEnterPressed()) { return true; } diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index 889206e0b..2cde19ae3 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -127,13 +127,21 @@ public class DNSHelper { ArrayList<Bundle> values = new ArrayList<>(); if (result.size() == 0) { DNSMessage response; - response = client.query(host, TYPE.A, CLASS.IN, dnsServer.getHostAddress()); - for(int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(host,5222,response.getAnswers()[i].getPayload())); + try { + response = client.query(host, TYPE.A, CLASS.IN, dnsServer.getHostAddress()); + for (int i = 0; i < response.getAnswers().length; ++i) { + values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload())); + } + } catch (SocketTimeoutException e) { + Log.d(Config.LOGTAG,"ignoring timeout exception when querying A record on "+dnsServer.getHostAddress()); } - response = client.query(host, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); - for(int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(host,5222,response.getAnswers()[i].getPayload())); + try { + response = client.query(host, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); + for (int i = 0; i < response.getAnswers().length; ++i) { + values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload())); + } + } catch (SocketTimeoutException e) { + Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress()); } values.add(createNamePortBundle(host,5222)); bundle.putParcelableArrayList("values", values); @@ -143,9 +151,13 @@ public class DNSHelper { if (ips6.containsKey(srv.getName())) { values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips6)); } else { - DNSMessage response = client.query(srv.getName(), TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); - for(int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(srv.getName(),srv.getPort(),response.getAnswers()[i].getPayload())); + try { + DNSMessage response = client.query(srv.getName(), TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); + for (int i = 0; i < response.getAnswers().length; ++i) { + values.add(createNamePortBundle(srv.getName(), srv.getPort(), response.getAnswers()[i].getPayload())); + } + } catch (SocketTimeoutException e) { + Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress()); } } if (ips4.containsKey(srv.getName())) { |