Loading media/java/android/mtp/MtpDatabase.java +150 −38 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,15 @@ public class MtpDatabase { private final IContentProvider mMediaProvider; private final IContentProvider mMediaProvider; private final String mVolumeName; private final String mVolumeName; private final Uri mObjectsUri; private final Uri mObjectsUri; private final String mMediaStoragePath; // path to primary storage // path to primary storage private final String mMediaStoragePath; // if not null, restrict all queries to these subdirectories private final String[] mSubDirectories; // where clause for restricting queries to files in mSubDirectories private String mSubDirectoriesWhere; // where arguments for restricting queries to files in mSubDirectories private String[] mSubDirectoriesWhereArgs; private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); // cached property groups for single properties // cached property groups for single properties Loading Loading @@ -112,7 +120,8 @@ public class MtpDatabase { System.loadLibrary("media_jni"); System.loadLibrary("media_jni"); } } public MtpDatabase(Context context, String volumeName, String storagePath) { public MtpDatabase(Context context, String volumeName, String storagePath, String[] subDirectories) { native_setup(); native_setup(); mContext = context; mContext = context; Loading @@ -122,6 +131,31 @@ public class MtpDatabase { mObjectsUri = Files.getMtpObjectsUri(volumeName); mObjectsUri = Files.getMtpObjectsUri(volumeName); mMediaScanner = new MediaScanner(context); mMediaScanner = new MediaScanner(context); mSubDirectories = subDirectories; if (subDirectories != null) { // Compute "where" string for restricting queries to subdirectories StringBuilder builder = new StringBuilder(); builder.append("("); int count = subDirectories.length; for (int i = 0; i < count; i++) { builder.append(Files.FileColumns.DATA + "=? OR " + Files.FileColumns.DATA + " LIKE ?"); if (i != count - 1) { builder.append(" OR "); } } builder.append(")"); mSubDirectoriesWhere = builder.toString(); // Compute "where" arguments for restricting queries to subdirectories mSubDirectoriesWhereArgs = new String[count * 2]; for (int i = 0, j = 0; i < count; i++) { String path = subDirectories[i]; mSubDirectoriesWhereArgs[j++] = path; mSubDirectoriesWhereArgs[j++] = path + "/%"; } } // Set locale to MediaScanner. // Set locale to MediaScanner. Locale locale = context.getResources().getConfiguration().locale; Locale locale = context.getResources().getConfiguration().locale; if (locale != null) { if (locale != null) { Loading Loading @@ -190,9 +224,44 @@ public class MtpDatabase { } } } } // check to see if the path is contained in one of our storage subdirectories // returns true if we have no special subdirectories private boolean inStorageSubDirectory(String path) { if (mSubDirectories == null) return true; if (path == null) return false; boolean allowed = false; int pathLength = path.length(); for (int i = 0; i < mSubDirectories.length && !allowed; i++) { String subdir = mSubDirectories[i]; int subdirLength = subdir.length(); if (subdirLength < pathLength && path.charAt(subdirLength) == '/' && path.startsWith(subdir)) { allowed = true; } } return allowed; } // check to see if the path matches one of our storage subdirectories // returns true if we have no special subdirectories private boolean isStorageSubDirectory(String path) { if (mSubDirectories == null) return false; for (int i = 0; i < mSubDirectories.length; i++) { if (path.equals(mSubDirectories[i])) { return true; } } return false; } private int beginSendObject(String path, int format, int parent, private int beginSendObject(String path, int format, int parent, int storageId, long size, long modified) { int storageId, long size, long modified) { // first make sure the object does not exist // if mSubDirectories is not null, do not allow copying files to any other locations if (!inStorageSubDirectory(path)) return -1; // make sure the object does not exist if (path != null) { if (path != null) { Cursor c = null; Cursor c = null; try { try { Loading Loading @@ -269,33 +338,40 @@ public class MtpDatabase { } } private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { String where; String[] whereArgs; if (storageID == 0xFFFFFFFF) { if (storageID == 0xFFFFFFFF) { // query all stores // query all stores if (format == 0) { if (format == 0) { // query all formats // query all formats if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null); where = null; } whereArgs = null; } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE, where = PARENT_WHERE; new String[] { Integer.toString(parent) }, null); whereArgs = new String[] { Integer.toString(parent) }; } } else { } else { // query specific format // query specific format if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE, where = FORMAT_WHERE; new String[] { Integer.toString(format) }, null); whereArgs = new String[] { Integer.toString(format) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE, where = FORMAT_PARENT_WHERE; new String[] { Integer.toString(format), Integer.toString(parent) }, null); whereArgs = new String[] { Integer.toString(format), Integer.toString(parent) }; } } } } else { } else { // query specific store // query specific store Loading @@ -303,37 +379,63 @@ public class MtpDatabase { // query all formats // query all formats if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE, where = STORAGE_WHERE; new String[] { Integer.toString(storageID) }, null); whereArgs = new String[] { Integer.toString(storageID) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE, where = STORAGE_PARENT_WHERE; new String[] { Integer.toString(storageID), Integer.toString(parent) }, whereArgs = new String[] { Integer.toString(storageID), null); Integer.toString(parent) }; } } else { } else { // query specific format // query specific format if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE, where = STORAGE_FORMAT_WHERE; new String[] { Integer.toString(storageID), Integer.toString(format) }, whereArgs = new String[] { Integer.toString(storageID), null); Integer.toString(format) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE, where = STORAGE_FORMAT_PARENT_WHERE; new String[] { Integer.toString(storageID), whereArgs = new String[] { Integer.toString(storageID), Integer.toString(format), Integer.toString(format), Integer.toString(parent) }, Integer.toString(parent) }; null); } } } } // if we are restricting queries to mSubDirectories, we need to add the restriction // onto our "where" arguments if (mSubDirectoriesWhere != null) { if (where == null) { where = mSubDirectoriesWhere; whereArgs = mSubDirectoriesWhereArgs; } else { where = where + " AND " + mSubDirectoriesWhere; // create new array to hold whereArgs and mSubDirectoriesWhereArgs String[] newWhereArgs = new String[whereArgs.length + mSubDirectoriesWhereArgs.length]; int i, j; for (i = 0; i < whereArgs.length; i++) { newWhereArgs[i] = whereArgs[i]; } for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) { newWhereArgs[i] = mSubDirectoriesWhereArgs[j]; } whereArgs = newWhereArgs; } } } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null); } private int[] getObjectList(int storageID, int format, int parent) { private int[] getObjectList(int storageID, int format, int parent) { Cursor c = null; Cursor c = null; try { try { Loading Loading @@ -613,6 +715,11 @@ public class MtpDatabase { return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; } } // do not allow renaming any of the special subdirectories if (isStorageSubDirectory(path)) { return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; } // now rename the file. make sure this succeeds before updating database // now rename the file. make sure this succeeds before updating database File oldFile = new File(path); File oldFile = new File(path); int lastSlash = path.lastIndexOf('/'); int lastSlash = path.lastIndexOf('/'); Loading Loading @@ -794,6 +901,11 @@ public class MtpDatabase { return MtpConstants.RESPONSE_GENERAL_ERROR; return MtpConstants.RESPONSE_GENERAL_ERROR; } } // do not allow deleting any of the special subdirectories if (isStorageSubDirectory(path)) { return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; } if (format == MtpConstants.FORMAT_ASSOCIATION) { if (format == MtpConstants.FORMAT_ASSOCIATION) { // recursive case - delete all children first // recursive case - delete all children first Uri uri = Files.getMtpObjectsUri(mVolumeName); Uri uri = Files.getMtpObjectsUri(mVolumeName); Loading media/mtp/MtpServer.cpp +7 −4 Original line number Original line Diff line number Diff line Loading @@ -1053,13 +1053,16 @@ MtpResponseCode MtpServer::doDeleteObject() { int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); if (result == MTP_RESPONSE_OK) { if (result == MTP_RESPONSE_OK) { LOGV("deleting %s", (const char *)filePath); LOGV("deleting %s", (const char *)filePath); result = mDatabase->deleteFile(handle); // Don't delete the actual files unless the database deletion is allowed if (result == MTP_RESPONSE_OK) { deletePath((const char *)filePath); deletePath((const char *)filePath); return mDatabase->deleteFile(handle); } else { return result; } } } } return result; } MtpResponseCode MtpServer::doGetObjectPropDesc() { MtpResponseCode MtpServer::doGetObjectPropDesc() { MtpObjectProperty propCode = mRequest.getParameter(1); MtpObjectProperty propCode = mRequest.getParameter(1); MtpObjectFormat format = mRequest.getParameter(2); MtpObjectFormat format = mRequest.getParameter(2); Loading Loading
media/java/android/mtp/MtpDatabase.java +150 −38 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,15 @@ public class MtpDatabase { private final IContentProvider mMediaProvider; private final IContentProvider mMediaProvider; private final String mVolumeName; private final String mVolumeName; private final Uri mObjectsUri; private final Uri mObjectsUri; private final String mMediaStoragePath; // path to primary storage // path to primary storage private final String mMediaStoragePath; // if not null, restrict all queries to these subdirectories private final String[] mSubDirectories; // where clause for restricting queries to files in mSubDirectories private String mSubDirectoriesWhere; // where arguments for restricting queries to files in mSubDirectories private String[] mSubDirectoriesWhereArgs; private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); // cached property groups for single properties // cached property groups for single properties Loading Loading @@ -112,7 +120,8 @@ public class MtpDatabase { System.loadLibrary("media_jni"); System.loadLibrary("media_jni"); } } public MtpDatabase(Context context, String volumeName, String storagePath) { public MtpDatabase(Context context, String volumeName, String storagePath, String[] subDirectories) { native_setup(); native_setup(); mContext = context; mContext = context; Loading @@ -122,6 +131,31 @@ public class MtpDatabase { mObjectsUri = Files.getMtpObjectsUri(volumeName); mObjectsUri = Files.getMtpObjectsUri(volumeName); mMediaScanner = new MediaScanner(context); mMediaScanner = new MediaScanner(context); mSubDirectories = subDirectories; if (subDirectories != null) { // Compute "where" string for restricting queries to subdirectories StringBuilder builder = new StringBuilder(); builder.append("("); int count = subDirectories.length; for (int i = 0; i < count; i++) { builder.append(Files.FileColumns.DATA + "=? OR " + Files.FileColumns.DATA + " LIKE ?"); if (i != count - 1) { builder.append(" OR "); } } builder.append(")"); mSubDirectoriesWhere = builder.toString(); // Compute "where" arguments for restricting queries to subdirectories mSubDirectoriesWhereArgs = new String[count * 2]; for (int i = 0, j = 0; i < count; i++) { String path = subDirectories[i]; mSubDirectoriesWhereArgs[j++] = path; mSubDirectoriesWhereArgs[j++] = path + "/%"; } } // Set locale to MediaScanner. // Set locale to MediaScanner. Locale locale = context.getResources().getConfiguration().locale; Locale locale = context.getResources().getConfiguration().locale; if (locale != null) { if (locale != null) { Loading Loading @@ -190,9 +224,44 @@ public class MtpDatabase { } } } } // check to see if the path is contained in one of our storage subdirectories // returns true if we have no special subdirectories private boolean inStorageSubDirectory(String path) { if (mSubDirectories == null) return true; if (path == null) return false; boolean allowed = false; int pathLength = path.length(); for (int i = 0; i < mSubDirectories.length && !allowed; i++) { String subdir = mSubDirectories[i]; int subdirLength = subdir.length(); if (subdirLength < pathLength && path.charAt(subdirLength) == '/' && path.startsWith(subdir)) { allowed = true; } } return allowed; } // check to see if the path matches one of our storage subdirectories // returns true if we have no special subdirectories private boolean isStorageSubDirectory(String path) { if (mSubDirectories == null) return false; for (int i = 0; i < mSubDirectories.length; i++) { if (path.equals(mSubDirectories[i])) { return true; } } return false; } private int beginSendObject(String path, int format, int parent, private int beginSendObject(String path, int format, int parent, int storageId, long size, long modified) { int storageId, long size, long modified) { // first make sure the object does not exist // if mSubDirectories is not null, do not allow copying files to any other locations if (!inStorageSubDirectory(path)) return -1; // make sure the object does not exist if (path != null) { if (path != null) { Cursor c = null; Cursor c = null; try { try { Loading Loading @@ -269,33 +338,40 @@ public class MtpDatabase { } } private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { String where; String[] whereArgs; if (storageID == 0xFFFFFFFF) { if (storageID == 0xFFFFFFFF) { // query all stores // query all stores if (format == 0) { if (format == 0) { // query all formats // query all formats if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null); where = null; } whereArgs = null; } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE, where = PARENT_WHERE; new String[] { Integer.toString(parent) }, null); whereArgs = new String[] { Integer.toString(parent) }; } } else { } else { // query specific format // query specific format if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE, where = FORMAT_WHERE; new String[] { Integer.toString(format) }, null); whereArgs = new String[] { Integer.toString(format) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE, where = FORMAT_PARENT_WHERE; new String[] { Integer.toString(format), Integer.toString(parent) }, null); whereArgs = new String[] { Integer.toString(format), Integer.toString(parent) }; } } } } else { } else { // query specific store // query specific store Loading @@ -303,37 +379,63 @@ public class MtpDatabase { // query all formats // query all formats if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE, where = STORAGE_WHERE; new String[] { Integer.toString(storageID) }, null); whereArgs = new String[] { Integer.toString(storageID) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE, where = STORAGE_PARENT_WHERE; new String[] { Integer.toString(storageID), Integer.toString(parent) }, whereArgs = new String[] { Integer.toString(storageID), null); Integer.toString(parent) }; } } else { } else { // query specific format // query specific format if (parent == 0) { if (parent == 0) { // query all objects // query all objects return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE, where = STORAGE_FORMAT_WHERE; new String[] { Integer.toString(storageID), Integer.toString(format) }, whereArgs = new String[] { Integer.toString(storageID), null); Integer.toString(format) }; } } else { if (parent == 0xFFFFFFFF) { if (parent == 0xFFFFFFFF) { // all objects in root of store // all objects in root of store parent = 0; parent = 0; } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE, where = STORAGE_FORMAT_PARENT_WHERE; new String[] { Integer.toString(storageID), whereArgs = new String[] { Integer.toString(storageID), Integer.toString(format), Integer.toString(format), Integer.toString(parent) }, Integer.toString(parent) }; null); } } } } // if we are restricting queries to mSubDirectories, we need to add the restriction // onto our "where" arguments if (mSubDirectoriesWhere != null) { if (where == null) { where = mSubDirectoriesWhere; whereArgs = mSubDirectoriesWhereArgs; } else { where = where + " AND " + mSubDirectoriesWhere; // create new array to hold whereArgs and mSubDirectoriesWhereArgs String[] newWhereArgs = new String[whereArgs.length + mSubDirectoriesWhereArgs.length]; int i, j; for (i = 0; i < whereArgs.length; i++) { newWhereArgs[i] = whereArgs[i]; } for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) { newWhereArgs[i] = mSubDirectoriesWhereArgs[j]; } whereArgs = newWhereArgs; } } } } return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null); } private int[] getObjectList(int storageID, int format, int parent) { private int[] getObjectList(int storageID, int format, int parent) { Cursor c = null; Cursor c = null; try { try { Loading Loading @@ -613,6 +715,11 @@ public class MtpDatabase { return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; } } // do not allow renaming any of the special subdirectories if (isStorageSubDirectory(path)) { return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; } // now rename the file. make sure this succeeds before updating database // now rename the file. make sure this succeeds before updating database File oldFile = new File(path); File oldFile = new File(path); int lastSlash = path.lastIndexOf('/'); int lastSlash = path.lastIndexOf('/'); Loading Loading @@ -794,6 +901,11 @@ public class MtpDatabase { return MtpConstants.RESPONSE_GENERAL_ERROR; return MtpConstants.RESPONSE_GENERAL_ERROR; } } // do not allow deleting any of the special subdirectories if (isStorageSubDirectory(path)) { return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; } if (format == MtpConstants.FORMAT_ASSOCIATION) { if (format == MtpConstants.FORMAT_ASSOCIATION) { // recursive case - delete all children first // recursive case - delete all children first Uri uri = Files.getMtpObjectsUri(mVolumeName); Uri uri = Files.getMtpObjectsUri(mVolumeName); Loading
media/mtp/MtpServer.cpp +7 −4 Original line number Original line Diff line number Diff line Loading @@ -1053,13 +1053,16 @@ MtpResponseCode MtpServer::doDeleteObject() { int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); if (result == MTP_RESPONSE_OK) { if (result == MTP_RESPONSE_OK) { LOGV("deleting %s", (const char *)filePath); LOGV("deleting %s", (const char *)filePath); result = mDatabase->deleteFile(handle); // Don't delete the actual files unless the database deletion is allowed if (result == MTP_RESPONSE_OK) { deletePath((const char *)filePath); deletePath((const char *)filePath); return mDatabase->deleteFile(handle); } else { return result; } } } } return result; } MtpResponseCode MtpServer::doGetObjectPropDesc() { MtpResponseCode MtpServer::doGetObjectPropDesc() { MtpObjectProperty propCode = mRequest.getParameter(1); MtpObjectProperty propCode = mRequest.getParameter(1); MtpObjectFormat format = mRequest.getParameter(2); MtpObjectFormat format = mRequest.getParameter(2); Loading