diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/roap/src/RoapParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/roap/src/RoapParser.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,897 @@ +/* +* Copyright (c) 2002-2008 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: ROAP response parser +* +*/ + + + +// INCLUDE FILES +#include + +#include "DeviceHello.h" +#include "JoinDomainReq.h" +#include "JoinDomainResp.h" +#include "LeaveDomainReq.h" +#include "LeaveDomainResp.h" +#ifdef RD_DRM_METERING +#include "MeteringReportReq.h" +#include "MeteringReportResp.h" +#include "MeteringReportRespParser.h" +#endif +#include "RIHello.h" +#include "RegistrationReq.h" +#include "RegistrationResp.h" +#include "RightsReq.h" +#include "RightsResp.h" +#include "RoapTrigger.h" +#include "RoapMessage.h" + +#include "RoapParser.h" +#include "RespParser.h" +#include "JoinDomainRespParser.h" +#include "LeaveDomainRespParser.h" +#include "RIHelloParser.h" +#include "RegistrationRespParser.h" +#include "RightsRespParser.h" +#include "RoapTriggerParser.h" +#include "RoapLog.h" + +using namespace Roap; + +// LOCAL CONSTANTS AND MACROS +#define ELEMENT_COUNT(x) static_cast((sizeof(x) / sizeof (x[0]))) + +const TInt KParserChunkSize = 512; +const TInt KRoapElementCount = ELast; +const TInt KMaxElementNesting = 24; + +struct TRoapElements + { + const TText8* iString; + TInt iNumber; + }; + +struct TStackState + { + TParserStackState iState; + TRoapElementEnum iStack[KMaxElementNesting]; + }; + +static const TRoapElements KStatusValues[] = + { + {_S8("Success"), ESuccess}, + {_S8("UnknownError"), EUnknownError}, + {_S8("Abort"), EAbort}, + {_S8("NotSupported"), ENotSupported}, + {_S8("AccessDenied"), Roap::EAccessDenied}, + {_S8("NotFound"), ENotFound}, + {_S8("MalformedRequest"), EMalformedRequest}, + {_S8("UnknownRequest"), EUnknownRequest}, + {_S8("UnknownCriticalExtension"), EUnknownCriticalExtension}, + {_S8("UnsupportedVersion"), EUnsupportedVersion}, + {_S8("UnsupportedAlgorithm"), EUnsupportedAlgorithm}, + {_S8("NoCertificateChain"), ENoCertificateChain}, + {_S8("InvalidCertificateChain"), EInvalidCertificateChain}, + {_S8("TrustedRootCertificateNotPresent"), ETrustedRootCertificateNotPresent}, + {_S8("SignatureError"), ESignatureError}, + {_S8("DeviceTimeError"), EDeviceTimeError}, + {_S8("NotRegistered"), ENotRegistered}, + {_S8("InvalidDCFHash"), EInvalidDCFHash}, + {_S8("InvalidDomain"), EInvalidDomain}, + {_S8("DomainFull"), EDomainFull}, + {_S8("MalformedMeteringReport"), EMalformedMeteringReport}, + {_S8("UnableToDecryptMeteringReport"), EUnableToDecryptMeteringReport}, + {_S8("UnableToValidateMeteringReportMAC"), EUnableToValidateMeteringReportMAC}, + }; + +static const TRoapElements KRoapElements[ELast] = + { + {_S8("certificate"), ECertificate}, + {_S8("certificateChain"), ECertificateChain}, + {_S8("CipherData"), ECipherData}, + {_S8("CipherValue"), ECipherValue}, + {_S8("contentID"), Roap::EContentID}, + {_S8("dcfHash"), EDcfHash}, + {_S8("deviceDetails"), EDeviceDetails}, + {_S8("deviceID"), EDeviceID}, + {_S8("DigestValue"), EDigestValue}, + {_S8("dn"), EDomainName}, + {_S8("domainAlias"), EDomainAlias}, + {_S8("domainID"), EDomainID}, + {_S8("domainInfo"), EDomainInfo}, + {_S8("domainKey"), EDomainKey}, + {_S8("encKey"), EEncKey}, + {_S8("EncryptionMethod"), EEncryptionMethod}, + {_S8("extension"), EExtension}, + {_S8("extensions"), EExtensions}, + {_S8("hash"), EHash}, + {_S8("id"), EId}, + {_S8("identifier"), EIdentifier}, + {_S8("joinDomain"), EJoinDomain}, + {_S8("joinDomainResponse"), EJoinDomainResponse}, + {_S8("keyIdentifier"), EKeyIdentifier}, + {_S8("leaveDomain"), ELeaveDomain}, + {_S8("leaveDomainResponse"), ELeaveDomainResponse}, + {_S8("mac"), EMac}, + {_S8("manufacturer"), EManufacturer}, + {_S8("model"), EModel}, + {_S8("nonce"), ENonce}, + {_S8("notAfter"), ENotAfter}, + {_S8("ocspResponse"), EOcspResponse}, + {_S8("protectedRO"), EProtectedRO}, + {_S8("registrationRequest"), ERegistrationRequest}, + {_S8("registrationResponse"), ERegistrationResponse}, + {_S8("riAlias"), ERiAlias}, + {_S8("rights"), Roap::ERights}, + {_S8("riHello"), ERiHello}, + {_S8("riID"), ERiID}, + {_S8("riNonce"), ERiNonce}, + {_S8("riURL"), ERiURL}, + {_S8("ro"), ERo}, + {_S8("roAcquisition"), ERoAcquisition}, + {_S8("roapTrigger"), ERoapTrigger}, + {_S8("roapURL"), ERoapURL}, + {_S8("roID"), ERoID}, + {_S8("roInfo"), ERoInfo}, + {_S8("roResponse"), ERoResponse}, + {_S8("selectedAlgorithm"), ESelectedAlgorithm}, + {_S8("selectedVersion"), ESelectedVersion}, + {_S8("serverInfo"), EServerInfo}, + {_S8("signature"), ESignature}, + {_S8("SignatureValue"), ESignatureValue}, + {_S8("supportedAlgorithm"), ESupportedAlgorithm}, + {_S8("time"), ETime}, + {_S8("timeStamp"), ETimeStamp}, + {_S8("trustedAuthorities"), ETrustedAuthorities}, + {_S8("version"), EVersion}, + {_S8("X509SPKIHash"), EX509SPKIHash}, +#ifdef RD_DRM_METERING + {_S8("extendedTrigger"), EExtendedTriggerElement}, + {_S8("meteringReport"), EMeteringReportRequest}, + {_S8("meteringReportResponse"), EMeteringReportResponse}, + {_S8("prURL"), EPrUrl} +#endif + }; + +// The stack states have to be sorted with descending length. The +// MatchStackState function searches for the first matching state. +static const TStackState KParserStackStates[] = + { + // 4 elements -------------------------------------------------------------- + {ERiIdRoResponseState, {EHash, EKeyIdentifier, ERiID, ERoResponse, ELast}}, + {ERiIdJoinDomainResponseState, {EHash, EKeyIdentifier, ERiID, EJoinDomainResponse, ELast}}, + // 3 elements -------------------------------------------------------------- +#ifdef RD_DRM_METERING + {EPostResponseUrlState, {EPrUrl, EExtension, EExtensions, ELast}}, +#endif + {EDeviceIdState, {EHash, EKeyIdentifier, EDeviceID, ELast}}, + {ETrustedAuthoritiesState, {EHash, EKeyIdentifier, ETrustedAuthorities, ELast}}, + {EPeerKeyIdentifierRIHelloState, {EIdentifier, EExtension, EExtensions, ELast}}, + {ETransactionIdState, {EId, EExtension, EExtensions, ELast}}, + {ETransactionIdContentIdState, {Roap::EContentID, EExtension, EExtensions, ELast}}, + {EWhiteListState, {EDomainName, EExtension, EExtensions, ELast}}, + {EDeviceDetailsState, {EDeviceDetails, EExtensions, ERiHello, ELast}}, + {ERiIdState, {EHash, EKeyIdentifier, ERiID, ELast}}, + {EEncKeyState, {ECipherValue, ECipherData, EEncKey, ELast}}, + {EDomainKeyEncryptionMethodState, {EEncryptionMethod, EEncKey, EDomainKey, ELast}}, + {EMacJoinDomainResponseState, {EMac, EDomainKey, EDomainInfo, ELast}}, + // 2 elements -------------------------------------------------------------- + {EDomainKeyEncKeyState, {EEncKey, EDomainKey, ELast}}, + {ECertificateState, {ECertificate, ECertificateChain, ELast}}, + {ESignatureRoResponseState, {ESignature, ERoResponse, ELast}}, + {EExtensionState, {EExtension, EExtensions, ELast}}, + // 1 element --------------------------------------------------------------- + {ERiAliasState, {ERiAlias, ELast}}, + {EDomainAliasState, {EDomainAlias, ELast}}, + {ERiHelloState, {ERiHello, ELast}}, + {ESelectedVersionState, {ESelectedVersion, ELast}}, + {ERiNonceState, {ERiNonce, ELast}}, + {EOcspResponseState, {EOcspResponse, ELast}}, + {ERiUrlState, {ERiURL, ELast}}, + {ESignatureState, {ESignature, ELast}}, + {ERegistrationResponseState, {ERegistrationResponse, ELast}}, + {ERoResponseState, {ERoResponse, ELast}}, + {EJoinDomainResponseState, {EJoinDomainResponse, ELast}}, + {ELeaveDomainResponseState, {ELeaveDomainResponse, ELast}}, + {EDomainIdState, {EDomainID, ELast}}, + {ENonceState, {ENonce, ELast}}, + {ENotAfterState, {ENotAfter, ELast}}, + {EDomainKeyState, {EDomainKey, ELast}}, + {ERoapTriggerState, {ERoapTrigger, ELast}}, + {ERoapUrlState, {ERoapURL, ELast}}, + {ERegistrationRequestState, {ERegistrationRequest, ELast}}, + {ERoAcquisitionState, {ERoAcquisition, ELast}}, + {EJoinDomainState, {EJoinDomain, ELast}}, + {ELeaveDomainState, {ELeaveDomain, ELast}}, + {ERoIdState, {ERoID, ELast}}, + {EContentIdState, {Roap::EContentID, ELast}}, + {ESignatureValueState, {ESignatureValue, ELast}}, + {EDigestValueState, {EDigestValue, ELast}}, + {EServerInfoState, {EServerInfo, ELast}}, + {ESupportedAlgorithmState, {ESupportedAlgorithm, ELast}}, + {ESelectedAlgorithmState, {ESelectedAlgorithm, ELast}}, +#ifdef RD_DRM_METERING + {EExtendedTriggerElementState, {EExtendedTriggerElement, ELast}}, + {EMeteringReportRequestState, {EMeteringReportRequest, ELast}}, + {EMeteringReportResponseState, {EMeteringReportResponse, ELast}} +#endif + }; + +_LIT8(KParserMimeType, "text/xml"); +_LIT8(KDomainKey, "domainKey"); +_LIT8(KMac, "mac>"); +_LIT8(KMacEnd, ""); + +// ============================ auto_handde helper class ======================= +//Auto handle for easening handle release on exceptional exit situations +template class auto_handle + { + public: + + auto_handle() {} + auto_handle(T aHandle) : iHandle( aHandle ) {} + auto_handle( auto_handle& aHandle) : iHandle( aHandle.release() ) {} + ~auto_handle() { iHandle.Close(); } + const T& operator()() const { return iHandle; } + T& operator()() { return iHandle; } + T get() const { return iHandle; } + T release() { T temp = iHandle; iHandle = 0; return temp; } + + private: + T iHandle; + }; + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CRoapParser::CRoapParser +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CRoapParser::CRoapParser(): + iParser(NULL), + iResponseParser(NULL) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CRoapParser::ConstructL() + { + TInt i; + + iParser = CParser::NewL(KParserMimeType, *this); + for (i = 0; i < KRoapElementCount; i++) + { + TPtrC8 ptr(KRoapElements[i].iString, User::StringLength( + KRoapElements[i].iString)); + iRoapElements[KRoapElements[i].iNumber] = + iParser->StringPool().OpenStringL(ptr); + } + } + +// ----------------------------------------------------------------------------- +// CRoapParser::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CRoapParser* CRoapParser::NewL() + { + CRoapParser* self = new( ELeave ) CRoapParser; + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +CRoapParser::~CRoapParser() + { + TInt i; + for (i = 0; i < ELEMENT_COUNT(KRoapElements); i++) + { + iRoapElements[KRoapElements[i].iNumber].Close(); + } + delete iParser; + delete iContent; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseMeteringRespL +// ----------------------------------------------------------------------------- +// +#ifndef RD_DRM_METERING +CMeteringResp* CRoapParser::ParseMeteringRespL( const TDesC8& /*aMessage*/ ) + { + return NULL; + } +#else +CMeteringResp* CRoapParser::ParseMeteringRespL( const TDesC8& aMessage ) + { + LOG( _L("CRoapParser::ParseMeteringRespL") ); + CMeteringResp* r = CMeteringResp::NewL(); + CleanupStack::PushL(r); + TMeteringRespParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } +#endif +// ----------------------------------------------------------------------------- +// CRoapParser::ParseJoinDomainRespL +// ----------------------------------------------------------------------------- +// +CJoinDomainResp* CRoapParser::ParseJoinDomainRespL( + const TDesC8& aMessage, RPointerArray& aDomainKeyElements) + { + LOG( _L("CRoapParser::ParseJoinDomainRespL") ); + + CJoinDomainResp* r = CJoinDomainResp::NewL(); + CleanupStack::PushL(r); + TJoinDomainRespParser p(r); + iResponseParser = &p; + ParseL(aMessage); + if ( r->iStatus == ESuccess ) + { + User::LeaveIfError( + ExtractDomainKeyElements(aMessage, aDomainKeyElements)); + } + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseLeaveDomainRespL +// ----------------------------------------------------------------------------- +// +CLeaveDomainResp* CRoapParser::ParseLeaveDomainRespL( + const TDesC8& aMessage) + { + LOG( _L("CRoapParser::ParseLeaveDomainRespL") ); + + CLeaveDomainResp* r = CLeaveDomainResp::NewL(); + CleanupStack::PushL(r); + TLeaveDomainRespParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseRegistrationResp +// ----------------------------------------------------------------------------- +// +CRegistrationResp* CRoapParser::ParseRegistrationRespL( + const TDesC8& aMessage) + { + LOG( _L("CRoapParser::ParseRegistrationRespL") ); + + CRegistrationResp* r = CRegistrationResp::NewL(); + CleanupStack::PushL(r); + TRegistrationRespParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseRightsRespL +// ----------------------------------------------------------------------------- +// +CRightsResp* CRoapParser::ParseRightsRespL( + const TDesC8& aMessage) + { + LOG( _L("CRoapParser::ParseRightsRespL") ); + + CRightsResp* r = CRightsResp::NewL(); + CleanupStack::PushL(r); + TRightsRespParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseRIHelloL +// ----------------------------------------------------------------------------- +// +CRIHello* CRoapParser::ParseRIHelloL( + const TDesC8& aMessage) + { + LOG( _L("CRoapParser::ParseRIHelloL") ); + + CRIHello* r = CRIHello::NewL(); + CleanupStack::PushL(r); + TRIHelloParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseRoapTriggerL +// ----------------------------------------------------------------------------- +// +CRoapTrigger* CRoapParser::ParseRoapTriggerL( + const TDesC8& aMessage) + { + LOG( _L("CRoapParser::ParseRoapTriggerL") ); + + CRoapTrigger* r = CRoapTrigger::NewL(); + CleanupStack::PushL(r); + TRoapTriggerParser p(r); + iResponseParser = &p; + ParseL(aMessage); + CleanupStack::Pop(r); + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ParseL +// ----------------------------------------------------------------------------- +// +void CRoapParser::ParseL( + const TDesC8& aMessage) + { + TInt i; + TInt n; + + iElementStackDepth = 0; + delete iContent; + iContent = NULL; + iParser->ParseBeginL(); + i = 0; + while (i < aMessage.Length()) + { + n = Min(aMessage.Length() - i, KParserChunkSize); + iParser->ParseL(aMessage.Mid(i, n)); + i += n; + } + iParser->ParseEndL(); + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnStartDocumentL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnStartDocumentL( + const RDocumentParameters& /*aDocParam*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnEndDocumentL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnEndDocumentL( + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnStartElementL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnStartElementL( + const RTagInfo& aElement, + const RAttributeArray& aAttributes, + TInt /*aErrorCode*/) + { + TInt i; + TInt state; + + if (iContent) + { + delete iContent; + iContent = NULL; + iContent = HBufC8::NewL(0); + } + + for (i = 0; i < KRoapElementCount; i++) + { + if (aElement.LocalName() == iRoapElements[i]) + { + iElementStack[iElementStackDepth] = + static_cast(i); + iElementStackDepth++; + state = MatchStackState(); + iResponseParser->OnStartElementL(*this, state, aElement, + aAttributes); + if (iElementStackDepth == KMaxElementNesting) + { + User::Leave(EXmlUnexpectedState); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnEndElementL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnEndElementL( + const RTagInfo& aElement, + TInt /*aErrorCode*/) + { + TInt i; + TInt state; + + for (i = 0; i < KRoapElementCount; i++) + { + if (aElement.LocalName() == iRoapElements[i]) + { + state = MatchStackState(); + iResponseParser->OnEndElementL(*this, state, aElement); + iElementStackDepth--; + if (iElementStackDepth < 0) + { + User::Leave(EXmlUnexpectedState); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnContentL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnContentL( + const TDesC8& aBytes, + TInt /*aErrorCode*/) + { + if ( !iContent ) + { + iContent = HBufC8::NewL(aBytes.Size()); + *iContent = aBytes; + } + else + { + iContent = iContent->ReAllocL(iContent->Size() + aBytes.Size()); + TPtr8 c(iContent->Des()); + c.Append(aBytes); + } + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnStartPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnStartPrefixMappingL( + const RString& /*aPrefix*/, + const RString& /*aUri*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnEndPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnEndPrefixMappingL( + const RString& /*aPrefix*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnIgnorableWhiteSpaceL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnIgnorableWhiteSpaceL( + const TDesC8& /*aBytes*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnSkippedEntityL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnSkippedEntityL( + const RString& /*aName*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnProcessingInstructionL +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnProcessingInstructionL( + const TDesC8& /*aTarget*/, + const TDesC8& /*aData*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnOutOfData +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnOutOfData() + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::OnError +// ----------------------------------------------------------------------------- +// +void CRoapParser::OnError( + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CRoapParser::GetExtendedInterface +// ----------------------------------------------------------------------------- +// +TAny* CRoapParser::GetExtendedInterface( + const TInt32 /*aUid*/) + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::MatchStackState +// ----------------------------------------------------------------------------- +// +TParserStackState CRoapParser::MatchStackState(void) + { + TInt i; + TInt j; + TInt k; + TParserStackState r = EUnknownState; + + for (i = 0; + r == EUnknownState && + i < ELEMENT_COUNT(KParserStackStates); i++) + { + for (j = iElementStackDepth - 1, k = 0; + j > 0 && KParserStackStates[i].iStack[k] != ELast; + j--, k++) + { + if (iElementStack[j] != KParserStackStates[i].iStack[k]) + { + break; + } + } + if ((j == 0 && iElementStack[j] == KParserStackStates[i].iStack[k]) || + KParserStackStates[i].iStack[k] == ELast) + { + r = KParserStackStates[i].iState; + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::GetAttributeValueL +// ----------------------------------------------------------------------------- +// +HBufC8* CRoapParser::GetAttributeValueL( + const RAttributeArray& aAttrList, + const TDesC8& aAttrName) + { + HBufC8* r = NULL; + RAttribute a; + TInt i; + + for (i = 0; !r && i < aAttrList.Count(); i++) + { + a = aAttrList[i]; + if (a.Attribute().LocalName().DesC().Compare(aAttrName) == 0) + { + r = a.Value().DesC().AllocL(); + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ConvertRoapStatus +// ----------------------------------------------------------------------------- +// +TRoapStatus CRoapParser::ConvertRoapStatus( + const TDesC8& aStatus) + { + TInt i; + TRoapStatus r = EUnknownStatus; + + for (i = 0; r == EUnknownStatus && i < ELEMENT_COUNT(KStatusValues); i++) + { + if (aStatus.Compare(TPtrC8(KStatusValues[i].iString, + aStatus.Size())) == 0) + { + r = static_cast(KStatusValues[i].iNumber); + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ExtractElement +// Note: uses auto_handle helper class +// ----------------------------------------------------------------------------- +// +TPtrC8 CRoapParser::ExtractElement( + const TDesC8& aMessage, const TDesC8& aElement, TInt& aOffset ) const + { + LOG( _L("CRoapParser::ExtractElement") ); + + TPtrC8 temp( KNullDesC8 ); + TInt pos = ( 0 ); + TInt startPos = ( 0 ); + TInt endPos = ( 0 ); + TInt ret( 0 ); + TInt startLength ( 0 ); + const TInt KSpaceForDelimiters( 3 ); // max "" + + auto_handle< RBuf8 > tagToBeFound; + // Must be nonleaving since this function is nonleaving + ret = tagToBeFound().Create( aElement.Length() + KSpaceForDelimiters ); + if ( ret != KErrNone ) + { + aOffset = -1; + return KNullDesC8(); + } + + //First we try to find start tag (as localname) + tagToBeFound().SetLength( 0 ); + tagToBeFound().AppendFormat( _L8( "<%S" ), &aElement ); + + temp.Set( aMessage.Mid( aOffset ) ); + + + startPos = temp.Find( tagToBeFound() ); + + if ( startPos < 0 ) + {//Not found, let's try with namespace start + tagToBeFound().SetLength( 0 ); + tagToBeFound().AppendFormat( _L8( ":%S" ), &aElement ); + pos = temp.Find( tagToBeFound() ); + if ( pos < 0 ) + {//Not possible to find valid tag with given name + aOffset = -1; + return KNullDesC8(); + } + temp.Set( aMessage.Left( pos ) ); + startPos = temp.LocateReverse('<'); + if ( startPos < 0 ) + { + aOffset = -1; + return KNullDesC8(); + } + //Calculate length for the new string to be stored + ret = tagToBeFound().ReAlloc( + ( pos - startPos ) + aElement.Length() + KSpaceForDelimiters ); + if ( ret != KErrNone ) + { + aOffset = -1; + return KNullDesC8(); + } + tagToBeFound().SetLength( 0 ); + tagToBeFound().Append( temp.Mid( startPos ) ); + tagToBeFound().AppendFormat( _L8( ":%S" ), &aElement ); + } + + startLength = tagToBeFound().Length(); //needed in later calculations + startPos += aOffset; + temp.Set( aMessage.Mid( startPos + startLength ) ); + + //Now find the end element. First prepare element to be found + tagToBeFound().Insert( 1, _L8( "/" ) ); // '/' after '<' + tagToBeFound().Append( _L8( ">" ) ); // '>' as last + + + endPos = temp.Find(tagToBeFound()); + if ( endPos < 0) + { + aOffset = -1; + return KNullDesC8(); + } + endPos += startPos + startLength + tagToBeFound().Length(); + + temp.Set( aMessage.Mid(startPos, endPos - startPos) ); + + aOffset = endPos; + LOG( _L( "Extracted element" ) ); + LOGHEX( temp.Ptr(), temp.Length() ); + + //auto_handle closes and frees allocated resources + return temp; + } + +// ----------------------------------------------------------------------------- +// CRoapParser::ExtractDomainKeyElements +// ----------------------------------------------------------------------------- +// +TInt CRoapParser::ExtractDomainKeyElements( + const TDesC8& aMessage, RPointerArray& aDomainKeyElements ) const + { + LOG( _L("CRoapParser::ExtractDomainKeyElements") ); + + TPtrC8 temp(KNullDesC8); + TPtrC8 elementPtr(KNullDesC8); + TInt pos = 0; + HBufC8* element = NULL; + TInt err = KErrNone; + TPtr8 ptr(0, 0); + TInt macStart = 0; + TInt macEnd = 0; + + // extract DomainKey elements to aDomainKeyElements array + while (true) + { + elementPtr.Set( ExtractElement( aMessage, KDomainKey(), pos ) ); + + if( pos < 0 ) + { + // no more DomainKeys present + if(aDomainKeyElements.Count()) + { + return KErrNone; + } + else + { + aDomainKeyElements.ResetAndDestroy(); + return KErrRoapServerFatal; + } + } + + element = elementPtr.Alloc(); + if(!element) + { + return KErrNoMemory; + } + + // remove mac element from found DomainKeyElement + macStart = element->Find( KMac ); + temp.Set(element->Left(macStart)); + macStart = temp.LocateReverse('<'); + macEnd = element->Find( KMacEnd ) + KMacEnd().Length(); + if ( macStart < 0 || macEnd < 0 ) + { + aDomainKeyElements.ResetAndDestroy(); + return KErrRoapServerFatal; + } + ptr.Set( element->Des() ); + ptr.Replace( macStart, macEnd - macStart, KNullDesC8 ); + + err = aDomainKeyElements.Append(element); + if(err) + { + delete element; + element = NULL; + aDomainKeyElements.ResetAndDestroy(); + return err; + } + } + } + +// End of File