Snap for 9157512 from 58f2719421b362b3a10655985f9adc0954c7bf8b to mainline-tzdata3-release
Change-Id: I5f65be7df419ced3e6ab86ff807c8d9f9e702295
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index f1a957b..b48ef02 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -56,7 +56,7 @@
<string name="picker_profile_admin_title" msgid="4172022376418293777">"आपके एडमिन ने रोक लगाई है"</string>
<string name="picker_profile_admin_msg_from_personal" msgid="1941639895084555723">"ऑफ़िस के काम से जुड़े डेटा को निजी ऐप्लिकेशन से ऐक्सेस करने की अनुमति नहीं है"</string>
<string name="picker_profile_admin_msg_from_work" msgid="8048524337462790110">"निजी डेटा को ऑफ़िस के काम से जुड़े ऐप्लिकेशन से ऐक्सेस करने की अनुमति नहीं है"</string>
- <string name="picker_profile_work_paused_title" msgid="382212880704235925">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन रोक दिए गए हैं"</string>
+ <string name="picker_profile_work_paused_title" msgid="382212880704235925">"वर्क ऐप्लिकेशन रोक दिए गए हैं"</string>
<string name="picker_profile_work_paused_msg" msgid="6321552322125246726">"वर्क फ़ोटो देखने के लिए, ऑफ़िस के काम से जुड़े ऐप्लिकेशन चालू करें और दोबारा कोशिश करें"</string>
<string name="picker_privacy_message" msgid="9132700451027116817">"इस ऐप्लिकेशन के पास आपकी उन फ़ोटो का ही ऐक्सेस होता है जिन्हें आपने चुना हो"</string>
<string name="picker_album_item_count" msgid="4420723302534177596">"{count,plural, =1{<xliff:g id="COUNT_0">^1</xliff:g> आइटम}one{<xliff:g id="COUNT_1">^1</xliff:g> आइटम}other{<xliff:g id="COUNT_1">^1</xliff:g> आइटम}}"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index a9a4905..015261b 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -50,7 +50,7 @@
<string name="picker_view_selected" msgid="2266031384396143883">"Таңдалғанды көру"</string>
<string name="picker_photos" msgid="7415035516411087392">"Фотосуреттер"</string>
<string name="picker_albums" msgid="4822511902115299142">"Aльбомдар"</string>
- <string name="picker_preview" msgid="6257414886055861039">"Алдын ала қарау"</string>
+ <string name="picker_preview" msgid="6257414886055861039">"Алдын ала көру"</string>
<string name="picker_work_profile" msgid="2083221066869141576">"Жұмыс профиліне ауысу"</string>
<string name="picker_personal_profile" msgid="639484258397758406">"Жеке профильге ауысу"</string>
<string name="picker_profile_admin_title" msgid="4172022376418293777">"Әкімшіңіз бөгеген"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 68a9347..ede431b 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -116,6 +116,6 @@
<string name="transcode_processing_success" msgid="447288876429730122">"ମିଡିଆ ପ୍ରକ୍ରିୟାକରଣ ସଫଳ ହୋଇଛି"</string>
<string name="transcode_processing_started" msgid="7789086308155361523">"ମିଡିଆ ପ୍ରକ୍ରିୟାକରଣ ଆରମ୍ଭ କରାଯାଇଛି"</string>
<string name="transcode_processing" msgid="6753136468864077258">"ମିଡିଆ ପ୍ରକ୍ରିୟାକରଣ କରାଯାଉଛି…"</string>
- <string name="transcode_cancel" msgid="8555752601907598192">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="transcode_cancel" msgid="8555752601907598192">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="transcode_wait" msgid="8909773149560697501">"ଅପେକ୍ଷା କରନ୍ତୁ"</string>
</resources>
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 1093f52..5dafff1 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -8300,7 +8300,7 @@
private void deleteIfAllowed(Uri uri, Bundle extras, String path) {
try {
- final File file = new File(path);
+ final File file = new File(path).getCanonicalFile();
checkAccess(uri, extras, file, true);
deleteAndInvalidate(file);
} catch (Exception e) {
diff --git a/src/com/android/providers/media/util/FileUtils.java b/src/com/android/providers/media/util/FileUtils.java
index ee421c9..bbf04de 100644
--- a/src/com/android/providers/media/util/FileUtils.java
+++ b/src/com/android/providers/media/util/FileUtils.java
@@ -49,8 +49,8 @@
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
-import android.os.UserHandle;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
@@ -973,12 +973,13 @@
"(?i)^Android/(?:data|media|obb)/([^/]+)(/?.*)?");
/**
- * Regex that matches Android/obb or Android/data path.
+ * Regex that matches exactly Android/obb or Android/data or Android/obb/ or Android/data/
+ * suffix absolute file path.
*/
private static final Pattern PATTERN_DATA_OR_OBB_PATH = Pattern.compile(
"(?i)^/storage/[^/]+/(?:[0-9]+/)?"
+ PROP_CROSS_USER_ROOT_PATTERN
- + "Android/(?:data|obb)(?:/.*)?$");
+ + "Android/(?:data|obb)/?$");
/**
* Regex that matches Android/obb or Android/data relative path (as defined in
@@ -1399,9 +1400,18 @@
resolvedDisplayName = displayName;
}
- final File filePath = buildPath(volumePath,
- values.getAsString(MediaColumns.RELATIVE_PATH), resolvedDisplayName);
- values.put(MediaColumns.DATA, filePath.getAbsolutePath());
+ String relativePath = values.getAsString(MediaColumns.RELATIVE_PATH);
+ if (relativePath == null) {
+ relativePath = "";
+ }
+ try {
+ final File filePath = buildPath(volumePath, relativePath, resolvedDisplayName);
+ values.put(MediaColumns.DATA, filePath.getCanonicalPath());
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ String.format("Failure in conversion to canonical file path. Failure path: %s.",
+ relativePath.concat(resolvedDisplayName)), e);
+ }
}
public static void sanitizeValues(@NonNull ContentValues values,
diff --git a/tests/src/com/android/providers/media/MediaProviderTest.java b/tests/src/com/android/providers/media/MediaProviderTest.java
index 6df8ab3..6d4ec37 100644
--- a/tests/src/com/android/providers/media/MediaProviderTest.java
+++ b/tests/src/com/android/providers/media/MediaProviderTest.java
@@ -78,6 +78,7 @@
import com.android.providers.media.util.SQLiteQueryBuilder;
import org.junit.AfterClass;
+import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Ignore;
@@ -375,6 +376,42 @@
}
}
+ @Test
+ public void testInsertionWithInvalidFilePath_throwsIllegalArgumentException() {
+ final ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Android/media/com.example");
+ values.put(MediaStore.Images.Media.DISPLAY_NAME,
+ "./../../../../../../../../../../../data/media/test.txt");
+
+ IllegalArgumentException illegalArgumentException = Assert.assertThrows(
+ IllegalArgumentException.class, () -> sIsolatedResolver.insert(
+ MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ values));
+
+ assertThat(illegalArgumentException).hasMessageThat().contains(
+ "Primary directory Android not allowed for content://media/external_primary/file;"
+ + " allowed directories are [Download, Documents]");
+ }
+
+ @Test
+ public void testUpdationWithInvalidFilePath_throwsIllegalArgumentException() {
+ final ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Download");
+ values.put(MediaStore.Images.Media.DISPLAY_NAME, "test.txt");
+ Uri uri = sIsolatedResolver.insert(
+ MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ values);
+
+ final ContentValues newValues = new ContentValues();
+ newValues.put(MediaStore.MediaColumns.DATA, "/storage/emulated/0/../../../data/media/");
+ IllegalArgumentException illegalArgumentException = Assert.assertThrows(
+ IllegalArgumentException.class,
+ () -> sIsolatedResolver.update(uri, newValues, null));
+
+ assertThat(illegalArgumentException).hasMessageThat().contains(
+ "Requested path /data/media doesn't appear under [/storage/emulated/0]");
+ }
+
/**
* We already have solid coverage of this logic in
* {@code CtsProviderTestCases}, but the coverage system currently doesn't
diff --git a/tests/src/com/android/providers/media/util/FileUtilsTest.java b/tests/src/com/android/providers/media/util/FileUtilsTest.java
index 574a2db..3fde6d9 100644
--- a/tests/src/com/android/providers/media/util/FileUtilsTest.java
+++ b/tests/src/com/android/providers/media/util/FileUtilsTest.java
@@ -63,6 +63,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -1013,11 +1014,16 @@
assertThat(isDataOrObbPath("/storage/emulated/0/Android/obb")).isTrue();
assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/data")).isTrue();
assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/obb")).isTrue();
- assertThat(isDataOrObbPath("/storage/emulated/0/Android/data/foo")).isTrue();
- assertThat(isDataOrObbPath("/storage/emulated/0/Android/obb/foo")).isTrue();
- assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/data/foo")).isTrue();
- assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/obb/foo")).isTrue();
+ assertThat(isDataOrObbPath("/storage/emulated/0/Android/data/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated/0/Android/obb/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/data/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/obb/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated/10/Android/obb/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated//Android/obb/foo")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated//Android/obb")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated/0//Android/obb")).isFalse();
+ assertThat(isDataOrObbPath("/storage/emulated/0//Android/obb/foo")).isFalse();
assertThat(isDataOrObbPath("/storage/emulated/0/Android/")).isFalse();
assertThat(isDataOrObbPath("/storage/emulated/0/Android/media/")).isFalse();
assertThat(isDataOrObbPath("/storage/ABCD-1234/Android/media/")).isFalse();
@@ -1192,4 +1198,27 @@
assertTrue(values.containsKey(MediaColumns.BUCKET_DISPLAY_NAME));
assertNull(values.get(MediaColumns.BUCKET_DISPLAY_NAME));
}
+
+ @Test
+ public void testComputeDataFromValuesForValidPath_success() {
+ final ContentValues values = new ContentValues();
+ values.put(MediaColumns.RELATIVE_PATH, "Android/media/com.example");
+ values.put(MediaColumns.DISPLAY_NAME, "./../../abc.txt");
+
+ FileUtils.computeDataFromValues(values, new File("/storage/emulated/0"), false);
+
+ assertThat(values.getAsString(MediaColumns.DATA)).isEqualTo(
+ "/storage/emulated/0/Android/abc.txt");
+ }
+
+ @Test
+ public void testComputeDataFromValuesForInvalidPath_throwsIllegalArgumentException() {
+ final ContentValues values = new ContentValues();
+ values.put(MediaColumns.RELATIVE_PATH, "\0");
+ values.put(MediaColumns.DISPLAY_NAME, "./../../abc.txt");
+
+ assertThrows(IllegalArgumentException.class,
+ () -> FileUtils.computeDataFromValues(values, new File("/storage/emulated/0"),
+ false));
+ }
}