omadrm/drmengine/dcf/src/Oma2Dcf.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
equal deleted inserted replaced
-1:000000000000 0:95b198f216e5
       
     1 /*
       
     2 * Copyright (c) 2002 - 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of class representeting discrete OMA2 DCF
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32const.h> // KMaxTUint32
       
    22 #include <e32cmn.h> // Max, Min
       
    23 #include <e32base.h>
       
    24 #include <f32file.h>
       
    25 #include <utf.h>
       
    26 #include <caf/caf.h>
       
    27 #include "Oma2Agent.h"
       
    28 #include "Oma2Dcf.h"
       
    29 #include "Oma2DcfPartInfo.h"
       
    30 
       
    31 // LOCAL CONSTANTS AND MACROS
       
    32 
       
    33 #define M4CC( a ) ( ( a[ 0 ] << 24 ) + ( a[ 1 ] << 16 ) + ( a[ 2 ] << 8 ) + a[ 3 ] )
       
    34 
       
    35 const TUint32 KDiscreteMediaHeaders( M4CC( "odhe" ) );
       
    36 const TUint32 KContainer( M4CC( "odrm" ) );
       
    37 const TUint32 KContentObject( M4CC( "odda" ) );
       
    38 const TUint32 KCommonHeaders( M4CC( "ohdr" ) );
       
    39 const TUint32 KMutableInfo( M4CC( "mdri" ) );
       
    40 const TUint32 KTransactionTracking( M4CC( "odtt" ) );
       
    41 const TUint32 KRightsObject( M4CC( "odrb" ) );
       
    42 const TUint32 KGroupId( M4CC( "grpi" ) );
       
    43 const TUint32 KUserData( M4CC( "udta" ) );
       
    44 
       
    45 // supported user data boxes
       
    46 _LIT8( KTitle, "titl" );
       
    47 _LIT8( KDescription, "dscp" );
       
    48 _LIT8( KCopyright, "cprt" );
       
    49 _LIT8( KAuthor, "auth" );
       
    50 _LIT8( KIconUri, "icnu" );
       
    51 _LIT8( KInfoURL, "infu" );
       
    52 _LIT8( KPerformer, "perf" );
       
    53 _LIT8( KGenre, "gnre" );
       
    54 _LIT8( KRating, "rtng" );
       
    55 _LIT8( KClassification, "clsf" );
       
    56 _LIT8( KKeyword, "kywd" );
       
    57 _LIT8( KLocationInformation, "loci" );
       
    58 _LIT8( KAlbum, "albm" );
       
    59 _LIT8( KRecordingYear, "yrrc" );
       
    60 _LIT8( KCoverUri, "cvru" );
       
    61 _LIT8( KLyricsURL, "lrcu" );
       
    62 
       
    63 
       
    64 _LIT8( KMdri, "mdri" );
       
    65 _LIT8( KOdtt, "odtt" );
       
    66 _LIT8( KOdrb, "odrb" );
       
    67 
       
    68 // textual headers
       
    69 _LIT8( KSilentHeader, "Silent" );
       
    70 _LIT8( KPreviewHeader, "Preview" );
       
    71 _LIT8( KContentURLHeader, "ContentURL" );
       
    72 _LIT8( KContentVersionHeader, "ContentVersion" );
       
    73 _LIT8( KContentLocationHeader, "Content-Location" );
       
    74 
       
    75 // supported custom textual headers
       
    76 _LIT8( KIconUriHeader, "IconURI" );
       
    77 _LIT8( KTitleHeader, "Title" );
       
    78 _LIT8( KDescriptionHeader, "Description" );
       
    79 _LIT8( KAuthorHeader, "Author" );
       
    80 _LIT8( KCopyrightHeader, "Copyright" );
       
    81 _LIT8( KInfoURLHeader, "InfoURL" );
       
    82 
       
    83 // textual headers, methods
       
    84 _LIT8( KSilentMethodOnDemand, "on-demand" );
       
    85 _LIT8( KSilentMethodInAdvance, "in-advance" );
       
    86 _LIT8( KPreviewMethodInstant, "instant" );
       
    87 _LIT8( KPreviewMethodPreviewRights, "preview-rights" );
       
    88 _LIT8( KEmptyTransactionId, "0000000000000000" );
       
    89 
       
    90 _LIT8( KTerminator, "\0" );
       
    91 _LIT8( KSeparator, ":" );
       
    92 _LIT8( KParamSeparator, ";" );
       
    93 
       
    94 const TInt KBrandingSize( 20 );
       
    95 const TInt KMaxBoxHeaderSize( 16 );
       
    96 const TInt KLengthBoxSize( 4 );
       
    97 const TInt KLengthBoxType( 4 );
       
    98 const TInt KLengthBoxSize64( 8 );
       
    99 const TInt KLengthVersion( 1 );
       
   100 const TInt KLengthFlags( 3 );
       
   101 const TInt KLengthEncMethod( 1 );
       
   102 const TInt KLengthPadType( 1 );
       
   103 const TInt KLengthPlainTextSize( 8 );
       
   104 const TInt KLengthDataLengthSize( 8 );
       
   105 const TInt KLengthContentIdSize( 2 );
       
   106 const TInt KLengthRiUrlSize( 2 );
       
   107 const TInt KLengthTextHeadersSize( 2 );
       
   108 const TInt KLengthTerminator( 1 );
       
   109 
       
   110 // Smallest possible ISO based media box size
       
   111 // See ISO/IEC 14496-12 and DRM-DCF-CLI-12 in OMA-TS-DRM-DCF-V2_1
       
   112 const TUint32 KMinBoxSize( KLengthBoxSize + KLengthBoxType );
       
   113 // Largest supported ISO based media box size
       
   114 const TUint32 KMaxBoxSize( KMaxTUint32 );
       
   115 
       
   116 const TUint KUserDataBoxMask( 0x000001 );
       
   117 
       
   118 // ============================= LOCAL FUNCTIONS ===============================
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // ReadUint32FromBlock
       
   122 // -----------------------------------------------------------------------------
       
   123 //
       
   124 LOCAL_C TUint32 ReadUint32FromBlock( const TDesC8& aBlock, TInt aOffset )
       
   125     {
       
   126     return ( aBlock[ aOffset ] << 24 ) +
       
   127         ( aBlock[ aOffset + 1 ] << 16 ) +
       
   128         ( aBlock[ aOffset + 2 ] << 8 ) +
       
   129         aBlock[ aOffset + 3 ];
       
   130     }
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // ReadUint16FromBlock
       
   134 // -----------------------------------------------------------------------------
       
   135 //
       
   136 LOCAL_C TUint16 ReadUint16FromBlock( const TDesC8& aBlock, TInt aOffset )
       
   137     {
       
   138     return ( ( aBlock[ aOffset ] << 8 ) + aBlock[ aOffset + 1 ] );
       
   139     }
       
   140 
       
   141 // -----------------------------------------------------------------------------
       
   142 // WriteIntToBlock
       
   143 // -----------------------------------------------------------------------------
       
   144 //
       
   145 LOCAL_C void WriteIntToBlock( TInt aValue, TDes8& aBlock, TInt aOffset )
       
   146     {
       
   147     aBlock.SetLength( 4 );
       
   148     aBlock[ aOffset ] =     ( aValue & 0xff000000 ) >> 24;
       
   149     aBlock[ aOffset + 1 ] = ( aValue & 0x00ff0000 ) >> 16;
       
   150     aBlock[ aOffset + 2 ] = ( aValue & 0x0000ff00 ) >> 8;
       
   151     aBlock[ aOffset + 3 ] = ( aValue & 0x000000ff );
       
   152     }
       
   153 
       
   154 // -----------------------------------------------------------------------------
       
   155 // ValidateBoxSizeL
       
   156 // -----------------------------------------------------------------------------
       
   157 //
       
   158 LOCAL_C void ValidateBoxSizeL(
       
   159     const TUint32 aSize,
       
   160     const TUint32 aMinSize = KMinBoxSize,
       
   161     const TUint32 aMaxSize = KMaxBoxSize )
       
   162     {
       
   163     TUint32 minSize( Max( aMinSize, KMinBoxSize) );
       
   164     TUint32 maxSize( Min( aMaxSize, KMaxBoxSize ) );
       
   165     if ( aSize < minSize )
       
   166         {
       
   167         User::Leave( KErrArgument );
       
   168         }
       
   169     if ( aSize > maxSize )
       
   170         {
       
   171         User::Leave( KErrArgument );
       
   172         }
       
   173     }
       
   174 
       
   175 // ============================ MEMBER FUNCTIONS ===============================
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // COma2Dcf::COma2Dcf
       
   179 // C++ default constructor can NOT contain any code, that
       
   180 // might leave.
       
   181 // -----------------------------------------------------------------------------
       
   182 //
       
   183 COma2Dcf::COma2Dcf():
       
   184     iEncrytionPadding( EPaddingNone ),
       
   185     iSilentRefresh( ENoSilentRefresh ),
       
   186     iPreview( ENoPreview ),
       
   187     iPreviewParameter( NULL ),
       
   188     iSilentParameter( NULL ),
       
   189     iTextualHeaders( NULL ),
       
   190     iContentUrl( NULL ),
       
   191     iContentVersion( NULL ),
       
   192     iContentLocation( NULL ),
       
   193     iTransactionTracking( NULL ),
       
   194     iUserData( NULL ),
       
   195     iAuthor( NULL ),
       
   196     iCopyRight( NULL ),
       
   197     iInfoUri( NULL ),
       
   198     iGroupId( NULL ),
       
   199     iGroupKey( NULL ),
       
   200     iGkEncryptionMethod( EMethodNULL ),
       
   201     iMutablePart( NULL ),
       
   202     iPerformer( NULL ),
       
   203     iGenre( NULL ),
       
   204     iRatingInfo( NULL ),
       
   205     iClassificationInfo( NULL ),
       
   206     iKeyword( NULL ),
       
   207     iLocInfoName( NULL ),
       
   208     iLocInfoAstronomicalBody( NULL ),
       
   209     iLocInfoAdditionalNotes( NULL ),
       
   210     iAlbumTitle( NULL ),
       
   211     iCoverUri( NULL ),
       
   212     iLyricsURL( NULL ),
       
   213     iRecordingYear( 0 ),
       
   214     iAlbumTrack( 0 )
       
   215     {
       
   216     }
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // COma2Dcf::ConstructL
       
   220 // Symbian 2nd phase constructor can leave.
       
   221 // -----------------------------------------------------------------------------
       
   222 //
       
   223 void COma2Dcf::ConstructL(
       
   224     const RFile& aFile,
       
   225     TInt aPart )
       
   226     {
       
   227     CDcfCommon::ConstructL( aFile );
       
   228     ReadPartsL();
       
   229     User::LeaveIfError( OpenPart( aPart ) );
       
   230     }
       
   231 
       
   232 // -----------------------------------------------------------------------------
       
   233 // COma2Dcf::NewL
       
   234 // Two-phased constructor.
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 EXPORT_C COma2Dcf* COma2Dcf::NewL(
       
   238     const RFile& aFile,
       
   239     TInt aPart )
       
   240     {
       
   241     COma2Dcf* self( new ( ELeave ) COma2Dcf );
       
   242 
       
   243     CleanupStack::PushL( self );
       
   244     self->ConstructL( aFile, aPart );
       
   245     CleanupStack::Pop( self );
       
   246 
       
   247     return self;
       
   248     }
       
   249 
       
   250 // Destructor
       
   251 EXPORT_C COma2Dcf::~COma2Dcf()
       
   252     {
       
   253     delete iPreviewParameter;
       
   254     delete iSilentParameter;
       
   255     delete iTextualHeaders;
       
   256     delete iContentUrl;
       
   257     delete iContentVersion;
       
   258     delete iContentLocation;
       
   259     delete iTransactionTracking;
       
   260     delete iUserData;
       
   261     delete iAuthor;
       
   262     delete iCopyRight;
       
   263     delete iInfoUri;
       
   264     delete iGroupId;
       
   265     delete iGroupKey;
       
   266     delete iPerformer;
       
   267     delete iGenre;
       
   268     delete iRatingInfo;
       
   269     delete iClassificationInfo;
       
   270     delete iKeyword;
       
   271     delete iLocInfoName;
       
   272     delete iLocInfoAstronomicalBody;
       
   273     delete iLocInfoAdditionalNotes;
       
   274     delete iAlbumTitle;
       
   275     delete iCoverUri;
       
   276     delete iLyricsURL;
       
   277     delete iMutablePart;
       
   278 
       
   279     iRightsObjects.ResetAndDestroy();
       
   280     iRightsObjects.Close();
       
   281     iParts.ResetAndDestroy();
       
   282     iParts.Close();
       
   283     }
       
   284 
       
   285 // -----------------------------------------------------------------------------
       
   286 // COma2Dcf::IsValidDcf
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 EXPORT_C TBool COma2Dcf::IsValidDcf(
       
   290     const TDesC8& aDcfFragment )
       
   291     {
       
   292     TBool r( EFalse );
       
   293 
       
   294     if ( aDcfFragment.Length() >= KBrandingSize &&
       
   295         aDcfFragment.Left( KBrandingSize ).Compare( KOma2DcfBranding ) == 0 )
       
   296         {
       
   297         r = ETrue;
       
   298         }
       
   299     return r;
       
   300     }
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // COma2Dcf::ReadPartsL
       
   304 // -----------------------------------------------------------------------------
       
   305 //
       
   306 void COma2Dcf::ReadPartsL( void )
       
   307     {
       
   308     TBuf8<KBrandingSize> buffer;
       
   309     TInt size;
       
   310     TUint32 type;
       
   311     TInt offset;
       
   312     TInt headerSize;
       
   313     COma2DcfPartInfo* part;
       
   314 
       
   315     User::LeaveIfError( iFile.Read( 0, buffer, KBrandingSize ) );
       
   316     if ( !IsValidDcf( buffer ) )
       
   317         {
       
   318         User::Leave( KErrArgument );
       
   319         }
       
   320     iVersion = ReadUint32FromBlock( buffer, 12 );
       
   321     offset = KBrandingSize;
       
   322     iParts.Reset();
       
   323     do
       
   324         {
       
   325         ReadBoxSizeAndTypeL( offset, size, type, headerSize );
       
   326         if ( headerSize > 0 )
       
   327             {
       
   328             part = COma2DcfPartInfo::NewL();
       
   329             part->iType = type;
       
   330             part->iSize = size;
       
   331             part->iOffset = offset;
       
   332             CleanupStack::PushL( part );
       
   333             if ( type == KContainer )
       
   334                 {
       
   335                 ReadPartInfoL( part, offset );
       
   336                 iParts.Append( part );
       
   337                 CleanupStack::Pop( part );
       
   338                 }
       
   339             else if ( type == KMutableInfo )
       
   340                 {
       
   341                 iMutablePart = part;
       
   342                 CleanupStack::Pop( part );
       
   343                 ReadMutableInfoL( offset, size );
       
   344                 }
       
   345             else
       
   346                 {
       
   347                 CleanupStack::PopAndDestroy( part );
       
   348                 }
       
   349             }
       
   350         offset += size;
       
   351         }
       
   352     while ( offset < iLength && headerSize > 0 );
       
   353 
       
   354     delete iContentID;
       
   355     iContentID = NULL;
       
   356     delete iMimeType;
       
   357     iMimeType = NULL;
       
   358 
       
   359     if ( iParts.Count() == 0 ||
       
   360         iParts[ 0 ]->iContentId == NULL ||
       
   361         iParts[ 0 ]->iMimeType == NULL )
       
   362         {
       
   363         User::LeaveIfError( KErrArgument );
       
   364         }
       
   365     iContentID = iParts[ 0 ]->iContentId->AllocL();
       
   366     iMimeType = iParts[ 0 ]->iMimeType->AllocL();
       
   367     }
       
   368 
       
   369 // -----------------------------------------------------------------------------
       
   370 // COma2Dcf::CheckUniqueId
       
   371 // -----------------------------------------------------------------------------
       
   372 //
       
   373 TInt COma2Dcf::CheckUniqueId( const TDesC& aUniqueId )
       
   374     {
       
   375     TInt r( CDcfCommon::CheckUniqueId( aUniqueId ) );
       
   376 
       
   377     if ( r == KErrNotFound )
       
   378         {
       
   379         HBufC8* id( NULL );
       
   380         TRAPD( err,
       
   381             id = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aUniqueId ) );
       
   382         if ( err == KErrNone )
       
   383             {
       
   384             r = KErrNotFound;
       
   385             for ( TInt i( 0 );
       
   386                 i < iParts.Count() && r == KErrNotFound;
       
   387                 i++ )
       
   388                 {
       
   389                 if ( !id->Compare( *iParts[ i ]->iContentId ) )
       
   390                     {
       
   391                     r = i;
       
   392                     }
       
   393                 }
       
   394             delete id;
       
   395             }
       
   396         else
       
   397             {
       
   398             r = err;
       
   399             }
       
   400         }
       
   401     return r;
       
   402     }
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 // COma2Dcf::OpenPart
       
   406 // -----------------------------------------------------------------------------
       
   407 //
       
   408 TInt COma2Dcf::OpenPart(
       
   409     const TDesC& aUniqueId )
       
   410     {
       
   411     return OpenPart( CheckUniqueId( aUniqueId ) );
       
   412     }
       
   413 
       
   414 // -----------------------------------------------------------------------------
       
   415 // COma2Dcf::OpenPart
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 TInt COma2Dcf::OpenPart(
       
   419     TInt aPart )
       
   420     {
       
   421     TInt r( KErrNone );
       
   422     TInt size( 0 );
       
   423 
       
   424     if ( aPart >= 0 && aPart < iParts.Count() )
       
   425         {
       
   426         TRAP( r, ReadContainerL( iParts[ aPart ]->iOffset, size ) );
       
   427         }
       
   428     else
       
   429         {
       
   430         r = KErrNotFound;
       
   431         }
       
   432     return r;
       
   433     }
       
   434 
       
   435 // -----------------------------------------------------------------------------
       
   436 // COma2Dcf::GetPartIdsL
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 void COma2Dcf::GetPartIdsL( RPointerArray<HBufC8>& aPartList )
       
   440     {
       
   441     aPartList.ResetAndDestroy();
       
   442     for ( TInt i( 0 ); i < iParts.Count(); i++ )
       
   443         {
       
   444         aPartList.Append( iParts[ i ]->iContentId->AllocL() );
       
   445         }
       
   446     }
       
   447 
       
   448 // -----------------------------------------------------------------------------
       
   449 // COma2Dcf::ReadContainerL
       
   450 // -----------------------------------------------------------------------------
       
   451 //
       
   452 void COma2Dcf::ReadContainerL(
       
   453     TInt aOffset,
       
   454     TInt& aSize )
       
   455     {
       
   456     TUint32 type( 0 );
       
   457     TInt size( 0 );
       
   458 
       
   459     ReadBoxSizeAndTypeL( aOffset, aSize, type, size );
       
   460     VerifyTypeL( type, KContainer );
       
   461     aOffset += size + KLengthVersion + KLengthFlags;
       
   462     ReadDiscreteMediaHeaderL( aOffset, size );
       
   463     aOffset += size;
       
   464     ReadContentObjectL( aOffset, size );
       
   465     }
       
   466 
       
   467 // -----------------------------------------------------------------------------
       
   468 // COma2Dcf::ReadDiscreteMediaHeaderL
       
   469 // -----------------------------------------------------------------------------
       
   470 //
       
   471 void COma2Dcf::ReadDiscreteMediaHeaderL(
       
   472     TInt aOffset,
       
   473     TInt& aSize )
       
   474     {
       
   475     TBuf8<1> valBuf;
       
   476     TBuf8<4> udtaBuf;
       
   477     TInt size( 0 );
       
   478     TUint32 type( 0 );
       
   479     TUint8 length( 0 );
       
   480     TPtr8 ptr( 0, 0 );
       
   481 
       
   482     TBuf8< KLengthVersion + KLengthFlags > buffer;
       
   483     TUint32 version_and_flags( 0 );
       
   484 
       
   485     ReadBoxSizeAndTypeL( aOffset, aSize, type, size );
       
   486     VerifyTypeL( type, KDiscreteMediaHeaders );
       
   487 
       
   488     // read flags and version
       
   489     aOffset += size;
       
   490     User::LeaveIfError( iFile.Read( aOffset, buffer ) );
       
   491     version_and_flags = ReadUint32FromBlock( buffer, 0 );
       
   492     aOffset += KLengthVersion + KLengthFlags;
       
   493 
       
   494     // read ContentType
       
   495     delete iMimeType;
       
   496     iMimeType = NULL;
       
   497 
       
   498     // input validation
       
   499     if ( aOffset < 0 )
       
   500         {
       
   501         // RFile::Read will panic if offset is negative
       
   502         User::Leave( KErrArgument );
       
   503         }
       
   504 
       
   505     User::LeaveIfError( iFile.Read( aOffset, valBuf, 1 ) );
       
   506     length = valBuf[ 0 ];
       
   507     aOffset += 1;
       
   508     iMimeType = HBufC8::NewMax( length );
       
   509     User::LeaveIfNull( iMimeType );
       
   510     ptr.Set( iMimeType->Des() );
       
   511     User::LeaveIfError( iFile.Read( ptr, length ) );
       
   512     aOffset += length;
       
   513 
       
   514     // read Common headers
       
   515     ReadCommonHeadersL( aOffset, size );
       
   516 
       
   517     // user data box would follow here
       
   518     if ( version_and_flags & KUserDataBoxMask )
       
   519         {
       
   520         aOffset += size;
       
   521         User::LeaveIfError( iFile.Read( aOffset, udtaBuf, 4 ) );
       
   522         size = ReadUint32FromBlock( udtaBuf, 0 );
       
   523         ReadUserDataL( aOffset, size );
       
   524         }
       
   525     }
       
   526 
       
   527 // -----------------------------------------------------------------------------
       
   528 // COma2Dcf::ReadContentObjectL
       
   529 // -----------------------------------------------------------------------------
       
   530 //
       
   531 void COma2Dcf::ReadContentObjectL(
       
   532     TInt aOffset,
       
   533     TInt& aSize )
       
   534     {
       
   535     TBuf8<KMaxBoxHeaderSize> valBuf;
       
   536     TInt size( 0 );
       
   537     TUint32 type( 0 );
       
   538 
       
   539     ReadBoxSizeAndTypeL( aOffset, aSize, type, size );
       
   540     VerifyTypeL( type, KContentObject );
       
   541     aOffset += size + KLengthVersion + KLengthFlags;
       
   542 
       
   543     // read data length
       
   544 
       
   545     // input validation
       
   546     if ( aOffset < 0 )
       
   547         {
       
   548         // RFile::Read will panic if offset is negative
       
   549         User::Leave( KErrArgument );
       
   550         }
       
   551 
       
   552     User::LeaveIfError( iFile.Read( aOffset, valBuf, KLengthDataLengthSize ) );
       
   553     if ( ReadUint32FromBlock( valBuf, 0 ) != 0 )
       
   554         {
       
   555         // the size is larger than 2^32-1, we can't handle this.
       
   556         User::Leave( KErrOverflow );
       
   557         }
       
   558     else
       
   559         {
       
   560         iDataLength = ReadUint32FromBlock( valBuf, KLengthDataLengthSize / 2 );
       
   561         if ( iPlainTextLengthValid )
       
   562             {
       
   563             iPadding = iDataLength - iPlainTextLength;
       
   564             }
       
   565         }
       
   566     iOffset = aOffset + KLengthDataLengthSize;
       
   567     }
       
   568 
       
   569 // -----------------------------------------------------------------------------
       
   570 // COma2Dcf::ReadCommonHeadersL
       
   571 // -----------------------------------------------------------------------------
       
   572 //
       
   573 void COma2Dcf::ReadCommonHeadersL(
       
   574     TInt aOffset,
       
   575     TInt& aSize )
       
   576     {
       
   577     TBuf8< KMaxBoxHeaderSize > valBuf;
       
   578     TInt size( 0 );
       
   579     TInt boxEnd( 0 );
       
   580     TUint32 type( 0 );
       
   581     TInt offset( 0 );
       
   582     TUint16 riURLLength( 0 );
       
   583     TUint16 contentIdLength( 0 );
       
   584     TUint16 textualHeadersLength( 0 );
       
   585     TUint16 length( 0 );
       
   586     HBufC8* buf( NULL );
       
   587     TPtr8 ptr( 0, 0 );
       
   588 
       
   589     ReadBoxSizeAndTypeL( aOffset, aSize, type, size );
       
   590     VerifyTypeL( type, KCommonHeaders );
       
   591     boxEnd = aOffset + aSize;
       
   592     aOffset += size + KLengthVersion + KLengthFlags;
       
   593 
       
   594     length = KLengthEncMethod + KLengthPadType + KLengthPlainTextSize
       
   595         + KLengthContentIdSize + KLengthRiUrlSize + KLengthTextHeadersSize;
       
   596     buf = HBufC8::NewLC( length );
       
   597     ptr.Set( buf->Des() );
       
   598 
       
   599     // input validation
       
   600     if ( aOffset < 0 )
       
   601         {
       
   602         // RFile::Read will panic if offset is negative
       
   603         User::Leave( KErrArgument );
       
   604         }
       
   605     User::LeaveIfError( iFile.Read( aOffset, ptr, length ) );
       
   606 
       
   607     offset = 0;
       
   608     iEncryptionMethod = static_cast< TEncryptionMethod >( ( *buf )[ 0 ] );
       
   609     offset += KLengthEncMethod;
       
   610     iEncrytionPadding = static_cast< TEncryptionPadding >( ( *buf )[ 1 ] );
       
   611     offset += KLengthPadType;
       
   612 
       
   613     iPlainTextLength = ReadUint32FromBlock( ptr, offset );
       
   614     offset +=  KLengthPlainTextSize / 2;
       
   615     if ( iPlainTextLength != 0 )
       
   616         {
       
   617         User::Leave( KErrOverflow );
       
   618         }
       
   619     else
       
   620         {
       
   621         iPlainTextLength = ReadUint32FromBlock( ptr, offset );
       
   622         if ( iPlainTextLength > 0 )
       
   623             {
       
   624             iPlainTextLengthValid = ETrue;
       
   625             }
       
   626         else
       
   627             {
       
   628             iPlainTextLengthValid = EFalse;
       
   629             }
       
   630         offset +=  KLengthPlainTextSize / 2;
       
   631         }
       
   632 
       
   633     contentIdLength = ReadUint16FromBlock( ptr, offset );
       
   634     offset += KLengthContentIdSize;
       
   635     riURLLength = ReadUint16FromBlock( ptr, offset );
       
   636     offset += KLengthRiUrlSize;
       
   637     textualHeadersLength  = ReadUint16FromBlock( ptr, offset );
       
   638     offset += KLengthTextHeadersSize;
       
   639     CleanupStack::PopAndDestroy( buf );
       
   640     buf = NULL;
       
   641 
       
   642     aOffset += offset;
       
   643     delete iContentID;
       
   644     iContentID = NULL;
       
   645     iContentID = HBufC8::NewMax( contentIdLength );
       
   646     User::LeaveIfNull( iContentID );
       
   647     ptr.Set( iContentID->Des() );
       
   648     User::LeaveIfError( iFile.Read( aOffset, ptr, contentIdLength ) );
       
   649     aOffset += contentIdLength;
       
   650 
       
   651     delete iRightsIssuerURL;
       
   652     iRightsIssuerURL = NULL;
       
   653     if ( riURLLength > 0 )
       
   654         {
       
   655         iRightsIssuerURL = HBufC8::NewL( riURLLength );
       
   656         ptr.Set( iRightsIssuerURL->Des() );
       
   657         User::LeaveIfError( iFile.Read( aOffset, ptr, riURLLength ) );
       
   658         aOffset += riURLLength;
       
   659         }
       
   660 
       
   661     delete iTextualHeaders;
       
   662     iTextualHeaders = NULL;
       
   663     if ( textualHeadersLength > 0 )
       
   664         {
       
   665         iTextualHeaders = HBufC8::NewL( textualHeadersLength );
       
   666         ptr.Set( iTextualHeaders->Des() );
       
   667         User::LeaveIfError( iFile.Read( aOffset, ptr, textualHeadersLength ) );
       
   668         aOffset += textualHeadersLength;
       
   669         ParseTextualHeadersL( ptr );
       
   670         }
       
   671 
       
   672     ReadExtendedHeadersL( aOffset, boxEnd );
       
   673     }
       
   674 
       
   675 // -----------------------------------------------------------------------------
       
   676 // COma2Dcf::ParseTextualHeadersL
       
   677 // -----------------------------------------------------------------------------
       
   678 //
       
   679 void COma2Dcf::ParseTextualHeadersL(
       
   680     const TDesC8& aMemoryBlock )
       
   681     {
       
   682     HBufC8* buf1( NULL );
       
   683     HBufC8* method( NULL );
       
   684     TInt r( KErrNone );
       
   685     TInt silentOffset( 0 );
       
   686     TInt previewOffset( 0 );
       
   687 
       
   688     silentOffset = ReadOneTextualHeaderL(
       
   689         aMemoryBlock, KSilentHeader, buf1, r );
       
   690     if ( r != KErrNotFound && buf1 )
       
   691         {
       
   692         CleanupStack::PushL( buf1 );
       
   693         SetHeaderWithParameterL( *buf1, method, iSilentParameter );
       
   694         CleanupStack::PopAndDestroy( buf1 );
       
   695         buf1 = NULL;
       
   696         if ( method )
       
   697             {
       
   698             if ( !method->Compare( KSilentMethodOnDemand ) )
       
   699                 {
       
   700                 iSilentRefresh = EOnDemand;
       
   701                 }
       
   702             else if ( !method->Compare( KSilentMethodInAdvance ) )
       
   703                 {
       
   704                 iSilentRefresh = EInAdvance;
       
   705                 }
       
   706             else
       
   707                 {
       
   708                 delete method;
       
   709                 User::Leave( KErrArgument );
       
   710                 }
       
   711             delete method;
       
   712             method = NULL;
       
   713             }
       
   714         }
       
   715     else
       
   716         {
       
   717         iSilentRefresh = ENoSilentRefresh;
       
   718         delete iSilentParameter;
       
   719         iSilentParameter = 0;
       
   720         }
       
   721 
       
   722     previewOffset = ReadOneTextualHeaderL(
       
   723         aMemoryBlock, KPreviewHeader, buf1, r );
       
   724     if ( r != KErrNotFound && buf1 )
       
   725         {
       
   726         CleanupStack::PushL( buf1 );
       
   727         SetHeaderWithParameterL( *buf1, method, iPreviewParameter );
       
   728         CleanupStack::PopAndDestroy( buf1 );
       
   729         buf1 = NULL;
       
   730         if ( method )
       
   731             {
       
   732             if ( !method->CompareF( KPreviewMethodInstant ) )
       
   733                 {
       
   734                 iPreview = EInstantPreview;
       
   735                 }
       
   736             else if ( !method->CompareF( KPreviewMethodPreviewRights ) )
       
   737                 {
       
   738                 iPreview = EPreviewRights;
       
   739                 }
       
   740             else
       
   741                 {
       
   742                 delete method;
       
   743                 User::Leave( KErrArgument );
       
   744                 }
       
   745             delete method;
       
   746             method = NULL;
       
   747             }
       
   748         }
       
   749     else
       
   750         {
       
   751         iPreview = ENoPreview;
       
   752         delete iPreviewParameter;
       
   753         iPreviewParameter = NULL;
       
   754         }
       
   755 
       
   756     iPreviewOverridesSilentRefresh = EFalse;
       
   757     if ( iSilentRefresh != ENoSilentRefresh && iPreview != ENoPreview )
       
   758         {
       
   759         if ( previewOffset < silentOffset )
       
   760             {
       
   761             iPreviewOverridesSilentRefresh = ETrue;
       
   762             }
       
   763         }
       
   764 
       
   765     ReadOneTextualHeaderL(
       
   766         aMemoryBlock, KContentLocationHeader, iContentLocation, r );
       
   767     if ( r == KErrNotFound )
       
   768         {
       
   769         delete iContentLocation;
       
   770         iContentLocation = NULL;
       
   771         }
       
   772 
       
   773     ReadOneTextualHeaderL( aMemoryBlock, KContentURLHeader, iContentUrl, r );
       
   774     if ( r == KErrNotFound )
       
   775         {
       
   776         delete iContentUrl;
       
   777         iContentUrl = NULL;
       
   778         }
       
   779 
       
   780     ReadOneTextualHeaderL(
       
   781         aMemoryBlock, KContentVersionHeader, iContentVersion, r );
       
   782     if ( r == KErrNotFound )
       
   783         {
       
   784         delete iContentVersion;
       
   785         iContentVersion = NULL;
       
   786         }
       
   787 
       
   788     // custom headers ->
       
   789     ReadOneTextualHeaderL( aMemoryBlock, KInfoURLHeader, iInfoUri, r );
       
   790     if ( r == KErrNotFound )
       
   791         {
       
   792         delete iInfoUri;
       
   793         iInfoUri = NULL;
       
   794         }
       
   795 
       
   796     // custom header
       
   797     ReadOneTextualHeaderL( aMemoryBlock, KTitleHeader, iTitle, r );
       
   798     if ( r == KErrNotFound )
       
   799         {
       
   800         delete iTitle;
       
   801         iTitle = NULL;
       
   802         }
       
   803 
       
   804     ReadOneTextualHeaderL( aMemoryBlock, KIconUriHeader, iIconUri, r );
       
   805     if ( r == KErrNotFound )
       
   806         {
       
   807         delete iIconUri;
       
   808         iIconUri = NULL;
       
   809         }
       
   810 
       
   811     ReadOneTextualHeaderL( aMemoryBlock, KAuthorHeader, iAuthor, r );
       
   812     if ( r == KErrNotFound )
       
   813         {
       
   814         delete iAuthor;
       
   815         iAuthor = NULL;
       
   816         }
       
   817 
       
   818     ReadOneTextualHeaderL( aMemoryBlock, KDescriptionHeader, iDescription, r );
       
   819     if ( r == KErrNotFound )
       
   820         {
       
   821         delete iDescription;
       
   822         iDescription = NULL;
       
   823         }
       
   824 
       
   825     ReadOneTextualHeaderL( aMemoryBlock, KCopyrightHeader, iCopyRight, r );
       
   826     if ( r == KErrNotFound )
       
   827         {
       
   828         delete iCopyRight;
       
   829         iCopyRight = NULL;
       
   830         }
       
   831 
       
   832 
       
   833     }
       
   834 
       
   835 // -----------------------------------------------------------------------------
       
   836 // COma2Dcf::SetHeaderWithParameterL
       
   837 // -----------------------------------------------------------------------------
       
   838 //
       
   839 void COma2Dcf::SetHeaderWithParameterL(
       
   840     const TDesC8& aValue,
       
   841     HBufC8*& aMethod,
       
   842     HBufC8*& aParameter )
       
   843     {
       
   844     TInt offset( 0 );
       
   845 
       
   846     delete aMethod;
       
   847     aMethod = NULL;
       
   848     delete aParameter;
       
   849     aParameter = NULL;
       
   850 
       
   851     offset = aValue.Find( KParamSeparator );
       
   852     if ( offset == KErrNotFound || offset == 0 )
       
   853         {
       
   854         aMethod = aValue.AllocL();
       
   855         }
       
   856     else
       
   857         {
       
   858         aMethod = aValue.Left( offset ).AllocLC();
       
   859         aParameter = aValue.Mid( offset + 1 ).AllocL();
       
   860         CleanupStack::Pop( aMethod );
       
   861         }
       
   862     }
       
   863 
       
   864 // -----------------------------------------------------------------------------
       
   865 // COma2Dcf::ReadOneTextualHeaderL
       
   866 // -----------------------------------------------------------------------------
       
   867 //
       
   868 TInt COma2Dcf::ReadOneTextualHeaderL(
       
   869     const TDesC8& aBlock,
       
   870     const TDesC8& aName,
       
   871     HBufC8*& aBuf,
       
   872     TInt& aError )
       
   873     {
       
   874     TInt offset( aBlock.Find( aName ) );
       
   875 
       
   876     delete aBuf;
       
   877     aBuf = NULL;
       
   878     if ( offset == KErrNotFound )
       
   879         {
       
   880         aError = KErrNotFound;
       
   881         return offset;
       
   882         }
       
   883     else
       
   884         {
       
   885         if ( offset + aName.Length() < aBlock.Length() &&
       
   886             aBlock.Mid( offset + aName.Length(), 1 ) == KSeparator )
       
   887             {
       
   888             TInt length( 0 );
       
   889             length =
       
   890                 aBlock.Mid( offset + aName.Length() + 1 ).Find( KTerminator );
       
   891             if ( length == KErrNotFound )
       
   892                 {
       
   893                 User::Leave( KErrArgument );
       
   894                 }
       
   895             else
       
   896                 {
       
   897                 aBuf = HBufC8::NewL( length );
       
   898                 *aBuf = aBlock.Mid( offset + aName.Length() + 1, length );
       
   899                 }
       
   900             }
       
   901         }
       
   902     aError = KErrNone;
       
   903     return offset;
       
   904     }
       
   905 
       
   906 // -----------------------------------------------------------------------------
       
   907 // COma2Dcf::ReadExtendedHeadersL
       
   908 // -----------------------------------------------------------------------------
       
   909 //
       
   910 void COma2Dcf::ReadExtendedHeadersL(
       
   911     TInt aOffset,
       
   912     TInt aEndOfBox )
       
   913     {
       
   914     TInt size( 1 );
       
   915     TInt groupIdSize( 0 );
       
   916     TInt groupKeySize( 0 );
       
   917     TUint32 type( 0 );
       
   918     TInt headerSize( 0 );
       
   919     TInt dataSize( 0 );
       
   920     TInt offset( 0 );
       
   921     TPtr8 ptr( 0, 0 );
       
   922     HBufC8* buffer( NULL );
       
   923 
       
   924     delete iGroupId;
       
   925     iGroupId = NULL;
       
   926     delete iGroupKey;
       
   927     iGroupKey = NULL;
       
   928 
       
   929     while ( size > 0 && aOffset < aEndOfBox && iGroupId == NULL )
       
   930         {
       
   931         size = 0;
       
   932         ReadBoxSizeAndTypeL( aOffset, size, type, headerSize );
       
   933         if ( type == KGroupId )
       
   934             {
       
   935             dataSize = size - headerSize - KLengthVersion - KLengthFlags;
       
   936             offset = aOffset + headerSize + KLengthVersion + KLengthFlags;
       
   937             // input validation
       
   938             if ( dataSize < 0 || dataSize > KMaxTInt / 2 )
       
   939                 {
       
   940                 User::Leave( KErrArgument );
       
   941                 }
       
   942             buffer = HBufC8::NewLC( dataSize );
       
   943             ptr.Set( buffer->Des() );
       
   944             User::LeaveIfError( iFile.Read( offset, ptr, dataSize ) );
       
   945             // input validation
       
   946             if ( ptr.Length() == 0 )
       
   947                 {
       
   948                 User::Leave( KErrArgument );
       
   949                 }
       
   950             iGkEncryptionMethod = static_cast< TEncryptionMethod >( ptr[ 2 ] );
       
   951             groupIdSize = ReadUint16FromBlock( ptr, 0 );
       
   952             if ( 5 + groupIdSize > ptr.Length() )
       
   953                 {
       
   954                 User::Leave( KErrArgument );
       
   955                 }
       
   956             iGroupId = ptr.Mid( 5, groupIdSize ).AllocL();
       
   957             groupKeySize = ReadUint16FromBlock( ptr, 3 );
       
   958             if ( 5 + groupIdSize + groupKeySize > ptr.Length() )
       
   959                 {
       
   960                 User::Leave( KErrArgument );
       
   961                 }
       
   962             iGroupKey = ptr.Mid( 5 + groupIdSize, groupKeySize ).AllocL();
       
   963 
       
   964             // Set the content ID of this file to the group ID
       
   965             delete iContentID;
       
   966             iContentID = NULL;
       
   967             iContentID = iGroupId->AllocL();
       
   968 
       
   969             CleanupStack::PopAndDestroy( buffer );
       
   970             }
       
   971         aOffset += size;
       
   972         }
       
   973     }
       
   974 
       
   975 // -----------------------------------------------------------------------------
       
   976 // COma2Dcf::ReadMutableInfoL
       
   977 // -----------------------------------------------------------------------------
       
   978 //
       
   979 void COma2Dcf::ReadMutableInfoL(
       
   980     TInt aOffset,
       
   981     TInt& aSize )
       
   982     {
       
   983     TInt size( 0 );
       
   984     TInt dataSize( 0 );
       
   985     TUint32 type( 0 );
       
   986     TInt headerSize( 0 );
       
   987     TPtr8 ptr( 0, 0 );
       
   988     HBufC8* buffer1( NULL );
       
   989     TInt boxEnd( 0 );
       
   990     TInt offset( 0 );
       
   991 
       
   992     delete iTransactionTracking;
       
   993     iTransactionTracking = NULL;
       
   994     iRightsObjects.ResetAndDestroy();
       
   995 
       
   996     ReadBoxSizeAndTypeL( aOffset, aSize, type, headerSize );
       
   997     VerifyTypeL( type, KMutableInfo );
       
   998 
       
   999     if ( !iMutablePart )
       
  1000         {
       
  1001         iMutablePart = COma2DcfPartInfo::NewL();
       
  1002         iMutablePart->iType = type;
       
  1003         iMutablePart->iSize = aSize;
       
  1004         iMutablePart->iOffset = aOffset;
       
  1005         }
       
  1006 
       
  1007 
       
  1008     boxEnd = aOffset + aSize;
       
  1009     aOffset += headerSize;
       
  1010 
       
  1011     do
       
  1012         {
       
  1013         ReadBoxSizeAndTypeL( aOffset, size, type, headerSize );
       
  1014         if ( headerSize > 0 )
       
  1015             {
       
  1016             dataSize = size - headerSize - KLengthVersion - KLengthFlags;
       
  1017             offset = aOffset + headerSize + KLengthVersion + KLengthFlags;
       
  1018             // input validation
       
  1019             if ( dataSize < 0 || dataSize > KMaxTInt / 2 )
       
  1020                 {
       
  1021                 User::Leave( KErrArgument );
       
  1022                 }
       
  1023             if ( type == KTransactionTracking && !iTransactionTracking )
       
  1024                 {
       
  1025                 buffer1 = HBufC8::NewLC( dataSize );
       
  1026                 ptr.Set( buffer1->Des() );
       
  1027                 User::LeaveIfError( iFile.Read( offset, ptr, dataSize ) );
       
  1028                 CleanupStack::Pop( buffer1 );
       
  1029                 iTransactionTracking = buffer1;
       
  1030                 }
       
  1031             else if ( type == KRightsObject )
       
  1032                 {
       
  1033                 buffer1 = HBufC8::NewLC( dataSize );
       
  1034                 ptr.Set( buffer1->Des() );
       
  1035                 User::LeaveIfError( iFile.Read( offset, ptr, dataSize ) );
       
  1036                 CleanupStack::Pop( buffer1 );
       
  1037                 iRightsObjects.Append( buffer1 );
       
  1038                 }
       
  1039             }
       
  1040         aOffset += size;
       
  1041 
       
  1042         }
       
  1043     while ( headerSize > 0 && aOffset < boxEnd && offset <= iLength );
       
  1044     }
       
  1045 
       
  1046 // -----------------------------------------------------------------------------
       
  1047 // COma2Dcf::ReadBoxSizeAndTypeL
       
  1048 // -----------------------------------------------------------------------------
       
  1049 //
       
  1050 void COma2Dcf::ReadBoxSizeAndTypeL(
       
  1051     TInt aOffset,
       
  1052     TInt& aSize,
       
  1053     TUint32& aType,
       
  1054     TInt& aHeaderSize )
       
  1055     {
       
  1056     TBuf8< KLengthBoxSize + KLengthBoxType > buffer;
       
  1057 
       
  1058     aHeaderSize = 0;
       
  1059     // input validation
       
  1060     if ( aOffset < 0 || aOffset > iLength )
       
  1061         {
       
  1062         // Valid offset can never be negative
       
  1063         // or greater than length of the opened file.
       
  1064         User::Leave( KErrArgument );
       
  1065         }
       
  1066     User::LeaveIfError( iFile.Read( aOffset, buffer ) );
       
  1067     if ( buffer.Length() == KLengthBoxSize + KLengthBoxType )
       
  1068         {
       
  1069         aSize = ReadUint32FromBlock( buffer, 0 );
       
  1070         aType = ReadUint32FromBlock( buffer, 4 );
       
  1071         aHeaderSize = KLengthBoxSize + KLengthBoxType;
       
  1072 
       
  1073         if ( aSize == 1 )
       
  1074             {
       
  1075             buffer.SetLength( 0 );
       
  1076             User::LeaveIfError( iFile.Read( buffer ) );
       
  1077             if ( buffer.Length() < KLengthBoxSize + KLengthBoxType )
       
  1078                 {
       
  1079                 User::Leave( KErrArgument );
       
  1080                 }
       
  1081             if ( ReadUint32FromBlock( buffer, 0 ) > 0 )
       
  1082                 {
       
  1083                 User::Leave( KErrOverflow );
       
  1084                 }
       
  1085             aSize = ReadUint32FromBlock( buffer, 4 );
       
  1086             aHeaderSize += KLengthBoxSize64;
       
  1087             }
       
  1088         else if ( aSize == 0 )
       
  1089             {
       
  1090             aSize = iLength - aOffset;
       
  1091             }
       
  1092         else if ( aType == KContainer )
       
  1093             {
       
  1094             // oma drm container box must always have large length field set
       
  1095             // See DRM-DCF-CLI-15 in OMA-TS-DRM-DCF-V2_1.
       
  1096             User::Leave( KErrArgument );
       
  1097             }
       
  1098         }
       
  1099     // Valid box size can never be smaller than discovered header size.
       
  1100     // Nor can it be larger than largest supported ISO based media box size.
       
  1101     ValidateBoxSizeL( aSize, aHeaderSize, KMaxBoxSize - aOffset );
       
  1102     }
       
  1103 
       
  1104 // -----------------------------------------------------------------------------
       
  1105 // COma2Dcf::VerifyTypeL
       
  1106 // -----------------------------------------------------------------------------
       
  1107 //
       
  1108 void COma2Dcf::VerifyTypeL( TUint32 aType, TUint32 aRefType )
       
  1109     {
       
  1110     if ( aRefType != aType )
       
  1111         {
       
  1112         User::Leave( KErrArgument );
       
  1113         };
       
  1114     }
       
  1115 
       
  1116 // -----------------------------------------------------------------------------
       
  1117 // COma2Dcf::SetTransactionIdL
       
  1118 // -----------------------------------------------------------------------------
       
  1119 //
       
  1120 EXPORT_C void COma2Dcf::SetTransactionIdL(
       
  1121     const TDesC8& aTransactionId )
       
  1122     {
       
  1123     // Overwrite existing ID, otherwise, recreate the whole MDRI box
       
  1124     if ( iTransactionTracking )
       
  1125         {
       
  1126         TInt size( 0 );
       
  1127         TUint32 type( 0 );
       
  1128         TInt headerSize( 0 );
       
  1129         TInt offset( 0 );
       
  1130 
       
  1131         offset = iMutablePart->iOffset;
       
  1132         // Read mutable box headers and skip them
       
  1133         ReadBoxSizeAndTypeL( offset, size, type, headerSize );
       
  1134         offset += headerSize;
       
  1135         do
       
  1136             {
       
  1137             ReadBoxSizeAndTypeL( offset, size, type, headerSize );
       
  1138             if ( type != KTransactionTracking )
       
  1139                 {
       
  1140                 offset += size;
       
  1141                 }
       
  1142             }
       
  1143         while ( headerSize > 0 &&
       
  1144             type != KTransactionTracking && offset <= iLength );
       
  1145 
       
  1146 
       
  1147         if ( type == KTransactionTracking )
       
  1148             {
       
  1149             offset += headerSize + KLengthVersion + KLengthFlags;
       
  1150             User::LeaveIfError( iFile.Write( offset, aTransactionId ) );
       
  1151             }
       
  1152         }
       
  1153     else
       
  1154         {
       
  1155         RewriteMutableInfoL( aTransactionId, iRightsObjects );
       
  1156         }
       
  1157     }
       
  1158 
       
  1159 // -----------------------------------------------------------------------------
       
  1160 // COma2Dcf::SetRightsObjectsL
       
  1161 // -----------------------------------------------------------------------------
       
  1162 //
       
  1163 EXPORT_C void COma2Dcf::SetRightsObjectsL(
       
  1164     RPointerArray<HBufC8>& aRoList )
       
  1165     {
       
  1166     // Always recreate the whole MDRI box, it's simpler
       
  1167     if ( iTransactionTracking )
       
  1168         {
       
  1169         RewriteMutableInfoL( *iTransactionTracking, aRoList );
       
  1170         }
       
  1171     else
       
  1172         {
       
  1173         RewriteMutableInfoL( KNullDesC8, aRoList );
       
  1174         }
       
  1175     }
       
  1176 
       
  1177 // -----------------------------------------------------------------------------
       
  1178 // COma2Dcf::RewriteMutableInfoL
       
  1179 // -----------------------------------------------------------------------------
       
  1180 //
       
  1181 void COma2Dcf::RewriteMutableInfoL(
       
  1182     const TDesC8& aTransactionId,
       
  1183     RPointerArray<HBufC8>& aRoList )
       
  1184     {
       
  1185     TInt offset( 0 );
       
  1186     TBuf8<4> buffer;
       
  1187     TInt sizeOfRoBoxes( 0 );
       
  1188     TInt roBoxSize( 0 );
       
  1189     TInt tidBoxSize( 0 );
       
  1190     TInt mutableBoxSize( 0 );
       
  1191 
       
  1192     // Remove the existing box
       
  1193     if ( iMutablePart )
       
  1194         {
       
  1195         User::LeaveIfError( iFile.SetSize( iMutablePart->iOffset ) );
       
  1196         }
       
  1197 
       
  1198     // Append the box to the end of the file
       
  1199     User::LeaveIfError( iFile.Size( offset ) );
       
  1200 
       
  1201     for ( TInt i( 0 ); i < aRoList.Count(); i++ )
       
  1202         {
       
  1203         sizeOfRoBoxes += aRoList[ i ]->Size() +
       
  1204             KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1205         }
       
  1206     tidBoxSize = 16 +
       
  1207         KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1208     mutableBoxSize =
       
  1209         KLengthBoxSize + KLengthBoxType + tidBoxSize + sizeOfRoBoxes;
       
  1210 
       
  1211     // MDRI box
       
  1212     WriteIntToBlock( mutableBoxSize, buffer, 0 );
       
  1213     User::LeaveIfError( iFile.Write( offset, buffer ) );
       
  1214     User::LeaveIfError( iFile.Write( KMdri ) );
       
  1215 
       
  1216     // ODTT box ( always written )
       
  1217     WriteIntToBlock( tidBoxSize, buffer, 0 );
       
  1218     User::LeaveIfError( iFile.Write( buffer ) );
       
  1219     User::LeaveIfError( iFile.Write( KOdtt ) );
       
  1220     buffer.FillZ();
       
  1221     User::LeaveIfError( iFile.Write( buffer ) );
       
  1222     if ( aTransactionId.Size() > 0 )
       
  1223         {
       
  1224         User::LeaveIfError( iFile.Write( aTransactionId ) );
       
  1225         }
       
  1226     else
       
  1227         {
       
  1228         User::LeaveIfError( iFile.Write( KEmptyTransactionId ) );
       
  1229         }
       
  1230 
       
  1231     // ODRB box
       
  1232     if ( sizeOfRoBoxes > 0 )
       
  1233         {
       
  1234         for ( TInt i( 0 ); i < aRoList.Count(); i++ )
       
  1235             {
       
  1236             roBoxSize = aRoList[ i ]->Size() +
       
  1237                 KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1238             WriteIntToBlock( roBoxSize, buffer, 0 );
       
  1239             User::LeaveIfError( iFile.Write( buffer ) );
       
  1240             User::LeaveIfError( iFile.Write( KOdrb ) );
       
  1241             buffer.FillZ();
       
  1242             User::LeaveIfError( iFile.Write( buffer ) );
       
  1243             User::LeaveIfError( iFile.Write( *aRoList[ i ] ) );
       
  1244             }
       
  1245         }
       
  1246 
       
  1247     // Reread the MDRI box
       
  1248     User::LeaveIfError( iFile.Size( iLength ) );
       
  1249     ReadMutableInfoL( offset, mutableBoxSize );
       
  1250     }
       
  1251 
       
  1252 
       
  1253 // -----------------------------------------------------------------------------
       
  1254 // COma2Dcf::ReadPartInfoL
       
  1255 // -----------------------------------------------------------------------------
       
  1256 //
       
  1257 void COma2Dcf::ReadPartInfoL(
       
  1258     COma2DcfPartInfo* aPart,
       
  1259     TInt aOffset )
       
  1260     {
       
  1261     TBuf8<4> buffer;
       
  1262     TUint32 size( 0 );
       
  1263     TPtr8 ptr( NULL, 0 );
       
  1264 
       
  1265     // ODRM box header
       
  1266     buffer.SetLength( 0 );
       
  1267 
       
  1268     // input validation
       
  1269     if ( aOffset < 0 )
       
  1270         {
       
  1271         // RFile::Read will panic if offset is negative
       
  1272         User::Leave( KErrArgument );
       
  1273         }
       
  1274 
       
  1275     iFile.Read( aOffset, buffer, 4 );
       
  1276     size = ReadUint32FromBlock( buffer, 0 );
       
  1277     aOffset += KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1278     if ( size == 1 )
       
  1279         {
       
  1280         aOffset += KLengthBoxSize64;
       
  1281         }
       
  1282 
       
  1283     // Discrete headers box header
       
  1284     buffer.SetLength( 0 );
       
  1285     iFile.Read( aOffset, buffer, 4 );
       
  1286     if ( buffer.Length() < 4 )
       
  1287         {
       
  1288         User::Leave( KErrArgument );
       
  1289         }
       
  1290     size = ReadUint32FromBlock( buffer, 0 );
       
  1291     aOffset += KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1292     if ( size == 1 )
       
  1293         {
       
  1294         aOffset += KLengthBoxSize64;
       
  1295         }
       
  1296 
       
  1297     // Content type
       
  1298     buffer.SetLength( 0 );
       
  1299     iFile.Read( aOffset, buffer, 1 );
       
  1300     if ( buffer.Length() < 1 )
       
  1301         {
       
  1302         User::Leave( KErrArgument );
       
  1303         }
       
  1304     aPart->iMimeType = HBufC8::NewL( buffer[ 0 ] );
       
  1305     ptr.Set( aPart->iMimeType->Des() );
       
  1306     iFile.Read( ptr, buffer[ 0 ] );
       
  1307     aOffset += 1 + buffer[ 0 ];
       
  1308 
       
  1309     // Common headers box header
       
  1310     buffer.SetLength( 0 );
       
  1311     iFile.Read( aOffset, buffer, 4 );
       
  1312     if ( buffer.Length() < 4 )
       
  1313         {
       
  1314         User::Leave( KErrArgument );
       
  1315         }
       
  1316     size = ReadUint32FromBlock( buffer, 0 );
       
  1317     aOffset += KLengthBoxSize + KLengthBoxType + KLengthVersion + KLengthFlags;
       
  1318     if ( size == 1 )
       
  1319         {
       
  1320         aOffset += KLengthBoxSize64;
       
  1321         }
       
  1322 
       
  1323     // Content ID
       
  1324     aOffset += KLengthEncMethod + KLengthPadType + KLengthPlainTextSize;
       
  1325     buffer.SetLength( 0 );
       
  1326     iFile.Read( aOffset, buffer, 2 );
       
  1327     if ( buffer.Length() < 2 )
       
  1328         {
       
  1329         User::Leave( KErrArgument );
       
  1330         }
       
  1331     aPart->iContentId = HBufC8::NewL( ReadUint16FromBlock( buffer, 0 ) );
       
  1332     ptr.Set( aPart->iContentId->Des() );
       
  1333     aOffset += KLengthContentIdSize + KLengthRiUrlSize + KLengthTextHeadersSize;
       
  1334     iFile.Read( aOffset, ptr, ReadUint16FromBlock( buffer, 0 ) );
       
  1335     }
       
  1336 
       
  1337 // -----------------------------------------------------------------------------
       
  1338 // COma2Dcf::ReadUserDataL
       
  1339 // -----------------------------------------------------------------------------
       
  1340 //
       
  1341 void COma2Dcf::ReadUserDataL(
       
  1342     TInt aOffset,
       
  1343     TInt& aSize )
       
  1344     {
       
  1345     TInt size( 0 );
       
  1346     TUint32 type( 0 );
       
  1347     TPtr8 ptr( 0, 0 );
       
  1348 
       
  1349     ReadBoxSizeAndTypeL( aOffset, aSize, type, size );
       
  1350     VerifyTypeL( type, KUserData );
       
  1351     aOffset += size;
       
  1352 
       
  1353     delete iUserData;
       
  1354     iUserData = NULL;
       
  1355     iUserData = HBufC8::NewL( aSize );
       
  1356     User::LeaveIfNull( iUserData );
       
  1357 
       
  1358     ptr.Set( iUserData->Des() );
       
  1359     User::LeaveIfError( iFile.Read( aOffset, ptr, aSize ) );
       
  1360     aOffset += aSize;
       
  1361 
       
  1362     ParseUserDataSubBoxesL( ptr );
       
  1363     }
       
  1364 
       
  1365 // -----------------------------------------------------------------------------
       
  1366 // COma2Dcf::ParseUserDataSubBoxesL
       
  1367 // -----------------------------------------------------------------------------
       
  1368 //
       
  1369 void COma2Dcf::ParseUserDataSubBoxesL(
       
  1370     const TDesC8& aMemoryBlock )
       
  1371     {
       
  1372 
       
  1373     // there MAY be zero to several boxes
       
  1374     // depending on language definition.
       
  1375     // here only the first boxes are read out.
       
  1376 
       
  1377     iUserDataLanguageDefined = ETrue;
       
  1378 
       
  1379     // if not found from textual custom headers, try to read out from udta
       
  1380     if ( !iTitle )
       
  1381         {
       
  1382         ReadOneUserDataBoxL( aMemoryBlock, KTitle, iTitle );
       
  1383         }
       
  1384 
       
  1385     // if not found from textual custom headers, try to read out from udta
       
  1386     if ( !iDescription )
       
  1387         {
       
  1388         ReadOneUserDataBoxL( aMemoryBlock, KDescription, iDescription );
       
  1389         }
       
  1390 
       
  1391     // if not found from textual custom headers, try to read out from udta
       
  1392     if ( !iCopyRight )
       
  1393         {
       
  1394         ReadOneUserDataBoxL( aMemoryBlock, KCopyright, iCopyRight );
       
  1395         }
       
  1396 
       
  1397     // if not found from textual custom headers, try to read out from udta
       
  1398     if ( !iAuthor )
       
  1399         {
       
  1400         ReadOneUserDataBoxL( aMemoryBlock, KAuthor, iAuthor );
       
  1401         }
       
  1402 
       
  1403     ReadOneUserDataBoxL( aMemoryBlock, KPerformer, iPerformer );
       
  1404 
       
  1405     ReadOneUserDataBoxL( aMemoryBlock, KGenre, iGenre );
       
  1406 
       
  1407     ReadOneUserDataBoxL( aMemoryBlock, KRating, iRatingInfo );
       
  1408 
       
  1409     ReadOneUserDataBoxL( aMemoryBlock, KClassification, iClassificationInfo );
       
  1410 
       
  1411     ReadOneUserDataBoxL( aMemoryBlock, KKeyword, iKeyword );
       
  1412 
       
  1413     ReadOneUserDataBoxL( aMemoryBlock, KLocationInformation, iLocInfoName );
       
  1414 
       
  1415     ReadOneUserDataBoxL( aMemoryBlock, KAlbum, iAlbumTitle );
       
  1416 
       
  1417 
       
  1418     // These boxes do not contain language information ->
       
  1419 
       
  1420     iUserDataLanguageDefined = EFalse;
       
  1421 
       
  1422     // if not found from textual custom headers, try to read out from udta
       
  1423     if ( !iIconUri )
       
  1424         {
       
  1425         ReadOneUserDataBoxL( aMemoryBlock, KIconUri, iIconUri );
       
  1426         }
       
  1427 
       
  1428     ReadOneUserDataBoxL( aMemoryBlock, KInfoURL, iInfoUri );
       
  1429 
       
  1430     ReadOneUserDataBoxL( aMemoryBlock, KCoverUri, iCoverUri );
       
  1431 
       
  1432     ReadOneUserDataBoxL( aMemoryBlock, KLyricsURL, iLyricsURL );
       
  1433 
       
  1434 
       
  1435     TInt yearOffset( iUserData->Find( KRecordingYear ) );
       
  1436     if ( yearOffset != KErrNotFound )
       
  1437         {
       
  1438         yearOffset += sizeof( tBoxHeaderStr ) - KLengthBoxSize;
       
  1439         iRecordingYear = ReadUint16FromBlock( iUserData->Des(), yearOffset );
       
  1440         }
       
  1441     }
       
  1442 
       
  1443 // -----------------------------------------------------------------------------
       
  1444 // COma2Dcf::ReadOneUserDataBoxL
       
  1445 // -----------------------------------------------------------------------------
       
  1446 //
       
  1447 void COma2Dcf::ReadOneUserDataBoxL(
       
  1448     const TDesC8& aBlock,
       
  1449     const TDesC8& aName,
       
  1450     HBufC8*& aBuffer )
       
  1451     {
       
  1452 
       
  1453     TInt offset( aBlock.Find( aName ) );
       
  1454     TUint32 length( 0 );
       
  1455     HBufC8* subBlock( NULL );
       
  1456     TInt subOffset( 0 );
       
  1457     TBuf8<12> buffer;
       
  1458 
       
  1459     delete aBuffer;
       
  1460     aBuffer = NULL;
       
  1461 
       
  1462     if ( offset == KErrNotFound )
       
  1463         {
       
  1464         return;
       
  1465         }
       
  1466     else
       
  1467         {
       
  1468 
       
  1469         TUint8* pData( const_cast< TUint8* >( aBlock.Ptr() ) );
       
  1470         offset -= KLengthBoxSize;
       
  1471         pData += offset;
       
  1472 
       
  1473         buffer.SetLength( 0 );
       
  1474         buffer.Copy( pData, 12 );
       
  1475 
       
  1476         tBoxHeaderStr* SubBox = ( tBoxHeaderStr* ) buffer.Ptr();
       
  1477         length = SWAP32( SubBox->size );
       
  1478 
       
  1479         subBlock = aBlock.Mid( offset, length ).AllocLC();
       
  1480 
       
  1481         subOffset += sizeof( tBoxHeaderStr );
       
  1482 
       
  1483         if ( aName == KClassification )
       
  1484             {
       
  1485             TUint32 classificationEntity(
       
  1486                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1487             subOffset += sizeof( classificationEntity );
       
  1488 
       
  1489             TUint16 classificationTable(
       
  1490                 ReadUint16FromBlock( subBlock->Des(), subOffset ) );
       
  1491             subOffset += sizeof( classificationTable );
       
  1492             }
       
  1493 
       
  1494         if ( aName == KRating )
       
  1495             {
       
  1496             TUint32 ratingEntity(
       
  1497                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1498             subOffset += sizeof( ratingEntity );
       
  1499 
       
  1500             TUint32 ratingCriteria(
       
  1501                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1502             subOffset += sizeof( ratingCriteria );
       
  1503             }
       
  1504 
       
  1505         if ( iUserDataLanguageDefined )
       
  1506             {
       
  1507             TUint16 PadAndLanguage(
       
  1508                 ReadUint16FromBlock( subBlock->Des(), subOffset ) );
       
  1509             subOffset += sizeof( PadAndLanguage );
       
  1510             }
       
  1511 
       
  1512 
       
  1513         if ( aName == KKeyword )
       
  1514             {
       
  1515             // we return all keywords here
       
  1516             aBuffer = HBufC8::NewL( length );
       
  1517             TUint8 keywordCnt( subBlock->Des()[ subOffset ] );
       
  1518             TUint8 keywordSize( 0 );
       
  1519 
       
  1520             subOffset += sizeof( keywordCnt );
       
  1521 
       
  1522             for ( TInt count( 0 ); count < keywordCnt; count++ )
       
  1523                 {
       
  1524                 keywordSize = subBlock->Des()[ subOffset ];
       
  1525                 subOffset += sizeof( keywordSize );
       
  1526                 aBuffer->Des().Append(
       
  1527                     subBlock->Des().Mid( subOffset, keywordSize ) );
       
  1528                 subOffset += keywordSize;
       
  1529                 keywordSize = 0;
       
  1530                 }
       
  1531             }
       
  1532 
       
  1533         else if ( aName == KAlbum )
       
  1534             {
       
  1535             TInt tracknbrFound(
       
  1536                 subBlock->Des().Mid( subOffset ).Find( KTerminator ) );
       
  1537 
       
  1538             if ( ( tracknbrFound == KErrNotFound ) ||
       
  1539                 ( tracknbrFound ==
       
  1540                   ( subBlock->Des().Length()-subOffset ) - 1 ) )
       
  1541                 {
       
  1542                 aBuffer = subBlock->Des().Mid( subOffset ).AllocL();
       
  1543                 iAlbumTrack = NULL;
       
  1544                 }
       
  1545             else
       
  1546                 {
       
  1547                 aBuffer =
       
  1548                     subBlock->Des().Mid( subOffset, tracknbrFound ).AllocL();
       
  1549                 subOffset += tracknbrFound + KLengthTerminator;
       
  1550                 iAlbumTrack = subBlock->Des()[ subOffset ];
       
  1551                 }
       
  1552             }
       
  1553 
       
  1554         else if ( aName == KLocationInformation )
       
  1555             {
       
  1556             TInt found( subBlock->Des().Mid( subOffset ).Find( KTerminator ) );
       
  1557             aBuffer = subBlock->Des().Mid( subOffset, found ).AllocL();
       
  1558             subOffset += found + KLengthTerminator;
       
  1559 
       
  1560             TUint8 role( subBlock->Des()[ subOffset ] );
       
  1561             subOffset += sizeof( role );
       
  1562             TUint32 longitude(
       
  1563                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1564             subOffset += sizeof( longitude );
       
  1565             TUint32 latitude(
       
  1566                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1567             subOffset += sizeof( latitude );
       
  1568             TUint32 altitude(
       
  1569                 ReadUint32FromBlock( subBlock->Des(), subOffset ) );
       
  1570             subOffset += sizeof( altitude );
       
  1571 
       
  1572             found = subBlock->Des().Mid( subOffset ).Find( KTerminator );
       
  1573 
       
  1574             // iLocInfoAstronomicalBody =
       
  1575             //    subBlock->Des().Mid( subOffset, found ).AllocL();
       
  1576             subOffset += found + KLengthTerminator;
       
  1577 
       
  1578             found = subBlock->Des().Mid( subOffset ).Find( KTerminator );
       
  1579             // iLocInfoAdditionalNotes =
       
  1580             //    subBlock->Des().Mid( subOffset, found ).AllocL();
       
  1581             }
       
  1582         else
       
  1583             {
       
  1584             aBuffer = subBlock->Des().Mid( subOffset ).AllocL();
       
  1585             }
       
  1586         CleanupStack::PopAndDestroy( subBlock );
       
  1587         }
       
  1588     }
       
  1589 
       
  1590 
       
  1591 //  End of File