javacommons/gcfprotocols/file/javasrc.s60/com/nokia/mj/impl/file/FileAccessHelper.java
branchRCL_3
changeset 24 0fd27995241b
parent 19 04becd199f91
equal deleted inserted replaced
20:f9bb0fca356a 24:0fd27995241b
    18 package com.nokia.mj.impl.file;
    18 package com.nokia.mj.impl.file;
    19 
    19 
    20 import java.util.Hashtable;
    20 import java.util.Hashtable;
    21 import java.util.Vector;
    21 import java.util.Vector;
    22 import com.nokia.mj.impl.rt.support.ApplicationInfo;
    22 import com.nokia.mj.impl.rt.support.ApplicationInfo;
       
    23 import com.nokia.mj.impl.fileutils.DriveInfo;
       
    24 import com.nokia.mj.impl.fileutils.DriveUtilities;
       
    25 
    23 
    26 
    24 public class FileAccessHelper implements FileConstants
    27 public class FileAccessHelper implements FileConstants
    25 {
    28 {
    26     public static int PATHS_EQUAL = 0;
    29     public static int PATHS_EQUAL = 0;
    27     public static int PATHS_NO_MATCH = 1;
    30     public static int PATHS_NO_MATCH = 1;
    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 }