aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian S <christian@pix-art.de>2016-04-09 20:46:13 +0200
committerChristian S <christian@pix-art.de>2016-04-09 20:46:13 +0200
commit4d4ec6824b6e49b0e241e5b69d49a89003a27f85 (patch)
tree3b17e8d73f5b258b406eeae81d70828f16c81aa4 /src
parentb8ec4663db7fb597ec4a4030ac9ea508e885d9e5 (diff)
parent65548ddccb7f63d623a86ad9a740ded87310e313 (diff)
Merge remote-tracking branch 'refs/remotes/siacs/master' into development
Diffstat (limited to 'src')
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Conversation.java4
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java32
-rw-r--r--src/main/java/eu/siacs/conversations/services/MessageArchiveService.java16
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java10
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java14
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java4
-rw-r--r--src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java13
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java22
-rw-r--r--src/main/res/values/strings.xml1
9 files changed, 92 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() {
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 1e54e2385..461cf75ae 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -637,4 +637,5 @@
<string name="this_account_is_disabled">You have disabled this account</string>
<string name="pref_plugin_voice_recorder">Voice Recorder</string>
<string name="pref_plugin_voice_recorder_summary">Send and receive voice messages</string>
+ <string name="security_error_invalid_file_access">Security error: Invalid file access</string>
</resources>