diff -r 000000000000 -r dfb7c4ff071f commsfwtools/preparedefaultcommsdatabase/src/CommsDatValidator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwtools/preparedefaultcommsdatabase/src/CommsDatValidator.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,2382 @@ +// Copyright (c) 2004-2009 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: +// Validation rules for some comms database elements +// MAINTENANCE - Some rules may need adding or amending whenever the database schema changes +// No need to validate every entry +// Mostly rely on compliance from writers as they are well trusted +// FILE CONTENTS : +// 1/ CCDValidator Base class implementation +// 2/ Validator classes for particular records +// a) CCDValidatorProxyRecord +// b) CCDValidatorLANServiceRecord +// c) CCDValidatorTierRecord +// d) CCDValidatorConnPref +// e) CCDValidatorIAPRecord +// All data in file +// +// + +/** + @file CommsDatValidator.cpp + @internalComponent +*/ + + +#include "CommsDatInternalDefs.h" +#include +#include "CommsDatValidator.h" +#include +#include +#include "CommsDatMapperAndValidatorUtils.h" + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif + +using namespace Meta; +using namespace CommsDatInternal; +using namespace CommsDat; + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +//anonymous namespace +namespace + { + const TInt KNumServiceType = 12; + + struct TMapBearerToServiceType + { + TCommDbBearer bearerMask; + TCommDbConnectionDirection direction; + const TText* serviceType; + }; + + const TMapBearerToServiceType KMap[KNumServiceType] = + { + {KCommDbBearerCSD, ECommDbConnectionDirectionOutgoing, DIAL_OUT_ISP}, + {KCommDbBearerCSD, ECommDbConnectionDirectionIncoming, DIAL_IN_ISP}, + {KCommDbBearerWcdma, ECommDbConnectionDirectionOutgoing, OUTGOING_GPRS}, + /** The following two mappings are only required for tornado */ + {KCommDbBearerWcdma, ECommDbConnectionDirectionIncoming, INCOMING_GPRS}, + {KCommDbBearerLAN, ECommDbConnectionDirectionIncoming, LAN_SERVICE}, + {KCommDbBearerLAN, ECommDbConnectionDirectionOutgoing, LAN_SERVICE}, + {KCommDbBearerVirtual, ECommDbConnectionDirectionIncoming, VPN_SERVICE}, + {KCommDbBearerVirtual, ECommDbConnectionDirectionOutgoing, VPN_SERVICE}, + /** PAN profile uses LAN service table, plus an extension service table */ + {KCommDbBearerPAN, ECommDbConnectionDirectionIncoming, LAN_SERVICE}, + {KCommDbBearerPAN, ECommDbConnectionDirectionOutgoing, LAN_SERVICE}, + /** WLAN uses LAN service table, plus an extension service table */ + {KCommDbBearerWLAN, ECommDbConnectionDirectionIncoming, LAN_SERVICE}, + {KCommDbBearerWLAN, ECommDbConnectionDirectionOutgoing, LAN_SERVICE} + }; + + //this function returns the index in the array of the service type which should be used based + //on the received bearer and direction parameters. + //it returns KErrNotFound if the service type cannot be found based on the received params. + TInt GetIAPServiceType(TUint32& aServTypeArrayStartIndex, TCommDbBearer aBearerSet, TCommDbConnectionDirection aDirection) + { + for (int i = aServTypeArrayStartIndex; i < KNumServiceType; i++) + { + if ((aBearerSet & KMap[i].bearerMask) != 0 && + (aDirection == KMap[i].direction || + aDirection == ECommDbConnectionDirectionUnknown )) + { + aServTypeArrayStartIndex = i; + return i; + } + } + return KErrNotFound; + } + + CMDBRecordLink* GetTheAPxLinkFromAPPrioritySelPol(CCDAPPrioritySelectionPolicyRecord* aAPSelPolRec, + TInt aRankingFromConnPref) + { + TMetaVTableIterator attribIter(aAPSelPolRec); + SVDataTableEntry const* entry = 0; + TInt fieldCounter(15); + TInt linkNumber(aRankingFromConnPref); + CMDBRecordLink* apPrioritySelPolLink = NULL; + + while ( (entry = attribIter++) != NULL && + linkNumber-- > 0 && + fieldCounter-- > 0 ) + { + apPrioritySelPolLink = reinterpret_cast*>(aAPSelPolRec->GetAttribPtr(entry->iOffset)); + } + + return apPrioritySelPolLink; + } + } +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +/**************************************************************************************** + * 1/ CCDValidator Base class implementaion + ****************************************************************************************/ + +CCDValidator::CCDValidator(CMDBElement* aElement,CMDBSessionImpl& aSession): +iElement(aElement),iSession(aSession) +/* +@internalComponent +*/ + { + iSession.iMapping = ETrue; + } + +CCDValidator::~CCDValidator() +/* +@internalComponent +*/ + { + iSession.iMapping = EFalse; + } + + +void CCDValidator::ValidateL(CMDBElement* aElement,CMDBSessionImpl& aSession +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + ,TOperation aValidatorOperation +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + ) +/* +Creates a validation object of the appropriate type +if there are validation rules for aElement +and calls validate + +@internalComponent +*/ + { + + if( aSession.iMapping ) + { + return; + } + + if( CommsDat::CommsDatSchema::IsTable(aElement->ElementId()) ) + { + return; + } + + // then create a validator for the business data if there are any rules set + CCDValidator* validator = NULL; + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if (EModify == aValidatorOperation || + EStore == aValidatorOperation) + //this is the original behaviour of this method + { +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if (! CommsDat::CommsDatSchema::IsNode(aElement->ElementId())) + { + // First validate the field type (see CommsDatSchema) + CommsDatSchema::ValidateFieldTypeL(aSession.iOwner, *aElement); + + /* Only compliant processes can write to the database + + don't see it is valuable to validate every field*/ + + //return; + } + + switch(aElement->ElementId() & KCDMaskShowRecordType) + { + case KCDTIdConnectionPrefsRecord: + { + validator = new(ELeave)CCDValidatorConnPref(aElement,aSession +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + , aValidatorOperation +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + ); + break; + } + + case KCDTIdIAPRecord: + { + validator = new(ELeave)CCDValidatorIAPRecord(aElement,aSession +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + , aValidatorOperation +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + ); + break; + } + + case KCDTIdLANServiceRecord: + { + validator = new(ELeave)CCDValidatorLANServiceRecord(aElement,aSession); + break; + } + + case KCDTIdProxiesRecord: + { + validator = new(ELeave)CCDValidatorProxyRecord(aElement,aSession); + break; + } + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + case KCDTIdTierRecord: + { + validator = new(ELeave)CCDValidatorTierRecord(aElement,aSession); + break; + } + + #endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + default : + { + return; // Exit quickly if there's no validator + } + } +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + } + else + //the validator should be created for deleting some other data... + { + switch(aElement->ElementId() & KCDMaskShowRecordType) + { + case KCDTIdConnectionPrefsRecord: + { + validator = new(ELeave)CCDValidatorConnPref(aElement,aSession, aValidatorOperation); + break; + } + case KCDTIdIAPRecord: + { + validator = new(ELeave)CCDValidatorIAPRecord(aElement,aSession, aValidatorOperation); + break; + } + default : + { + return; // Exit quickly if there's no validator + } + } + } +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + CleanupStack::PushL(validator); + + validator->DoValidateL(); + + CleanupStack::PopAndDestroy(validator); + } + + + +void CCDValidator::DoValidateL() +/* +Default is nothing to validate so return + +@internalComponent +*/ + { + User::LeaveIfError(1 == 1); + } + + +void CCDValidator::OnDeleteL() +/* +Default is nothing to delete; + +@internalTechnology +*/ + { + User::LeaveIfError(1 == 1); + } + + + + + +/*************************************************************************************** + * 2/ VALIDATION CLASSES FOR INDIVIDUAL RECORDS + **************************************************************************************/ + + + +/************************* 2a) Validate Proxy Record ************************************ +Validate open link to service record +*/ +void CCDValidatorProxyRecord::SetShadowElementL() + { + iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdProxiesRecord); + iShadowElement->SetRecordId(iElement->RecordId()); + iShadowElement->LoadL(iSession.iOwner); + + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + CMDBElement* shadowFieldPtr = static_cast(iShadowElement)->GetFieldByIdL(iElement->ElementId()); + + if ( KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType) || + KCDTIdProxyServiceType == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdServerName == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdProtocolName == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdExceptions == (iElement->ElementId() & KCDMaskShowType) ) + { + CMDBField* nameField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + nameField->SetL(*origField); + } + else + { + CMDBField* numField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + numField->SetL(*origField); + } + } + + iElement = iShadowElement; + } + + +void CCDValidatorProxyRecord::DoValidateL() +/* +Just validate the linked field +@internalComponent +*/ + { + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId())) + { + //field validation + SetShadowElementL(); + } + +#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS + CCDProxiesRecord* proxyRecord = static_cast(iElement); + + if (! proxyRecord->iService.IsNull() && ! proxyRecord->iServiceType.IsNull()) + { + TMDBElementId serviceTypeId = CommsDatSchemaV1_1::LookupTableId(proxyRecord->iServiceType.GetL()); + proxyRecord->iService = CommsDatSchema::GetLinkIdL(iSession.iOwner, proxyRecord->iService.ElementId(), proxyRecord->iService.GetL(), serviceTypeId/*, &proxyRecord*/); + } +#endif // SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS + } + + +/************************* 2b) Validate LANService Record *********************************** +Validate open link to service extension record +*/ + +void CCDValidatorLANServiceRecord::SetShadowElementL() + { + iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdLANServiceRecord); + iShadowElement->SetRecordId(iElement->RecordId()); + iShadowElement->LoadL(iSession.iOwner); + + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + CMDBElement* shadowFieldPtr = static_cast(iShadowElement)->GetFieldByIdL(iElement->ElementId()); + + if ( KCDTIdRecordTag == (iElement->ElementId() & KCDMaskShowFieldType) || + KCDTIdLANIpAddrFromServer == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdLANIpDNSAddrFromServer == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdLANIp6DNSAddrFromServer == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdLANServiceExtensionTableRecordId == (iElement->ElementId() & KCDMaskShowType) ) + { + CMDBField* numField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + numField->SetL(*origField); + } + else + { + CMDBField* nameField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + nameField->SetL(*origField); + } + } + + iElement = iShadowElement; + } + +void CCDValidatorLANServiceRecord::DoValidateL() +/* +Just validate the linked field +@internalComponent +*/ + { + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId())) + { + //field validation + SetShadowElementL(); + } + +#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS + CCDLANServiceRecord* lanServiceRecord = static_cast(iElement); + + if (! lanServiceRecord->iServiceExtensionTableRecordId.IsNull() && ! lanServiceRecord->iServiceExtensionTableName.IsNull()) + { + //this was caught in testing but it is not valid to have a real record without these fields... + TMDBElementId serviceExtTypeId = CommsDatSchemaV1_1::LookupTableId(lanServiceRecord->iServiceExtensionTableName.GetL()); + + lanServiceRecord->iServiceExtensionTableRecordId = + CommsDatSchema::GetLinkIdL(iSession.iOwner, lanServiceRecord->iServiceExtensionTableRecordId.ElementId(), lanServiceRecord->iServiceExtensionTableRecordId.GetL(), serviceExtTypeId/*, &lanServiceRecord*/); + } +#endif + } + + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +// because tier record doesn't exist before then + +/************************* 2c) Validate Tier Record ************************************* +Tier thread name needs to be short name for Tier thread +*/ + +void CCDValidatorTierRecord::SetShadowElementL() + { + iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdTierRecord); + iShadowElement->SetRecordId(iElement->RecordId()); + iShadowElement->LoadL(iSession.iOwner); + + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + CMDBElement* shadowFieldPtr = static_cast(iShadowElement)->GetFieldByIdL(iElement->ElementId()); + + if ( KCDTIdRecordTag == (iElement->ElementId() & KCDMaskShowFieldType) || + KCDTIdDefaultAccessPoint == (iElement->ElementId() & KCDMaskShowType) ) + { + CMDBField* numField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + numField->SetL(*origField); + } + else + { + CMDBField* nameField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + nameField->SetL(*origField); + } + } + + iElement = iShadowElement; + } + +void CCDValidatorTierRecord::DoValidateL() +/* +@internalComponent +*/ + { + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + SetShadowElementL(); + } + + CCDTierRecord* tierRec = static_cast(iElement); + if(static_cast(tierRec->iTierThreadName).Length() > KShortTextLength) + { + __FLOG_STATIC(KLogComponent, KCDErrLog, + _L("CCDValidatorTierRecord::DoValidateL() - TierThreadName > KShortTextLength chars")); + User::Leave(KErrTooBig); + } + } + + + + +/***************** 2d) Validate Connection Preference Record ***************************** +*/ +void CCDValidatorConnPref::SetShadowElementL() + { + iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord); + iShadowElement->SetRecordId(iElement->RecordId()); + iShadowElement->LoadL(iSession.iOwner); + + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + CMDBElement* shadowFieldPtr = static_cast(iShadowElement)->GetFieldByIdL(iElement->ElementId()); + + + if (KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType)) + { + CMDBField* nameField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + nameField->SetL(*origField); + } + else + { + //the only reason this cast can be done here is that the connPref record contains only + //numerical based fields... (except the name field -> handled above...) + CMDBField* numField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + if (EDelete == iOperation) + { + numField->SetL(0); + } + else + { + numField->SetL(*origField); + } + + //in the case of the IAP link it has to be checked whether is it + //given as a full link or only as a record number + if (KCDTIdIAPLink == (iElement->ElementId() & KCDMaskShowType)) + { + if ((*origField & KCDMaskShowType) == KCDMaskShowType) + { + //the value is only a record id + numField->SetL(*origField); + } + else + { + //the value is a TMDBElementId. Now only the reocrdId is important -> the + //connprefValidator is working only with the recId + numField->SetL((*origField & KCDMaskShowRecordId) >> 8); + } + } + } + } + + iElement = iShadowElement; + } +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +void CCDValidatorConnPref::DoValidateL() + { +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) || + EDelete == iOperation ) + { + // a) field validation -> in this case the validator should load the whole record from the DB + // mimicing record validation + // b) this is a delete operation where only the record id is set on the record container + // the validator should load the correct element in order to delete the 399 path + SetShadowElementL(); + } +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + TBool clearHiddenFlag = EFalse; + + CCDConnectionPrefsRecord* ptrConnPref = static_cast(iElement); + + TInt rank = ptrConnPref->iRanking; + TCommDbConnectionDirection direction = ptrConnPref->iDirection; + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if (EDelete != iOperation) + { +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + //this kind of validation is needed if there is some other operation than delete... + + if(ptrConnPref->iDefaultIAP == 0) + { + /* + Since phones get shipped without any predefined IAPs, when a connpref record + is stored with the IAP(iDefaultIAP) not set, CED sets its value to 0. + Such records hence should be exempted from validation. + [Instead of a 0, the behaviour could have been a negative value to remove ambiguity and also + could have been mandatory to set that value in the configuration file as well] + */ + // return; + } + /* This test is here returniong KErrNotFound for BC reasons. + It used to assume that value of iDefaultIAP would always be a straight record id + have now modified it to take account of different link values*/ + if( ptrConnPref->iDefaultIAP != 0 && + ptrConnPref->iDefaultIAP >= KCDMaxRecords ) + { + if( (ptrConnPref->iDefaultIAP & KLinkableTag) != 0 || + (ptrConnPref->iDefaultIAP & KCDMaskShowRecordType ) != KCDTIdIAPRecord ) + { + // this can't be a valid IAP record + User::Leave(KErrNotFound); + } + } + + if(rank > 2) + { + User::Leave(KErrOverflow); + } + + if (direction == ECommDbConnectionDirectionIncoming && rank > 1) + { + User::Leave(KErrNotSupported); + } + //Re-setting the hidden flag in the case of a leave?????? + clearHiddenFlag = ! iSession.IsSetAttributeMask(ECDHidden); + if (clearHiddenFlag) + { + iSession.SetAttributeMask(ECDHidden); + } + + //check if a record with the same rank already exists + CCDConnectionPrefsRecord* ptrConnprefTestRecord = NULL; + + // secondly check records already in the db. + + ptrConnprefTestRecord = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord)); + CleanupStack::PushL(ptrConnprefTestRecord); + + ptrConnprefTestRecord->iRanking = rank; + ptrConnprefTestRecord->iDirection = direction; + + // conditions does not apply for rank 0 + if (rank > 0 && ptrConnprefTestRecord->FindL(iSession.iOwner)) + { + // Since Validation can occur from ModifyL as well, only leave if this isn't the same record + if (ptrConnprefTestRecord->RecordId() != ptrConnPref->RecordId() && + ptrConnprefTestRecord->RecordId() != KCDDefaultRecord) + { + User::Leave(KErrAlreadyExists); + } + } + CleanupStack::PopAndDestroy(ptrConnprefTestRecord); + + // Check the IAP record id. look first in cache then in repository + if (ptrConnPref->iDefaultIAP != 0) + { + TInt boo = ptrConnPref->iDialogPref; + TCommDbDialogPref dialogpref = (TCommDbDialogPref)boo;//TODO change the templated type def of this field; + + + if ( (*(ptrConnPref->iDefaultIAP.Data()) & KCDChangedFlag) == KCDChangedFlag || + (*(ptrConnPref->iBearerSet.Data()) & KCDChangedFlag) == KCDChangedFlag ) + { + CMDBField* iapServiceType = new(ELeave) CMDBField(KCDTIdIAPServiceType); + CleanupStack::PushL(iapServiceType); + iapServiceType->SetMaxLengthL(KMaxTextLength); + iapServiceType->SetRecordId(ptrConnPref->iDefaultIAP); + iapServiceType->LoadL(iSession.iOwner); + TPtrC serviceType(*iapServiceType); + + ValidateBearerAndDirectionL(serviceType, ptrConnPref->iDirection, ptrConnPref->iBearerSet, dialogpref); + CleanupStack::PopAndDestroy(iapServiceType); + } + } +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + } +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if ( (ECommDbConnectionDirectionIncoming != direction && // -| + rank > 0 && // | -> related to sore, modify + !iSession.UsingLatestVersion()) ) // | -> related to the latest session + { + IPProtoAPGenerationOrModificationL(); + } +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + if (clearHiddenFlag) + { + iSession.ClearAttributeMask(ECDHidden); + } + } + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +CCDAPPrioritySelectionPolicyRecord* CCDValidatorConnPref::FindTheAPPrioritySelPolRecL(TInt aReferredIAPRecId) + { + //CCDConnectionPrefsRecord* ptrConnPref = static_cast(&iElement); + + CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = NULL; + + //1st step - Search for the AP which has its tagID with the same value as the + // recordNumber in the iDefaultIAP field in the ConnPref record or the calculated IAP number. + // This AP will be the AP on the Link layer. + + // This is a checking too to be sure that the AP is existing. + CMDBField* linkLayerAPTagIDField = new(ELeave) CMDBField(KCDTIdAccessPointRecord | KCDTIdRecordTag); + *linkLayerAPTagIDField = aReferredIAPRecId; + CleanupStack::PushL(linkLayerAPTagIDField); + + if (EDelete == iOperation || + linkLayerAPTagIDField->FindL(iSession.iOwner)) + { + //2nd step - Search for the default Tier in the GlobalSettings Record + // (The Global Settings record has to be stored before inserting + // the ConnectionPreferences record!!!!). + CMDBRecordLink* defaultTierField = new(ELeave) CMDBRecordLink(KCDTIdGlobalSettingsRecord | KCDTIdDefaultTier); + defaultTierField->SetRecordId(1); + CleanupStack::PushL(defaultTierField); + + //this field HAS to be in the GlobalSettings table as we are in 399 config... + defaultTierField->LoadL(iSession.iOwner); + + //3rd step - Follow the defaultAccessPoint link in the defaultTier record which points to + // the default AP record on the Network level. + TInt recId = (*defaultTierField) << 8; + CMDBRecordLink* networkDefAPField = + new(ELeave) CMDBRecordLink(recId | + KCDTIdDefaultAccessPoint); + CleanupStack::PushL(networkDefAPField); + + networkDefAPField->LoadL(iSession.iOwner); + + //4th step - Follow the link from the default AP record to the linked APPrioritySelPol record. + CMDBRecordLink* networkSelPolField = + new(ELeave) CMDBRecordLink(((*networkDefAPField) & KCDMaskShowRecordId) | + KCDTIdSelectionPolicy); + CleanupStack::PushL(networkSelPolField); + + networkSelPolField->LoadL(iSession.iOwner); + + //at this point we already know the complete elementId of the default APPrioritySelPol record. + //Read the whole record because it will be needed by the IPProto AP generation logic... + + defAPSelPolRec = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdApPrioritySelectionPolicyRecord)); + + CleanupStack::PushL(defAPSelPolRec); + + defAPSelPolRec->SetElementId(*networkSelPolField); + defAPSelPolRec->LoadL(iSession.iOwner); + + //we will transfer the ownership of this object to the IPProtoGenerator object + CleanupStack::Pop(defAPSelPolRec); + CleanupStack::PopAndDestroy(networkSelPolField); + CleanupStack::PopAndDestroy(networkDefAPField); + CleanupStack::PopAndDestroy(defaultTierField); + } + else + //The link layer AP is not existing. Leaving... + { + User::Leave(KErrNotFound); + } + + CleanupStack::PopAndDestroy(linkLayerAPTagIDField); + + return defAPSelPolRec; + } + + +void CCDValidatorConnPref::IPProtoAPGenerationOrModificationL() + { + CCDConnectionPrefsRecord* ptrConnPref = static_cast(iElement); + + TInt referredIAPRecId = 0; + + if (EModify == iOperation || + EStore == iOperation) + { + if (!(ptrConnPref->iDefaultIAP)) + /* There is no default IAP in the ConnPref record so this means that + * there is no default legacy path in the DB. + * + * - If the connpref record is prompting: + * Insert an ipproto AP with a cprconfig field which contains the + * full TMDBElementID of the given connpref record + * + * - If the connpref record is not prompting: + * - If the rank1 record is the record which has the 0 as the IAP field + * then: + * - if there is IAP in the DB: + * a default IAP has to be calculated + * - if there isn't any IAP rec: + * - if there is any default ipproto AP: + * the Default ipproto AP should be used here as the 399 path. + * - if there isn't any default ipproto AP: + * one should be generated and linked + * + * - If the rank2 record is modified like this then: + * - if there is IAP in the DB: + * a default IAP has to calculated + * - if there isn't any IAP rec: + * nothing can be done... + */ + { + if (1 == ptrConnPref->iRanking) + { + if (CommsDatMapperAndValidator::IsIAPRecInDB(iSession.iOwner)) + { + //there is IAP in the DB - > we can calculate a default one... + referredIAPRecId = FindIAPWithoutDefIAPL(); + } + else + { + //there is no IAP in the DB + CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = CommsDatMapperAndValidator::FindTheAPPrioritySelPolRecL(iSession.iOwner); + + CleanupStack::PushL(defAPSelPolRec); + + //Check whether the AP is already filled or not. + + // - If it's already filled this means that the IPProto level AP is already existing and + // needs to be modified only. + + // - If it's not existing yet this means that a new one has to be generated and all the links + // from or to the new record have to maintained. + CMDBRecordLink* apPrioritySelPolLink = + GetTheAPxLinkFromAPPrioritySelPol(defAPSelPolRec, + ptrConnPref->iRanking); + + __ASSERT_DEBUG(apPrioritySelPolLink, User::Panic(KCommsDatName,EWrongAPPrioritySelPolRecord)); + if (!apPrioritySelPolLink) + { + User::Leave(KErrArgument); + } + + CCDAccessPointRecord* defIPProtoAP = NULL; + + if (CommsDatMapperAndValidator::IsDefIPProtoAPInDB(iSession.iOwner)) + { + //there is an AP with the customSelPol field CCDAccessPointRecord::KNoPolicy. Use that record. + defIPProtoAP = CommsDatMapperAndValidator::GetTheDefIPProtoAP(iSession.iOwner); + CleanupStack::PushL(defIPProtoAP); + } + else + { + //there isn't any default ipproto AP -> have to generate one + defIPProtoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, + CCDAccessPointRecord::KNoPolicy, + iSession.iOwner); + + CleanupStack::PushL(defIPProtoAP); + + defIPProtoAP->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length()); + defIPProtoAP->iRecordName = KDefaultIPProtoRecName; + + //save the generated AP record + defIPProtoAP->StoreL(iSession.iOwner); + } + + TMDBElementId elemId = defIPProtoAP->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + //update the APPrioritySelPol record to point to the default IPProto AP record + CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolLink, + defAPSelPolRec, + elemId); + + defAPSelPolRec->ModifyL(iSession.iOwner); + + //modify the ipproto tier + CMDBRecordLink* ipProtoDefAccessPoint = new(ELeave)CMDBRecordLink(KCDTIdDefaultAccessPoint); + CleanupStack::PushL(ipProtoDefAccessPoint); + + TInt ipProtoRecId = CommsDatMapperAndValidator::GetIPProtoTierRecordIdL(iSession.iOwner); + ipProtoDefAccessPoint->SetRecordId(ipProtoRecId); + + *ipProtoDefAccessPoint = elemId; + ipProtoDefAccessPoint->ModifyL(iSession.iOwner); + + if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag)) + { + /* The dialogPref field has changed -> This means that: + * a) we have to create a 'prompting AP' which means that the AP has to + * contain the full TMDBElement ID of the given connpref record in its' + * CprConfig field (prompting connpref rec). + * b) the CprConfig field has to contain the IAP record number this + * IPProto AP points to (not prompting connpref rec). + */ + TBool isPromptingAPNeeded; + + if (ECommDbDialogPrefUnknown == ptrConnPref->iDialogPref || + ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref) + { + isPromptingAPNeeded = EFalse; + } + else + { + isPromptingAPNeeded = ETrue; + } + + if (isPromptingAPNeeded) + { + //the cprConfig has to contain the full TMDBElementId of the connpref record + defIPProtoAP->iCprConfig = ptrConnPref->ElementId(); + } + else + { + /* the cprConfig field has to contain the IAP record id + * Because this mapping/validation is done from a legacy configuration + * commsdat can assume here that there will be only 3 layers. + * + * The following line says that the IAP pointed by the cprConfig and the + * Link level AP pointed by the customSelectionPolicy field are the same. + */ + defIPProtoAP->iCprConfig.SetL(ptrConnPref->iDefaultIAP); + } + + defIPProtoAP->ModifyL(iSession.iOwner); + } + + CleanupStack::PopAndDestroy(ipProtoDefAccessPoint); + CleanupStack::PopAndDestroy(defIPProtoAP); + CleanupStack::PopAndDestroy(defAPSelPolRec); + + return; + } + } + else + { + //rank2 record is modified + if (CommsDatMapperAndValidator::IsIAPRecInDB(iSession.iOwner)) + { + //there is IAP in the DB - > we can calculate a default one... + referredIAPRecId = FindIAPWithoutDefIAPL(); + } + else + { + /* - there is no IAP in the DB + * - somebody is inserting a ranking2 connpref record + * + * Is this a normal case????? How should we handle it? + */ + return; + } + } + } + else + //There is a default IAP in the record so just read it... + //NOTE that this piece of code here assumes that the IAP in the ConnPref record is only a + // number and _NOT_ a fully qualified link!!! + { + referredIAPRecId = ptrConnPref->iDefaultIAP.GetL(); + } + } + + //1st step - Search for the AP which has its tagID with the same value as the + // recordNumber in the iDefaultIAP field in the ConnPref record or the calculated IAP number. + // This AP will be the AP on the Link layer. + + // This is a checking too to be sure that the AP is existing. + CMDBField* linkLayerAPTagIDField = new(ELeave) CMDBField(KCDTIdAccessPointRecord | KCDTIdRecordTag); + *linkLayerAPTagIDField = referredIAPRecId; + CleanupStack::PushL(linkLayerAPTagIDField); + + TBool foundLinkLayerAP = linkLayerAPTagIDField->FindL(iSession.iOwner); + + if (EDelete == iOperation || + foundLinkLayerAP ) + { + //CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = FindTheAPPrioritySelPolRecL(referredIAPRecId); + + CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = CommsDatMapperAndValidator::FindTheAPPrioritySelPolRecL(iSession.iOwner); + + CleanupStack::PushL(defAPSelPolRec); + + //Check whether the AP is already filled or not. + + // - If it's already filled this means that the IPProto level AP is already existing and + // needs to be modified only. + + // - If it's not existing yet this means that a new one has to be generated and all the links + // from or to the new record have to maintained. + CMDBRecordLink* apPrioritySelPolLink = + GetTheAPxLinkFromAPPrioritySelPol(defAPSelPolRec, + ptrConnPref->iRanking); + + __ASSERT_DEBUG(apPrioritySelPolLink, User::Panic(KCommsDatName,EWrongAPPrioritySelPolRecord)); + if (!apPrioritySelPolLink) + { + User::Leave(KErrArgument); + } + + if (*apPrioritySelPolLink) + //the AP field has been already filled so the IPProto level AP is already existing. Only + //modification is needed. + { + if (EModify == iOperation || + EStore == iOperation) + { + iIPProtoGenerator = new(ELeave) CIPProtoAPModifier(defAPSelPolRec, + *iElement, + iSession, + referredIAPRecId); + + //we transferred the ownership of this object to the IPProtoGenerator object + CleanupStack::Pop(defAPSelPolRec); + } + else + //The pointed AP should be deleted... + { + iIPProtoGenerator = new(ELeave) CIPProtoAPRemover(defAPSelPolRec, + *iElement, + iSession); + + //we transferred the ownership of this object to the IPProtoGenerator object + CleanupStack::Pop(defAPSelPolRec); + } + } + else + //the AP field has not been filled yet so creation is needed. + { + if (EModify == iOperation || + EStore == iOperation) + { + iIPProtoGenerator = new(ELeave) CIPProtoAPCreator(defAPSelPolRec, + *iElement, + iSession, + referredIAPRecId); + + //we transferred the ownership of this object to the IPProtoGenerator object + CleanupStack::Pop(defAPSelPolRec); + } + else + //hm... This is a delete operation and the AP field is not filled in the + //APPrioritySelPol record. Database is inconsistent - would be better to leave?? + { + CleanupStack::PopAndDestroy(defAPSelPolRec); + CleanupStack::PopAndDestroy(linkLayerAPTagIDField); + return; + } + } + + //Modify or generate the IPProto level AP. + iIPProtoGenerator->DoTheWorkL(); + } + else + //The link layer AP is not existing. Leaving... + { + User::Leave(KErrNotFound); + } + + CleanupStack::PopAndDestroy(linkLayerAPTagIDField); + } + + +/** +NOTE: This function is a modified copy from the void CCommsDbTableView::ConstructL(TUint32 aBearerSet, TCommDbConnectionDirection aDirection) + function (in the commdb/commdbshim/scdb/cdbtable.cpp)!! +*/ +TInt CCDValidatorConnPref::FindIAPWithoutDefIAPL() + { + CCDConnectionPrefsRecord* ptrConnPref = static_cast(iElement); + + CCDIAPRecord* iapRecord = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord)); + CleanupStack::PushL(iapRecord); + + CMDBField& direction = ptrConnPref->iDirection; + CMDBField& bearerSet = ptrConnPref->iBearerSet; + + TUint32 tempBearer = static_cast(bearerSet); + TCommDbConnectionDirection tempDirection = static_cast(direction); + + TBool defIAPFound = EFalse; + + TUint32 servTypeArrayStartIndex = 0; + + while ((!defIAPFound) && ((TInt)servTypeArrayStartIndex < KNumServiceType)) + { + TInt serviceTypeIndex = GetIAPServiceType( servTypeArrayStartIndex, (TCommDbBearer)tempBearer, tempDirection ); + __ASSERT_DEBUG(serviceTypeIndex!=KErrNotFound, User::Panic(KCommsDatName,EWrongIAPServiceType)); + if (KErrNotFound == serviceTypeIndex) + { + User::LeaveIfError(serviceTypeIndex); + } + + const TPtrC serviceType(KMap[serviceTypeIndex].serviceType); + + // prime the service type + iapRecord->iServiceType.SetMaxLengthL(serviceType.Length()); + iapRecord->iServiceType = serviceType; + + defIAPFound = iapRecord->FindL(iSession.iOwner); + if (!defIAPFound) + { + //No IAP record can be found with the given service + ++servTypeArrayStartIndex; + } + } + + if (!defIAPFound) + { + //No IAP record can be found with the given service(s) + User::Leave(KErrNotFound); + } + + + TInt tempRecId = iapRecord->RecordId(); + + CleanupStack::PopAndDestroy(iapRecord); + + return tempRecId; + } +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +void CCDValidatorConnPref::ValidateBearerAndDirectionL(const TDesC& aServiceType, TCommDbConnectionDirection aDirection, TUint32 aBearerSet, TCommDbDialogPref aDlgPref) + { + TCommDbConnectionDirection expectedDirection = ECommDbConnectionDirectionUnknown; + TInt expectedBearer = KCommDbBearerUnknown; + + if (aServiceType == TPtrC(DIAL_OUT_ISP)) + { + expectedDirection = ECommDbConnectionDirectionOutgoing; + expectedBearer = KCommDbBearerCSD; + } + else if (aServiceType == TPtrC(DIAL_IN_ISP)) + { + expectedDirection = ECommDbConnectionDirectionIncoming; + expectedBearer = KCommDbBearerCSD; + } + else if (aServiceType == TPtrC(OUTGOING_GPRS)) + { + expectedDirection = ECommDbConnectionDirectionOutgoing; + expectedBearer = KCommDbBearerWcdma; + } + else if (aServiceType == TPtrC(INCOMING_GPRS)) + { + expectedDirection = ECommDbConnectionDirectionIncoming; + expectedBearer = KCommDbBearerWcdma; + } + else if (aServiceType == TPtrC(LAN_SERVICE)) + { + expectedBearer = KCommDbBearerLAN | KCommDbBearerPAN | KCommDbBearerWLAN; + } + else if (aServiceType == TPtrC(VPN_SERVICE)) + { + expectedBearer = KCommDbBearerVirtual; + } + + TBool valid; + if (aDlgPref == ECommDbDialogPrefPromptIfWrongMode) + { + // this pref should only be used for PSD bearers + // if expectedBearer == KCommDbBearerWcdma then bearer set should + // include something other than KCommDbBearerWcdma + valid = (~expectedBearer & aBearerSet) != 0 && (expectedBearer == KCommDbBearerWcdma); + } + else if (aDlgPref == ECommDbDialogPrefPrompt) + { + // the expected bearer should be included in the bearer set + // along with any other bearer + + if (aServiceType == TPtrC(VPN_SERVICE)) + valid = ETrue; + else + valid = (expectedBearer & aBearerSet) != 0; + } + else + { + // no restriction on the dialog preference + valid = ETrue; + } + + if (valid) + { + valid = aDirection == expectedDirection || + expectedDirection == ECommDbConnectionDirectionUnknown; + } + + if (!valid) + User::Leave(KErrArgument); + } + + + +/************************ 2e) Validate IAP Record ************************************ +*/ + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + +// The relation of an IAP to its mapped AccessPoint records is as depicted below: +// +// IAP table (index == RecordId) AP table (index == Tag) +// --------- -------- +// +// +// ----- iCprConfig == 1 (a) ----- +// | 1|<------------------------------------| 1| +// | |- - - - - - - - - - - - - - - - - - >| |<----------- + +// ----- (inferred association) ----- | +// ^ | link AP | +// | | | +// | | | +// | | | +// | | | +// | | | +// | | iAccessPoint == 256 (b) ----- | +// | +-------------------------------------->| 256| iSelectionPolicy == 257 (c) +// | | |----+ | +// | ----- | | +// | net AP | | +// | | | +// | iCprConfig == 1 (a) ----- | | +// +-----------------------------------------| 257|<---+ | +// | |-------------+ +// ----- iSelectionPolicy == 1 (d) +// ipProto AP +// +// +// The following expressions are used to link the IAP and AP records: +// where: +// n = IAP record's recordId. +// B = the LinkBoundary (reserved Tags, currently 255) +// +// (a) = n +// (b) = B + 2n - 1 +// (c) = (b) + 1 +// (d) = n +// + +// The first 'KAPToIAPMappingThreshold' Tag Ids ('B' in the diagram above) are reserved for direct IAP to AP mapping, +// for those AP records where the index must match that of the RecordId of the corresponding IAP record. +// +// Note: +// We put the mapped AP's at the top of the permissible recordIds (being 254) and grows downwards. +// +// This should avoid colliding with any user created (either via input file, or dynamically). +// At time of writing, in the XML files, the RecordId cannot be specified (unlike in .cfg files) and a record's Id +// is calculated on the basis of its order of declaration in its table (in the markup). +// +// In .cfg files (where it is able and usual to specify the recordId - using the well known "# COMMDB_ID = x" +// statements) it is usual to start from 1 and count upwards. +// +// This might change, so is not included in the check at top of the function, when finding mapped AP records. +// +//static const TUint KAPToIAPTagMappingThreshold = 255; +static const TUint KAPToIAPRecordIdMappingConstant = 251; + +// TCleanupOperation function. +// +template +void DestroyRPointerArray(TAny* aPtr) + { + RPointerArray* self = static_cast*>(aPtr); + self->ResetAndDestroy(); + } + + +static const TUint32 KZero = 0; + +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +void CCDValidatorIAPRecord::DeleteAssociatedLinkLevelAPL() + { + CCDAccessPointRecord* linkAPRecord = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(linkAPRecord); + + linkAPRecord->iRecordTag = iElement->RecordId(); + + if (linkAPRecord->FindL(iSession.iOwner)) + { + linkAPRecord->DeleteL(iSession.iOwner); + } + + CleanupStack::PopAndDestroy(linkAPRecord); + } +#endif + +void CCDValidatorIAPRecord::ServiceAndBearerValidationL() + { +#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS + //at this point iElement has to be an IAP record!!! + CCDIAPRecord* iapRecord = static_cast(iElement); + + if (!iapRecord->iService.IsNull() && !iapRecord->iServiceType.IsNull()) + { + //this was caught in testing but actually it is not valid to have a real record without these fields... + + TMDBElementId tableTypeId = CommsDatSchemaV1_1::LookupTableId(iapRecord->iServiceType.GetL()); + iapRecord->iService = CommsDatSchema::GetLinkIdL(iSession.iOwner, iapRecord->iService.ElementId(), iapRecord->iService.GetL(), tableTypeId/*, &iapRecord*/); + } + + if (!iapRecord->iBearer.IsNull() && !iapRecord->iBearerType.IsNull()) + { + //this was caught in testing but actually it is not valid to have a real record without these fields... + + TMDBElementId tableTypeId = CommsDatSchemaV1_1::LookupTableId(iapRecord->iBearerType.GetL()); + iapRecord->iBearer = CommsDatSchema::GetLinkIdL(iSession.iOwner, iapRecord->iBearer.ElementId(), iapRecord->iBearer.GetL(), tableTypeId/*, &iapRecord*/); + } +#endif + } + + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +void CCDValidatorIAPRecord::AssociatedLinkLevelAPGenerationL() + { + + // map to AP record + + //at this point iElement has to be an IAP record!!! + CCDIAPRecord* iapRecord = static_cast(iElement); + + /* + some of this work is a bit like mapping, but + the IAP record is still present in the database so doing this as validation + */ + TInt err = KErrNone; + + //typedef enum {ENetworkAP, EIPProtocolAP, ELinkAP, EAPRecordIndicesLast = ELinkAP, EAPRecordIndicesRange = EAPRecordIndicesLast + 1} TAPRecordIndices; + + // Calculate the 3 potential AP indices + // + const TInt KThisIAPRecordId = iapRecord->RecordId(); + const TInt KLinkAPTag = KThisIAPRecordId; + //const TInt KNetworkAPTag = KAPToIAPTagMappingThreshold + (2 * KThisIAPRecordId) - 1; + //const TInt KIPProtoAPTag = KNetworkAPTag + 1; + + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::DoValidateL() - Processing IAP record <%d>"), + KThisIAPRecordId); + + + // 666 + // Should tidy these variables up into a class, but the turgidness of it all is just + // distracting from getting immediate objective of getting over-night build tests going. + // + // Create copies of these recordIds, not so clever. + // + + //const TInt KAPRecordIdsTable[] = {KNetworkAPTag, KIPProtoAPTag, KLinkAPTag}; + TUint numberOfAPRecordsFound = 0; + + //RPointerArray apRecords; + //CleanupStack::PushL(TCleanupItem(DestroyRPointerArray, &apRecords)); + + TBuf tempName; + _LIT(KMappedFrom, "MappedFromIAP"); + + // See which, if any of the records of interest exist already. + // + //for (TUint i = 0; i <= EAPRecordIndicesLast; i++) + // { + CCDAccessPointRecord* record = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(record); + //apRecords.InsertL(record, i); + + // Prime the search record and load it. + + TBool found = EFalse; + record->iRecordTag = KLinkAPTag; //KAPRecordIdsTable[i]; + TRAPD(loadErr, found = record->FindL(iSession.iOwner)); + + // Apply additional rules when validating, a mapped IAP must conform to. + // + if (loadErr == KErrNone && found) + { + _LIT(KAPNameCheckFormat, "%S%d"); + tempName.Format(KAPNameCheckFormat, &KMappedFrom, KThisIAPRecordId); + + // Its name should be that expected (ie which was applied by this function). + // + TPtrC tempPtr(static_cast(record->iRecordName)); + if (tempPtr.Find(tempName) != KErrNotFound + && record->iSelectionPolicy == 0) + + // And the selection policy and cpr config should conform to the diagram at the top of this function. + // + { + numberOfAPRecordsFound++; + } + } + if (loadErr != KErrNone && loadErr != KErrNotFound) + { + CleanupStack::PopAndDestroy(record); + record = NULL; + User::Leave(loadErr); + } + // } // for... + + + // Now let's evaluate what we've found. + // + if (numberOfAPRecordsFound == 0) + { + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::DoValidateL() - Creating AP record for IAP record <%d>"), + KThisIAPRecordId); + + // No AP records exist for this IAP, the IAP record therefore needs to be mapped. + + // Go on and create the 3 new AP records... neatly presented from top to bottom of stack. + + _LIT(KAPNameFormat, "%S%S%d"); + + + CCDAccessPointRecord *newAPRecord = + static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(newAPRecord); + + const TInt KBaseAPRecordId = KAPToIAPRecordIdMappingConstant - KThisIAPRecordId; + + // ... and finally the link record + + // The clean up stack handling of 'pBearerType' seems a bit contorted. + + CCDBearerTypeRecord* pBearerType = NULL; + TRAPD(ret, pBearerType = NewBearerTypeRecordL(iSession.iOwner, *iapRecord)); + if (ret != KErrNone || !pBearerType) + { + // Unfortunately, there are incorrect/unused IAPs in some of these configuration files (presumably they're dead). + // + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::DoValidateL() - error when mapping IAP record %d to its bearer"), + KThisIAPRecordId); + + if (pBearerType) + { + CleanupStack::PushL(pBearerType); + } + + // But since we're not aiming to validate their config files, don't flag error, otherwise we'll leave and + // the user will never get to create a (to them) usable database. + } + else if (ret == KErrNone && pBearerType) + { + CleanupStack::PushL(pBearerType); + + TPtrC name(pBearerType->iRecordName); + tempName.Format(KAPNameFormat, &name, &KMappedFrom, KThisIAPRecordId); + InitialiseAccessPointRecordL( + *newAPRecord, + tempName, + KBaseAPRecordId - KThisIAPRecordId, + KLinkAPTag, + pBearerType->iTier, + pBearerType->iMCpr, + KZero, + pBearerType->iCpr, + KZero, + pBearerType->iSCpr, + pBearerType->iProtocol); + newAPRecord->StoreL(iSession.iOwner); // 666 - TRAP + + TInt linkAPTagId = newAPRecord->iRecordTag; + + if (!CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(linkAPTagId, iSession.iOwner)) + { + //The IPProto AP is not existing yet. Generate one. + CCDAccessPointRecord* ipprotoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, linkAPTagId, iSession.iOwner); + CleanupStack::PushL(ipprotoAP); + + //save the generated AP record + ipprotoAP->StoreL(iSession.iOwner); + CleanupStack::PopAndDestroy(ipprotoAP); + } + + + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::DoValidateL() - Created AP records for IAP record <%d>"), + KThisIAPRecordId); + + // Update the IAP record itself to point to top-most AP tier record. + // + //thisIAPRecord->iAccessPoint = KNetworkAPTag; + } + else + { + // 666 All 1 expected AP records exist and the links between records make sense. + // So we assume that they have been correctly mapped already - perhaps have been called from ModifyL()? + // Do nothing + // + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::DoValidateL() - Found existing valid AP record for IAP record <%d>"), + KThisIAPRecordId); + } + + + if (pBearerType) + { + CleanupStack::PopAndDestroy(pBearerType); + } + CleanupStack::PopAndDestroy(newAPRecord); + } + + CleanupStack::PopAndDestroy(record); + + if (err != KErrNone) + { + //User::Leave(err); + __FLOG_STATIC2(KLogComponent, KCDErrLog, + _L("CCDValidatorIAPRecord::DoValidateL() - error <%d> when mapping IAP record <%d> to AP - indeterminate state"), + err, KThisIAPRecordId); + } + + } +#endif + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +void CCDValidatorIAPRecord::SetShadowElementL() + { + iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord); + iShadowElement->SetRecordId(iElement->RecordId()); + iShadowElement->LoadL(iSession.iOwner); + + if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //field validation + CMDBElement* shadowFieldPtr = static_cast(iShadowElement)->GetFieldByIdL(iElement->ElementId()); + + + if ( KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType) || + KCDTIdIAPServiceType == (iElement->ElementId() & KCDMaskShowType) || + KCDTIdIAPBearerType == (iElement->ElementId() & KCDMaskShowType) ) + { + CMDBField* nameField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + nameField->SetL(*origField); + } + else + { + //the only reason this cast can be done here is that the iap record contains only + //numerical based fields... (except the name, bearertype, servicetype fields -> handled above...) + CMDBField* numField = static_cast*>(shadowFieldPtr); + CMDBField* origField = static_cast*>(iElement); + + if (EDelete == iOperation) + { + numField->SetL(0); + } + else + { + numField->SetL(*origField); + } + } + } + + iElement = iShadowElement; + } +#endif + +void CCDValidatorIAPRecord::DoValidateL() +/* + 1/ Validate the record links for service and bearer records + ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + 2/ Create an AP record etc + endif SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +@internalComponent +*/ + { +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + if (EDelete == iOperation ) + { + if ( KCDMaskShowFieldType == (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //deleting a whole IAP record -> the associated AP record should be deleted as well + DeleteAssociatedLinkLevelAPL(); + } + else + { + //deleting only a field from the record. Here the validator checks the inegrity of the IAP record. + //So if the client deleted one of the bearer or service fields the integrity check won't be successful + //we have to copy the origElemId because the SetShadowElementL will reset it... + TUint origElemId = iElement->ElementId(); + + SetShadowElementL(); + ServiceAndBearerValidationL(); + + if ( KCDTIdIAPAppSid == (origElemId & KCDMaskShowType) ) + { + //this field has to be mapped to the associated AP + CMDBField* linkAPTagId = new(ELeave)CMDBField(KCDTIdAccessPointRecord | KCDTIdRecordTag); + CleanupStack::PushL(linkAPTagId); + + *linkAPTagId = iElement->RecordId(); + if (linkAPTagId->FindL(iSession.iOwner)) + { + CMDBField* appSidField = new(ELeave)CMDBField(KCDTIdAppSID); + CleanupStack::PushL(appSidField); + + appSidField->SetRecordId(linkAPTagId->RecordId()); + appSidField->DeleteL(iSession.iOwner); + + CleanupStack::PopAndDestroy(appSidField); + } + CleanupStack::PopAndDestroy(linkAPTagId); + } + } + } + else if (EStore == iOperation || + EModify == iOperation ) + { + if ( KCDMaskShowFieldType == (KCDMaskShowFieldType & iElement->ElementId()) ) + { + //ModifyL or StoreL is called on a record container + ServiceAndBearerValidationL(); + } + else + { + //it's a field modification + SetShadowElementL(); + ServiceAndBearerValidationL(); + } + + if (EModify == iOperation) + { + DeleteAssociatedLinkLevelAPL(); + } + + AssociatedLinkLevelAPGenerationL(); + } +#else + ServiceAndBearerValidationL(); +#endif + } // CCDMapperIAPRecord::DoValidateL() + + +void CCDValidatorIAPRecord::OnDeleteL() + { + // TODO Cleanup on deletion of IAP record (cleanup matching AP?) + // meanwhile do nothing + User::LeaveIfError(ETrue); + } + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +void CCDValidatorIAPRecord::InitialiseAccessPointRecordL( CCDAccessPointRecord& lhs, + const TDesC& aRecordName, + TInt aRecordId, + TInt aTag, + TUint32 aTier, + TUint32 aMCpr, + TUint32 aSelectionPolicy, + TUint32 aCpr, + TUint32 aCprConfig, + TUint32 aSCpr, + TUint32 aProtocol) + { + lhs.iRecordName.SetMaxLengthL(aRecordName.Length()); + lhs.iRecordName = aRecordName; + lhs.SetRecordId(aRecordId); + lhs.iRecordTag = aTag; + lhs.iTier = aTier; + lhs.iMCpr = aMCpr; + lhs.iSelectionPolicy = aSelectionPolicy; + lhs.iCpr = aCpr; + lhs.iCprConfig = aCprConfig; + lhs.iSCpr = aSCpr; + lhs.iProtocol = aProtocol; + + CCDIAPRecord* iapRecord = static_cast(iElement); + + lhs.iAppSID.SetL(iapRecord->iAppSid); + lhs.iPriority = KMaxTUint; + } +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +CCDBearerTypeRecord* CCDValidatorIAPRecord::NewBearerTypeRecordL(CMDBSession& aSessionOwner, CCDIAPRecord& aIAPRecord) + { + typedef enum {EModemBearer, ELANBearer, EVirtualBearer, TBearersLast = EVirtualBearer} TBearers; + + CCDBearerTypeRecord* pBearerType = NULL; + + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDValidatorIAPRecord::NewBearerTypeRecordL() - Searching for bearer-type for IAP <%d>"), + aIAPRecord.RecordId()); + + // Note: + // These constants and tables are all grouped together at the top of the function. + // + // When intelligent links are added to CommsDat, much of this, and associated code, should become redundant. + + // Lookup table of the relevant bearer string identifiers. + // Keys for the IAP record's 'iBearerType' field. + // + const TText* const KBearerLookupTable[] = + { + KCDTypeNameModemBearer, + KCDTypeNameLANBearer, + KCDTypeNameVirtualBearer + }; + + // Lookup table of the relevant TMDBElementIds + // + const TMDBElementId KBearerIdLookupTable[] = + { + KCDTIdModemBearerRecord, + KCDTIdLANBearerRecord, + KCDTIdVirtualBearerRecord + }; + + _LIT(KSpudNif, "spud"); + _LIT(KSpudNifPrefix, "spud-%S"); + _LIT(KOutgoingGPRS, "outgoinggprs"); + _LIT(KLowerNifKey, "lowernif="); + + + TBearers thisBearer = EModemBearer; + TBool found = EFalse; + if (!aIAPRecord.iBearerType.IsNull()) + { + TPtrC bearerType(aIAPRecord.iBearerType); + + for (TInt i = 0; i <= TBearersLast; i++) + { + if (bearerType.CompareF(TPtrC(KBearerLookupTable[i])) == 0) + { + thisBearer = static_cast(i); + __FLOG_STATIC1(KLogComponent, KCDInfoLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Found bearer-type <%d>"), + thisBearer); + found = ETrue; + break; + } + } + } + + + if (!found) + { + return pBearerType; + } + + + CCDBearerRecordBase* pBearer = static_cast(CCDRecordBase::RecordFactoryL(KBearerIdLookupTable[thisBearer])); + CleanupStack::PushL(pBearer); + + __FLOG_STATIC2(KLogComponent, KCDInfoLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Loading bearer record <%d>, for bearer-type <%d>"), + static_cast(aIAPRecord.iBearer), + thisBearer); + + pBearer->SetRecordId(aIAPRecord.iBearer); + pBearer->LoadL(aSessionOwner); + + + pBearerType = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdBearerTypeRecord)); + CleanupStack::PushL(pBearerType); + + + TBool keepGoing = ETrue; + + TBuf thisNifName; + + // Get the bearer's nif name (shouldn't the NifName be a member of the base class?, oh well, too late now). + // Requires horrible switch statement. + // + switch (thisBearer) + { + case EModemBearer: + { + // The usual modem bearer case is: + // + // ModemBearer[IAP.iBearer]->iNifName + // + // SPUD is an exception (if ModemBearer[IAP.iBearer]->iNifName == "SPUD"): + // + // OutgoingGPRS[IAP.Service]->iIfParame + // Extract the nif's name from the resultant string, of form "lowernif=xxxxx" + + + TPtrC nifName(static_cast(pBearer)->iNifName); + + if (nifName.CompareF(KSpudNif) == 0) + { + // Do "special" SPUD related processing to find the lowernif from the OutgoingGPRS table. + + TPtrC serviceType(aIAPRecord.iServiceType); + + // Check the expected service type + // + if (serviceType.CompareF(KOutgoingGPRS) == 0) + { + CCDOutgoingGprsRecord* pOutgoingGprs = + static_cast(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord)); + CleanupStack::PushL(pOutgoingGprs); + + // Load the associated OutgoingGPRS record. + + pOutgoingGprs->SetRecordId(aIAPRecord.iService); + pOutgoingGprs->LoadL(aSessionOwner); + + // Get the 'iGPRSIfParams' value. + + TPtrC gprsIfParams(static_cast(pOutgoingGprs)->iGPRSIfParams); + + // And search for the key and its value (which should be the Nif we want) + // + TInt lowerNifIndex = gprsIfParams.FindF(KLowerNifKey); + if (lowerNifIndex >= 0) + { + TPtrC lowerNifName = gprsIfParams.Mid(lowerNifIndex + KLowerNifKey().Length()); + + // Cannot work out how to use the iRecordName member itself to call Format() on. + + thisNifName.Format(KSpudNifPrefix, &lowerNifName); + } + else + { + __FLOG_STATIC1(KLogComponent, KCDErrLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Failed to find \"lowernif=\" for IAP record <%d>"), + aIAPRecord.RecordId()); + keepGoing = EFalse; + } + + CleanupStack::PopAndDestroy(pOutgoingGprs); + } + else + { + __FLOG_STATIC1(KLogComponent, KCDErrLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - unexpected SPUD bearer for IAP record <%d>"), + aIAPRecord.RecordId()); + keepGoing = EFalse; + } + } + else + { + // That's easy + thisNifName = nifName; + } + } + break; + + case ELANBearer: + { + TPtrC nifName(static_cast(pBearer)->iLanBearerNifName); + thisNifName = nifName; + } + break; + + case EVirtualBearer: + { + TPtrC nifName(static_cast(pBearer)->iVirtualBearerNifName); + thisNifName = nifName; + } + break; + + default: + keepGoing = EFalse; + break; + } + + + if (keepGoing) + { + __FLOG_STATIC2(KLogComponent, KCDInfoLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Looking up data for bearer-type <%S> for IAP <%d>"), + &thisNifName, + aIAPRecord.RecordId()); + + // The letters in the name of the bearer can appear in various cases. therefore + // convert the name of the bearer (however it was found) to lower-case letters. + // + // Note: + // Constraint is that the names of the bearer types in the preface file must also be lower-case. + // + thisNifName.LowerCase(); + pBearerType->iRecordName.SetMaxLengthL(thisNifName.Length()); + pBearerType->iRecordName = thisNifName; + + if (!pBearerType->FindL(aSessionOwner)) + { + __FLOG_STATIC2(KLogComponent, KCDErrLog, + _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Failed to find bearer-type <%S> for IAP <%d>"), + &thisNifName, + aIAPRecord.RecordId()); + + User::Leave(KErrNotFound); + } + } + + CleanupStack::Pop(pBearerType); + CleanupStack::PopAndDestroy(pBearer); + + return pBearerType; + } // NewBearerTypeRecordL() + +#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + + + +//---------- The IPProto AP handler classes ------------- + +/*virtual*/ void CIPProtoAPCreator::DoTheWorkL() + { + CCDConnectionPrefsRecord* ptrConnPref = static_cast(&iElement); + + CMDBRecordLink* apPrioritySelPolFieldToBeModified = + GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec, + ptrConnPref->iRanking); + CCDAccessPointRecord* ipprotoAP = NULL; + + TBool modified = EFalse; + TBool isIPProtoAPExisting = EFalse; + + if (ECommDbDialogPrefUnknown == ptrConnPref->iDialogPref || + ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref) + { + //this is a non prompting connpref rec + isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, + iSession.iOwner); + } + else + { + //this connpref rec is prompting so we need to consider the cprConfig field of the possibly + //existing IPProtoAP too + isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, + ptrConnPref->ElementId(), + iSession.iOwner); + } + + if (!isIPProtoAPExisting) + { + //The IPProto AP is not existing yet. Generate one. + ipprotoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, + iLinkAPTagId, + iSession.iOwner); + + CleanupStack::PushL(ipprotoAP); + + ipprotoAP->StoreL(iSession.iOwner); + + //modified = ETrue; + } + else + { + //The IPProto AP is already exsiting. Use that one. + ipprotoAP = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner); + + CleanupStack::PushL(ipprotoAP); + } + + + if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag)) + { + /* The dialogPref field has changed -> This means that: + * a) we have to create a 'prompting AP' which means that the AP has to + * contain the full TMDBElement ID of the given connpref record in its' + * CprConfig field (prompting connpref rec). + * b) the CprConfig field has to contain the IAP record number this + * IPProto AP points to (not prompting connpref rec). + */ + TBool isPromptingAPNeeded; + + if (ECommDbDialogPrefUnknown == ptrConnPref->iDialogPref || + ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref) + { + isPromptingAPNeeded = EFalse; + } + else + { + isPromptingAPNeeded = ETrue; + } + + if (isPromptingAPNeeded) + { + //the cprConfig has to contain the full TMDBElementId of the connpref record + ipprotoAP->iCprConfig = ptrConnPref->ElementId(); + } + else + { + /* the cprConfig field has to contain the IAP record id + * Because this mapping/validation is done from a legacy configuration + * commsdat can assume here that there will be only 3 layers. + * + * The fillowing line says that the IAP pointed by the cprConfig and the + * Link level AP pointed by the customSelectionPolicy field are the same. + */ + ipprotoAP->iCprConfig.SetL(ipprotoAP->iCustomSelectionPolicy); + } + + modified = ETrue; + } + + if (modified) + { + ipprotoAP->ModifyL(iSession.iOwner); + } + + TMDBElementId elemId = ipprotoAP->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + //a) update the APPrioritySelPol record to point to the newly creeated AP record + CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, + iAPSelPolRec, + elemId); + + + iAPSelPolRec->ModifyL(iSession.iOwner); + + //maintain the link from the IPProto Tier record + if (1 == ptrConnPref->iRanking) + { + CommsDatMapperAndValidator::ModifyDefaultTierRecordL(elemId, iSession.iOwner); + } + + CleanupStack::PopAndDestroy(ipprotoAP); + } + + + +/*virtual*/ void CIPProtoAPModifier::DoTheWorkL() + { + TBool modified = EFalse; + CCDConnectionPrefsRecord* ptrConnPref = static_cast(&iElement); + + CMDBRecordLink* apPrioritySelPolFieldToBeModified = + GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec, + ptrConnPref->iRanking); + + CCDAccessPointRecord* apRecordToBeModified = NULL; + + /* At this point we have to check: + * + * Is there any other link to this AP. + * If there is: + * ------------ + * a new AP should be generated and linked from the given + * APPrioritySelPol field + * + * If there isn't: + * --------------- + * Is there any other IPProto AP which contains the given link AP tagId + * in its' customSelPolField? + * If there is: + * No new AP should be generated but the already existing one + * should be used + * The AP which is not used anymore should be deleted + * + * If there isn't + * this means that the given AP can be modified. + */ + if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified, + iSession.iOwner)) + { + /* There is only 1 reference to this AP. Here the following should be considered: + * If there is already an IPProto AP whith the given link AP tagId value in the customselPol field + * no new AP should be generated but the one should be used, and the old one should be deleted!. + * If there is no AP with the given link AP tagId value in the customselPol field + * a new one should be generated. + */ + + if (!CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, iSession.iOwner)) + { + //ok, there is no AP with the given customSelPol field + apRecordToBeModified = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(apRecordToBeModified); + + apRecordToBeModified->SetElementId(*apPrioritySelPolFieldToBeModified); + + apRecordToBeModified->LoadL(iSession.iOwner); + } + else + { + //there is already an AP with the given customSelPol field + //delete the currently used IPProto AP + apRecordToBeModified = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner); + + CleanupStack::PushL(apRecordToBeModified); + + CCDAccessPointRecord* apRecordToBeDeleted = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(apRecordToBeDeleted); + //DeleteL needs the '7F' in the FieldType... + apRecordToBeDeleted->SetElementId(*apPrioritySelPolFieldToBeModified | KCDMaskShowFieldType); + + if (apRecordToBeDeleted->RecordId() != apRecordToBeModified->RecordId()) + { + //we can delete the actual AP... + apRecordToBeDeleted->DeleteL(iSession.iOwner); + + TMDBElementId elemId = apRecordToBeModified->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + //update the APPrioritySelPol record to point to the newly creeated AP record + CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, + iAPSelPolRec, + elemId); + } + + CleanupStack::PopAndDestroy(apRecordToBeDeleted); + + } + } + else + { + /* There is more than 1 link to the given AP record. + * If we would modify it with the same Link level TagId -> no necessary to do anything... + * This could happen if we processed already the IAPPrioritySelPol record and there + * is a ConnPref record too where the default IAP is the same as in the orig + * IAPPriorioritySelPol record. + * If it's a different Link level TagId -> Can't modify the AP instead create a new one. + */ + + TBool isIPProtoAPExisting = EFalse; + + if (ECommDbDialogPrefUnknown == ptrConnPref->iDialogPref || + ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref) + { + //this is a non prompting connpref rec + isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, + iSession.iOwner); + } + else + { + //this connpref rec is prompting so we need to consider the cprConfig field of the possibly + //existing IPProtoAP too + isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, + ptrConnPref->ElementId(), + iSession.iOwner); + } + + if (isIPProtoAPExisting) + { + //the given IPProto is already existing with the received Link TagId (and cprConfig + //field if the connpref is prompting). Let's use that one + apRecordToBeModified = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner); + + CleanupStack::PushL(apRecordToBeModified); + + } + else + { + apRecordToBeModified = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, + iLinkAPTagId, + iSession.iOwner); + + CleanupStack::PushL(apRecordToBeModified); + + //save the generated AP record + apRecordToBeModified->StoreL(iSession.iOwner); + } + + TMDBElementId elemId = apRecordToBeModified->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + //update the APPrioritySelPol record to point to the newly creeated AP record + CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, + iAPSelPolRec, + elemId); + } + + if (0 != apRecordToBeModified->iSelectionPolicy) + //it is possible from the cfg files that the iSelectionPolicy field is used to link to the + //link layer AP. If this is the case it should be 0ed. + { + apRecordToBeModified->iSelectionPolicy.SetL(0); + modified = ETrue; + } + + if (apRecordToBeModified->iCustomSelectionPolicy != iLinkAPTagId) + { + apRecordToBeModified->iCustomSelectionPolicy.SetL(iLinkAPTagId); + apRecordToBeModified->iCprConfig.SetL(iLinkAPTagId); + modified = ETrue; + } + + /* This is just cosmetics here. If we modify the default IPProto AP, which is + * coming from the meshpreface, then the name of the record should be modified. + */ + TPtrC recName(apRecordToBeModified->iRecordName); + if (0 == recName.Compare(KDefaultIPProtoRecName)) + { + //buffer for the record name + TBuf recordName; + CommsDatMapperAndValidator::GenerateRecordName(recordName, apRecordToBeModified->iRecordTag); + apRecordToBeModified->iRecordName.SetMaxLengthL(recordName.Length()); + apRecordToBeModified->iRecordName = recordName; + modified = ETrue; + } + + if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag)) + { + /* The dialogPref field has changed -> This means that: + * a) we have to create a 'prompting AP' which means that the AP has to + * contain the full TMDBElement ID of the given connpref record in its' + * CprConfig field (prompting connpref rec). + * b) the CprConfig field has to contain the IAP record number this + * IPProto AP points to (not prompting connpref rec). + */ + TBool isPromptingAPNeeded; + + if (ECommDbDialogPrefUnknown == ptrConnPref->iDialogPref || + ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref) + { + isPromptingAPNeeded = EFalse; + } + else + { + isPromptingAPNeeded = ETrue; + } + + if (isPromptingAPNeeded) + { + //the cprConfig has to contain the full TMDBElementId of the connpref record + apRecordToBeModified->iCprConfig = ptrConnPref->ElementId(); + } + else + { + /* the cprConfig field has to contain the IAP record id + * Because this mapping/validation is done from a legacy configuration + * commsdat can assume here that there will be only 3 layers. + * + * The following line says that the IAP pointed by the cprConfig and the + * Link level AP pointed by the customSelectionPolicy field are the same. + */ + apRecordToBeModified->iCprConfig.SetL(apRecordToBeModified->iCustomSelectionPolicy); + } + + modified = ETrue; + } + + iAPSelPolRec->ModifyL(iSession.iOwner); + + if (modified) + { + apRecordToBeModified->ModifyL(iSession.iOwner); + } + + //maintain the link from the IPProto Tier record + if (1 == ptrConnPref->iRanking) + { + TMDBElementId elemId = apRecordToBeModified->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + CommsDatMapperAndValidator::ModifyDefaultTierRecordL(elemId, iSession.iOwner); + } + + + + /* one last checking: if there is another IPProto AP with the same cusomtSelPol + * and CprConfig fields then only 1 can be in the database the other should be deleted. + */ + if (CommsDatMapperAndValidator::GetNumberOfThisIPProtoAPL(apRecordToBeModified, iSession.iOwner) > 1) + { + //this means that we have 2 IPProto AP with the same CustomSelPol and CprConfig + //fields + + //Correct the links from the defaultTier and APPriotySelPol links + //This is the elementId which will be deleted + CommsDatMapperAndValidator::CorrectLinksL(apRecordToBeModified->ElementId(), iSession.iOwner); + + //delete the AP + apRecordToBeModified->DeleteL(iSession.iOwner); + } + + CleanupStack::PopAndDestroy(apRecordToBeModified); + } + +/*virtual*/ void CIPProtoAPRemover::DoTheWorkL() + { + CCDConnectionPrefsRecord* ptrConnPref = static_cast(&iElement); + + + CMDBRecordLink* apPrioritySelPolFieldToBeModified = + GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec, + ptrConnPref->iRanking); + + CCDAccessPointRecord* ipprotoAPRec = NULL; + + + + //if this was a ranking1 AP then the tier record has to be modified too... + if (1 == ptrConnPref->iRanking) + { + /** + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + The RANK1 connpref record is deleted which means that there is no default legacy path + in the database. In the 399 architecture in this case we create the default IPProto AP + which is in the meshpreface file by default (it's possible that it's overwritten) so + we modify the current AP by not deleting it but modifying it to contain the CCDAccessPointRecord::KNoPolicy value + in its' CustomSelectionPolicy field. + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified, + iSession.iOwner)) + { + //ok there is only 1 link to this AP -> we can modify it + + ipprotoAPRec = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(ipprotoAPRec); + + ipprotoAPRec->SetRecordId((*apPrioritySelPolFieldToBeModified & KCDMaskShowRecordId) >> 8); + + + ipprotoAPRec->LoadL(iSession.iOwner); + + ipprotoAPRec->iCustomSelectionPolicy = CCDAccessPointRecord::KNoPolicy; + + ipprotoAPRec->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length()); + ipprotoAPRec->iRecordName = KDefaultIPProtoRecName; + + ipprotoAPRec->iCprConfig = 0; + + ipprotoAPRec->ModifyL(iSession.iOwner); + } + else + { + //a new default AP should be generated + ipprotoAPRec = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, + CCDAccessPointRecord::KNoPolicy, + iSession.iOwner); + + CleanupStack::PushL(ipprotoAPRec); + + ipprotoAPRec->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length()); + ipprotoAPRec->iRecordName = KDefaultIPProtoRecName; + + //save the generated AP record + ipprotoAPRec->StoreL(iSession.iOwner); + + + TMDBElementId elemId = ipprotoAPRec->ElementId(); + elemId &= KCDMaskHideAttrAndRes; + TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId; + elemId &= tableAndRecordBitMask; + + //update the APPrioritySelPol record to point to the newly creeated AP record + CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, + iAPSelPolRec, + elemId); + + iAPSelPolRec->ModifyL(iSession.iOwner); + + //modify the IPProto tier to point to this new default AP + CMDBRecordLink* ipProtoDefAccessPoint = new(ELeave)CMDBRecordLink(KCDTIdDefaultAccessPoint); + CleanupStack::PushL(ipProtoDefAccessPoint); + + TInt ipProtoRecId = CommsDatMapperAndValidator::GetIPProtoTierRecordIdL(iSession.iOwner); + ipProtoDefAccessPoint->SetRecordId(ipProtoRecId); + + *ipProtoDefAccessPoint = elemId; + ipProtoDefAccessPoint->ModifyL(iSession.iOwner); + + CleanupStack::PopAndDestroy(ipProtoDefAccessPoint); + } + //no further modification is needed here... + } + else + { + //RANK2 record is deleted + iAPSelPolRec->iApCount.SetL(1); + + if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified, + iSession.iOwner)) + { + //ok, there is only 1 link to this AP -> it can be deleted + ipprotoAPRec = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord)); + + CleanupStack::PushL(ipprotoAPRec); + + ipprotoAPRec->SetRecordId((*apPrioritySelPolFieldToBeModified & KCDMaskShowRecordId) >> 8); + + ipprotoAPRec->DeleteL(iSession.iOwner); + } + + //update the APPrioritySelPol record. + *apPrioritySelPolFieldToBeModified = 0; + iAPSelPolRec->ModifyL(iSession.iOwner); + } + + if (ipprotoAPRec) + { + CleanupStack::PopAndDestroy(ipprotoAPRec); + } + } +#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY +//EOF