diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/ro/src/DrmProtectedRoParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/ro/src/DrmProtectedRoParser.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,1297 @@ +/* +* Copyright (c) 2005 - 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: Implementation of a parser for protected OMA DRM rights + * +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include + +#ifdef _DEBUG +#include +#endif // _DEBUG +#include "base64.h" +#include "DcfCommon.h" +#include "DrmRightsParser.h" +#include "DrmProtectedRoParser.h" +#include "DrmRightsClient.h" +#include "hash.h" +#include "DRMCommon.h" +#include "OmaCrypto.h" +#include "CmlaCrypto.h" +#include "DrmPermission.h" +#include "RoapMessage.h" +#include "DcfRep.h" +#include "DcfEntry.h" +#include "Oma2Dcf.h" + +using namespace Roap; +using namespace Xml; + +// MODULE DATA STRUCTURES +NONSHARABLE_CLASS(CDrmProtectedRoParser::CParsedProtectedRo): public CBase + { +public: + static CParsedProtectedRo* NewL(); + ~CParsedProtectedRo(); + +protected: + CParsedProtectedRo(); + +public: + TKeyTransportScheme iTransportScheme; + HBufC8* iKey; + TBool iDomainRo; + HBufC8* iId; + HBufC8* iRiUrl; + HBufC8* iDomainId; + HBufC8* iRightsIssuerId; + TTime iTimeStamp; + HBufC8* iMac; + HBufC8* iMacDigest; + }; + +enum TElementEnum + { + EProtectedRo = 0, + ERo, + EDomainRo, + EId, + EStateful, + EVersion, + ERiId, + EKeyIdentifier, + EHash, + ETimeStamp, + EEncKey, + EEncryptionMethod, + EKeyInfo, + EX509SPKIHash, + ECipherData, + ECipherValue, + EMac, + ESignedInfo, + ECanonicalizationMethod, + ESignatureMethod, + EReference, + EDigestMethod, + EDigestValue, + ESignatureValue, + ERetreivalMethod, + ERoapDomainId, + EDomainIdentifier, + ERoapDomainIdentifier, + ERoResponse, + ELast, + }; + +enum TParserStackState + { + ERoState, + ECipherValueState, + EDomainIdentifierState, + EEncryptionMethodState, + ERightsIssuerIdState, + ETimeStampState, + EMacValueState, + EMacDigestValueState, + EUnknownState = -1, + }; + +struct TElements + { + const TText8* iString; + TInt iNumber; + }; + +// MACROS +#define ELEMENT_COUNT(x) static_cast((sizeof(x) / sizeof (x[0]))) + +#ifdef _DEBUG +_LIT(KParseLogDir, "DRM"); +_LIT(KParseLogFile, "Parse.log"); +#define DEBUGLOG( a ) { _LIT(KDebugString, a); RFileLogger::Write( KParseLogDir(), KParseLogFile(), EFileLoggingModeAppend, KDebugString() ); } +#define DEBUGLOGHEX( ptr, len ) RFileLogger::HexDump( KParseLogDir(), KParseLogFile(), EFileLoggingModeAppend, _S(""), _S(""), ptr, len ); +#else +#define DEBUGLOG( a ) +#define DEBUGLOGHEX( ptr, len ) +#endif // _DEBUG + +// LOCAL CONSTANTS AND MACROS +const TInt KParserChunkSize = 512; +const TInt KMaxElementNesting = 24; +const TInt KMaxElementLen = 80; + +_LIT8(KXmlParserMimeType, "text/xml"); +_LIT8(KIdAttr, "id"); +_LIT8(KDomainRoAttr, "domainRO"); +_LIT8(KRiUrlAttr, "riURL"); +_LIT8(KAlgorithmAttr, "Algorithm"); +_LIT8(KProtectedRoElement, "protectedRO"); +_LIT8(KRoapPrefix, "roap:"); +_LIT8(KStartElementStart, "<"); +_LIT8(KEndElementStart, "" ); +_LIT8(KQualifiedProtectedRo, "roap:protectedRO"); +_LIT8(KSignedInfoElement, "ds:SignedInfo"); +_LIT8(KRoapXmlNs, " xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\""); +_LIT8(KRoapXmlNsUri, "urn:oma:bac:dldrm:roap-1.0"); +_LIT8(KMacStart, " 0) + { + lex = aTimeString; + lex.Val(year); + lex.Inc(); + lex.Val(month); + lex.Inc(); + lex.Val(day); + lex.Inc(); + lex.Val(hour); + lex.Inc(); + lex.Val(minute); + lex.Inc(); + lex.Val(second); + r = TTime(TDateTime(year, static_cast(month - 1), day - 1, + hour, minute, second, 0)); + if (lex.Get() != 'Z') + { + r += offset; + } + } + return r; + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CDrmProtectedRo::NewL +// Allocate a new protected RO object +// ----------------------------------------------------------------------------- +// +CDrmProtectedRoParser::CParsedProtectedRo* CDrmProtectedRoParser::CParsedProtectedRo::NewL() + { + CParsedProtectedRo* self = new(ELeave) CParsedProtectedRo; + return self; + } + +// ----------------------------------------------------------------------------- +// CParsedProtectedRo::~CParsedProtectedRo +// Release all data +// ----------------------------------------------------------------------------- +// +CDrmProtectedRoParser::CParsedProtectedRo::~CParsedProtectedRo() + { + delete iKey; + delete iId; + delete iRiUrl; + delete iDomainId; + delete iRightsIssuerId; + delete iMac; + delete iMacDigest; + } + +// ----------------------------------------------------------------------------- +// CParsedProtectedRo::CParsedProtectedRo +// Initialize all member data +// ----------------------------------------------------------------------------- +// +CDrmProtectedRoParser::CParsedProtectedRo::CParsedProtectedRo() : + iTransportScheme(EOma), iKey(NULL), iDomainRo(EFalse), iId(NULL), + iRiUrl(NULL), iDomainId(NULL), iRightsIssuerId(NULL), iMac(NULL) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::CDrmProtectedRoParser +// Reset all member variables +// ----------------------------------------------------------------------------- +// +CDrmProtectedRoParser::CDrmProtectedRoParser() : + iParser(NULL), iRights(NULL), iContent(NULL) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::ConstructL +// Initialize the string pool elements +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::ConstructL() + { + iParser = CParser::NewL(KXmlParserMimeType, *this); + for (TInt i = 0; i < ELEMENT_COUNT(KElements); i++) + { + TPtrC8 ptr(KElements[i].iString, + User::StringLength(KElements[i].iString)); + iElements[KElements[i].iNumber] = iParser->StringPool().OpenStringL(ptr); + } + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CDrmProtectedRoParser* CDrmProtectedRoParser::NewL() + { + CDrmProtectedRoParser* self = new(ELeave) CDrmProtectedRoParser; + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::~CDrmProtectedRoParser +// Release the allocated strings +// ----------------------------------------------------------------------------- +// +EXPORT_C CDrmProtectedRoParser::~CDrmProtectedRoParser() + { + for (TInt i = 0; i < ELEMENT_COUNT(KElements); i++) + { + iElements[KElements[i].iNumber].Close(); + } + delete iParser; + delete iRights; + delete iContent; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::ParseL +// Parses one element +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::ParseL(const TDesC8& aProtectedRo, + CParsedProtectedRo*& aResultRights) + { + TInt i( 0 ); + + iElementStackDepth = 0; + delete iRights; + delete iContent; + iContent = NULL; + iRights = NULL; + iRights = CParsedProtectedRo::NewL(); + iParser->ParseBeginL(); + + i = aProtectedRo.Find( KRoapXmlNsUri ); + + if ( i == KErrNotFound ) + { + // Feed in the ROAP XML namespace declaration + i = aProtectedRo.Find(KProtectedRoElement); + if ( i == KErrNotFound ) + { + User::Leave(KErrCorrupt); + } + i += KProtectedRoElement().Length(); + iParser->ParseL( aProtectedRo.Left( i ) ); + iParser->ParseL( KRoapXmlNs() ); + } + else + { + i = 0; + } + + while ( i < aProtectedRo.Length() ) + { + TInt n( Min( aProtectedRo.Length() - i, KParserChunkSize ) ); + iParser->ParseL( aProtectedRo.Mid( i, n ) ); + i += n; + } + iParser->ParseEndL(); + aResultRights = iRights; + iRights = NULL; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetRiUrlL +// Parse the RO and return the RI URL +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC8* CDrmProtectedRoParser::GetRiUrlL( + const TDesC8& aProtectedRo) + { + TInt i( 0 ); + HBufC8* r( NULL ); + + iElementStackDepth = 0; + delete iRights; + delete iContent; + iRights = NULL; + iContent = NULL; + iRights = CParsedProtectedRo::NewL(); + iParser->ParseBeginL(); + while (i < aProtectedRo.Length()) + { + TInt n( Min( aProtectedRo.Length() - i, KParserChunkSize ) ); + iParser->ParseL( aProtectedRo.Mid( i, n ) ); + i += n; + } + iParser->ParseEndL(); + if ( iRights->iRiUrl ) + { + r = iRights->iRiUrl->AllocL(); + } + delete iRights; + iRights = NULL; + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetRiUrlL +// Parse the RO and return the RI ID +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC8* CDrmProtectedRoParser::GetRiIdL( + const TDesC8& aProtectedRo) + { + HBufC8* r = NULL; + + iElementStackDepth = 0; + delete iRights; + delete iContent; + iRights = NULL; + iContent = NULL; + iRights = CParsedProtectedRo::NewL(); + iParser->ParseBeginL(); + TInt i( 0 ); + while (i < aProtectedRo.Length()) + { + TInt n( Min( aProtectedRo.Length() - i, KParserChunkSize ) ); + iParser->ParseL(aProtectedRo.Mid(i, n)); + i += n; + } + iParser->ParseEndL(); + if ( iRights->iRightsIssuerId ) + { + r = iRights->iRightsIssuerId->AllocL(); + } + delete iRights; + iRights = NULL; + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetDomainIdL +// Parse the RO and return the domain ID +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC8* CDrmProtectedRoParser::GetDomainIdL( + const TDesC8& aProtectedRo) + { + HBufC8* r = NULL; + + iElementStackDepth = 0; + delete iRights; + iRights = NULL; + delete iContent; + iContent = NULL; + iRights = CParsedProtectedRo::NewL(); + iParser->ParseBeginL(); + TInt i( 0 ); + while (i < aProtectedRo.Length()) + { + TInt n( Min(aProtectedRo.Length() - i, KParserChunkSize) ); + iParser->ParseL(aProtectedRo.Mid(i, n)); + i += n; + } + iParser->ParseEndL(); + if ( iRights->iDomainId ) + { + r = iRights->iDomainId->AllocL(); + } + delete iRights; + iRights = NULL; + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::ParseAndStoreL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CDrmProtectedRoParser::ParseAndStoreL( + const TDesC8& aRightsObject, + RPointerArray& aResultRights) + { + RDRMRightsClient client; + CDrmRightsParser* parser = NULL; + CDRMRights* rights = NULL; + CParsedProtectedRo* parsedRo = NULL; + TDRMUniqueID id = 0; + HBufC8 *cid = NULL; + TPtr8 ptr(0, 0); + TBool domain = EFalse; + TPtrC8 riId(0, 0); + TInt start = 0; + TInt end = 0; + TInt roStart = 0; + TInt roEnd = 0; + TInt signedInfoStart = 0; + TInt signedInfoEnd = 0; + TInt n( 0 ); + TInt r( 0 ); + TBool inCache = EFalse; + CSHA1* sha1 = NULL; + TBool integrityCheck = ETrue; + HBufC8* roWithNs = NULL; + TPtr8 roWithNsPtr(NULL, NULL); + + User::LeaveIfError(client.Connect()); + CleanupClosePushL(client); + + // Loop through the complete roResponse and find all embedded protected + // rights objects + while (GetElementStartEnd(KProtectedRoElement, aRightsObject, start, end)) + { + TPtrC8 protectedRo = aRightsObject.Mid(start, end - start); + if (GetElementStartEnd(KRoElement, protectedRo, roStart, roEnd) == EFalse) + { + User::Leave(KErrCorrupt); + } + TPtrC8 ro = protectedRo.Mid(roStart, roEnd - roStart); + + ParseL(protectedRo, parsedRo); + User::LeaveIfNull(parsedRo); + CleanupStack::PushL(parsedRo); + + parser = CDrmRightsParser::NewL(); + CleanupStack::PushL(parser); + parser->ParseL(protectedRo, aResultRights); + CleanupStack::PopAndDestroy( parser ); + + ////////////////////////// + // Replay protection + ////////////////////////// + + if (parsedRo->iTimeStamp == Time::NullTTime()) + { + User::LeaveIfError(client.IsInCache(*parsedRo->iId, inCache)); + if (inCache) + { + User::Leave(KErrAlreadyExists); + } + } + else + { + User::LeaveIfError(client.IsInCache(*parsedRo->iId, parsedRo->iTimeStamp, inCache)); + if (inCache) + { + User::Leave(KErrAlreadyExists); + } + } + + /////////////////////////////////////////////////////// + // Unwrap MAC and REK + // The plain keys are stored on the server side session + /////////////////////////////////////////////////////// + if (parsedRo->iDomainRo) + { + User::LeaveIfError( client.UnwrapMacAndRek(*parsedRo->iKey, + parsedRo->iTransportScheme, + *parsedRo->iRightsIssuerId, + *parsedRo->iDomainId) ); + } + else + { + User::LeaveIfError( client.UnwrapMacAndRek(*parsedRo->iKey, + parsedRo->iTransportScheme, + *parsedRo->iRightsIssuerId, + KNullDesC8) ); + } + + ////////////////////////// + // Validate digest and MAC + ////////////////////////// + roWithNs = AddRoapNamespaceL(ro); + if (roWithNs) + { + CleanupStack::PushL(roWithNs); + roWithNsPtr.Set(roWithNs->Des()); + } + + // Validate RO digest + sha1 = CSHA1::NewL(); + if (roWithNs) + { + DEBUGLOGHEX( roWithNsPtr.Ptr(), roWithNsPtr.Length() ); + sha1->Update(roWithNsPtr); + CleanupStack::PopAndDestroy(roWithNs); + } + else + { + DEBUGLOGHEX( ro.Ptr(), ro.Length() ); + sha1->Update(ro); + } + + CleanupStack::PushL(sha1); + HBufC8* calculatedHash( sha1->Final().AllocL() ); + CleanupStack::PopAndDestroy( sha1 ); + sha1 = NULL; + CleanupStack::PushL( calculatedHash ); + + if (calculatedHash->Compare(*parsedRo->iMacDigest) == KErrNone) + { + // Digest OK -> now verify the MAC + signedInfoStart = protectedRo.Find(KMacStart()); + + if (signedInfoStart < KErrNone) + { + integrityCheck = EFalse; + r = KErrCorrupt; + } + + if (integrityCheck && GetElementStartEnd(KSignedInfoElement, protectedRo, signedInfoStart, signedInfoEnd) == EFalse) + { + integrityCheck = EFalse; + r = KErrCorrupt; + } + + if(integrityCheck) + { + TPtrC8 signedInfo = protectedRo.Mid(signedInfoStart, signedInfoEnd - signedInfoStart); + r = client.VerifyMacL(signedInfo, *parsedRo->iMac); + + if (r == KErrNone) + { + // MAC validation OK + // If we parsed a domain RO, store it in its original form as well + if (parsedRo->iDomainRo) + { + HBufC8* protRoWithNs = NULL; + protRoWithNs = AddRoapNamespaceL(protectedRo); + if(protRoWithNs) + { + client.AddDomainRO(*parsedRo->iId, *protRoWithNs); + delete protRoWithNs; + protRoWithNs = NULL; + } + else + { + client.AddDomainRO(*parsedRo->iId, protectedRo); + } + } + + // Add RO to replay cache + if (parsedRo->iTimeStamp == Time::NullTTime()) + { + User::LeaveIfError(client.AddToCache(*parsedRo->iId)); + } + else + { + User::LeaveIfError(client.AddToCache(*parsedRo->iId, parsedRo->iTimeStamp)); + } + } + else + { + integrityCheck = EFalse; + } + } + } + else + { + integrityCheck = EFalse; + r = KErrCorrupt; + } + CleanupStack::PopAndDestroy( calculatedHash ); + calculatedHash = NULL; + + if ( integrityCheck && !r ) + { + // Only add the rigths which were parsed in this loop + + for ( TInt i( n ); i < aResultRights.Count(); i++) + { + cid = NULL; + rights = aResultRights[i]; + rights->GetContentURI(cid); + CleanupStack::PushL(cid); + rights->GetPermission().iOriginalInsertTime = + parsedRo->iTimeStamp; + rights->GetPermission().iRoID = (*parsedRo->iId).AllocL(); + rights->GetPermission().iRiId.Copy(*parsedRo->iRightsIssuerId); + if (parsedRo->iDomainRo) + { + domain = ETrue; + rights->GetPermission().iDomainID = + parsedRo->iDomainId->AllocL(); + } + if (parsedRo->iRightsIssuerId) + { + riId.Set(*parsedRo->iRightsIssuerId); + } + if (parsedRo->iTransportScheme == EOma) + { + rights->GetPermission().iRightsObjectVersion.iVersionMain = + EOma2Rights; + } + else + { + rights->GetPermission().iRightsObjectVersion.iVersionMain = + ECmlaRights; + } + r = client.AddProtectedRecord( rights->GetAsset().iProtectedKey, + domain, rights->GetPermission(), + *cid, id ); + if (!r) + { + if (rights->GetAsset().iProtectedAuthSeed.Length()> 0) + { + r = client.SetAuthenticationSeed(*cid, + rights->GetAsset().iProtectedAuthSeed); + } + } + + User::LeaveIfError(r); + rights->SetLocalID(id); + CleanupStack::PopAndDestroy(cid); + } + } + else + { + User::Leave(KErrCorrupt); + } + + start = end; + n = aResultRights.Count(); + CleanupStack::PopAndDestroy(parsedRo); + parsedRo = NULL; + } + CleanupStack::PopAndDestroy( &client ); + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnStartDocumentL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnStartDocumentL( + const RDocumentParameters& /*aDocParam*/, TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnEndDocumentL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnEndDocumentL(TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnStartElementL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnStartElementL(const RTagInfo& aElement, + const RAttributeArray& aAttributes, TInt /*aErrorCode*/) + { + HBufC8* b= NULL; + + if (iContent) + { + delete iContent; + iContent = NULL; + iContent = HBufC8::NewL(0); + } + + for (TInt i = 0; i < KMaxElementCount; i++) + { + if (aElement.LocalName() == iElements[i]) + { + iElementStack[iElementStackDepth] = static_cast(i); + iElementStackDepth++; + if (iElementStackDepth == KMaxElementNesting) + { + User::Leave(EXmlUnexpectedState); + } + TInt state( MatchStackState() ); + if (state == ERoState) + { + _LIT8( KTrue, "true" ); + iRights->iId = GetAttributeValueL(aAttributes, KIdAttr); + iRights->iRiUrl = GetAttributeValueL(aAttributes, KRiUrlAttr); + b = GetAttributeValueL(aAttributes, KDomainRoAttr); + if ( b && b->Compare( KTrue() ) == 0 ) + { + iRights->iDomainRo = ETrue; + } + else + { + iRights->iDomainRo = EFalse; + } + delete b; + } + else + if (state == EEncryptionMethodState) + { + b = GetAttributeValueL(aAttributes, KAlgorithmAttr); + if ( b ) + { + iRights->iTransportScheme + = CmlaCrypto::AlgorithmIdToTransportScheme(*b); + delete b; + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnEndElementL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnEndElementL(const RTagInfo& aElement, TInt /*aErrorCode*/) + { + for (TInt i = 0; i < KMaxElementCount; i++) + { + if (aElement.LocalName() == iElements[i]) + { + switch (MatchStackState()) + { + case ECipherValueState: + iRights->iKey = Base64DecodeL(iContent->Des()); + break; + case EDomainIdentifierState: + iRights->iDomainId = iContent->AllocL(); + break; + case ERightsIssuerIdState: + iRights->iRightsIssuerId = Base64DecodeL(iContent->Des()); + break; + case ETimeStampState: + iRights->iTimeStamp = Iso8601ToTime(*iContent); + break; + case EMacValueState: + iRights->iMac = Base64DecodeL(iContent->Des()); + break; + case EMacDigestValueState: + iRights->iMacDigest = Base64DecodeL(iContent->Des()); + break; + } + iElementStackDepth--; + if (iElementStackDepth < 0) + { + User::Leave(EXmlUnexpectedState); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnContentL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::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); + } + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnStartPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnStartPrefixMappingL(const RString& /*aPrefix*/, + const RString& /*aUri*/, TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnEndPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnEndPrefixMappingL(const RString& /*aPrefix*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnIgnorableWhiteSpaceL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, + TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnSkippedEntityL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnProcessingInstructionL +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnProcessingInstructionL( + const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnOutOfData +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnOutOfData() + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::OnError +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::OnError(TInt /*aErrorCode*/) + { + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetExtendedInterface +// ----------------------------------------------------------------------------- +// +TAny* CDrmProtectedRoParser::GetExtendedInterface(const TInt32 /*aUid*/) + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::MatchStackState +// ----------------------------------------------------------------------------- +// +TInt CDrmProtectedRoParser::MatchStackState() + { + TInt i( 0 ); + TInt j( 0 ); + TInt k( 0 ); + 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; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetAttributeValueL +// Allocate the attribute value as a buffer if it is found, otherwise it's NULL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmProtectedRoParser::GetAttributeValueL( + const RAttributeArray& aAttrList, const TDesC8& aAttrName) + { + HBufC8* r( NULL ); + + for ( TInt i(0); !r && i < aAttrList.Count(); i++ ) + { + const RAttribute& a( aAttrList[i] ); + if ( a.Attribute().LocalName().DesC().Compare( aAttrName ) == 0 ) + { + r = a.Value().DesC().AllocL(); + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::GetElementStartEnd +// Search for the element as a string +// ----------------------------------------------------------------------------- +// +TBool CDrmProtectedRoParser::GetElementStartEnd(const TDesC8& aElement, + const TDesC8& aData, TInt& aStart, TInt& aEnd) + { + TInt i( 0 ); + TInt j( 0 ); + TBool r( EFalse ); + TBuf8 element; + + DEBUGLOG( "CDrmProtectedRoParser::GetElementStartEnd ->" ); + + DEBUGLOG( "aElement" ); + DEBUGLOGHEX( aElement.Ptr(), aElement.Length() ); + DEBUGLOG( "aData" ); + DEBUGLOGHEX( aData.Ptr(), aData.Length() ); + element.Copy(KStartElementStart); + element.Append(aElement); + // Find the start tag, which has to end with a "<" or whitespace + i = aData.Mid(aStart).Find(element); + + if (i == KErrNotFound) + { + // try the same thing with ROAP prefix + element.Copy(KStartElementStart); + element.Append(KRoapPrefix); + element.Append(aElement); + i = aData.Mid(aStart).Find(element); + } + + while (i != KErrNotFound && !(aData[aStart + i + element.Length()] == '>' || aData[aStart + i + element.Length()] <= ' ')) + { + aStart += i; + i = aData.Mid(aStart + element.Length() + 1).Find(element); + } + + if (i != KErrNotFound) + { + aStart += i; + i = aStart; + element.Copy(KEndElementStart); + element.Append(aElement); + element.Append(KElementEnd); + j = aData.Mid(i + 1).Find(element); + if (j == KErrNotFound) + { + // try the same thing with ROAP prefix + element.Copy(KEndElementStart); + element.Append(KRoapPrefix); + element.Append(aElement); + element.Append(KElementEnd); + j = aData.Mid(i + 1).Find(element); + } + if (j != KErrNotFound) + { + aEnd = i + 1 + j + element.Length(); + r = ETrue; + } + } +#ifdef _DEBUG + if ( r ) + { + TPtrC8 extracted( aData.Mid( aStart, aEnd - aStart ) ); + DEBUGLOG( "got element: " ); + DEBUGLOGHEX( extracted.Ptr(), extracted.Length() ); + } +#endif + DEBUGLOG( "-> CDrmProtectedRoParser::GetElementStartEnd" ); + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::HandleUnregisteredDomainRoL +// Embed the domain RO into all matching DCF files +// ----------------------------------------------------------------------------- +// +void CDrmProtectedRoParser::HandleUnregisteredDomainRoL( + const TDesC8& aContentId, const TDesC8& aDomainRoData, + CParsedProtectedRo* /*aDomainRo*/) + { + CDcfRep* rep( NULL ); + COma2Dcf* dcf( NULL ); + CDcfEntry* entry( NULL ); + RFile file; + RFs fs; + TBool exists( EFalse ); + TInt r( KErrNone ); + + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + rep = CDcfRep::NewL(); + CleanupStack::PushL( rep ); + TRAP( r, rep->OrderListL( aContentId ) ); + if ( r == KErrNone ) + { + entry = rep->NextL(); + } + while ( r == KErrNone && entry ) + { + CleanupStack::PushL( entry ); + + r = file.Open( fs, entry->FileName(), EFileWrite + | EFileShareReadersOrWriters ); + if ( r == KErrInUse ) + { + r = file.Open(fs, entry->FileName(), EFileWrite | EFileShareAny); + } + + if ( r == KErrNone ) + { + CleanupClosePushL( file ); + dcf = COma2Dcf::NewL( file ); + CleanupStack::PushL( dcf ); + for ( TInt i = 0; !exists && i < dcf->iRightsObjects.Count(); i++ ) + { + if ( dcf->iRightsObjects[i]->Compare(aDomainRoData) == 0 ) + { + exists = ETrue; + } + } + if ( !exists ) + { + dcf->iRightsObjects.Append( aDomainRoData.AllocL() ); + dcf->SetRightsObjectsL( dcf->iRightsObjects ); + } + CleanupStack::PopAndDestroy( dcf ); + CleanupStack::PopAndDestroy( &file ); + } + CleanupStack::PopAndDestroy( entry ); + entry = rep->NextL(); + } + CleanupStack::PopAndDestroy( rep ); + CleanupStack::PopAndDestroy( &fs ); + } + +// ----------------------------------------------------------------------------- +// CDrmProtectedRoParser::AddRoapNamespaceL +// Add ROAP namespace declaration if needed +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmProtectedRoParser::AddRoapNamespaceL(TDesC8& aProtectedRo) const + { + TInt index = 0; + HBufC8* roWithNs= NULL; + TPtr8 roWithNsPtr(NULL, NULL); + + if (aProtectedRo.Find(KRoapXmlNsUri) == KErrNotFound) + { + roWithNs = HBufC8::NewLC(aProtectedRo.Length() + KRoapXmlNs().Length()); + roWithNsPtr.Set(roWithNs->Des()); + index = aProtectedRo.Find(KQualifiedProtectedRo); + if (index == KErrNotFound) + { + index = aProtectedRo.Find(KRoElement); + if (index == KErrNotFound) + { + User::Leave(KErrCorrupt); + } + index += KRoElement().Length(); + } + else + { + index += KQualifiedProtectedRo().Length(); + } + roWithNsPtr.Copy(aProtectedRo.Left(index)); + roWithNsPtr.Append(KRoapXmlNs()); + roWithNsPtr.Append(aProtectedRo.Right(aProtectedRo.Length() - index)); + CleanupStack::Pop(roWithNs); + } + return roWithNs; + } + +// End of File