diff -r cd501b96611d -r ece3df019add authenticationservices/authenticationserver/source/common/authexpression.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authenticationservices/authenticationserver/source/common/authexpression.cpp Tue Nov 24 09:06:03 2009 +0200 @@ -0,0 +1,891 @@ +/* +* Copyright (c) 2005-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 "authcommon_impl.h" +#include + +using namespace AuthServer; + +const TInt CAuthExpressionImpl::KVersion = 1; + +// -------- TAuthExpressionWrapper -------- + + +TAuthExpressionWrapper::TAuthExpressionWrapper(CAuthExpression* aExpression) +/** + This constructor stores the supplied expression pointer. + + @param aExpression A pointer to the supplied expression + is stored in the TAuthExpressionWrapper + object. On exit, this object owns + the expression. + */ +: iPtr(aExpression) + { + // empty. + } + + +TAuthExpressionWrapper::TAuthExpressionWrapper(TAuthPluginType aType) +/** + Allocates a new instance of CAuthExpressionImpl which + describes the supplied plugin type. If there is not + enough memory, the pointer is NULL on exit. + + @param aType Plugin type used to create new instance + of CAuthExpressionImpl. + */ +: iPtr(new CAuthExpressionImpl(aType)) + { + // empty. + } + + +TAuthExpressionWrapper::TAuthExpressionWrapper(TPluginId aPluginId) +/** + Allocates a new instance of CAuthExpressionImpl which + describes the supplied plugin ID. If there is not + enough memory, the pointer is NULL on exit. + + @param aPluginId Value which describes a specific plugin. + */ +: iPtr(new CAuthExpressionImpl(aPluginId)) + { + // empty. + } + +TAuthExpressionWrapper::TAuthExpressionWrapper() +/** + Allocates a new instance of CAuthExpressionImpl which + describes the default plugin ID. If there is not + enough memory, the pointer is NULL on exit. + + */ +: iPtr(new CAuthExpressionImpl()) + { + // empty. + } + +// -------- factory functions -------- + + +static CAuthExpressionImpl* AuthComb( + CAuthExpressionImpl::TType aType, CAuthExpressionImpl* aLeft, CAuthExpressionImpl* aRight); + + +EXPORT_C TAuthExpressionWrapper AuthServer::AuthExpr(TAuthPluginType aType) +/** + Returns a wrapper around a new authentication expression. + + @param aType Identifies a type of plugin. + @return Wrapper object for an instance + of CAuthExpressionImpl. The authentication + expression is allocated on the heap, + and is NULL if there is not + enough memory. + */ + { + return TAuthExpressionWrapper(aType); + } + + +EXPORT_C TAuthExpressionWrapper AuthServer::AuthExpr(TPluginId aPluginId) +/** + Returns a wrapper around a new authentication expression. + + @param aPluginId Identifies a specific plugin. + @return Wrapper object for an instance + of CAuthExpressionImpl. The authentication + expression is allocated on the heap, + and is NULL if there is not + enough memory. + */ + { + return TAuthExpressionWrapper(aPluginId); + } + +EXPORT_C TAuthExpressionWrapper AuthServer::AuthExpr() +/** + Returns a wrapper around a new authentication expression. + + @return Wrapper object for an instance + of CAuthExpressionImpl. The authentication + expression is allocated on the heap, + and is NULL if there is not + enough memory. + */ + { + return TAuthExpressionWrapper(); + } + +EXPORT_C TAuthExpressionWrapper AuthServer::AuthOr(CAuthExpression* aLeft, CAuthExpression* aRight) +/** + Allocate a CAuthExpressionImpl node which combines the supplied + left and right nodes as an OR operation. + + If either aLeft or aRight are NULL, or this operation fails + to allocate the required memory, then any allocated memory + is cleaned up NULL is returned. + + @param aLeft Left node. This must be an instance + of CAuthExpresionImpl. + @param aRight Right node. This must be an instance + of CAuthExpresionImpl. + @return New wrapper around CAuthExpression, NULL + if could not allocate, or if either the + supplied nodes were NULL. + */ + { + CAuthExpressionImpl* leftImpl = static_cast(aLeft); + CAuthExpressionImpl* rightImpl = static_cast(aRight); + return AuthComb(CAuthExpressionImpl::EOr, leftImpl, rightImpl); + } + + +EXPORT_C TAuthExpressionWrapper AuthServer::AuthAnd(CAuthExpression* aLeft, CAuthExpression* aRight) +/** + Allocate a CAuthExpressionImpl node which combines the supplied + left and right nodes as an AND operation. + + If either aLeft or aRight are NULL, or this operation fails + to allocate the required memory, then the subexpressions are + deleted and this function returns NULL. + + @param aLeft Left node. + @param aRight Right node. + @return New wrapper around CAuthExpression, NULL + if could not allocate, or if either the + supplied nodes were NULL. + @see AuthOr + */ + { + CAuthExpressionImpl* leftImpl = static_cast(aLeft); + CAuthExpressionImpl* rightImpl = static_cast(aRight); + return AuthComb(CAuthExpressionImpl::EAnd, leftImpl, rightImpl); + } + + +static CAuthExpressionImpl* AuthComb( + CAuthExpressionImpl::TType aType, CAuthExpressionImpl* aLeft, CAuthExpressionImpl* aRight) +/** + Helper function for AuthOr and AuthAnd. This function + allocates the combining node, storing the combining method (AND + or OR) and pointers to the left and right nodes. + + If aLeft or aRight are NULL on entry, or this function cannot + allocate the required memory, then any previously allocated nodes + are freed, and this function returns NULL. + + @param aType Type of expression, AND/OR + @param aLeft Left node. + @param aRight Right node. + @return New wrapper around CAuthExpression, NULL + if could not allocate, or if either the + supplied nodes were NULL. + @see AuthAnd + @see AuthOr + */ + { + CAuthExpressionImpl* compound = 0; + + if (aLeft == 0 || aRight == 0) + goto failed; + + compound = new CAuthExpressionImpl(aType, aLeft, aRight); + if (compound == 0) + goto failed; + + return compound; + +failed: + delete aLeft; + delete aRight; + + return 0; + } + + +// -------- TSizeStream -------- + + +EXPORT_C void TSizeStream::DoWriteL(const TAny* /* aPtr */, TInt aLength) +/** + Override MStreamBuf by incrementing the + accumulated size by aLength. + + @param aLength Length of data to write to stream. + */ + { + iSize += aLength; + } + + +// -------- CAuthExpressionImpl -------- + + +#ifdef _DEBUG +#define VAR_FOLLOWS(___c, ___v1, ___v2) \ + (_FOFF(___c, ___v2) >= _FOFF(___c, ___v1) + sizeof(___c::___v1)) +#endif + + +CAuthExpressionImpl::CAuthExpressionImpl(TAuthPluginType aType) +: iType(EPluginType), + iPluginType(aType) +/** + Initialise this leaf node authentication expression + as describing a plugin type. + + @param aType Identifies a type of plugin. + @panic AUTHEXPR 16 This constructed object is internally + inconsistent (debug only.) + */ + { +#ifdef _DEBUG + // non-aligned value to detect invalid node pointers + __ASSERT_COMPILE(VAR_FOLLOWS(CAuthExpressionImpl, iPluginType, iComb.iRight)); + iComb.iRight = (CAuthExpressionImpl*)0xB51DE; +#endif + + __ASSERT_DEBUG(Invariant(), Panic(ECtTyInvariant)); + } + + +CAuthExpressionImpl::CAuthExpressionImpl(TPluginId aPluginId) +/** + Initialise this leaf node authentication expression + as describing a specific plugin. + + @param aPluginId Identifies a specific plugin. + @panic AUTHEXPR 32 This constructed object is internally + inconsistent (debug only.) + */ +: iType(EPluginId), + iPluginId(aPluginId) + { +#ifdef _DEBUG + // non-aligned value to detect invalid node pointers + __ASSERT_COMPILE(VAR_FOLLOWS(CAuthExpressionImpl, iPluginId, iComb.iRight)); + iComb.iRight = (CAuthExpressionImpl*)0xB51DE; +#endif + + __ASSERT_DEBUG(Invariant(), Panic(ECtIdInvariant)); + } + +CAuthExpressionImpl::CAuthExpressionImpl() +/** + Initialise this leaf node authentication expression + as describing a specific plugin. + + @panic AUTHEXPR 32 This constructed object is internally + inconsistent (debug only.) + */ +: iType(ENull) + { +#ifdef _DEBUG + // non-aligned value to detect invalid node pointers + __ASSERT_COMPILE(VAR_FOLLOWS(CAuthExpressionImpl, iPluginId, iComb.iRight)); + iComb.iRight = (CAuthExpressionImpl*)0xB51DE; +#endif + + __ASSERT_DEBUG(Invariant(), Panic(ECtIdInvariant)); + + } + + +CAuthExpressionImpl::CAuthExpressionImpl(TType aType, CAuthExpressionImpl* aLeft, CAuthExpressionImpl* aRight) +/** + Initialise a complex - AND or OR - expression. + + @param aType The type of combination. The only + allowed values are EAnd and EOr. + @param aLeft Left expression. This cannot be NULL. + @param aRight Right expression. This cannot be NULL. + @panic AUTHEXPR 48 Called with expression type that was + neither AND nor OR (debug only.) + @panic AUTHEXPR 49 Called with NULL left node (debug only.) + @panic AUTHEXPR 50 Called with NULL right node (debug only.) + @panic AUTHEXPR 51 This object is internally inconsistent + after construction (debug only.) + */ +: iType(aType) + { + __ASSERT_DEBUG(aType == EAnd || aType == EOr, Panic(ECt2BadComb)); + __ASSERT_DEBUG(aLeft != 0, Panic(ECt2NullLeft)); + __ASSERT_DEBUG(aRight != 0, Panic(ECt2NullRight)); + + iComb.iLeft = aLeft; + iComb.iRight = aRight; + aLeft->iParent = aRight->iParent = this; + + __ASSERT_DEBUG(Invariant(), Panic(ECt2Invariant)); + } + + +CAuthExpressionImpl::~CAuthExpressionImpl() +/** + Deletes resources used by this expression. If this is a complex + expression then it deletes the subexpression nodes. + */ + { + // by construction iType is always correctly initialized + // before this function is called. + if (iType == EAnd || iType == EOr) + { + delete iComb.iLeft; + delete iComb.iRight; + } + } + + +EXPORT_C void CAuthExpressionImpl::ExternalizeL(RWriteStream& aWriteStream) const +/** + Write a persistent version of this object to the supplied + stream. This function is used to transfer the expression + to the authentication server. + + @param aWriteStream Stream to write object to. + @panic AUTHEXPR 160 This object is internally inconsistent + when this function is called. + */ + { + __ASSERT_DEBUG(Invariant(), Panic(EExtInvariant)); + + aWriteStream.WriteInt8L(KVersion); + Externalize2L(aWriteStream); + } + + +void CAuthExpressionImpl::Externalize2L(RWriteStream& aWriteStream) const +/** + Helper function for ExternalizeL. This function writes + a persistent version of this expression object, including + any subexpressions, to the supplied stream. + + @param aWriteStream Stream to write object to. + @panic AUTHEXPR 144 This object is internally inconsistent + when this function is called. + */ + { + __ASSERT_DEBUG(Invariant(), Panic(EExtInvariant)); + + aWriteStream.WriteInt8L(iType); + + switch (iType) + { + case EAnd: + case EOr: + iComb.iLeft->Externalize2L(aWriteStream); + iComb.iRight->Externalize2L(aWriteStream); + break; + + case EPluginId: + aWriteStream.WriteInt32L(iPluginId); + break; + + case EPluginType: + aWriteStream.WriteInt32L(iPluginType); + break; + + case ENull: + aWriteStream.WriteInt32L(iPluginId); + break; + default: + // this case should not be reached because this + // object has passed the invariant. + break; + } + } + + +// restore the encoded authentication expression + + +EXPORT_C CAuthExpressionImpl* CAuthExpressionImpl::NewL(RReadStream& aReadStream) +/** + Factory function reconstructs an authentication + expression from the supplied stream. + + @param aReadStream Stream containing externalized + authentication expression. This must + have been generated with CAuthExpressionImpl::ExternalizeL. + @return Authorisation expression internalized + from the supplied stream. + @leave KErrNoMemory Not enough memory to reconstruct the expression. + @leave KErrInternalizeInvalidAuthExpr The supplied stream does not + describe a valid authentication expression. + @leave KErrAuthServUnsupportedExprVersion The supplied stream + was created with a later version of CAuthExpressionImpl. + @see CAuthExpressionImpl::ExternalizeL + */ + { + TInt8 ver = aReadStream.ReadInt8L(); + if (ver > KVersion) + User::Leave(KErrAuthServUnsupportedExprVersion); + + return New2L(aReadStream); + } + +CAuthExpressionImpl* CAuthExpressionImpl::New2L(RReadStream& aReadStream) +/** + Helper function for NewL. This recursively constructs the + authentication expression after NewL has checked that it + supports the encoded version. + + @param aReadStream Stream containing externalized + authentication expression. This must + have been generated with CAuthExpressionImpl::ExternalizeL. + @return Authorisation expression internalized + from the supplied stream. + @leave KErrNoMemory Not enough memory to reconstruct the expression. + @leave KErrInternalizeInvalidAuthExpr The supplied stream does not + describe a valid authentication expression. + @see CAuthExpressionImpl::ExternalizeL + */ + { + CAuthExpressionImpl::TType t; + t = static_cast(aReadStream.ReadInt8L()); + + switch(t) + { + case CAuthExpressionImpl::EAnd: + case CAuthExpressionImpl::EOr: + { + CAuthExpressionImpl* left = CAuthExpressionImpl::New2L(aReadStream); + CleanupStack::PushL(left); + CAuthExpressionImpl* right = CAuthExpressionImpl::New2L(aReadStream); + CleanupStack::PushL(right); + CAuthExpressionImpl* complex = new(ELeave) CAuthExpressionImpl(t, left, right); + CleanupStack::Pop(2, left); // complex now owns left and right + return complex; + } + + case CAuthExpressionImpl::EPluginId: + return new(ELeave) CAuthExpressionImpl( + static_cast(aReadStream.ReadInt32L())); + + case CAuthExpressionImpl::EPluginType: + return new(ELeave) CAuthExpressionImpl( + static_cast(aReadStream.ReadInt32L())); + + + case CAuthExpressionImpl::ENull: + return new(ELeave) CAuthExpressionImpl(); + + default: + User::Leave(KErrAuthServInvalidInternalizeExpr); + return 0; // avoid 'return value expected' warning + } + } + +/** + Helper function which converts the string into a form that can + be processed as tokens by TLex.Essentially, this method parses and appends + space in the input string when delimiters("(",")","&" and "|") are + encountered, consequenty the resultant string thus obtained can be parsed + using TLex. + + @param aStringToBeProcessed string to be processed. + @param aResultantString a buffer which does not already own any allocated memory, and is populated + with a string resulting from processing aStringToBeProcessed. + + */ + +EXPORT_C void CAuthExpressionImpl::InsertSpaceBetweenOperatorsL(const TDesC& aStringToBeProcessed, RBuf& aResultantString) + { + TChar ch = 0; + _LIT(KSeparator, " "); + HBufC* strBuffer = HBufC::NewLC(KMaxBufferSize); + TPtr strPtr(strBuffer->Des()); + + // length of 2 KSeparator and 1 ch. + const TInt KAddLength = 3; + + for(TInt i = 0; i < aStringToBeProcessed.Length(); ++i) + { + ch = aStringToBeProcessed[i]; + + // check whether appending 3 characters(2 KSeparator and 1 ch) to + // aResultantAliasString exceeds the Maxlength. + TInt resultingLen = strPtr.Length() + KAddLength; + if(resultingLen > KMaxBufferSize) + { + strBuffer->ReAllocL(resultingLen); + } + + if(ch == '(' || ch == ')' || ch == '&' || ch == '|') + { + strPtr.Append(KSeparator); + strPtr.Append(ch); + strPtr.Append(KSeparator); + } + + else + { + strPtr.Append(ch); + } + } + + CleanupStack::Pop(strBuffer); + aResultantString.Assign(strBuffer); + } + +/** + Creates CAuthExpression object from a string defining an authentication. + strength.The ownership of CAuthExpression object is transferred to the caller. + + @param aStrengthAliasString a string defining an authentication. + strength obtained from the authserver cenrep file. + + @return CAuthExpression object. + + @leave KErrAuthServInvalidAliasStringExpression, when aStrengthAliasString contains tokens other than pluginId, pluginType + and operators '&', '|', '(' and ')' + + */ + + EXPORT_C CAuthExpression* CAuthExpressionImpl::CreateAuthExprObjectL(const TDesC& aStrengthAliasString) + { + RBuf resultantAliasString; + CleanupClosePushL(resultantAliasString); + + // tokenize aStrengthAliasString, to facilitate parsing using TLex. + InsertSpaceBetweenOperatorsL(aStrengthAliasString, resultantAliasString); + + // facilitates ordering of expression evaluation via brackets. + CAuthExpression* authExpression = EvaluateAliasStringL(resultantAliasString); + CleanupStack::PopAndDestroy(); + + return authExpression; + } + + + /** + This method facilitates ordering of alias string expression (containing pluginIds or pluginTypes + or a combination of both) evaluation via brackets.The ownership of CAuthExpression object is + transferred to the caller. + + @param aStrengthAliasString an alias string to be parsed and processed.This must be enclosed within brackets. + + @return CAuthExpression object. + + @leave KErrAuthServInvalidAliasStringExpression, when aStrengthAliasString contains tokens other than pluginId, pluginType + and operators('&', '|') and brackets. + + */ + + CAuthExpression* CAuthExpressionImpl::EvaluateAliasStringL(const RBuf& aStrengthAliasString) + { + TLex input(aStrengthAliasString); + + // array of operators (& and |) and brackets. + const TInt KGranularity = 8; + CArrayFixFlat* opStack = new(ELeave) CArrayFixFlat(KGranularity); + CleanupStack::PushL(opStack); + + // array of CAuthExpression objects. + RPointerArray authExpressionArray; + CleanupResetAndDestroyPushL(authExpressionArray); + + for (TPtrC token = input.NextToken(); token.Size() > 0 ; + token.Set(input.NextToken())) + { + TInt count = 0; + TInt index = 0; + if(token.CompareF(KAuthOpOr) == 0) + { + count = opStack->Count(); + index = count - 1; + // only when the previous element in the opStack is not "&" , will token be added on the opStack. + if(index >= 0 && opStack->At(index) != KAuthOpAnd) + { + opStack->AppendL(token); + } + + else + { + // atleast 1 element in opStack is "&",hence iterate through opStack and + // keep creating auth expression object until the loop ends. + while(index >= 0 && opStack->At(index) == KAuthOpAnd) + { + CAuthExpression* authExpr = CreateAuthExpressionL(authExpressionArray, opStack->At(index)); + opStack->Delete(index); + opStack->Compress(); + CleanupStack::PushL(authExpr); + authExpressionArray.AppendL(authExpr); + CleanupStack::Pop(authExpr); + --index; + } + + opStack->AppendL(token); + } + } //if(token.CompareF(KAuthOpOr) == 0) + + else if(token.CompareF(KAuthOpAnd) == 0 || token.CompareF(KOpenBracket) == 0) + { + opStack->AppendL(token); + } + + else if(token.CompareF(KCloseBracket) == 0) + { + // when the previous element in the opStack is "(", delete it. + count = opStack->Count(); + index = count - 1; + TInt exprCount = authExpressionArray.Count(); + + if(index >= 0 && opStack->At(index) == KOpenBracket) + { + opStack->Delete(index); + opStack->Compress(); + } + + // the previous element could be an operator/operators of same precedence. + else + { + while(index >= 0 && opStack->At(index) != KOpenBracket) + { + CAuthExpression* expr = CreateAuthExpressionL(authExpressionArray, opStack->At(index)); + CleanupStack::PushL(expr); + authExpressionArray.AppendL(expr); + CleanupStack::Pop(expr); + opStack->Delete(index); + opStack->Compress(); + --index; + } //while + + if(index == -1) + { + User::Leave(KErrAuthServInvalidAliasStringExpression); + } + + opStack->Delete(index); + opStack->Compress(); + } + } //else if(token.CompareF(KCloseBracket) == 0) + + //when the token is neither "(","|","&" and ")" , it must be a plugin id or plugin Type, + //hence create a CAuthExpression object. + else + { + CAuthExpression* expression = CreateAuthExpressionL(token); + CleanupStack::PushL(expression); + authExpressionArray.AppendL(expression); + CleanupStack::Pop(expression); + } + } //for loop + + // since authExpressionArray will eventually contain only 1 authExpression pointer, + // remove it from the array, as the ownership of this pointer is transferred to the caller. + __ASSERT_ALWAYS((authExpressionArray.Count() == 1), User::Leave(KErrAuthServInvalidAliasStringExpression)); + + CAuthExpression* authExpression = authExpressionArray[0]; + authExpressionArray.Remove(0); + + CleanupStack::PopAndDestroy(2, opStack); //opStack and authExpressionArray + return authExpression; + + } + +/** + Creates CAuthExpression object from an alias string containing either + plugin Id or plugin type.The ownership of the object is transferred to the caller. + + @param aAliasString string containing either plugin Id or plugin Type. + + @return CAuthExpression object. + + @leave KErrAuthServInvalidAliasStringExpression, if the operands or operators are invalid strings. + + @leave KErrNoMemory, if there was insufficient memory to allocate the CAuthExpression object. + */ + CAuthExpression* CAuthExpressionImpl::CreateAuthExpressionL(const TDesC& aAliasString) + { + TLex input(aAliasString); + CAuthExpression* expression = 0; + TPluginId plugin = 0; + + for (TPtrC token = input.NextToken(); token.Size() > 0 ; + token.Set(input.NextToken())) + { + TLex lexer(token); + if(token.CompareF(KAuthBiometric) == 0) + { + expression = AuthExpr(EAuthBiometric); + } + else if(token.CompareF(KAuthKnowledge) == 0) + { + expression = AuthExpr(EAuthKnowledge); + } + else if(token.CompareF(KAuthToken) == 0) + { + expression = AuthExpr(EAuthToken); + } + else if(token.CompareF(KAuthPerformance) == 0) + { + expression = AuthExpr(EAuthPerformance); + } + else if(token.CompareF(KAuthDefault) == 0) + { + expression = AuthExpr(EAuthDefault); + } + else if(lexer.Val(plugin, EHex) == KErrNone) + { + expression = AuthExpr(plugin); + } + else + { + User::Leave(KErrAuthServInvalidAliasStringExpression); + } + } + + + if(expression == NULL) + { + User::Leave(KErrNoMemory); + } + + return expression; + } + +/** + Creates CAuthExpression object from an array of authexpression objects and an operator. + The ownership of the object is transferred to the caller. + + @param aAuthExprArray an array of authexpression objects. + @param aOperator an authexpression operator ( '&' or '|'). + + @return CAuthExpression object. + @leave KErrAuthServInvalidAliasStringExpression, if the operands or operators are invalid strings. + + */ + CAuthExpression* CAuthExpressionImpl::CreateAuthExpressionL(RPointerArray& aAuthExprArray, TPtrC aOperator) + { + // aAuthExprArray must contain minimum of 2 elements. + __ASSERT_ALWAYS((aAuthExprArray.Count() >= 2), User::Leave(KErrAuthServInvalidAliasStringExpression)); + + CAuthExpression* authExpression = 0; + TInt exprIndex = aAuthExprArray.Count() - 1; + + if(aOperator.CompareF(KAuthOpAnd) == 0) + { + authExpression = AuthAnd(aAuthExprArray[exprIndex], aAuthExprArray[exprIndex-1]); + } + + else if(aOperator.CompareF(KAuthOpOr) == 0) + { + authExpression = AuthOr(aAuthExprArray[exprIndex], aAuthExprArray[exprIndex-1]); + } + + else + { + User::Leave(KErrAuthServInvalidAliasStringExpression); + } + + // array elements are not deleted since the ownership is transferred to authExpression, + aAuthExprArray.Remove(exprIndex); + aAuthExprArray.Remove(exprIndex-1); + aAuthExprArray.Compress(); + + return authExpression; + } + + +#ifndef _DEBUG +// In release mode provide stub functions for Panic() and Invariant(). + +EXPORT_C void CAuthExpressionImpl::Panic(TPanic /* aPanic */) + { + // empty. + } + +EXPORT_C TBool CAuthExpressionImpl::Invariant() const + { + return ETrue; + } + +#else + +EXPORT_C void CAuthExpressionImpl::Panic(TPanic aPanic) +/** + This function is defined for debug builds only. + It halts the current thread when an invalid + argument is supplied to one of CAuthExpressionImpl's functions. + + The current thread is panicked with category "AUTHEXPR" + and the supplied reason. + + @param aPanic Panic reason. + */ + { + _LIT(KPanicCat, "AUTHEXPR"); + User::Panic(KPanicCat, aPanic); + } + +EXPORT_C TBool CAuthExpressionImpl::Invariant() const +/** + This function is defined for debug builds, and + checks that the object is internally consistent. + + The node's type must be a supported value - AND, OR, + plugin ID, or plugin type. + + If this is a combining node then recursively ensure + that both the left and right nodes are internally + consistent. + */ + { + // this node's parent sees it as a child + if (iParent != 0 && !(iParent->iComb.iLeft == this || iParent->iComb.iRight == this)) + return EFalse; + + switch (iType) + { + case EPluginId: + case EPluginType: + return ETrue; + + case EAnd: + case EOr: + // these will fault, as opposed to fail the invariant, + // if the pointers are invalid, but so would the original + // call to this function if the this pointer were invalid. + + // this node's children see it as the parent + // don't use Parent() because that asserts on the + // subexpression, whereas this function should + // return EFalse. + if (iComb.iLeft->iParent != this) + return EFalse; + + if (iComb.iRight->iParent != this) + return EFalse; + + return iComb.iLeft->Invariant() && iComb.iRight->Invariant(); + + case ENull: + return ETrue; + + default: + // unrecognized node type, so fail invariant + return EFalse; + } + } + +#endif // #ifdef _DEBUG + +