diff options
Diffstat (limited to 'packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java')
-rw-r--r-- | packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 066acac..073d9c7 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -43,6 +43,7 @@ import android.util.Log; import android.webkit.MimeTypeMap; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -53,6 +54,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; +import java.util.Objects; public class ExternalStorageProvider extends DocumentsProvider { private static final String TAG = "ExternalStorage"; @@ -313,27 +315,19 @@ public class ExternalStorageProvider extends DocumentsProvider { @Override public String createDocument(String docId, String mimeType, String displayName) throws FileNotFoundException { + displayName = FileUtils.buildValidFatFilename(displayName); + final File parent = getFileForDocId(docId); if (!parent.isDirectory()) { throw new IllegalArgumentException("Parent document isn't a directory"); } - File file; + final File file = buildUniqueFile(parent, mimeType, displayName); if (Document.MIME_TYPE_DIR.equals(mimeType)) { - file = new File(parent, displayName); if (!file.mkdir()) { throw new IllegalStateException("Failed to mkdir " + file); } } else { - displayName = removeExtension(mimeType, displayName); - file = new File(parent, addExtension(mimeType, displayName)); - - // If conflicting file, try adding counter suffix - int n = 0; - while (file.exists() && n++ < 32) { - file = new File(parent, addExtension(mimeType, displayName + " (" + n + ")")); - } - try { if (!file.createNewFile()) { throw new IllegalStateException("Failed to touch " + file); @@ -342,11 +336,78 @@ public class ExternalStorageProvider extends DocumentsProvider { throw new IllegalStateException("Failed to touch " + file + ": " + e); } } + return getDocIdForFile(file); } + private static File buildFile(File parent, String name, String ext) { + if (TextUtils.isEmpty(ext)) { + return new File(parent, name); + } else { + return new File(parent, name + "." + ext); + } + } + + @VisibleForTesting + public static File buildUniqueFile(File parent, String mimeType, String displayName) + throws FileNotFoundException { + String name; + String ext; + + if (Document.MIME_TYPE_DIR.equals(mimeType)) { + name = displayName; + ext = null; + } else { + String mimeTypeFromExt; + + // Extract requested extension from display name + final int lastDot = displayName.lastIndexOf('.'); + if (lastDot >= 0) { + name = displayName.substring(0, lastDot); + ext = displayName.substring(lastDot + 1); + mimeTypeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension( + ext.toLowerCase()); + } else { + name = displayName; + ext = null; + mimeTypeFromExt = null; + } + + if (mimeTypeFromExt == null) { + mimeTypeFromExt = "application/octet-stream"; + } + + final String extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType( + mimeType); + if (Objects.equals(mimeType, mimeTypeFromExt) || Objects.equals(ext, extFromMimeType)) { + // Extension maps back to requested MIME type; allow it + } else { + // No match; insist that create file matches requested MIME + name = displayName; + ext = extFromMimeType; + } + } + + File file = buildFile(parent, name, ext); + + // If conflicting file, try adding counter suffix + int n = 0; + while (file.exists()) { + if (n++ >= 32) { + throw new FileNotFoundException("Failed to create unique file"); + } + file = buildFile(parent, name + " (" + n + ")", ext); + } + + return file; + } + @Override public String renameDocument(String docId, String displayName) throws FileNotFoundException { + // Since this provider treats renames as generating a completely new + // docId, we're okay with letting the MIME type change. + displayName = FileUtils.buildValidFatFilename(displayName); + final File before = getFileForDocId(docId); final File after = new File(before.getParentFile(), displayName); if (after.exists()) { @@ -482,34 +543,6 @@ public class ExternalStorageProvider extends DocumentsProvider { return "application/octet-stream"; } - /** - * Remove file extension from name, but only if exact MIME type mapping - * exists. This means we can reapply the extension later. - */ - private static String removeExtension(String mimeType, String name) { - final int lastDot = name.lastIndexOf('.'); - if (lastDot >= 0) { - final String extension = name.substring(lastDot + 1).toLowerCase(); - final String nameMime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (mimeType.equals(nameMime)) { - return name.substring(0, lastDot); - } - } - return name; - } - - /** - * Add file extension to name, but only if exact MIME type mapping exists. - */ - private static String addExtension(String mimeType, String name) { - final String extension = MimeTypeMap.getSingleton() - .getExtensionFromMimeType(mimeType); - if (extension != null) { - return name + "." + extension; - } - return name; - } - private void startObserving(File file, Uri notifyUri) { synchronized (mObservers) { DirectoryObserver observer = mObservers.get(file); |