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