summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/Helpers.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2015-07-13 10:25:58 -0700
committerJeff Sharkey <jsharkey@android.com>2015-07-14 13:04:39 -0700
commited30deae5fe5b9de142b44933001c9b098c47712 (patch)
treef2bca00dbce87798aca9e73c43b8abb074e10d14 /src/com/android/providers/downloads/Helpers.java
parentd473cf8f85f60d53b20270a263afe6b138671cb5 (diff)
downloadandroid_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.tar.gz
android_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.tar.bz2
android_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.zip
Relax permissions on package-specific paths.
Normally apps must hold the WRITE_EXTERNAL_STORAGE permission in order to use DownloadManager. However, now that the platform has relaxed permissions on package-specific directories, we relax the DownloadManager check in a similar way. This also opens up using DownloadManager to save files on secondary external storage devices. Fix bug so that we now check the relevant volume state when thinking about resuming a download. Bug: 22135060 Change-Id: If439340ea48789ea167f49709b5b69a4f0883150
Diffstat (limited to 'src/com/android/providers/downloads/Helpers.java')
-rw-r--r--src/com/android/providers/downloads/Helpers.java78
1 files changed, 67 insertions, 11 deletions
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java
index 0aa49c0a..098d11b7 100644
--- a/src/com/android/providers/downloads/Helpers.java
+++ b/src/com/android/providers/downloads/Helpers.java
@@ -16,6 +16,10 @@
package com.android.providers.downloads;
+import static android.os.Environment.buildExternalStorageAppCacheDirs;
+import static android.os.Environment.buildExternalStorageAppFilesDirs;
+import static android.os.Environment.buildExternalStorageAppMediaDirs;
+import static android.os.Environment.buildExternalStorageAppObbDirs;
import static com.android.providers.downloads.Constants.TAG;
import android.content.Context;
@@ -23,6 +27,9 @@ import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.provider.Downloads;
import android.util.Log;
import android.webkit.MimeTypeMap;
@@ -334,31 +341,80 @@ public class Helpers {
throw new IOException("Failed to generate an available filename");
}
+ static boolean isFilenameValid(Context context, File file) {
+ return isFilenameValid(context, file, true);
+ }
+
+ static boolean isFilenameValidInExternal(Context context, File file) {
+ return isFilenameValid(context, file, false);
+ }
+
+ /**
+ * Test if given file exists in one of the package-specific external storage
+ * directories that are always writable to apps, regardless of storage
+ * permission.
+ */
+ static boolean isFilenameValidInExternalPackage(Context context, File file,
+ String packageName) {
+ try {
+ file = file.getCanonicalFile();
+
+ if (containsCanonical(buildExternalStorageAppFilesDirs(packageName), file) ||
+ containsCanonical(buildExternalStorageAppObbDirs(packageName), file) ||
+ containsCanonical(buildExternalStorageAppCacheDirs(packageName), file) ||
+ containsCanonical(buildExternalStorageAppMediaDirs(packageName), file)) {
+ return true;
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to resolve canonical path: " + e);
+ return false;
+ }
+
+ Log.w(TAG, "Path appears to be invalid: " + file);
+ return false;
+ }
+
/**
* Checks whether the filename looks legitimate for security purposes. This
* prevents us from opening files that aren't actually downloads.
*/
- static boolean isFilenameValid(Context context, File file) {
- final File[] whitelist;
+ static boolean isFilenameValid(Context context, File file, boolean allowInternal) {
try {
file = file.getCanonicalFile();
- whitelist = new File[] {
- context.getFilesDir().getCanonicalFile(),
- context.getCacheDir().getCanonicalFile(),
- Environment.getDownloadCacheDirectory().getCanonicalFile(),
- Environment.getExternalStorageDirectory().getCanonicalFile(),
- };
+
+ if (allowInternal) {
+ if (containsCanonical(context.getFilesDir(), file)
+ || containsCanonical(context.getCacheDir(), file)
+ || containsCanonical(Environment.getDownloadCacheDirectory(), file)) {
+ return true;
+ }
+ }
+
+ final StorageVolume[] volumes = StorageManager.getVolumeList(UserHandle.myUserId());
+ for (StorageVolume volume : volumes) {
+ if (containsCanonical(volume.getPathFile(), file)) {
+ return true;
+ }
+ }
} catch (IOException e) {
Log.w(TAG, "Failed to resolve canonical path: " + e);
return false;
}
- for (File testDir : whitelist) {
- if (FileUtils.contains(testDir, file)) {
+ Log.w(TAG, "Path appears to be invalid: " + file);
+ return false;
+ }
+
+ private static boolean containsCanonical(File dir, File file) throws IOException {
+ return FileUtils.contains(dir.getCanonicalFile(), file);
+ }
+
+ private static boolean containsCanonical(File[] dirs, File file) throws IOException {
+ for (File dir : dirs) {
+ if (containsCanonical(dir, file)) {
return true;
}
}
-
return false;
}