|
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 |