30 private static String PATH_PRIVATE = "private"; |
33 private static String PATH_PRIVATE = "private"; |
31 private static String PATH_SYSTEM = "system"; |
34 private static String PATH_SYSTEM = "system"; |
32 private static String[] iRestrictedPathList; |
35 private static String[] iRestrictedPathList; |
33 private static String[] iForbiddenPathList; |
36 private static String[] iForbiddenPathList; |
34 |
37 |
35 static |
38 // getMidpRoot get the midp private directory such as "/private/102033E6" |
36 { |
39 private static String iMidpRoot = FileSystemUtils.getMidpRoot().toLowerCase(); |
37 // Populate forbidden path list. |
|
38 Vector forbidden = FileSystemUtils.getForbiddenPaths(); |
|
39 iForbiddenPathList = new String[forbidden.size()]; |
|
40 for (int index = 0; index < forbidden.size(); index++) |
|
41 { |
|
42 iForbiddenPathList[index] = (String) forbidden.elementAt(index); |
|
43 } |
|
44 |
|
45 // Populate restricted path list. |
|
46 Vector restricted = FileSystemUtils.getRestrictedPaths(); |
|
47 iRestrictedPathList = new String[restricted.size() + 1]; |
|
48 for (int index = 0; index < restricted.size(); index++) |
|
49 { |
|
50 iRestrictedPathList[index] = (String) restricted.elementAt(index); |
|
51 } |
|
52 // Add midlet's private directory also to restricted path list. |
|
53 iRestrictedPathList[restricted.size()] = FileSystemUtils |
|
54 .getAppPrivateDir(); |
|
55 } |
|
56 |
40 |
57 /** |
41 /** |
58 * Checks to see if the application has access to a specific path. |
42 * Checks to see if the application has access to a specific path. |
59 * |
43 * |
60 * @param aPath |
44 * @param aPath |
61 * path which the application is trying to access. |
45 * path which the application is trying to access. |
62 * @param aIntent |
|
63 * mode in which the application wants to access the target. |
|
64 * @param aDomain |
46 * @param aDomain |
65 * domain of the application |
47 * domain of the application |
66 * @param aIsOpening |
48 * @param aIsOpening |
67 * if the operation being performed is equivalent to opening a |
49 * if the operation being performed is equivalent to opening a |
68 * connection. |
50 * connection. |
69 * @return true in case access is allowed. False otherwise |
51 * @return true in case access is allowed. False otherwise |
70 */ |
52 */ |
71 public static boolean accessAllowed(String aPath, String aIntent, |
53 public static boolean accessAllowed(String aPath, String aDomain) |
72 String aDomain, boolean aIsOpening) |
|
73 { |
54 { |
74 FileLogger.Log("FileAccessHelper.accessAllowed: Checking access: \n"); |
55 FileLogger.Log("FileAccessHelper.accessAllowed: Checking access: \n"); |
|
56 |
|
57 if(aPath.endsWith("/") == false) |
|
58 aPath += "/"; |
75 |
59 |
76 if (isHomeDir(aPath)) |
60 if (isHomeDir(aPath)) |
77 { |
61 { |
78 return true; |
62 return true; |
79 } |
63 } |
80 |
64 |
81 if (isForbidden(aPath)) |
65 // The basic assumption for this check is |
|
66 // always drive name is a single character. |
|
67 if (aPath.substring(2).toLowerCase().startsWith(iMidpRoot)) |
82 { |
68 { |
83 return false; |
69 // Allowed only for Manufacturer domain. |
84 } |
70 if (aDomain.equals(ApplicationInfo.MANUFACTURER_DOMAIN) == false) |
85 |
|
86 if (isIllegalAccessToRestrictedDir(aPath, aIntent, aIsOpening, aDomain)) |
|
87 { |
|
88 return false; |
|
89 } |
|
90 |
|
91 if (aDomain.equals(ApplicationInfo.MANUFACTURER_DOMAIN)) |
|
92 { |
|
93 return manufacturerDomainChecks(aPath, aIntent, aIsOpening); |
|
94 } |
|
95 else |
|
96 { |
|
97 return otherDomainChecks(aPath, aIntent, aIsOpening); |
|
98 } |
|
99 } |
|
100 |
|
101 /** |
|
102 * To be used in case of list. If list is done on a directory that is equal |
|
103 * to, or higher in path hierarchy than one of the restricted paths, then we |
|
104 * need to check for access for all files, if not, then no need. |
|
105 */ |
|
106 public static boolean isDirRestricted(String aPath) |
|
107 { |
|
108 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
109 { |
|
110 int matchResult = matchPaths(aPath, iRestrictedPathList[index]); |
|
111 if ((matchResult != PATHS_NO_MATCH) |
|
112 && (matchResult != PATH_BELOWIN_HIERARCHY)) |
|
113 { |
|
114 return true; |
|
115 } |
|
116 } |
|
117 return false; |
|
118 } |
|
119 |
|
120 /** |
|
121 * Checks to see if the path being accessed in forbidden. |
|
122 * |
|
123 * @param aPath |
|
124 * path being accessed |
|
125 * @return true in case the path is forbidden, false otherwise |
|
126 */ |
|
127 private static boolean isForbidden(String aPath) |
|
128 { |
|
129 for (int index = 0; index < iForbiddenPathList.length; index++) |
|
130 { |
|
131 int matchPathResult = matchPaths(aPath, iForbiddenPathList[index]); |
|
132 |
|
133 // Forbidden paths should match exactly or should be such that the |
|
134 // path must be lower in hierarchy. |
|
135 // Example: e:/system is forbidden, e:/ is not. |
|
136 // e:/system is forbidden, e:/system/dir is also forbidden |
|
137 if ((matchPathResult == PATHS_EQUAL) |
|
138 || (matchPathResult == PATH_BELOWIN_HIERARCHY)) |
|
139 { |
|
140 return true; |
|
141 } |
|
142 } |
|
143 return false; |
|
144 } |
|
145 |
|
146 /** |
|
147 * Checks if the access to restricted paths is being made in correct intent |
|
148 * based on the domain. |
|
149 * |
|
150 * @param aPath |
|
151 * path of the file/directory being accessed |
|
152 * @param aIntent |
|
153 * intent with which it is being accessed (read or write) |
|
154 * @param aOpening |
|
155 * set to true in case it is being used by Connector.open or |
|
156 * setFileConnection. Both are considered as open and not as |
|
157 * acutal read or write operations. |
|
158 * @param aDomain |
|
159 * domain of the application. |
|
160 * @return true in case there is an access violation, false if the access is |
|
161 * allowed. |
|
162 */ |
|
163 public static boolean isIllegalAccessToRestrictedDir(String aPath, |
|
164 String aIntent, boolean aOpening, String aDomain) |
|
165 { |
|
166 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
167 { |
|
168 int matchResult = matchPaths(aPath, iRestrictedPathList[index]); |
|
169 if ((matchResult != PATHS_NO_MATCH) |
|
170 && (matchResult != PATH_BELOWIN_HIERARCHY)) |
|
171 { |
|
172 if (aIntent.equals(INTENT_WRITE) |
|
173 || aIntent.equals(INTENT_READ_WRITE)) |
|
174 { |
|
175 if (!aOpening) |
|
176 { |
|
177 return true; |
|
178 } |
|
179 } |
|
180 } |
|
181 } |
|
182 return false; |
|
183 } |
|
184 |
|
185 /** |
|
186 * Performs manufacturer domain specific checks. Manufacturer domain apps |
|
187 * are not allowed to access any path in C:/private apart from its private |
|
188 * directory. Other checks are forbidden directories and restricted paths. |
|
189 * This is done before (accessAllowed()) So, no need to check once again. |
|
190 * |
|
191 * @param aPath |
|
192 * path which is being accessed |
|
193 * @param aIntent |
|
194 * intent with which access is being made. read, write |
|
195 * @param aIsOpening |
|
196 * true in case its an open operation (open, setFileConnection) |
|
197 * @return true in case access is allowed. false otherwise. |
|
198 */ |
|
199 public static boolean manufacturerDomainChecks(String aPath, |
|
200 String aIntent, boolean aIsOpening) |
|
201 { |
|
202 // Check if it is private directory. |
|
203 if (aPath.indexOf(PATH_PRIVATE) == 3) |
|
204 { |
|
205 if (matchPaths(aPath, FileSystemUtils.getAppPrivateDir()) == PATHS_NO_MATCH) |
|
206 { |
71 { |
207 return false; |
72 return false; |
208 } |
73 } |
209 } |
74 |
210 return true; |
|
211 } |
|
212 |
|
213 /** |
|
214 * Performs domains other than manufacturer domain. |
|
215 * |
|
216 * @param aPath |
|
217 * path which is being accessed |
|
218 * @param aIntent |
|
219 * intent with which access is being made. read, write |
|
220 * @param aIsOpening |
|
221 * true in case its an open operation (open, setFileConnection) |
|
222 * @return true in case access is allowed. false otherwise. |
|
223 */ |
|
224 private static boolean otherDomainChecks(String aPath, String aIntent, |
|
225 boolean aIsOpening) |
|
226 { |
|
227 if (aPath.length() < 3) |
|
228 { |
|
229 // Path will be valid. This will be only in case file:///c: is given |
|
230 aPath += "/"; |
|
231 } |
|
232 |
|
233 String rom = FileSystemUtils.getRomDrive().toLowerCase() |
|
234 .substring(0, 2); |
|
235 String temp = FileSystemUtils.getTemporaryDrive().toLowerCase() |
|
236 .substring(0, 2); |
|
237 |
|
238 if (aPath.toLowerCase().startsWith(rom) |
|
239 || aPath.toLowerCase().startsWith(temp)) |
|
240 { |
|
241 return false; |
|
242 } |
|
243 |
|
244 // Other domains can access only below restricted paths or |
|
245 // in other drives. |
|
246 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
247 { |
|
248 int matchResult = matchPaths(aPath, iRestrictedPathList[index]); |
|
249 |
|
250 if ((matchResult != PATH_BELOWIN_HIERARCHY) |
|
251 && (matchResult != PATHS_NO_MATCH)) |
|
252 { |
|
253 if ((!aIntent.equals(INTENT_READ)) && (!aIsOpening)) |
|
254 { |
|
255 // Anything other than read operation on par or above |
|
256 // restricted path hierarchy is not allowed when not opening |
|
257 return false; |
|
258 } |
|
259 } |
|
260 } |
|
261 |
|
262 if (partialMatchWithRestrictedPaths(aPath)) |
|
263 { |
|
264 return false; |
|
265 } |
75 } |
266 |
76 |
267 return true; |
77 return true; |
268 } |
|
269 |
|
270 private static boolean partialMatchWithRestrictedPaths(String aPath) |
|
271 { |
|
272 String path1 = aPath; |
|
273 boolean initialNoMatch = true; |
|
274 |
|
275 // Partial match is only when path is not a substring initially, |
|
276 // but when stripped, becomes a substring of one of the restricted paths |
|
277 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
278 { |
|
279 int matchResult = matchPaths(aPath, iRestrictedPathList[index]); |
|
280 if (matchResult == PATH_BELOWIN_HIERARCHY |
|
281 || matchResult == PATH_ABOVEIN_HIERARCHY |
|
282 || matchResult == PATHS_EQUAL) |
|
283 { |
|
284 return false; |
|
285 } |
|
286 } |
|
287 |
|
288 if (path1.length() > 3) |
|
289 { |
|
290 path1 = path1.substring(0, path1.lastIndexOf('/')); |
|
291 } |
|
292 |
|
293 // path1 is stripped to know in case the file is being created inside |
|
294 // root. |
|
295 while (path1.length() > 3) |
|
296 { |
|
297 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
298 { |
|
299 if (iRestrictedPathList[index].toLowerCase().startsWith( |
|
300 path1.toLowerCase())) |
|
301 { |
|
302 return true; |
|
303 } |
|
304 } |
|
305 path1 = path1.substring(0, path1.lastIndexOf('/')); |
|
306 } |
|
307 |
|
308 // C:/data/somefile should be matched with c:/data/images,c:/data/videos |
|
309 // and must return true but c:/data or c:/ must not return as true |
|
310 return false; |
|
311 } |
|
312 |
|
313 /** |
|
314 * Resolves a path to a one of the following categories: |
|
315 * |
|
316 * <pre> |
|
317 * PUBLIC_DIRS - C:/Data/Images |
|
318 * C:/Data/Videos |
|
319 * C:/Data/Graphics |
|
320 * C:/Data/Sounds |
|
321 * C:/Data/Music |
|
322 * C:/Data/Recordings and all files therein |
|
323 * HOME_DIR - App's private directory |
|
324 * PRIVATE_USER_FILES - All files and directories higher in path hierarchy |
|
325 * of PUBLIC_DIRS |
|
326 * SYSTEM_FILES - Z drive |
|
327 * </pre> |
|
328 * |
|
329 * @param aPath |
|
330 * path that has to be mapped to a particular category. |
|
331 * @return category of the path specified.<br/> One of the following: |
|
332 * SYSTEM_FILES, PRIVATE_USER_FILES, PUBLIC_DIRS, HOME_DIR |
|
333 */ |
|
334 public static String getCategory(String aPath) |
|
335 { |
|
336 FileLogger.Log("+ FileAccessHelper: getCategory: " + aPath); |
|
337 // SYSTEM_FILES, PRIVATE_USER_FILES, PUBLIC_DIRS, HOME_DIR |
|
338 if (aPath.equals(SYSTEM_FILES) || aPath.equals(PRIVATE_USER_FILES) |
|
339 || aPath.equals(PUBLIC_DIRS) || aPath.equals(HOME_DIR) |
|
340 || aPath.equals(RESTRICTED_PUBLIC_FILES)) |
|
341 { |
|
342 // if it is already mapped |
|
343 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
344 + aPath); |
|
345 return aPath; |
|
346 } |
|
347 |
|
348 if (aPath.equals("")) |
|
349 { |
|
350 // Used in case of FileSystemRegistry |
|
351 return PUBLIC_DIRS; |
|
352 } |
|
353 |
|
354 // First check for Home directory. Restricted paths list contains |
|
355 // app's private directory too. |
|
356 if (isHomeDir(aPath)) |
|
357 { |
|
358 return HOME_DIR; |
|
359 } |
|
360 |
|
361 int matchResult = PATHS_NO_MATCH; |
|
362 // Paths below restricted paths in hierarchy are part of Public files |
|
363 // Paths above in hierarchy are part of private used files. |
|
364 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
365 { |
|
366 matchResult = matchPaths(aPath, iRestrictedPathList[index]); |
|
367 if (PATH_BELOWIN_HIERARCHY == matchResult) |
|
368 { |
|
369 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
370 + PUBLIC_DIRS); |
|
371 return PUBLIC_DIRS; |
|
372 } |
|
373 |
|
374 if (PATHS_EQUAL == matchResult) |
|
375 { |
|
376 return PUBLIC_DIRS; |
|
377 } |
|
378 |
|
379 // Do we need this at all? Restricted PUBLIC Files can be removed |
|
380 if (PATH_ABOVEIN_HIERARCHY == matchResult) |
|
381 { |
|
382 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
383 + PUBLIC_DIRS); |
|
384 return PUBLIC_DIRS; |
|
385 } |
|
386 } |
|
387 |
|
388 String rom = FileSystemUtils.getRomDrive().toLowerCase() |
|
389 .substring(0, 2); |
|
390 String temp = FileSystemUtils.getTemporaryDrive().toLowerCase() |
|
391 .substring(0, 2); |
|
392 |
|
393 if (aPath.toLowerCase().startsWith(rom) |
|
394 || aPath.toLowerCase().startsWith(temp)) |
|
395 { |
|
396 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
397 + SYSTEM_FILES); |
|
398 return SYSTEM_FILES; |
|
399 |
|
400 } |
|
401 else if (aPath.toLowerCase().startsWith( |
|
402 FileSystemUtils.getDefaultRoot().toLowerCase())) |
|
403 { |
|
404 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
405 + RESTRICTED_PUBLIC_FILES); |
|
406 // It is however known that the default root of the device can |
|
407 // change. |
|
408 return RESTRICTED_PUBLIC_FILES; |
|
409 } |
|
410 else if ((aPath.toLowerCase().indexOf(PATH_PRIVATE) == 3) |
|
411 || (aPath.toLowerCase().indexOf(PATH_SYSTEM) == 3)) |
|
412 { |
|
413 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
414 + SYSTEM_FILES); |
|
415 return SYSTEM_FILES; |
|
416 } |
|
417 |
|
418 FileLogger.Log("- FileAccessHelper: getCategory: returning: " |
|
419 + PUBLIC_DIRS); |
|
420 return PUBLIC_DIRS; |
|
421 } |
78 } |
422 |
79 |
423 /** |
80 /** |
424 * Checks to see if the specified path is same as application's private |
81 * Checks to see if the specified path is same as application's private |
425 * directory. |
82 * directory. |
426 */ |
83 */ |
427 private static boolean isHomeDir(String aPath) |
84 private static boolean isHomeDir(String aPath) |
428 { |
85 { |
429 String appPrivateDir = FileSystemUtils.getAppPrivateDir(); |
86 String appPrivateDir = FileSystemUtils.getAppPrivateDir(); |
430 if (aPath.equalsIgnoreCase(appPrivateDir)) |
87 |
431 { |
88 if (aPath.toLowerCase().startsWith(appPrivateDir.toLowerCase())) |
432 return true; |
|
433 } |
|
434 if (aPath.startsWith(appPrivateDir)) |
|
435 { |
89 { |
436 return true; |
90 return true; |
437 } |
91 } |
438 |
92 |
439 return false; |
93 return false; |
440 } |
94 } |
441 |
|
442 /** |
|
443 * Checks to see if a file/directory can be created within the specidied |
|
444 * path. |
|
445 * |
|
446 * @param aPath |
|
447 * directory within which the application intends to create a |
|
448 * file. |
|
449 * @param aDomain |
|
450 * domain of the application |
|
451 * @return true in case access is allowed, false otherwise. |
|
452 */ |
|
453 public static boolean isCreateAllowedWithinDir(String aPath, String aDomain) |
|
454 { |
|
455 if (aDomain.equals(ApplicationInfo.MANUFACTURER_DOMAIN)) |
|
456 { |
|
457 return true; |
|
458 } |
|
459 |
|
460 boolean allowed = false; |
|
461 |
|
462 if (!aPath.startsWith(FileSystemUtils.getDefaultRoot())) |
|
463 { |
|
464 return true; |
|
465 } |
|
466 |
|
467 for (int index = 0; index < iRestrictedPathList.length; index++) |
|
468 { |
|
469 String path = iRestrictedPathList[index]; |
|
470 int matchResult = matchPaths(aPath, path); |
|
471 // Domains other than manufacturer are allowed to create content |
|
472 // only within restricted directories. |
|
473 if ((PATHS_EQUAL == matchResult) |
|
474 || (PATH_BELOWIN_HIERARCHY == matchResult)) |
|
475 { |
|
476 allowed = true; |
|
477 break; |
|
478 } |
|
479 } |
|
480 return allowed; |
|
481 } |
|
482 |
|
483 /** |
|
484 * Tries to match paths. Returns how "path2" is related to "path1". Checks if |
|
485 * the path is above or below in path hierarchy. Also checks to see if paths |
|
486 * are same or are totally different. |
|
487 */ |
|
488 private static int matchPaths(String aPath1, String aPath2) |
|
489 { |
|
490 // Strip trailing slash in case its present. |
|
491 String path1 = aPath1.endsWith("/") ? aPath1.substring(0, aPath1 |
|
492 .length() - 1) : aPath1; |
|
493 |
|
494 String path2 = aPath2.endsWith("/") ? aPath2.substring(0, aPath2 |
|
495 .length() - 1) : aPath2; |
|
496 |
|
497 // In case both paths are the same. |
|
498 if (path1.equalsIgnoreCase(path2)) |
|
499 { |
|
500 return PATHS_EQUAL; |
|
501 } |
|
502 |
|
503 // Check if path1 is higher in path hierarchy |
|
504 if (path2.toLowerCase().startsWith(path1.toLowerCase())) |
|
505 { |
|
506 return PATH_ABOVEIN_HIERARCHY; |
|
507 } |
|
508 |
|
509 if (path1.toLowerCase().startsWith(path2.toLowerCase())) |
|
510 { |
|
511 return PATH_BELOWIN_HIERARCHY; |
|
512 } |
|
513 |
|
514 return PATHS_NO_MATCH; |
|
515 } |
|
516 } |
95 } |