javacommons/security/legacysupport/midp2securitypolicyv2/plugins/securitypolicyV2/src/CPathAccessPolicy.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/security/legacysupport/midp2securitypolicyv2/plugins/securitypolicyV2/src/CPathAccessPolicy.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,371 @@
+/*
+* Copyright (c) 2003 - 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+/**
+Holds a set of path access and mapping policies for one or more drives. These
+are associated with a particular drive in a CDriveAccessPolicy object.
+@file
+@internalComponent
+@see MIDP::MDriveAccessPolicy
+*/
+
+#include <e32base.h>
+#include <f32file.h>
+#include "PathAccessPolicy.h"
+
+
+namespace MIDP
+{
+
+/**
+Creates a new path access policy object. The default access is ENone for all
+paths. When additional references to the object are taken, AddRef() must be
+called. When a reference is no longer required, the object should not be deleted
+but Release() called instead.
+@return The path access policy object.
+*/
+CPathAccessPolicy* CPathAccessPolicy::NewL()
+{
+    return new(ELeave) CPathAccessPolicy();
+}
+
+
+CPathAccessPolicy::CPathAccessPolicy()
+        : iCount(1)
+{
+}
+
+
+
+CPathAccessPolicy::~CPathAccessPolicy()
+{
+    iAccessPathList.ResetAndDestroy();
+    iAccessModeList.Close();
+    iRootDirList.ResetAndDestroy();
+    iRootMapList.ResetAndDestroy();
+    iUseMidletHomePrefix.Close();
+}
+
+
+/**
+Increments the reference count to the object.
+*/
+void CPathAccessPolicy::AddRef()
+{
+    iCount++;
+}
+
+
+/**
+Decrements the reference count to the object. When this reaches zero, the object
+is deleted.
+*/
+void CPathAccessPolicy::Release()
+{
+    __ASSERT_DEBUG(iCount > 0, User::Invariant());
+
+    if (--iCount == 0)
+    {
+        delete this;
+    }
+}
+
+
+/**
+Case-insensitive descriptor comparator.
+@param aFirst The first descriptor to compare.
+@param aSecond The second descriptor to compare.
+@return The result of the comparison.
+@see TDesC::Compare
+*/
+LOCAL_C TInt HBufCCompare(const HBufC& aFirst, const HBufC& aSecond)
+{
+    // Note that since paths are case insensitive, the folded form of comparison
+    // is used.
+    return aFirst.CompareF(aSecond);
+}
+
+
+/**
+Implements finding the path access mode for a drive access policy.
+@see MIDP::MDriveAccessPolicy::PathAccess
+*/
+CPathAccessPolicy::TPathAccessMode CPathAccessPolicy::PathAccess(const TDesC& aPath) const
+{
+    // Create a copy of the path, with space for a trailing separator if needed.
+    HBufC* pathCopy = HBufC::New(aPath.Length() + 1);
+    if (!pathCopy)
+    {
+        return MDriveAccessPolicy::ENone;
+    }
+    TPtr pathPtr = pathCopy->Des();
+    pathPtr = aPath;
+
+    TPathAccessMode access = SubPathAccess(pathCopy, ETrue);
+    delete pathCopy;
+
+    return access;
+}
+
+
+_LIT(KSeparator, "\\");
+
+/**
+Used recursively when searching for the path access policy for a path.
+@param aPath The path to examine. There must be at least space for one
+additional character to be added at the end.
+@param aAllowNonRecursiveMatch Set to ETrue when a non-recursive path specifier
+(i.e. without a trailing separator) can be used to match the path. Otherwise,
+only recursive path specifiers can match the given path.
+@return The access mode for the path given.
+*/
+CPathAccessPolicy::TPathAccessMode CPathAccessPolicy::SubPathAccess(HBufC* aPath,
+        TBool aAllowNonRecursiveMatch) const
+{
+    // Append a separator if one isn't present, since most path specifications
+    // will include one and this will increase the likelihood of an exact match.
+    TPtr pathPtr = aPath->Des();
+    if (pathPtr.Right(1) != KSeparator)
+    {
+        pathPtr.Append(KSeparator);
+    }
+
+    TLinearOrder<HBufC> comparator(HBufCCompare);
+    TInt index;
+    TInt error = iAccessPathList.FindInOrder(aPath, index, comparator);
+
+    if (error == KErrNone)
+    {
+        // Exact match found so use that access mode.
+        return iAccessModeList[ index ];
+    }
+
+    if (error != KErrNotFound)
+    {
+        // Some unexpected error occurred, so prevent access.
+        return MDriveAccessPolicy::ENone;
+    }
+
+    // Error is KErrNotFound - no exact match found. The index will be between
+    // the two closest matches. Longer matches are irrelevant since they could
+    // only be subdirectories or other paths, but the previous entry (if
+    // present) may match up to the path's trailing separator and be acceptable
+    // if the flag passed in is set.
+
+    // Remove the trailing slash
+    pathPtr.SetLength(pathPtr.Length() - 1);
+
+    if (aAllowNonRecursiveMatch && (index > 0))
+    {
+        const TDesC& previous = *iAccessPathList[ index - 1 ];
+        if (previous == pathPtr)
+        {
+            return iAccessModeList[ index ];
+        }
+    }
+
+    // If the string is empty, there is nothing more to check.
+    if (pathPtr.Length() == 0)
+    {
+        return MDriveAccessPolicy::ENone;
+    }
+
+    // Otherwise try checking the parent directory. This must match a recursive
+    // path pattern (i.e. that ends with a separator).
+
+    TInt separator = pathPtr.LocateReverse(TChar('\\'));
+    // Modify path to remove this directory.
+    pathPtr.SetLength((separator >= 0) ? separator : 0);
+
+    return SubPathAccess(aPath, EFalse);
+}
+
+
+
+/**
+Implements the root directory listing for a drive access policy.
+@see MIDP::MDriveAccessPolicy::RootDirectoryListL
+*/
+const RPointerArray<HBufC>& CPathAccessPolicy::RootDirectoryListL() const
+{
+    return iRootDirList;
+}
+
+
+/**
+Implements the path mapping for a drive access policy.
+@see MIDP::MDriveAccessPolicy::MapPathL
+*/
+TBool CPathAccessPolicy::MapPathL(const TDesC& aFrom, TDes& aTo) const
+{
+    TInt mappingCount = iRootDirList.Count();
+
+    if (mappingCount == 0)
+    {
+        // Special case 1: when no mappings are defined, direct mapping is used.
+        aTo = aFrom;
+        return EFalse;
+    }
+
+    if (mappingCount == 1 && iRootDirList[0]->Length() == 0)
+    {
+        // Special case 2: when one mapping is defined, and it is from the empty
+        // string, everything is mapped by prepending the map string.
+        aTo = *iRootMapList[0];
+        aTo.Append(aFrom);
+        return iUseMidletHomePrefix[0];
+    }
+
+    TInt separator = aFrom.Locate(TChar('\\'));
+    HBufC* fromCopy;
+
+    if (separator == KErrNotFound)
+    {
+        // No separator, this is just the directory name.
+        fromCopy = aFrom.AllocL();
+    }
+    else
+    {
+        // Match up to, but not including, the separator if it is present.
+        fromCopy = aFrom.Left(separator).AllocL();
+    }
+
+    if (fromCopy->Length() == 0)
+    {
+        // Special case 3: where the root mapping is requested. This must not
+        // leave, otherwise the root could not be inspected. Just pass back
+        // whatever was passed in (may include a separator or not).
+        delete fromCopy;
+        aTo = aFrom;
+        return EFalse;
+    }
+
+    TLinearOrder<HBufC> comparator(HBufCCompare);
+    TInt index;
+    TInt error = iRootDirList.FindInOrder(fromCopy, index, comparator);
+
+    delete fromCopy;
+    User::LeaveIfError(error);
+
+    // Found the directory in the list, so use the mapping.
+    aTo = *iRootMapList[ index ];
+
+    if (separator != KErrNotFound)
+    {
+        // Add the rest of the original path.
+        aTo.Append(aFrom.Mid(separator));
+    }
+
+    return iUseMidletHomePrefix[ index ];
+}
+
+
+/**
+Adds the access mode for a path specifier to the policy. If the specifier ends
+in a separator, it applies to that directory and everything in it, otherwise it
+applies only to that file or directory. A special case is the path specifier
+consisting of just a separator. This means the access mode applies to all files
+on the drive, unless overridden by a more specific path specifier.
+@param aPath The path specifier.
+@param aMode The access mode.
+*/
+void CPathAccessPolicy::AddPathAccessL(const TDesC& aPath, TPathAccessMode aMode)
+{
+    HBufC* path = aPath.AllocL();
+    TInt index;
+    TLinearOrder<HBufC> comparator(HBufCCompare);
+    TInt error = iAccessPathList.FindInOrder(path, index, comparator);
+
+    if (error == KErrNone)
+    {
+        // Already in list, so leave the path in the path list and replace the
+        // existing access mode in the mode list.
+        delete path;
+        iAccessModeList[ index ] = aMode;
+    }
+    else if (error == KErrNotFound)
+    {
+        // Not found, so add the entries to each list at the same point. The
+        // index returned by FindInOrder() will be the correct insertion point.
+        User::LeaveIfError(iAccessPathList.Insert(path, index));
+        User::LeaveIfError(iAccessModeList.Insert(aMode, index));
+    }
+    else
+    {
+        // An unhandled error occurred
+        delete path;
+        User::Leave(error);
+    }
+}
+
+
+/**
+Adds a mapping from one path to another. Also specifies whether the destination
+path is complete in itself or needs to be prefixed by the MIDlet's home path.
+The source directory cannot contain any separators or the function will leave.
+@param aDir The sub-directory of the root to map.
+@param aPath The destination path for this mapping.
+@param aInMidletHome ETrue if the destination path should be prefixed by the
+MIDlet's home path.
+*/
+void CPathAccessPolicy::AddPathMappingL(const TDesC& aDir, const TDesC& aPath,
+                                        TBool aInMidletHome)
+{
+    if (aDir.Locate(TChar('\\')) != KErrNotFound)
+    {
+        User::Leave(KErrArgument);
+    }
+
+    HBufC* dir = aDir.AllocL();
+    TInt index;
+    TLinearOrder<HBufC> comparator(HBufCCompare);
+    TInt error = iRootDirList.FindInOrder(dir, index, comparator);
+
+    if (error == KErrNone)
+    {
+        // Already in root list, so leave the dir in the dir list and replace
+        // the existing mapping in the map list.
+        delete dir;
+        HBufC* oldPath = iRootMapList[ index ];
+        iRootMapList[ index ] = aPath.AllocL();
+        iUseMidletHomePrefix[ index ] = aInMidletHome;
+        delete oldPath;
+    }
+    else if (error == KErrNotFound)
+    {
+        // Not found, so add the entries to each list at the same point. The
+        // index returned by FindInOrder() will be the correct insertion point.
+        HBufC* path = aPath.AllocLC();
+        CleanupStack::PushL(dir);
+        User::LeaveIfError(iRootDirList.Insert(dir, index));
+        CleanupStack::Pop(dir);
+        User::LeaveIfError(iRootMapList.Insert(path, index));
+        CleanupStack::Pop(path);
+        User::LeaveIfError(iUseMidletHomePrefix.Insert(aInMidletHome, index));
+    }
+    else
+    {
+        // An unhandled error occurred
+        delete dir;
+        User::Leave(error);
+    }
+}
+
+} // end of namespace MIDP
+