summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java19
-rwxr-xr-xsrc/com/android/providers/downloads/DownloadThread.java2
-rw-r--r--src/com/android/providers/downloads/Helpers.java12
-rw-r--r--src/com/android/providers/downloads/StorageManager.java49
4 files changed, 66 insertions, 16 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index 0928fdfc..132deb9a 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -710,14 +710,15 @@ public final class DownloadProvider extends ContentProvider {
if (path == null) {
throw new IllegalArgumentException("Invalid file URI: " + uri);
}
- try {
- final String canonicalPath = new File(path).getCanonicalPath();
- final String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
- if (!canonicalPath.startsWith(externalPath)) {
- throw new SecurityException("Destination must be on external storage: " + uri);
- }
- } catch (IOException e) {
- throw new SecurityException("Problem resolving path: " + uri);
+
+ final String phoneStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
+ String sdCardStoragePath = null;
+ if (StorageManager.isSecondStorageSupported()) {
+ sdCardStoragePath = StorageManager.getExternalStorageDirectory(getContext());
+ }
+ if (!path.startsWith(phoneStoragePath)
+ && !(sdCardStoragePath != null && path.startsWith(sdCardStoragePath))) {
+ throw new SecurityException("Destination must be on external storage: " + uri);
}
}
@@ -1209,7 +1210,7 @@ public final class DownloadProvider extends ContentProvider {
if (path == null) {
throw new FileNotFoundException("No filename found.");
}
- if (!Helpers.isFilenameValid(path, mDownloadsDataDir)) {
+ if (!Helpers.isFilenameValid(getContext(), path, mDownloadsDataDir)) {
throw new FileNotFoundException("Invalid filename: " + path);
}
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 9d5274c4..88cd9162 100755
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -769,7 +769,7 @@ public class DownloadThread implements Runnable {
Log.i(Constants.TAG, "have run thread before for id: " + mInfo.mId +
", and state.mFilename: " + state.mFilename);
}
- if (!Helpers.isFilenameValid(state.mFilename,
+ if (!Helpers.isFilenameValid(mContext, state.mFilename,
mStorageManager.getDownloadDataDirectory())) {
// this should never happen
throw new StopRequestException(Downloads.Impl.STATUS_FILE_ERROR,
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java
index 3562dac7..d9b38b50 100644
--- a/src/com/android/providers/downloads/Helpers.java
+++ b/src/com/android/providers/downloads/Helpers.java
@@ -375,6 +375,18 @@ public class Helpers {
}
/**
+ * Checks whether the filename looks legitimate
+ */
+ static boolean isFilenameValid(Context context, String filename, File downloadsDataDir) {
+ filename = filename.replaceFirst("/+", "/"); // normalize leading slashes
+ return filename.startsWith(Environment.getDownloadCacheDirectory().toString())
+ || filename.startsWith(downloadsDataDir.toString())
+ || filename.startsWith(Environment.getExternalStorageDirectory().toString())
+ || (StorageManager.isSecondStorageSupported() && filename.startsWith(StorageManager
+ .getExternalStorageDirectory(context)));
+ }
+
+ /**
* Checks whether this looks like a legitimate selection parameter
*/
public static void validateSelection(String selection, Set<String> allowedColumns) {
diff --git a/src/com/android/providers/downloads/StorageManager.java b/src/com/android/providers/downloads/StorageManager.java
index deb412e7..a0ceae6a 100644
--- a/src/com/android/providers/downloads/StorageManager.java
+++ b/src/com/android/providers/downloads/StorageManager.java
@@ -19,6 +19,7 @@ package com.android.providers.downloads;
import static com.android.providers.downloads.Constants.LOGV;
import static com.android.providers.downloads.Constants.TAG;
+import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.res.Resources;
@@ -27,6 +28,7 @@ import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
+import android.os.storage.StorageVolume;
import android.provider.Downloads;
import android.text.TextUtils;
import android.util.Log;
@@ -77,6 +79,8 @@ class StorageManager {
/** misc members */
private final Context mContext;
+ private static String sdCardStorageDir;
+ private static final String LOGTAG = "StorageManager";
public StorageManager(Context context) {
mContext = context;
@@ -84,6 +88,11 @@ class StorageManager {
mExternalStorageDir = Environment.getExternalStorageDirectory();
mSystemCacheDir = Environment.getDownloadCacheDirectory();
startThreadToCleanupDatabaseAndPurgeFileSystem();
+ if (isSecondStorageSupported()) {
+ sdCardStorageDir = getExternalStorageDirectory(context);
+ } else {
+ sdCardStorageDir = null;
+ }
}
/** How often should database and filesystem be cleaned up to remove spurious files
@@ -149,7 +158,9 @@ class StorageManager {
dir = mSystemCacheDir;
break;
case Downloads.Impl.DESTINATION_FILE_URI:
- if (path.startsWith(mExternalStorageDir.getPath())) {
+ if (isSecondStorageSupported() && path.startsWith(sdCardStorageDir)) {
+ dir = new File(sdCardStorageDir);
+ } else if (path.startsWith(mExternalStorageDir.getPath())) {
dir = mExternalStorageDir;
} else if (path.startsWith(mDownloadDataDir.getPath())) {
dir = mDownloadDataDir;
@@ -175,11 +186,13 @@ class StorageManager {
if (targetBytes == 0) {
return;
}
- if (destination == Downloads.Impl.DESTINATION_FILE_URI ||
- destination == Downloads.Impl.DESTINATION_EXTERNAL) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- throw new StopRequestException(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
- "external media not mounted");
+ if (!(isSecondStorageSupported() && root.getPath().startsWith(sdCardStorageDir))) {
+ if (destination == Downloads.Impl.DESTINATION_FILE_URI ||
+ destination == Downloads.Impl.DESTINATION_EXTERNAL) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new StopRequestException(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
+ "external media not mounted");
+ }
}
}
// is there enough space in the file system of the given param 'root'.
@@ -469,4 +482,28 @@ class StorageManager {
private synchronized void resetBytesDownloadedSinceLastCheckOnSpace() {
mBytesDownloadedSinceLastCheckOnSpace = 0;
}
+
+ /**
+ * Whether support Second Storage
+ *
+ * @return boolean true support Second Storage, false will be not
+ */
+ public static boolean isSecondStorageSupported() {
+ return true;
+ }
+
+ public static String getExternalStorageDirectory(Context context) {
+ String sdCardDir = null;
+ android.os.storage.StorageManager storageManager =
+ (android.os.storage.StorageManager) context
+ .getSystemService(Context.STORAGE_SERVICE);
+ StorageVolume[] volumes = storageManager.getVolumeList();
+ for (int i = 0; i < volumes.length; i++) {
+ if (volumes[i].isRemovable() && volumes[i].allowMassStorage()) {
+ sdCardDir = volumes[i].getPath();
+ break;
+ }
+ }
+ return sdCardDir;
+ }
}