omadrm/drmengine/roap/src/RoapParser.cpp
changeset 0 95b198f216e5
--- /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 <e32base.h>
+
+#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<TInt>((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, "</mac>");
+
+// ============================ auto_handde helper class =======================
+//Auto handle for easening handle release on exceptional exit situations
+template<class T> class auto_handle
+    {
+    public:
+
+    auto_handle() {}
+    auto_handle(T aHandle) : iHandle( aHandle ) {}
+    auto_handle( auto_handle<T>& 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<HBufC8>& 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<TRoapElementEnum>(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<TRoapStatus>(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 "</" aElement ">"
+
+    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<HBufC8>& 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