Skip to content

Commit 1a3ece9

Browse files
Mike LockwoodAndroid (Google) Code Review
authored andcommitted
Merge "MTP: Add support for restricting PTP to only certain subdirectories of the storage DO NOT MERGE" into ics-mr1
2 parents 7f87d9c + 7944c1b commit 1a3ece9

File tree

2 files changed

+157
-42
lines changed

2 files changed

+157
-42
lines changed

media/java/android/mtp/MtpDatabase.java

Lines changed: 150 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,15 @@ public class MtpDatabase {
5151
private final IContentProvider mMediaProvider;
5252
private final String mVolumeName;
5353
private final Uri mObjectsUri;
54-
private final String mMediaStoragePath; // path to primary storage
54+
// path to primary storage
55+
private final String mMediaStoragePath;
56+
// if not null, restrict all queries to these subdirectories
57+
private final String[] mSubDirectories;
58+
// where clause for restricting queries to files in mSubDirectories
59+
private String mSubDirectoriesWhere;
60+
// where arguments for restricting queries to files in mSubDirectories
61+
private String[] mSubDirectoriesWhereArgs;
62+
5563
private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>();
5664

5765
// cached property groups for single properties
@@ -112,7 +120,8 @@ public class MtpDatabase {
112120
System.loadLibrary("media_jni");
113121
}
114122

115-
public MtpDatabase(Context context, String volumeName, String storagePath) {
123+
public MtpDatabase(Context context, String volumeName, String storagePath,
124+
String[] subDirectories) {
116125
native_setup();
117126

118127
mContext = context;
@@ -122,6 +131,31 @@ public MtpDatabase(Context context, String volumeName, String storagePath) {
122131
mObjectsUri = Files.getMtpObjectsUri(volumeName);
123132
mMediaScanner = new MediaScanner(context);
124133

134+
mSubDirectories = subDirectories;
135+
if (subDirectories != null) {
136+
// Compute "where" string for restricting queries to subdirectories
137+
StringBuilder builder = new StringBuilder();
138+
builder.append("(");
139+
int count = subDirectories.length;
140+
for (int i = 0; i < count; i++) {
141+
builder.append(Files.FileColumns.DATA + "=? OR "
142+
+ Files.FileColumns.DATA + " LIKE ?");
143+
if (i != count - 1) {
144+
builder.append(" OR ");
145+
}
146+
}
147+
builder.append(")");
148+
mSubDirectoriesWhere = builder.toString();
149+
150+
// Compute "where" arguments for restricting queries to subdirectories
151+
mSubDirectoriesWhereArgs = new String[count * 2];
152+
for (int i = 0, j = 0; i < count; i++) {
153+
String path = subDirectories[i];
154+
mSubDirectoriesWhereArgs[j++] = path;
155+
mSubDirectoriesWhereArgs[j++] = path + "/%";
156+
}
157+
}
158+
125159
// Set locale to MediaScanner.
126160
Locale locale = context.getResources().getConfiguration().locale;
127161
if (locale != null) {
@@ -190,9 +224,44 @@ private void initDeviceProperties(Context context) {
190224
}
191225
}
192226

227+
// check to see if the path is contained in one of our storage subdirectories
228+
// returns true if we have no special subdirectories
229+
private boolean inStorageSubDirectory(String path) {
230+
if (mSubDirectories == null) return true;
231+
if (path == null) return false;
232+
233+
boolean allowed = false;
234+
int pathLength = path.length();
235+
for (int i = 0; i < mSubDirectories.length && !allowed; i++) {
236+
String subdir = mSubDirectories[i];
237+
int subdirLength = subdir.length();
238+
if (subdirLength < pathLength &&
239+
path.charAt(subdirLength) == '/' &&
240+
path.startsWith(subdir)) {
241+
allowed = true;
242+
}
243+
}
244+
return allowed;
245+
}
246+
247+
// check to see if the path matches one of our storage subdirectories
248+
// returns true if we have no special subdirectories
249+
private boolean isStorageSubDirectory(String path) {
250+
if (mSubDirectories == null) return false;
251+
for (int i = 0; i < mSubDirectories.length; i++) {
252+
if (path.equals(mSubDirectories[i])) {
253+
return true;
254+
}
255+
}
256+
return false;
257+
}
258+
193259
private int beginSendObject(String path, int format, int parent,
194260
int storageId, long size, long modified) {
195-
// first make sure the object does not exist
261+
// if mSubDirectories is not null, do not allow copying files to any other locations
262+
if (!inStorageSubDirectory(path)) return -1;
263+
264+
// make sure the object does not exist
196265
if (path != null) {
197266
Cursor c = null;
198267
try {
@@ -269,69 +338,102 @@ private void endSendObject(String path, int handle, int format, boolean succeede
269338
}
270339

271340
private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException {
341+
String where;
342+
String[] whereArgs;
343+
272344
if (storageID == 0xFFFFFFFF) {
273345
// query all stores
274346
if (format == 0) {
275347
// query all formats
276348
if (parent == 0) {
277349
// query all objects
278-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null);
279-
}
280-
if (parent == 0xFFFFFFFF) {
281-
// all objects in root of store
282-
parent = 0;
350+
where = null;
351+
whereArgs = null;
352+
} else {
353+
if (parent == 0xFFFFFFFF) {
354+
// all objects in root of store
355+
parent = 0;
356+
}
357+
where = PARENT_WHERE;
358+
whereArgs = new String[] { Integer.toString(parent) };
283359
}
284-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE,
285-
new String[] { Integer.toString(parent) }, null);
286360
} else {
287361
// query specific format
288362
if (parent == 0) {
289363
// query all objects
290-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE,
291-
new String[] { Integer.toString(format) }, null);
292-
}
293-
if (parent == 0xFFFFFFFF) {
294-
// all objects in root of store
295-
parent = 0;
364+
where = FORMAT_WHERE;
365+
whereArgs = new String[] { Integer.toString(format) };
366+
} else {
367+
if (parent == 0xFFFFFFFF) {
368+
// all objects in root of store
369+
parent = 0;
370+
}
371+
where = FORMAT_PARENT_WHERE;
372+
whereArgs = new String[] { Integer.toString(format),
373+
Integer.toString(parent) };
296374
}
297-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE,
298-
new String[] { Integer.toString(format), Integer.toString(parent) }, null);
299375
}
300376
} else {
301377
// query specific store
302378
if (format == 0) {
303379
// query all formats
304380
if (parent == 0) {
305381
// query all objects
306-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE,
307-
new String[] { Integer.toString(storageID) }, null);
308-
}
309-
if (parent == 0xFFFFFFFF) {
310-
// all objects in root of store
311-
parent = 0;
382+
where = STORAGE_WHERE;
383+
whereArgs = new String[] { Integer.toString(storageID) };
384+
} else {
385+
if (parent == 0xFFFFFFFF) {
386+
// all objects in root of store
387+
parent = 0;
388+
}
389+
where = STORAGE_PARENT_WHERE;
390+
whereArgs = new String[] { Integer.toString(storageID),
391+
Integer.toString(parent) };
312392
}
313-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE,
314-
new String[] { Integer.toString(storageID), Integer.toString(parent) },
315-
null);
316393
} else {
317394
// query specific format
318395
if (parent == 0) {
319396
// query all objects
320-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE,
321-
new String[] { Integer.toString(storageID), Integer.toString(format) },
322-
null);
397+
where = STORAGE_FORMAT_WHERE;
398+
whereArgs = new String[] { Integer.toString(storageID),
399+
Integer.toString(format) };
400+
} else {
401+
if (parent == 0xFFFFFFFF) {
402+
// all objects in root of store
403+
parent = 0;
404+
}
405+
where = STORAGE_FORMAT_PARENT_WHERE;
406+
whereArgs = new String[] { Integer.toString(storageID),
407+
Integer.toString(format),
408+
Integer.toString(parent) };
323409
}
324-
if (parent == 0xFFFFFFFF) {
325-
// all objects in root of store
326-
parent = 0;
410+
}
411+
}
412+
413+
// if we are restricting queries to mSubDirectories, we need to add the restriction
414+
// onto our "where" arguments
415+
if (mSubDirectoriesWhere != null) {
416+
if (where == null) {
417+
where = mSubDirectoriesWhere;
418+
whereArgs = mSubDirectoriesWhereArgs;
419+
} else {
420+
where = where + " AND " + mSubDirectoriesWhere;
421+
422+
// create new array to hold whereArgs and mSubDirectoriesWhereArgs
423+
String[] newWhereArgs =
424+
new String[whereArgs.length + mSubDirectoriesWhereArgs.length];
425+
int i, j;
426+
for (i = 0; i < whereArgs.length; i++) {
427+
newWhereArgs[i] = whereArgs[i];
327428
}
328-
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE,
329-
new String[] { Integer.toString(storageID),
330-
Integer.toString(format),
331-
Integer.toString(parent) },
332-
null);
429+
for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) {
430+
newWhereArgs[i] = mSubDirectoriesWhereArgs[j];
431+
}
432+
whereArgs = newWhereArgs;
333433
}
334434
}
435+
436+
return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null);
335437
}
336438

337439
private int[] getObjectList(int storageID, int format, int parent) {
@@ -613,6 +715,11 @@ private int renameFile(int handle, String newName) {
613715
return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
614716
}
615717

718+
// do not allow renaming any of the special subdirectories
719+
if (isStorageSubDirectory(path)) {
720+
return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
721+
}
722+
616723
// now rename the file. make sure this succeeds before updating database
617724
File oldFile = new File(path);
618725
int lastSlash = path.lastIndexOf('/');
@@ -794,6 +901,11 @@ private int deleteFile(int handle) {
794901
return MtpConstants.RESPONSE_GENERAL_ERROR;
795902
}
796903

904+
// do not allow deleting any of the special subdirectories
905+
if (isStorageSubDirectory(path)) {
906+
return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
907+
}
908+
797909
if (format == MtpConstants.FORMAT_ASSOCIATION) {
798910
// recursive case - delete all children first
799911
Uri uri = Files.getMtpObjectsUri(mVolumeName);

media/mtp/MtpServer.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,11 +1053,14 @@ MtpResponseCode MtpServer::doDeleteObject() {
10531053
int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
10541054
if (result == MTP_RESPONSE_OK) {
10551055
LOGV("deleting %s", (const char *)filePath);
1056-
deletePath((const char *)filePath);
1057-
return mDatabase->deleteFile(handle);
1058-
} else {
1059-
return result;
1056+
result = mDatabase->deleteFile(handle);
1057+
// Don't delete the actual files unless the database deletion is allowed
1058+
if (result == MTP_RESPONSE_OK) {
1059+
deletePath((const char *)filePath);
1060+
}
10601061
}
1062+
1063+
return result;
10611064
}
10621065

10631066
MtpResponseCode MtpServer::doGetObjectPropDesc() {

0 commit comments

Comments
 (0)