diff options
Diffstat (limited to '')
8 files changed, 91 insertions, 24 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index dfc371864..2f086a34d 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -337,6 +337,10 @@ public class Conversation extends AbstractEntity implements Blockable { return this.correctingMessage; } + public boolean withSelf() { + return getContact().isSelf(); + } + public interface OnMessageFound { void onMessageFound(final Message message); } diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 21ba45093..0861a3a86 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.persistance; +import android.annotation.TargetApi; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -9,8 +11,12 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; import android.net.Uri; +import android.os.Build; import android.os.Environment; +import android.os.ParcelFileDescriptor; import android.provider.OpenableColumns; +import android.system.Os; +import android.system.StructStat; import android.util.Base64; import android.util.Base64OutputStream; import android.util.Log; @@ -19,6 +25,7 @@ import android.webkit.MimeTypeMap; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -646,4 +653,29 @@ public class FileBackend { } } } + + + public static boolean weOwnFile(Uri uri) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return false; + } else { + return uri != null + && ContentResolver.SCHEME_FILE.equals(uri.getScheme()) + && weOwnFileLollipop(uri); + } + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static boolean weOwnFileLollipop(Uri uri) { + try { + File file = new File(uri.getPath()); + FileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).getFileDescriptor(); + StructStat st = Os.fstat(fd); + return st.st_uid == android.os.Process.myUid(); + } catch (FileNotFoundException e) { + return false; + } catch (Exception e) { + return true; + } + } } diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java index e8616bd8f..06df1b38a 100644 --- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java @@ -45,8 +45,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } - long startCatchup = getLastMessageTransmitted(account); + Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); + long startCatchup = pair == null ? 0 : pair.first; long endCatchup = account.getXmppConnection().getLastSessionEstablished(); + final Query query; if (startCatchup == 0) { return; } else if (endCatchup - startCatchup >= Config.MAM_MAX_CATCHUP) { @@ -57,8 +59,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.query(conversation,startCatchup); } } + query = new Query(account, startCatchup, endCatchup); + } else { + query = new Query(account, startCatchup, endCatchup); + query.reference = pair.second; } - final Query query = new Query(account, startCatchup, endCatchup); this.queries.add(query); this.execute(query); } @@ -75,11 +80,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } - private long getLastMessageTransmitted(final Account account) { - Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); - return pair == null ? 0 : pair.first; - } - public Query query(final Conversation conversation) { if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) { return query(conversation, @@ -282,7 +282,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.end = end; this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); } - + private Query page(String reference) { Query query = new Query(this.account,this.start,this.end); query.reference = reference; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 878b4334f..7849f8a39 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -403,6 +403,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void attachFileToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) { + if (FileBackend.weOwnFile(uri)) { + Log.d(Config.LOGTAG,"trying to attach file that belonged to us"); + callback.error(R.string.security_error_invalid_file_access, null); + return; + } final Message message; if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) { message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED); @@ -441,6 +446,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) { + if (FileBackend.weOwnFile(uri)) { + Log.d(Config.LOGTAG,"trying to attach file that belonged to us"); + callback.error(R.string.security_error_invalid_file_access, null); + return; + } final String compressPictures = getCompressPicturesPreference(); if ("never".equals(compressPictures) || ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 980e51441..868835da8 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -490,6 +490,8 @@ public class ConversationActivity extends XmppActivity menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); menuSecure.setVisible((Config.supportOpenPgp() || Config.supportOmemo()) && Config.multipleEncryptionChoices()); //only if pgp is supported we have a choice } else { + menuContactDetails.setVisible(!this.getSelectedConversation().withSelf()); + menuMucDetails.setVisible(false); menuSecure.setVisible(Config.multipleEncryptionChoices()); } if (this.getSelectedConversation().isMuted()) { @@ -1382,10 +1384,6 @@ public class ConversationActivity extends XmppActivity } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) { final List<Uri> uris = extractUriFromIntent(data); final Conversation c = getSelectedConversation(); - final long max = c.getAccount() - .getXmppConnection() - .getFeatures() - .getMaxHttpUploadSize(); final OnPresenceSelected callback = new OnPresenceSelected() { @Override public void onPresenceSelected() { @@ -1398,8 +1396,8 @@ public class ConversationActivity extends XmppActivity } } }; - if (c.getMode() == Conversation.MODE_MULTI - || FileBackend.allFilesUnderSize(this, uris, max) + if (c == null || c.getMode() == Conversation.MODE_MULTI + || FileBackend.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c)) || c.getNextEncryption() == Message.ENCRYPTION_OTR) { callback.onPresenceSelected(); } else { @@ -1448,6 +1446,10 @@ public class ConversationActivity extends XmppActivity } } + private long getMaxHttpUploadSize(Conversation conversation) { + return conversation.getAccount().getXmppConnection().getFeatures().getMaxHttpUploadSize(); + } + private void setNeverAskForBatteryOptimizationsAgain() { getPreferences().edit().putBoolean("show_battery_optimization", false).commit(); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index c43059170..ca996b505 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -468,7 +468,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa highlightInConference(user); } } else { - activity.switchToContactDetails(message.getContact(), message.getFingerprint()); + if (!message.getContact().isSelf()) { + activity.switchToContactDetails(message.getContact(), message.getFingerprint()); + } } } else { Account account = message.getConversation().getAccount(); diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index cb164b95a..2b25ad321 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -24,6 +24,7 @@ import java.io.File; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.utils.FileUtils; import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.xmpp.pep.Avatar; @@ -188,9 +189,13 @@ public class PublishProfilePictureActivity extends XmppActivity { protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { + Uri source = data.getData(); switch (requestCode) { case REQUEST_CHOOSE_FILE_AND_CROP: - Uri source = data.getData(); + if (FileBackend.weOwnFile(source)) { + Toast.makeText(this,R.string.security_error_invalid_file_access,Toast.LENGTH_SHORT).show(); + return; + } String original = FileUtils.getPath(this, source); if (original != null) { source = Uri.parse("file://"+original); @@ -200,7 +205,11 @@ public class PublishProfilePictureActivity extends XmppActivity { Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this); break; case REQUEST_CHOOSE_FILE: - this.avatarUri = data.getData(); + if (FileBackend.weOwnFile(source)) { + Toast.makeText(this,R.string.security_error_invalid_file_access,Toast.LENGTH_SHORT).show(); + return; + } + this.avatarUri = source; if (xmppConnectionServiceBound) { loadImageIntoPreview(this.avatarUri); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 58e510e12..6427c3471 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -118,6 +118,7 @@ public class XmppConnection implements Runnable { private long lastDiscoStarted = 0; private AtomicInteger mPendingServiceDiscoveries = new AtomicInteger(0); private AtomicBoolean mIsServiceItemsDiscoveryPending = new AtomicBoolean(true); + private boolean mWaitForDisco = true; private final ArrayList<String> mPendingServiceDiscoveriesIds = new ArrayList<>(); private boolean mInteractive = false; private int attempt = 0; @@ -1011,8 +1012,9 @@ public class XmppConnection implements Runnable { synchronized (this.disco) { this.disco.clear(); } - mPendingServiceDiscoveries.set(mServerIdentity == Identity.NIMBUZZ ? 1 : 0); + mPendingServiceDiscoveries.set(0); mIsServiceItemsDiscoveryPending.set(true); + mWaitForDisco = mServerIdentity != Identity.NIMBUZZ; lastDiscoStarted = SystemClock.elapsedRealtime(); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": starting service discovery"); mXmppConnectionService.scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode()); @@ -1031,13 +1033,14 @@ public class XmppConnection implements Runnable { } sendServiceDiscoveryInfo(account.getJid().toBareJid()); sendServiceDiscoveryItems(account.getServer()); + if (!mWaitForDisco) { + finalizeBind(); + } this.lastSessionStarted = SystemClock.elapsedRealtime(); } private void sendServiceDiscoveryInfo(final Jid jid) { - if (mServerIdentity != Identity.NIMBUZZ) { - mPendingServiceDiscoveries.incrementAndGet(); - } + mPendingServiceDiscoveries.incrementAndGet(); final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(jid); iq.query("http://jabber.org/protocol/disco#info"); @@ -1081,7 +1084,9 @@ public class XmppConnection implements Runnable { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco info for " + jid.toString()); } if (packet.getType() != IqPacket.TYPE.TIMEOUT) { - if (mPendingServiceDiscoveries.decrementAndGet() == 0 && !mIsServiceItemsDiscoveryPending.get()) { + if (mPendingServiceDiscoveries.decrementAndGet() == 0 + && !mIsServiceItemsDiscoveryPending.get() + && mWaitForDisco) { finalizeBind(); } } @@ -1117,7 +1122,7 @@ public class XmppConnection implements Runnable { final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#items"); - this.sendIqPacket(iq, new OnIqPacketReceived() { + String id = this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { @@ -1136,12 +1141,15 @@ public class XmppConnection implements Runnable { } if (packet.getType() != IqPacket.TYPE.TIMEOUT) { mIsServiceItemsDiscoveryPending.set(false); - if (mPendingServiceDiscoveries.get() == 0) { + if (mPendingServiceDiscoveries.get() == 0 && mWaitForDisco) { finalizeBind(); } } } }); + synchronized (this.mPendingServiceDiscoveriesIds) { + this.mPendingServiceDiscoveriesIds.add(id); + } } private void sendEnableCarbons() { |