|
1 /* |
|
2 * Copyright (c) 2006 - 2007 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 asf file handler class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <e32base.h> |
|
22 #include <f32file.h> |
|
23 #include <utf.h> |
|
24 #include <caf/caf.h> |
|
25 #include "asf.h" |
|
26 |
|
27 #define _LOGGING_FILE L"asf.txt" |
|
28 |
|
29 #include "logfn.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 _LIT8 (KASFHeaderObject, "75B22630668E11CFA6D900AA0062CE6C"); |
|
36 _LIT8 (KASFFilePropertiesObject, "8CABDCA1A94711CF8EE400C00C205365"); |
|
37 _LIT8 (KASFContentDescriptionObject, "75B22633668E11CFA6D900AA0062CE6C"); |
|
38 _LIT8 (KASFExtendedContentDescriptionObject, "D2D0A440E30711D297F000A0C95EA850"); |
|
39 _LIT8 (KASFContentEncryptionObject, "2211B3FBBD2311D2B4B700A0C955FC6E"); |
|
40 _LIT8 (KASFExtendedContentEncryptionObject, "298AE61426224C17B935DAE07EE9289C"); |
|
41 _LIT8 (KASFDigitalSignatureObject, "2211B3FCBD2311D2B4B700A0C955FC6E"); |
|
42 |
|
43 _LIT(KWMAlbumTitle, "WM/AlbumTitle\0"); |
|
44 _LIT(KWMPicture, "WM/Picture\0"); |
|
45 _LIT(KWMText, "WM/Text\0"); |
|
46 _LIT(KWMComposer, "WM/Composer\0"); |
|
47 _LIT(KWMGenre, "WM/Genre\0"); |
|
48 _LIT(KWMYear, "WM/Year\0"); |
|
49 _LIT(KWMYear1, "WM/OriginalReleaseYear\0"); |
|
50 _LIT(KWMOriginalArtist, "WM/OriginalArtist\0"); |
|
51 _LIT(KWMTrackNumber, "WM/TrackNumber\0"); |
|
52 _LIT(KWMUniqueFileIdentifier, "WM/UniqueFileIdentifier\0"); |
|
53 _LIT(KWMAudioFileURL, "WM/AudioFileURL\0"); |
|
54 _LIT(KWMSharedUserRating, "WM/SharedUserRating\0"); |
|
55 _LIT(KWMDate, "WM/OriginalReleaseTime\0"); |
|
56 |
|
57 _LIT8(KWrmHeader, "W\0R\0M\0H\0E\0A\0D\0E\0R\0"); |
|
58 |
|
59 _LIT(KAsfMimeType, "application/vnd.drm.asf"); |
|
60 _LIT(KWmaMimeType, "audio/x-ms-wma"); |
|
61 _LIT(KWmvMimeType, "video/x-ms-wmv"); |
|
62 |
|
63 _LIT(KAsfExtension, ".asf"); |
|
64 _LIT(KWmaExtension, ".wma"); |
|
65 _LIT(KWmvExtension, ".wmv"); |
|
66 |
|
67 #define SET_PTR16(ptr, descriptor, offset, length) \ |
|
68 ptr.Set( reinterpret_cast<const TUint16*>( (descriptor).Ptr() + (offset) ), length ); |
|
69 |
|
70 /* |
|
71 * 16 B Obj GUID |
|
72 * 8 B Obj Size |
|
73 * xx B Obj Data |
|
74 */ |
|
75 const TInt KObjectID( 16 ); |
|
76 const TInt KObjectSize( 8 ); |
|
77 |
|
78 // ============================= LOCAL FUNCTIONS =============================== |
|
79 |
|
80 LOCAL_C TUint32 ReadUint64FromBlockL( const TDesC8& aBlock, TInt aOffset ); |
|
81 LOCAL_C TUint32 ReadUint32FromBlockL( const TDesC8& aBlock, TInt aOffset ); |
|
82 LOCAL_C TUint16 ReadUint16FromBlockL( const TDesC8& aBlock, TInt aOffset ); |
|
83 |
|
84 LOCAL_C HBufC16* HBuf16FromBlockL( |
|
85 const TDesC8& aBlock, |
|
86 TInt aOffset, |
|
87 TInt aLength ); |
|
88 |
|
89 LOCAL_C TUint32 ReadUint64FromBlockL( const TDesC8& aBlock, TInt aOffset ) |
|
90 { |
|
91 if ( aBlock.Length() <= ( aOffset + 3 ) ) |
|
92 { |
|
93 User::Leave( KErrArgument ); |
|
94 } |
|
95 return ( aBlock[aOffset + 3] << 24 ) + |
|
96 ( aBlock[aOffset + 2] << 16 ) + |
|
97 ( aBlock[aOffset + 1] << 8 ) + |
|
98 aBlock[aOffset]; |
|
99 } |
|
100 |
|
101 LOCAL_C TUint32 ReadUint32FromBlockL( const TDesC8& aBlock, TInt aOffset ) |
|
102 { |
|
103 if ( aBlock.Length() <= ( aOffset + 3 ) ) |
|
104 { |
|
105 User::Leave( KErrArgument ); |
|
106 } |
|
107 return ( aBlock[aOffset + 3] << 24 ) + |
|
108 ( aBlock[aOffset + 2] << 16 ) + |
|
109 ( aBlock[aOffset + 1] << 8 ) + |
|
110 aBlock[aOffset]; |
|
111 } |
|
112 |
|
113 LOCAL_C TUint16 ReadUint16FromBlockL( const TDesC8& aBlock, TInt aOffset ) |
|
114 { |
|
115 if ( aBlock.Length() <= ( aOffset + 1 ) ) |
|
116 { |
|
117 User::Leave( KErrArgument ); |
|
118 } |
|
119 return ( aBlock[aOffset + 1] << 8 ) + |
|
120 aBlock[aOffset]; |
|
121 } |
|
122 |
|
123 LOCAL_C HBufC16* HBuf16FromBlockL( |
|
124 const TDesC8& aBlock, |
|
125 TInt aOffset, |
|
126 TInt aLength ) |
|
127 { |
|
128 if ( aBlock.Length() < ( aOffset + aLength ) ) |
|
129 { |
|
130 User::Leave( KErrArgument ); |
|
131 } |
|
132 HBufC16* buffer( HBufC16::NewL( aLength / 2 + 1 ) ); |
|
133 TPtr ptr( buffer->Des() ); |
|
134 |
|
135 for ( TInt i( 0 ) ; i < aLength; i+=2 ) |
|
136 { |
|
137 ptr.Append( aBlock[aOffset + i] ); |
|
138 } |
|
139 |
|
140 return buffer; |
|
141 } |
|
142 |
|
143 // ============================ MEMBER FUNCTIONS =============================== |
|
144 |
|
145 // ----------------------------------------------------------------------------- |
|
146 // CAsf::CAsf |
|
147 // C++ default constructor can NOT contain any code, that |
|
148 // might leave. |
|
149 // ----------------------------------------------------------------------------- |
|
150 // |
|
151 CAsf::CAsf(): |
|
152 iTitle( NULL ), |
|
153 iAuthor( NULL ), |
|
154 iCopyright( NULL ), |
|
155 iDescription( NULL ), |
|
156 iRating( NULL ), |
|
157 iAlbumTitle( NULL ), |
|
158 iPicture( NULL ), |
|
159 iText( NULL ), |
|
160 iComposer( NULL ), |
|
161 iGenre( NULL ), |
|
162 iOriginalArtist( NULL ), |
|
163 iTrackNumber( NULL ), |
|
164 iUniqueFileID( NULL ), |
|
165 iAudioFileUrl( NULL ), |
|
166 iSharedUserRating( NULL ), |
|
167 iDate( NULL ), |
|
168 iYear( NULL ), |
|
169 iIsDrmProtected( EFalse ), |
|
170 iIsValidated( EFalse ), |
|
171 iHeaderData( NULL ), |
|
172 iSecretData( NULL ), |
|
173 iProtectionType( NULL ), |
|
174 iKeyId( NULL ), |
|
175 iLicenseUrl( NULL ), |
|
176 iExtendedContentEncryptionObject( NULL ), |
|
177 iContentDescriptionObjectExists( EFalse ), |
|
178 iFilePropertiesObjectExists( EFalse ), |
|
179 iExtendedContentDescriptionObjectExists( EFalse ), |
|
180 iExtendedContentEncryptionObjectExists( EFalse ), |
|
181 iContentEncryptionObjectExists( EFalse ), |
|
182 iMimeType( KAsfMimeType ) |
|
183 { |
|
184 LOGFN( "CAsf::CAsf" ); |
|
185 } |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CAsf::ConstructL |
|
189 // Symbian 2nd phase constructor can leave. |
|
190 // ----------------------------------------------------------------------------- |
|
191 // |
|
192 void CAsf::ConstructL( const TDesC& aFileName ) |
|
193 { |
|
194 TInt r = KErrNone; |
|
195 |
|
196 LOGFN( "CAsf::ConstructL" ); |
|
197 LOG( aFileName ); |
|
198 User::LeaveIfError( iFs.Connect() ); |
|
199 r = iFile.Open( iFs, aFileName, EFileStream | EFileRead | EFileShareReadersOrWriters ); |
|
200 if( r == KErrInUse ) |
|
201 { |
|
202 r = iFile.Open( iFs, aFileName, EFileStream | EFileRead | EFileShareAny); |
|
203 if ( r == KErrInUse ) |
|
204 { |
|
205 r = iFile.Open( iFs, aFileName, EFileStream | EFileRead | |
|
206 EFileShareReadersOnly); |
|
207 } |
|
208 } |
|
209 User::LeaveIfError( r ); |
|
210 InitializeL(); |
|
211 } |
|
212 |
|
213 // ----------------------------------------------------------------------------- |
|
214 // CAsf::ConstructL |
|
215 // Symbian 2nd phase constructor can leave. |
|
216 // ----------------------------------------------------------------------------- |
|
217 // |
|
218 void CAsf::ConstructL( const RFile& aFile ) |
|
219 { |
|
220 LOGFN( "CAsf::ConstructL (2)" ); |
|
221 iFile.Duplicate( aFile ); |
|
222 iFile.Size( iLength ); |
|
223 InitializeL(); |
|
224 } |
|
225 |
|
226 // ----------------------------------------------------------------------------- |
|
227 // CAsf::InitializeL |
|
228 // |
|
229 // ----------------------------------------------------------------------------- |
|
230 // |
|
231 void CAsf::InitializeL() |
|
232 { |
|
233 TFileName name; |
|
234 |
|
235 LOGFN( "CAsf::InitializeL" ); |
|
236 iFile.FullName( name ); |
|
237 if ( name.Right( 4 ).CompareF( KWmaExtension ) == 0 ) |
|
238 { |
|
239 iMimeType.Set( KWmaMimeType ); |
|
240 } |
|
241 else if ( name.Right( 4 ).CompareF( KWmvExtension ) == 0 || |
|
242 name.Right( 4 ).CompareF( KAsfExtension ) == 0 ) |
|
243 { |
|
244 iMimeType.Set( KWmvMimeType ); |
|
245 } |
|
246 |
|
247 ValidateL(); |
|
248 } |
|
249 |
|
250 // ----------------------------------------------------------------------------- |
|
251 // CAsf::NewL |
|
252 // Two-phased constructor. |
|
253 // ----------------------------------------------------------------------------- |
|
254 // |
|
255 EXPORT_C CAsf* CAsf::NewL( const RFile& aFile ) |
|
256 { |
|
257 LOGFN( "CAsf::NewL" ); |
|
258 CAsf* self = new (ELeave) CAsf; |
|
259 CleanupStack::PushL( self ); |
|
260 self->ConstructL( aFile ); |
|
261 CleanupStack::Pop( self ); |
|
262 return self; |
|
263 } |
|
264 |
|
265 // ----------------------------------------------------------------------------- |
|
266 // CAsf::NewL |
|
267 // Two-phased constructor. |
|
268 // ----------------------------------------------------------------------------- |
|
269 // |
|
270 EXPORT_C CAsf* CAsf::NewL( const TDesC& aFileName ) |
|
271 { |
|
272 LOGFN( "CAsf::NewL (2)" ); |
|
273 CAsf* self = new (ELeave) CAsf; |
|
274 CleanupStack::PushL( self ); |
|
275 self->ConstructL( aFileName ); |
|
276 CleanupStack::Pop( self ); |
|
277 return self; |
|
278 } |
|
279 |
|
280 // ----------------------------------------------------------------------------- |
|
281 // CAsf::~CAsf |
|
282 // Destructor |
|
283 // ----------------------------------------------------------------------------- |
|
284 // |
|
285 |
|
286 EXPORT_C CAsf::~CAsf() |
|
287 { |
|
288 LOGFN( "CAsf::~CAsf" ); |
|
289 if ( iFile.SubSessionHandle() != KNullHandle ) |
|
290 { |
|
291 iFile.Close(); |
|
292 } |
|
293 if ( iFs.Handle() != KNullHandle ) |
|
294 { |
|
295 iFs.Close(); |
|
296 } |
|
297 |
|
298 delete iHeaderData; |
|
299 delete iSecretData; |
|
300 delete iProtectionType; |
|
301 delete iKeyId; |
|
302 delete iLicenseUrl; |
|
303 delete iExtendedContentEncryptionObject; |
|
304 delete iDigitalSignatureObject; |
|
305 delete iSignedData; |
|
306 |
|
307 // Content description Object |
|
308 delete iTitle; |
|
309 delete iAuthor; |
|
310 delete iCopyright; |
|
311 delete iDescription; |
|
312 delete iRating; |
|
313 |
|
314 // Extended Content description Object |
|
315 delete iAlbumTitle; |
|
316 delete iPicture; |
|
317 delete iText; |
|
318 delete iComposer; |
|
319 delete iGenre; |
|
320 delete iYear; |
|
321 delete iOriginalArtist; |
|
322 delete iTrackNumber; |
|
323 delete iUniqueFileID; |
|
324 delete iAudioFileUrl; |
|
325 delete iSharedUserRating; |
|
326 delete iDate; |
|
327 } |
|
328 |
|
329 // ----------------------------------------------------------------------------- |
|
330 // CAsf:: |
|
331 // |
|
332 // ----------------------------------------------------------------------------- |
|
333 // |
|
334 EXPORT_C TBool CAsf::IsProtected( const TDesC8& aAsfHeader ) |
|
335 { |
|
336 LOGFN( "CAsf::IsProtected" ); |
|
337 if ( aAsfHeader.Find( KWrmHeader ) == KErrNotFound ) |
|
338 { |
|
339 return EFalse; |
|
340 } |
|
341 else |
|
342 { |
|
343 return ETrue; |
|
344 } |
|
345 } |
|
346 |
|
347 |
|
348 // ----------------------------------------------------------------------------- |
|
349 // CAsf::ValidateL |
|
350 // |
|
351 // ----------------------------------------------------------------------------- |
|
352 // |
|
353 void CAsf::ValidateL() |
|
354 { |
|
355 // ASF_Header_Object GUID 128 bits. |
|
356 TBuf8<32> header; |
|
357 |
|
358 LOGFN( "CAsf::ValidateL" ); |
|
359 iFile.Read( 0, header, KObjectID ); |
|
360 if ( header.Length() < KObjectID ) |
|
361 { |
|
362 User::Leave( KErrOverflow ); |
|
363 } |
|
364 FormatGUID( header ); |
|
365 if ( header != KASFHeaderObject ) |
|
366 { |
|
367 User::Leave( KErrArgument ); |
|
368 } |
|
369 |
|
370 // read header object size. |
|
371 iFile.Read( header, KObjectSize ); |
|
372 iHeaderSize = ReadUint64FromBlockL( header, 0 ); |
|
373 if ( iHeaderSize <= 30 || iHeaderSize > KMaxTInt / 2 - 1 ) |
|
374 { |
|
375 User::Leave( KErrOverflow ); |
|
376 } |
|
377 |
|
378 // read header object |
|
379 // 2~31 = 2 GB, size of header would not be greater than this, |
|
380 // also, HBufC does not have a NewL with TInt64 as arguement. |
|
381 iHeaderData = HBufC8::NewL( iHeaderSize ); |
|
382 TPtr8 headerPtr = iHeaderData->Des(); |
|
383 iFile.Read( headerPtr, iHeaderSize - ( KObjectID + KObjectSize ) ); |
|
384 |
|
385 iNbrOfObjects = ReadUint32FromBlockL( *iHeaderData, 0 ); |
|
386 if ( iNbrOfObjects <= 0 ) |
|
387 { |
|
388 User::Leave( KErrArgument ); |
|
389 } |
|
390 |
|
391 TInt objOffset( 6 ); |
|
392 if ( iHeaderData->Length() < ( objOffset + KObjectID ) ) |
|
393 { |
|
394 User::Leave( KErrArgument ); |
|
395 } |
|
396 //Read next object GUID |
|
397 TBuf8<32> objGUID = iHeaderData->Mid( objOffset, KObjectID ); |
|
398 FormatGUID( objGUID ); |
|
399 TBool loop( ETrue ); |
|
400 |
|
401 //Loop until all needed headers are handled or top level header is finished |
|
402 while ( loop ) |
|
403 { |
|
404 //Read current object size |
|
405 TUint32 objSize( ReadUint64FromBlockL( *iHeaderData, objOffset + KObjectID ) ); |
|
406 if ( objSize < 24 ) |
|
407 { |
|
408 User::Leave( KErrArgument ); |
|
409 } |
|
410 |
|
411 if ( !iContentDescriptionObjectExists && objGUID == |
|
412 KASFContentDescriptionObject ) |
|
413 { |
|
414 iContentDescriptionObjectExists = ETrue; |
|
415 iContentDescriptionOffset = objOffset; |
|
416 ParseContentDescriptionObjectL(); |
|
417 } |
|
418 else if ( !iFilePropertiesObjectExists && objGUID == |
|
419 KASFFilePropertiesObject ) |
|
420 { |
|
421 iFilePropertiesObjectExists = ETrue; // must exist |
|
422 iFilePropertiesOffset = objOffset; |
|
423 iFilePropertiesEndOffset = iFilePropertiesOffset + objSize; |
|
424 } |
|
425 else if ( !iExtendedContentDescriptionObjectExists && objGUID == |
|
426 KASFExtendedContentDescriptionObject ) |
|
427 { |
|
428 iExtendedContentDescriptionObjectExists = ETrue; |
|
429 iExtendedContentDescriptionOffset = objOffset; |
|
430 ParseExtendedContentDescriptionObjectL(); |
|
431 } |
|
432 else if ( !iExtendedContentEncryptionObjectExists && objGUID == |
|
433 KASFExtendedContentEncryptionObject ) |
|
434 { |
|
435 iExtendedContentEncryptionObjectExists = ETrue; |
|
436 iExtendedContentEncryptionOffset = objOffset; |
|
437 iIsDrmProtected = ETrue; |
|
438 TInt eCEODataOffset( objOffset + KObjectID + KObjectSize + 4 ); |
|
439 TInt eCEODataLength( objSize - ( KObjectID + KObjectSize + 4 ) ); |
|
440 if ( iHeaderData->Length() < eCEODataOffset + eCEODataLength || |
|
441 eCEODataLength < 0) |
|
442 { |
|
443 User::Leave( KErrArgument ); |
|
444 } |
|
445 iExtendedContentEncryptionObject = iHeaderData->Mid( eCEODataOffset, |
|
446 eCEODataLength ).AllocL(); |
|
447 } |
|
448 else if ( !iContentEncryptionObjectExists && objGUID == |
|
449 KASFContentEncryptionObject ) |
|
450 { |
|
451 iContentEncryptionObjectExists = ETrue; |
|
452 iContentEncryptionOffset = objOffset; |
|
453 iIsDrmProtected = ETrue; |
|
454 ParseContentEncryptionObjectL(); |
|
455 } |
|
456 else if ( !iDigitalSignatureObjectExists && objGUID == |
|
457 KASFDigitalSignatureObject ) |
|
458 { |
|
459 iDigitalSignatureObjectExists = ETrue; |
|
460 iDigitalSignatureOffset = objOffset; |
|
461 |
|
462 TInt dSODataOffset( objOffset + KObjectID + KObjectSize + 8 ); |
|
463 TInt dSODataLength( objSize - ( KObjectID + KObjectSize + 8 ) ); |
|
464 if ( iHeaderData->Length() < dSODataOffset + dSODataLength || |
|
465 dSODataLength < 0 ) |
|
466 { |
|
467 User::Leave( KErrArgument ); |
|
468 } |
|
469 iDigitalSignatureObject = iHeaderData->Mid( dSODataOffset, |
|
470 dSODataLength ).AllocL(); |
|
471 |
|
472 if ( iHeaderData->Length() < iFilePropertiesEndOffset + ( iDigitalSignatureOffset - iFilePropertiesEndOffset ) || |
|
473 iDigitalSignatureOffset - iFilePropertiesEndOffset < 0 || |
|
474 iFilePropertiesEndOffset < 0 ) |
|
475 { |
|
476 iDigitalSignatureObjectExists = EFalse; |
|
477 iDigitalSignatureOffset = 0; |
|
478 delete iDigitalSignatureObject; |
|
479 iDigitalSignatureObject = NULL; |
|
480 } |
|
481 else |
|
482 { |
|
483 iSignedData = |
|
484 iHeaderData->Mid( iFilePropertiesEndOffset, |
|
485 iDigitalSignatureOffset - iFilePropertiesEndOffset ).AllocL(); |
|
486 } |
|
487 } |
|
488 |
|
489 //Move object offset to the end of the current header object |
|
490 objOffset += objSize; |
|
491 //End loop, if top level header is finished or all needed headers are handled |
|
492 if ( objOffset >= iHeaderSize - 30 || |
|
493 ( iContentDescriptionObjectExists && |
|
494 iFilePropertiesObjectExists && |
|
495 iExtendedContentDescriptionObjectExists && |
|
496 iExtendedContentEncryptionObjectExists && |
|
497 iDigitalSignatureObjectExists ) ) |
|
498 { |
|
499 loop = EFalse; |
|
500 } |
|
501 //Loop isn't finished, read next object GUID |
|
502 else |
|
503 { |
|
504 if ( iHeaderData->Length() < ( objOffset + KObjectID ) || objOffset < 0 ) |
|
505 { |
|
506 User::Leave( KErrArgument ); |
|
507 } |
|
508 objGUID = iHeaderData->Mid( objOffset, KObjectID ); |
|
509 FormatGUID( objGUID ); |
|
510 } |
|
511 } |
|
512 if ( iFilePropertiesObjectExists ) |
|
513 { |
|
514 iIsValidated = ETrue; |
|
515 } |
|
516 } |
|
517 |
|
518 |
|
519 // ----------------------------------------------------------------------------- |
|
520 // CAsf::FormatGUID |
|
521 // ----------------------------------------------------------------------------- |
|
522 // |
|
523 void CAsf::FormatGUID( TDes8 &aGUID ) |
|
524 { |
|
525 LOGFN( "CAsf::FormatGUID" ); |
|
526 |
|
527 TBuf8<16> copyGUID( aGUID ); |
|
528 TInt i; |
|
529 for( i = 0; i < 4; i++ ) |
|
530 { |
|
531 copyGUID[i] = aGUID[3-i]; |
|
532 } |
|
533 for( i = 4; i < 6; i++ ) |
|
534 { |
|
535 copyGUID[i] = aGUID[9 - i]; |
|
536 } |
|
537 for ( i = 6; i < 8; i++ ) |
|
538 { |
|
539 copyGUID[i] = aGUID[13 - i]; |
|
540 } |
|
541 for( i = 8; i < 16 ; i++ ) |
|
542 { |
|
543 copyGUID[i] = aGUID[i]; |
|
544 } |
|
545 aGUID.Delete( 0, 32 ); |
|
546 for( i = 0; i < 16; i++ ) |
|
547 { |
|
548 aGUID.AppendNumFixedWidthUC( copyGUID[i], EHex, 2 ); |
|
549 } |
|
550 } |
|
551 |
|
552 // ----------------------------------------------------------------------------- |
|
553 // CAsf::ParseContentDescriptionObject |
|
554 // ----------------------------------------------------------------------------- |
|
555 // |
|
556 void CAsf::ParseContentDescriptionObjectL() |
|
557 { |
|
558 LOGFN( "CAsf::ParseContentDescriptionObjectL" ); |
|
559 TInt offset( iContentDescriptionOffset + KObjectID ); |
|
560 TUint32 objSize( ReadUint64FromBlockL( *iHeaderData, offset ) ); |
|
561 |
|
562 if ( iHeaderData->Length() < iContentDescriptionOffset + objSize ) |
|
563 { |
|
564 User::Leave( KErrOverflow ); |
|
565 } |
|
566 |
|
567 offset += KObjectSize; |
|
568 iTitleLength = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
569 offset += 2; |
|
570 iAuthorLength = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
571 offset += 2; |
|
572 iCopyrightLength = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
573 offset += 2; |
|
574 iDescriptionLength = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
575 offset += 2; |
|
576 iRatingLength = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
577 offset += 2; |
|
578 |
|
579 TInt length( iTitleLength + iAuthorLength + iCopyrightLength + iDescriptionLength + iRatingLength ); |
|
580 if ( length > objSize - ( KObjectID + KObjectSize + 10 ) ) |
|
581 { |
|
582 User::Leave( KErrOverflow ); |
|
583 } |
|
584 |
|
585 iTitle = HBuf16FromBlockL( *iHeaderData, offset, iTitleLength ); |
|
586 offset += iTitleLength; |
|
587 iAuthor = HBuf16FromBlockL( *iHeaderData, offset, iAuthorLength ); |
|
588 offset += iAuthorLength; |
|
589 iCopyright = HBuf16FromBlockL( *iHeaderData, offset, iCopyrightLength ); |
|
590 offset += iCopyrightLength; |
|
591 iDescription = HBuf16FromBlockL( *iHeaderData, offset, iDescriptionLength ); |
|
592 offset += iDescriptionLength; |
|
593 iRating = HBuf16FromBlockL( *iHeaderData, offset, iRatingLength ); |
|
594 offset += iRatingLength; |
|
595 } |
|
596 |
|
597 // ----------------------------------------------------------------------------- |
|
598 // CAsf::ParseContentEncryptionObject |
|
599 // ----------------------------------------------------------------------------- |
|
600 // |
|
601 void CAsf::ParseContentEncryptionObjectL() |
|
602 { |
|
603 LOGFN( "CAsf::ParseContentEncryptionObject" ); |
|
604 TInt offset( iContentEncryptionOffset + KObjectID ); |
|
605 TUint32 objSize( ReadUint64FromBlockL( *iHeaderData, offset ) ); |
|
606 |
|
607 if ( iHeaderData->Length() < iContentEncryptionOffset + objSize ) |
|
608 { |
|
609 User::Leave( KErrOverflow ); |
|
610 } |
|
611 |
|
612 offset += KObjectSize; |
|
613 TInt len( ReadUint32FromBlockL( *iHeaderData, offset ) ); |
|
614 offset += 4; |
|
615 if ( iHeaderData->Length() < ( offset + len ) ) |
|
616 { |
|
617 User::Leave( KErrArgument ); |
|
618 } |
|
619 iSecretData = iHeaderData->Mid( offset, len ).AllocL(); |
|
620 offset += len; |
|
621 |
|
622 len = ReadUint32FromBlockL( *iHeaderData, offset ); |
|
623 offset += 4; |
|
624 if ( iHeaderData->Length() < ( offset + len ) ) |
|
625 { |
|
626 User::Leave( KErrArgument ); |
|
627 } |
|
628 iProtectionType = iHeaderData->Mid( offset, len ).AllocL(); |
|
629 offset += len; |
|
630 |
|
631 len = ReadUint32FromBlockL( *iHeaderData, offset ); |
|
632 offset += 4; |
|
633 if ( iHeaderData->Length() < ( offset + len ) ) |
|
634 { |
|
635 User::Leave( KErrArgument ); |
|
636 } |
|
637 iKeyId = iHeaderData->Mid( offset, len ).AllocL(); |
|
638 offset += len; |
|
639 |
|
640 len = ReadUint32FromBlockL( *iHeaderData, offset ); |
|
641 offset += 4; |
|
642 if ( iHeaderData->Length() < ( offset + len ) ) |
|
643 { |
|
644 User::Leave( KErrArgument ); |
|
645 } |
|
646 iLicenseUrl = iHeaderData->Mid( offset, len ).AllocL(); |
|
647 } |
|
648 |
|
649 // ----------------------------------------------------------------------------- |
|
650 // CAsf::ParseExtendedContentDescriptionObjectL |
|
651 // ----------------------------------------------------------------------------- |
|
652 // |
|
653 void CAsf::ParseExtendedContentDescriptionObjectL() |
|
654 { |
|
655 TInt i; |
|
656 |
|
657 LOGFN( "CAsf::ParseExtendedContentDescriptionObjectL" ); |
|
658 TInt offset( iExtendedContentDescriptionOffset + KObjectID ); |
|
659 TUint32 objSize( ReadUint64FromBlockL( *iHeaderData, offset ) ); |
|
660 |
|
661 if ( iHeaderData->Length() < iExtendedContentDescriptionOffset + objSize ) |
|
662 { |
|
663 User::Leave( KErrOverflow ); |
|
664 } |
|
665 |
|
666 offset += KObjectSize; |
|
667 iExtendedContentDescriptionCount = ReadUint16FromBlockL( *iHeaderData, offset ); |
|
668 offset += 2; |
|
669 |
|
670 for ( i = 0 ; i < iExtendedContentDescriptionCount; i++ ) |
|
671 { |
|
672 TInt nameLength( ReadUint16FromBlockL( *iHeaderData, offset ) ); |
|
673 offset += 2; |
|
674 HBufC16* name16( HBuf16FromBlockL( *iHeaderData, offset, nameLength ) ); |
|
675 offset += nameLength; |
|
676 CleanupStack::PushL( name16 ); |
|
677 if( !name16->CompareF( KWMAlbumTitle ) ) |
|
678 { |
|
679 iAlbumTitle = ReadExtendedContentObjectL( offset ); |
|
680 } |
|
681 else if( !name16->CompareF( KWMPicture ) ) |
|
682 { |
|
683 iPicture = ReadExtendedContentObjectL( offset ); |
|
684 } |
|
685 else if( !name16->CompareF( KWMText) ) |
|
686 { |
|
687 iText = ReadExtendedContentObjectL( offset ); |
|
688 } |
|
689 else if( !name16->CompareF( KWMComposer ) ) |
|
690 { |
|
691 iComposer = ReadExtendedContentObjectL( offset ); |
|
692 } |
|
693 else if( !name16->CompareF( KWMGenre ) ) |
|
694 { |
|
695 iGenre = ReadExtendedContentObjectL( offset ); |
|
696 } |
|
697 else if( !name16->CompareF( KWMYear ) || !name16->CompareF( KWMYear1 ) ) |
|
698 { |
|
699 if ( !iYear ) |
|
700 { |
|
701 iYear = ReadExtendedContentObjectL( offset ); |
|
702 } |
|
703 } |
|
704 else if( !name16->CompareF( KWMOriginalArtist) ) |
|
705 { |
|
706 iOriginalArtist = ReadExtendedContentObjectL( offset ); |
|
707 } |
|
708 else if( !name16->CompareF( KWMTrackNumber ) ) |
|
709 { |
|
710 iTrackNumber = ReadExtendedContentObjectL( offset ); |
|
711 } |
|
712 else if( !name16->CompareF( KWMUniqueFileIdentifier ) ) |
|
713 { |
|
714 iUniqueFileID = ReadExtendedContentObjectL( offset ); |
|
715 } |
|
716 else if( !name16->CompareF( KWMAudioFileURL ) ) |
|
717 { |
|
718 iAudioFileUrl = ReadExtendedContentObjectL( offset ); |
|
719 } |
|
720 else if( !name16->CompareF( KWMSharedUserRating ) ) |
|
721 { |
|
722 iSharedUserRating = ReadExtendedContentObjectL( offset ); |
|
723 } |
|
724 else if( !name16->CompareF( KWMDate ) ) |
|
725 { |
|
726 iDate = ReadExtendedContentObjectL( offset ); |
|
727 } |
|
728 CleanupStack::PopAndDestroy( name16 ); |
|
729 |
|
730 offset += 2; // data type |
|
731 TInt valueLength( ReadUint16FromBlockL( *iHeaderData, offset ) ); |
|
732 offset += 2; |
|
733 offset += valueLength; |
|
734 } |
|
735 } |
|
736 |
|
737 // ----------------------------------------------------------------------------- |
|
738 // CAsf::ReadExtendedContentObjectL |
|
739 // ----------------------------------------------------------------------------- |
|
740 // |
|
741 HBufC16* CAsf::ReadExtendedContentObjectL( TInt aOffset ) |
|
742 { |
|
743 HBufC16* buffer( NULL ); |
|
744 |
|
745 LOGFN( "CAsf::ReadExtendedContentObjectL" ); |
|
746 TInt dataTypeInt( ReadUint16FromBlockL( *iHeaderData, aOffset ) ); |
|
747 if ( dataTypeInt == 0x00 ) |
|
748 { |
|
749 TInt length( ReadUint16FromBlockL( *iHeaderData, aOffset + 2 ) ); |
|
750 if ( length > 0 ) |
|
751 { |
|
752 buffer = HBuf16FromBlockL( *iHeaderData, aOffset + 4, length - 2 ); |
|
753 } |
|
754 } |
|
755 else if ( dataTypeInt == 0x02 || dataTypeInt == 0x03 ) |
|
756 { |
|
757 TUint32 dword( ReadUint32FromBlockL( *iHeaderData, aOffset + 4 ) ); |
|
758 buffer = HBufC::NewL( 16 ); |
|
759 TPtr dataString( buffer ->Des() ); |
|
760 dataString.Num( dword ); |
|
761 } |
|
762 else if ( dataTypeInt == 0x05 ) |
|
763 { |
|
764 TUint16 word( ReadUint16FromBlockL( *iHeaderData, aOffset + 4 ) ); |
|
765 buffer = HBufC::NewL( 8 ); |
|
766 TPtr dataString( buffer->Des() ); |
|
767 dataString.Num( word ) ; |
|
768 } |
|
769 return buffer; |
|
770 } |
|
771 |
|
772 // End of File |