diff -r 675a964f4eb5 -r 35751d3474b7 authorisation/userpromptservice/policies/source/policycache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authorisation/userpromptservice/policies/source/policycache.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,349 @@ +/* +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* +*/ + + +#include "policycache.h" +#include "policylist.h" +#include "policyreader.h" +#include "promptrequest.h" +#include "serviceconfig.h" +#include +#include +#include "upslog.h" + +using namespace UserPromptService; + +EXPORT_C CPolicyCache* CPolicyCache::NewL(RFs& aFs, const TDesC& aPolicyPath) +/** +Creates a new policy cache. +@param aFs The file server session used to load policy files.\n + Ownership is not transferred. +@param aPolicyPath The path of the policy files (minus the drive). It must be + in the following form "\private\sid\policies\" +@return A pointer to the new policy cache object. +*/ + { + CPolicyCache* self = new(ELeave) CPolicyCache(aFs); + CleanupStack::PushL(self); + self->ConstructL(aPolicyPath); + CleanupStack::Pop(self); + return self; + } + +CPolicyCache::CPolicyCache(RFs& aFs) +/** +Constructor +@param aFs The file server session used to load policy files. +*/ + : iFs(aFs) + { + } + +CPolicyCache::~CPolicyCache() +/** +Destructor +*/ + { + iPolicyLists.ResetAndDestroy(); + delete iPolicyPath; + } + +void CPolicyCache::ConstructL(const TDesC& aPolicyPath) +/** +Second phase constructor, resolves the system drive. +@param aPolicyPath The directory where the policy files are stored. +*/ + { + iPolicyPath = aPolicyPath.AllocL(); + iSystemDriveChar = iFs.GetSystemDriveChar(); + } + +EXPORT_C const CPolicy* CPolicyCache::MatchL(const CPromptRequest& aRequest) +/** +Finds the first policy that matches the request. + +@param aRequest The request data from the system server. +@return A copy of the policy object to apply to the request. If a policy + file exists but no policy is defined then a default policy object + is returned that current request to be accepted or denied. + +@leave KErrUpsMissingPolicyFile If no policy file is found for the requested server sid and service id. +@leave KErrUpsBadPolicyFile If an error occured whilst parsing a policy file. +*/ + { + CPolicyList::TId id(aRequest.ServerSid(), aRequest.ServiceId()); + const CPolicyList* list = PolicyList(id); + + if (!list) + { + // Policy list not found so try and load it. This + // leaves if a UPS policy file is not found. + list = LoadPolicyListL(id); + } + + ASSERT(list); + return list->Match(aRequest); + } + +const CPolicyList* CPolicyCache::PolicyList(const CPolicyList::TId& aId) const +/** +Gets the specified policy list if it is loaded. +@param The ID of the policy list. +@return A pointer to the policy list if it is loaded; otherwise, is returned. +*/ + { + TInt count = iPolicyLists.Count(); + for (TInt i = 0; i < count; ++i) // Check if policy list is in the cache + { + if (iPolicyLists[i]->Id() == aId) + { + return iPolicyLists[i]; + } + } + return 0; + } + +CPolicyList* CPolicyCache::LoadPolicyListL(const CPolicyList::TId& aId) +/** +Loads a list of policies from the policy file for the specified system server and service. +@param aId A tuple of the system server SID and service UID that identifies a policy file. + +@return The list of policies, or N +@leave KErrUpsBadPolicyFile if an error occured whilst parsing a policy file. + KErrUpsMissingPolicyFile if the policy file was not found on the Z or the system drive. +*/ + { + RBuf fn; + fn.CreateL(KMaxFileName); + CleanupClosePushL(fn); + + LocatePolicyFileL(fn, aId); + + CPolicyList* l(0); + TRAPD(err, l = ParseListL(aId, fn)); + if (err != KErrNone && err != KErrNoMemory) + { + DEBUG_PRINTF2(_L("Unable to parse %S"), &fn); + err = KErrUpsBadPolicyFile; + + if (fn[0] == 'Z') + { + DEBUG_PRINTF2(_L("Unable to parse %S"), &fn); + User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy); + } + else { + // If we failed to read the policy file from the system + // drive then try the Z drive. + fn[0] = 'Z'; + TRAP(err, l = ParseListL(aId, fn)); + if (err == KErrNone) + { + DEBUG_PRINTF2(_L("Ignoring corrupt policy file on system drive. Loading %S"), &fn); + } + else if (err != KErrNotFound && err != KErrNoMemory) + { + DEBUG_PRINTF2(_L("Unable to parse %S"), &fn); + User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy); + } + } + } + User::LeaveIfError(err); + + CleanupStack::PushL(l); + iPolicyLists.AppendL(l); + CleanupStack::Pop(l); + CleanupStack::PopAndDestroy(&fn); + return l; + } + +void CPolicyCache::LocatePolicyFileL(TDes& aPolicyFileName, const CPolicyList::TId& aId) +/** +Determines whether the policy file should be loaded from the Z drive +or the system drive and returns the filename. + +@param aPolicyFileName Descriptor to populate with the filename. +@param aId The id of the policy file to load. + +@leave KErrUpsMissingPolicyFile The policy file was not found on either the Z drive + or the system drive. +*/ + { + _LIT(KDriveSpec, "!:"); + + aPolicyFileName.Zero(); + aPolicyFileName.Append(KDriveSpec); + aPolicyFileName.Append(*iPolicyPath); + aId.AppendNameToPath(aPolicyFileName); + + // System drive eclipses Z drive + aPolicyFileName[0] = iSystemDriveChar; + if (! FileExistsL(aPolicyFileName)) + { + aPolicyFileName[0] = 'Z'; + if (! FileExistsL(aPolicyFileName)) + { + DEBUG_PRINTF3(_L8("No policy file for system server sid = 0x%08x, service id = 0x%08x"), + aId.iServerSid.iId, aId.iServiceId.iUid); + User::Leave(KErrUpsMissingPolicyFile); + } + } + } + +CPolicyList* CPolicyCache::ParseListL(const CPolicyList::TId& aId, const TDesC& aPolicyFileName) +/** +Parses a policy file and constructs a policy list object. + +@param aId The policy file id that will be used to locate the policy list within + the policy cache. +@param aPolicyFileName The absolute path of the policy file to parse. +@return The new policy list object. +*/ + { + CPolicyReader* r = CPolicyReader::NewLC(iFs, aPolicyFileName); + CPolicyList* l = CPolicyList::NewL(aId, *r); + CleanupStack::PopAndDestroy(r); + return l; + } + +EXPORT_C void CPolicyCache::ServiceConfigL(const TSecureId& aServerSid, RArray& aConfigs) +/** +Loads the service configuration data from the policy files for every service provided +by a given system server. +@param aServerSid The secure id of the system server. +@param aConfigs The RArray to populate with the configuration data. +*/ + { + RArray services; + CleanupClosePushL(services); + + DEBUG_PRINTF2(_L8("Loading service configuration for system server 0x%08x"), aServerSid.iId); + + FindServicesL(aServerSid, services); + TInt numServices = services.Count(); + + // Load the services + for (TInt i = 0; i < numServices; ++i) + { + CPolicyList::TId id(aServerSid, TUid::Uid(services[i])); + const CPolicyList* list = PolicyList(id); + if (list) + { + // Use in-memory service configuration + aConfigs.AppendL(list->ServiceConfig()); + } + else + { + // Load policy file into cache + CPolicyList* loadedList = LoadPolicyListL(id); + aConfigs.AppendL(loadedList->ServiceConfig()); + } + } + CleanupStack::PopAndDestroy(&services); + } + +void CPolicyCache::FindServicesL(const TSecureId& aServerSid, RArray& aServices) +/** +Finds all of the policy files on Z drive and C drive for this system server +A wildcard string is used to filter out policy files for other system servers. + +@param aServerSid The secure id of the system server. +@param aServices The array of service ids to populate. +*/ + { + _LIT(KFilenameTemplate, "ups_%08x_????????.rsc"); + TBuf<32> pattern; + pattern.AppendFormat(KFilenameTemplate, aServerSid.iId); + + RBuf fn; // Store current file/directory name. + fn.CreateL(KMaxFileName); + CleanupClosePushL(fn); + for (TInt i = 0; i < 2; ++i) + { + TUint driveChar = (i == 0) ? TChar('Z') : iSystemDriveChar; + + fn.Zero(); + _LIT(KDirFormat, "%c:%S"); + fn.AppendFormat(KDirFormat, driveChar, &*iPolicyPath); + + CDir* dir(0); + TInt err = iFs.GetDir(fn, KEntryAttNormal, ESortNone, dir); + if (err == KErrPathNotFound) + { + continue; + } + User::LeaveIfError(err); + CleanupStack::PushL(dir); + + // Find the services + TInt count = dir->Count(); + for (TInt j = 0; j < count; ++j) + { + const TEntry& e((*dir)[j]); + if (e.iName.MatchF(pattern) >= 0) + { + fn.Zero(); + _LIT(KFileFormat, "%C:%S%S"); + fn.AppendFormat(KFileFormat, driveChar, iPolicyPath, &e.iName); + + CPolicyList::TId policyListId; + TRAP(err, CPolicyList::TId::IdL(fn, policyListId)) + if (err == KErrNoMemory) + { + // Do not let OOM cause us to ignore policy files + User::Leave(err); + } + if (err == KErrNone) + { + // Ensure there are no duplicate service configs due to eclisped policy files. + err = aServices.InsertInOrder(static_cast(policyListId.iServiceId.iUid)); + if (err != KErrAlreadyExists) + { + User::LeaveIfError(err); + } + } + else + { + DEBUG_PRINTF2(_L("%S does not match UPS policy filename rules"), &fn); + } + } + // Policy file is for a different system server + } + CleanupStack::PopAndDestroy(dir); + } + CleanupStack::PopAndDestroy(&fn); + } + +TBool CPolicyCache::FileExistsL(const TDesC& aFileName) +/** +Checks whether a file exists. +- If the FileName corresponds to a directory then EFalse is returned. + +@param aFileName The absolute path of the file to check. +@return ETrue, if aFileName exists; otherwise, EFalse is returned. +*/ + { + TBool exists = EFalse; + TEntry* e = new(ELeave) TEntry(); + TInt err = iFs.Entry(aFileName, *e); + if (err == KErrNone && ! e->IsDir()) + { + exists = ETrue; + } + delete e; + return exists; + } +