diff options
author | Vincent Breitmoser <valodim@mugenguild.com> | 2015-10-09 14:57:54 +0200 |
---|---|---|
committer | Vincent Breitmoser <valodim@mugenguild.com> | 2015-10-09 14:57:54 +0200 |
commit | 759ffc5a4b79a87c6c916bb44a1570613235bdc8 (patch) | |
tree | 1def4d8fb47b25d44193463251a5eb081e68bc2a /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util | |
parent | 315ed608ae977f1a25f1cd06a4e2d52ca09e01b2 (diff) | |
parent | eff4ae5551f286f4c870c3f9db44ceb73c3c2fcf (diff) | |
download | open-keychain-759ffc5a4b79a87c6c916bb44a1570613235bdc8.tar.gz open-keychain-759ffc5a4b79a87c6c916bb44a1570613235bdc8.tar.bz2 open-keychain-759ffc5a4b79a87c6c916bb44a1570613235bdc8.zip |
Merge branch 'master' into encrypted-export
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java index 902af3932..671275823 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java @@ -22,6 +22,7 @@ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -32,6 +33,7 @@ import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Point; @@ -39,13 +41,19 @@ import android.net.Uri; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Environment; +import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract; import android.provider.OpenableColumns; import android.support.v4.app.Fragment; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import static android.system.OsConstants.S_IROTH; /** This class offers a number of helper functions for saving documents. * @@ -261,6 +269,62 @@ public class FileHelper { return true; } + /** + * Tests whether a file is readable by others + */ + @TargetApi(VERSION_CODES.LOLLIPOP) + public static boolean S_IROTH(int mode) { + return (mode & S_IROTH) == S_IROTH; + } + + /** + * A replacement for ContentResolver.openInputStream() that does not allow the usage of + * "file" Uris that point to private files owned by the application only. + * + * This is not allowed: + * am start -a android.intent.action.SEND -t text/plain -n + * "org.sufficientlysecure.keychain.debug/org.sufficientlysecure.keychain.ui.EncryptFilesActivity" --eu + * android.intent.extra.STREAM + * file:///data/data/org.sufficientlysecure.keychain.debug/databases/openkeychain.db + * + * @throws FileNotFoundException + */ + @TargetApi(VERSION_CODES.LOLLIPOP) + public static InputStream openInputStreamSafe(ContentResolver resolver, Uri uri) + throws FileNotFoundException { + + // Not supported on Android < 5 + if (Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) { + return resolver.openInputStream(uri); + } + + String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_FILE.equals(scheme)) { + ParcelFileDescriptor pfd = ParcelFileDescriptor.open( + new File(uri.getPath()), ParcelFileDescriptor.parseMode("r")); + + try { + final StructStat st = Os.fstat(pfd.getFileDescriptor()); + if (!S_IROTH(st.st_mode)) { + Log.e(Constants.TAG, "File is not readable by others, aborting!"); + throw new FileNotFoundException("Unable to create stream"); + } + } catch (ErrnoException e) { + Log.e(Constants.TAG, "fstat() failed: " + e); + throw new FileNotFoundException("fstat() failed"); + } + + AssetFileDescriptor fd = new AssetFileDescriptor(pfd, 0, -1); + try { + return fd.createInputStream(); + } catch (IOException e) { + throw new FileNotFoundException("Unable to create stream"); + } + } else { + return resolver.openInputStream(uri); + } + } + public interface FileDialogCallback { void onFileSelected(File file, boolean checked); } |