|
1 /* |
|
2 * Copyright (c) 2004 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: This class implements the BbB-functionality. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 |
|
21 #include <e32base.h> |
|
22 #include <s32file.h> |
|
23 #include <s32mem.h> |
|
24 #include <caf/caftypes.h> |
|
25 #include <wspdecoder.h> |
|
26 #include <wspencoder.h> |
|
27 |
|
28 #ifdef RD_MULTIPLE_DRIVE |
|
29 #include <DriveInfo.h> |
|
30 #endif |
|
31 |
|
32 #include "DrmRights.h" |
|
33 #include "Oma1DcfCreator.h" |
|
34 #include "b64.h" |
|
35 #include "DRMMessageParser.h" |
|
36 #include "DRMRightsParser.h" |
|
37 #include "DRMRightsClient.h" |
|
38 #include "DrmKeyStorage.h" |
|
39 |
|
40 |
|
41 // EXTERNAL DATA STRUCTURES |
|
42 // EXTERNAL FUNCTION PROTOTYPES |
|
43 // CONSTANTS |
|
44 // MACROS |
|
45 // LOCAL CONSTANTS AND MACROS |
|
46 LOCAL_C const TInt KDefaultInputBufferSize = 2048; |
|
47 LOCAL_C const TInt KDRMMessageMalformed = KErrGeneral; |
|
48 |
|
49 _LIT8( KCIDString, "cid:" ); |
|
50 LOCAL_C const TInt KCIDStringLength = 4; |
|
51 |
|
52 _LIT8( KFLPrefix, "flk:"); |
|
53 LOCAL_C const TInt KFLKPrefixLength = 4; |
|
54 |
|
55 _LIT8( KFLSuffix, "@localhost"); |
|
56 LOCAL_C const TUint8 KCDContentIDLength = 25; // 4 + 11 + 10 |
|
57 LOCAL_C const TUint8 KCDPlainIDLength = 11; |
|
58 |
|
59 LOCAL_C const TInt KInputBufferSize = 2048; |
|
60 LOCAL_C const TInt KBoundaryMarkLength = 2; |
|
61 |
|
62 LOCAL_C const TUint KInitialDCFBufferSize = 4096; |
|
63 |
|
64 #ifdef RD_MULTIPLE_DRIVE |
|
65 _LIT( KTempPath, "%c:\\system\\temp\\" ); |
|
66 #else |
|
67 _LIT( KTempPath, "c:\\system\\temp\\" ); |
|
68 #endif |
|
69 |
|
70 _LIT8( KColon, ":" ); |
|
71 _LIT8( KSemiColon, ";" ); |
|
72 _LIT8( KNewLine, "\n" ); |
|
73 _LIT8( KEndLine, "\r\n" ); |
|
74 LOCAL_C const TUint8 KEndLineLength = 2; |
|
75 |
|
76 _LIT8( KBoundaryMark, "--" ); |
|
77 _LIT8( KContentType, "Content-Type" ); |
|
78 _LIT8( KContentTransferEncoding, "Content-Transfer-Encoding" ); |
|
79 _LIT8( KEncodingBase64, "base64" ); |
|
80 _LIT8( KEncoding7bit, "7bit" ); |
|
81 _LIT8( KEncoding8bit, "8bit" ); |
|
82 _LIT8( KEncodingBinary, "binary" ); |
|
83 _LIT8( KDRMXMLRightsType, "application/vnd.oma.drm.rights+xml"); |
|
84 _LIT8( KDRMWBXMLRightsType, "application/vnd.oma.drm.rights+wbxml" ); |
|
85 _LIT8( KDRMContentType, "application/vnd.oma.drm.content" ); |
|
86 _LIT8( KRightsIssuer, "Rights-Issuer" ); |
|
87 |
|
88 _LIT8( KRightsStartTag, "<o-ex:rights"); |
|
89 |
|
90 _LIT8( KROPart1, "Content-Type: application/vnd.oma.drm.rights+xml\r\n\ |
|
91 Content-Transfer-Encoding: binary\r\n\r\n\ |
|
92 <o-ex:rights xmlns:o-ex=\"http://odrl.net/1.1/ODRL-EX\" \ |
|
93 xmlns:o-dd=\"http://odrl.net/1.1/ODRL-DD\" \ |
|
94 xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#/\">\ |
|
95 <o-ex:context><o-dd:version>1.0</o-dd:version></o-ex:context>\ |
|
96 <o-ex:agreement><o-ex:asset><o-ex:context>\ |
|
97 <o-dd:uid>"); |
|
98 |
|
99 _LIT8( KROPart2, "</o-dd:uid></o-ex:context></o-ex:asset><o-ex:permission>\ |
|
100 <o-dd:display/><o-dd:play/><o-dd:execute/><o-dd:print/>\ |
|
101 </o-ex:permission></o-ex:agreement></o-ex:rights>"); |
|
102 |
|
103 const TInt KFLROSize = sizeof(KROPart1) + sizeof(KROPart2); |
|
104 |
|
105 // MODULE DATA STRUCTURES |
|
106 struct TDeleteFileData |
|
107 { |
|
108 RFs aFs; |
|
109 TFileName aName; |
|
110 }; |
|
111 |
|
112 // LOCAL FUNCTION PROTOTYPES |
|
113 LOCAL_C void DoResetAndDestroy( TAny* aPtr ); |
|
114 LOCAL_C void DoResetAndDestroy2( TAny* aPtr ); |
|
115 LOCAL_C void DoDeleteFile( TAny* aPtr ); |
|
116 LOCAL_C void ConvertPermissionL( CDRMRights*& aRights, |
|
117 CDRMPermission& aPermission, |
|
118 const TDesC8& aURI ); |
|
119 // FORWARD DECLARATIONS |
|
120 |
|
121 // ============================= LOCAL FUNCTIONS =============================== |
|
122 // ----------------------------------------------------------------------------- |
|
123 // DoResetAndDestroy |
|
124 // Does ResetAndDestroy() to given RPointerArray< CDRMRights > |
|
125 // ----------------------------------------------------------------------------- |
|
126 void DoResetAndDestroy( TAny* aPtr ) |
|
127 { |
|
128 __ASSERT_DEBUG( aPtr, User::Invariant() ); |
|
129 |
|
130 reinterpret_cast< RPointerArray< CDRMRights >* >( aPtr )->ResetAndDestroy(); |
|
131 } |
|
132 |
|
133 void DoResetAndDestroy2( TAny* aPtr ) |
|
134 { |
|
135 __ASSERT_DEBUG( aPtr, User::Invariant() ); |
|
136 |
|
137 reinterpret_cast< RPointerArray< CDRMPermission >* >( aPtr )->ResetAndDestroy(); |
|
138 } |
|
139 // ----------------------------------------------------------------------------- |
|
140 // DoDeleteFile |
|
141 // Delete the file presented by TDeleteFileData pointer. |
|
142 // ----------------------------------------------------------------------------- |
|
143 void DoDeleteFile( TAny* aPtr ) |
|
144 { |
|
145 __ASSERT_DEBUG( aPtr, User::Invariant() ); |
|
146 TDeleteFileData* data = reinterpret_cast< TDeleteFileData* >( aPtr ); |
|
147 data->aFs.Delete( data->aName ); |
|
148 } |
|
149 |
|
150 void ConvertPermissionL( CDRMRights*& aRights, |
|
151 CDRMPermission& aPermission, |
|
152 const TDesC8& aURI ) |
|
153 { |
|
154 CDRMAsset* asset( NULL ); |
|
155 CDRMRights* rights( NULL ); |
|
156 |
|
157 aRights = NULL; |
|
158 |
|
159 rights = CDRMRights::NewL(); |
|
160 CleanupStack::PushL( rights ); |
|
161 |
|
162 asset = CDRMAsset::NewL(); |
|
163 CleanupStack::PushL( asset ); |
|
164 |
|
165 asset->iUid = aURI.AllocL(); |
|
166 |
|
167 if ( aPermission.iParentUID ) |
|
168 { |
|
169 asset->iParentRights = aPermission.iParentUID->AllocL(); |
|
170 } |
|
171 |
|
172 rights->SetPermissionL( aPermission ); |
|
173 rights->SetAssetL( *asset ); |
|
174 |
|
175 CleanupStack::PopAndDestroy(); // asset |
|
176 CleanupStack::Pop(), // rights |
|
177 |
|
178 aRights = rights; |
|
179 } |
|
180 |
|
181 // ============================ MEMBER FUNCTIONS =============================== |
|
182 // ----------------------------------------------------------------------------- |
|
183 // CDRMMessageParser::NewL |
|
184 // Two-phased constructor. |
|
185 // ----------------------------------------------------------------------------- |
|
186 // |
|
187 EXPORT_C CDRMMessageParser* CDRMMessageParser::NewL( void ) |
|
188 { |
|
189 CDRMMessageParser* self = new( ELeave ) CDRMMessageParser(); |
|
190 |
|
191 CleanupStack::PushL( self ); |
|
192 self->ConstructL(); |
|
193 CleanupStack::Pop(); |
|
194 |
|
195 return self; |
|
196 } |
|
197 |
|
198 // ----------------------------------------------------------------------------- |
|
199 // CDRMMessageParser::CDRMMessageParser |
|
200 // Constructor. |
|
201 // ----------------------------------------------------------------------------- |
|
202 // |
|
203 CDRMMessageParser::CDRMMessageParser() : |
|
204 iDcfCreator( NULL ), |
|
205 iBoundary( NULL ), |
|
206 iContentType( NULL ), |
|
207 iState( ESearchingBoundary ), |
|
208 iInputBuffer( NULL, 0, 0 ) |
|
209 { |
|
210 iDCFHeaderSize[ 0 ] = KMaxTUint32; |
|
211 iDCFHeaderSize[ 1 ] = KMaxTUint32; |
|
212 } |
|
213 |
|
214 // ----------------------------------------------------------------------------- |
|
215 // Destructor. |
|
216 // ----------------------------------------------------------------------------- |
|
217 // |
|
218 EXPORT_C CDRMMessageParser::~CDRMMessageParser() |
|
219 { |
|
220 TInt error = KErrNone; |
|
221 TRAP( error, FinalizeMessageParserL() ); |
|
222 |
|
223 Reset(); |
|
224 |
|
225 User::Free( const_cast< TUint8* >( iInputBuffer.Ptr() ) ); |
|
226 } |
|
227 |
|
228 // ----------------------------------------------------------------------------- |
|
229 // CDRMMessageParser:: |
|
230 // |
|
231 // ----------------------------------------------------------------------------- |
|
232 // |
|
233 EXPORT_C void CDRMMessageParser::InitializeMessageParserL( RWriteStream& aStream ) |
|
234 { |
|
235 Reset(); |
|
236 |
|
237 iDcfCreator = COma1DcfCreator::NewL(); |
|
238 |
|
239 iOutputStream = aStream; |
|
240 } |
|
241 |
|
242 // ----------------------------------------------------------------------------- |
|
243 // CDRMMessageParser::ProcessDataL |
|
244 // Choose which operation is required. |
|
245 // ----------------------------------------------------------------------------- |
|
246 EXPORT_C void CDRMMessageParser::ProcessMessageDataL( const TDesC8& aMessageData ) |
|
247 { |
|
248 /* |
|
249 * What happens here is: |
|
250 * - a boundary string is located and extracted |
|
251 * - MIME header is read, and based on content-type field the internal |
|
252 * state is set to either EReadingRightsPart or EReadingContentPart. |
|
253 * - after processing the MIME part, internal state is updated again to |
|
254 * EReadingHeaderPart if there are several MIME parts in the DRM |
|
255 * message. |
|
256 * - data is consumed from iInputData in each phase. |
|
257 * - after everything is done, internal state is set to EAllDone. |
|
258 */ |
|
259 if ( iState & EBroken ) |
|
260 { |
|
261 User::Leave( KErrNotReady ); |
|
262 } |
|
263 |
|
264 if ( iState & EAllDone ) |
|
265 { |
|
266 return; |
|
267 } |
|
268 |
|
269 iInputData.Set( aMessageData ); |
|
270 |
|
271 while( iInputData.Length() ) |
|
272 { |
|
273 if ( iState & EReadingHeaderPart ) |
|
274 { |
|
275 ReadHeaderL(); |
|
276 } |
|
277 else |
|
278 { |
|
279 if ( iState & EReadingContentPart ) |
|
280 { |
|
281 HandleContentDataL(); |
|
282 } |
|
283 else |
|
284 { |
|
285 if ( iState & EReadingRightsPart ) |
|
286 { |
|
287 HandleRightsDataL(); |
|
288 } |
|
289 else |
|
290 { |
|
291 FindBoundaryL(); |
|
292 } |
|
293 } |
|
294 } |
|
295 } |
|
296 } |
|
297 |
|
298 // ----------------------------------------------------------------------------- |
|
299 // CDRMMessageParser::FinalizeL |
|
300 // Finalize the message parser. |
|
301 // ----------------------------------------------------------------------------- |
|
302 EXPORT_C void CDRMMessageParser::FinalizeMessageParserL() |
|
303 { |
|
304 TInt error( KErrNone ); |
|
305 |
|
306 if ( iState & EEncryptStreamOk ) |
|
307 { |
|
308 if ( iInputBuffer.Length() ) |
|
309 { |
|
310 // Message is not parsed fully ==> error. |
|
311 // Try to delete the RO if it is possible. |
|
312 DeletePermission(); |
|
313 error = KDRMMessageMalformed; |
|
314 } |
|
315 |
|
316 ClearBit( EEncryptStreamOk ); |
|
317 iDcfCreator->EncryptFinalizeL(); |
|
318 |
|
319 iOutputStream.CommitL(); |
|
320 } |
|
321 |
|
322 Reset(); |
|
323 |
|
324 User::LeaveIfError( error ); |
|
325 } |
|
326 |
|
327 // ----------------------------------------------------------------------------- |
|
328 // CDRMMessageParser::ConstructL |
|
329 // Symbian 2nd phase constructor can leave. |
|
330 // ----------------------------------------------------------------------------- |
|
331 // |
|
332 void CDRMMessageParser::ConstructL() |
|
333 { |
|
334 // Make some extra room for crazy b64decode(). |
|
335 iInputBuffer.Set( reinterpret_cast< TUint8* >( |
|
336 User::AllocL( KInputBufferSize + 2 ) ), |
|
337 0, |
|
338 KInputBufferSize ); |
|
339 } |
|
340 |
|
341 // ----------------------------------------------------------------------------- |
|
342 // CDRMMessageParser::HandleContentDataL |
|
343 // Process the content data: |
|
344 // - base64 decoding |
|
345 // - boundary checks |
|
346 // - forward the processed data to ProcessContentDataL |
|
347 // ----------------------------------------------------------------------------- |
|
348 // |
|
349 void CDRMMessageParser::HandleContentDataL() |
|
350 { |
|
351 TPtrC8 res( NULL, 0 ); |
|
352 TBool cont( ETrue ); |
|
353 TInt remainder( 0 ); |
|
354 |
|
355 // Loop until |
|
356 // - PrepareContentDataL leaves |
|
357 // - boundary end marker is found |
|
358 // - iInputBuffer is not updated anymore. |
|
359 for ( PrepareContentDataL(); |
|
360 iInputBuffer.Length() && |
|
361 ( remainder != iInputBuffer.Length() ) && |
|
362 cont; |
|
363 PrepareContentDataL() ) |
|
364 { |
|
365 TInt pos = iInputBuffer.Find( *iBoundary ); |
|
366 |
|
367 if ( pos >= 0 ) |
|
368 { |
|
369 if ( pos < KBoundaryMarkLength + 1 ) |
|
370 { |
|
371 SetBrokenStateL( KDRMMessageMalformed ); |
|
372 } |
|
373 |
|
374 res.Set( iInputBuffer.Left( pos - KBoundaryMarkLength ) ); |
|
375 |
|
376 StripEndLineL( res ); |
|
377 |
|
378 cont = EFalse; |
|
379 } |
|
380 else |
|
381 { |
|
382 // All the data cannot be processed immediately, because |
|
383 // there may be only a part of boundary string in this buffer |
|
384 // and the rest is got from the next input descriptor. |
|
385 remainder = iBoundary->Length() + KBoundaryMarkLength + 1; |
|
386 |
|
387 if ( iInputBuffer.Length() <= remainder ) |
|
388 { |
|
389 return; |
|
390 } |
|
391 |
|
392 res.Set( iInputBuffer.Left( iInputBuffer.Length() - |
|
393 remainder ) ); |
|
394 } |
|
395 |
|
396 if ( iState & EBase64 ) |
|
397 { |
|
398 iUsedFromInput = HandleBase64DataL( res ); |
|
399 } |
|
400 |
|
401 else |
|
402 { |
|
403 iUsedFromInput = res.Length(); |
|
404 } |
|
405 |
|
406 ProcessContentDataL( res ); |
|
407 |
|
408 CompressInputBuffer(); |
|
409 |
|
410 remainder = iInputBuffer.Length(); |
|
411 } |
|
412 |
|
413 if ( !cont ) |
|
414 { |
|
415 // Discard all the remaining data. |
|
416 ClearBit( EReadingContentPart ); |
|
417 SetBit( EAllDone ); |
|
418 iInputBuffer.SetLength( 0 ); |
|
419 iInputData.Set( NULL, 0 ); |
|
420 } |
|
421 } |
|
422 |
|
423 // ----------------------------------------------------------------------------- |
|
424 // CDRMMessageParser::HandleRightsDataL |
|
425 // - check if the boundary is reached |
|
426 // - check if the whole rights part is read, and allocate memory && copy the RO |
|
427 // if so |
|
428 // - save the rights object |
|
429 // ----------------------------------------------------------------------------- |
|
430 // |
|
431 void CDRMMessageParser::HandleRightsDataL() |
|
432 { |
|
433 TPtrC8 res( NULL, 0 ); |
|
434 |
|
435 do |
|
436 { |
|
437 res.Set( GetLineL() ); |
|
438 |
|
439 TInt pos = res.Find( *iBoundary ); |
|
440 |
|
441 if ( pos >= KBoundaryMarkLength ) |
|
442 { |
|
443 if ( res.Left( KBoundaryMarkLength ) == KBoundaryMark ) |
|
444 { |
|
445 // Allow empty RO here. If it is not allowed by |
|
446 // HandleRightsMessagePart(), an error is thrown. |
|
447 TBool last = EFalse; |
|
448 |
|
449 // Returns always true. |
|
450 IsBoundary( res, last ); |
|
451 |
|
452 if ( last ) |
|
453 { |
|
454 TInt error( KErrNone ); |
|
455 RPointerArray< CDRMRights > rights; |
|
456 TPtrC8 ptr( iInputBuffer.Ptr(), |
|
457 pos - KBoundaryMarkLength ); |
|
458 |
|
459 error = ProcessRightsObject(ptr, rights); |
|
460 rights.ResetAndDestroy(); |
|
461 |
|
462 if ( !error ) |
|
463 { |
|
464 SetBit( EAllDone ); |
|
465 } |
|
466 else |
|
467 { |
|
468 SetBrokenStateL( error ); |
|
469 } |
|
470 } |
|
471 else |
|
472 { |
|
473 // Save the RO since the CID needs to be either changed |
|
474 // or created. |
|
475 iRightsData = iInputBuffer.Left( iUsedFromInput - |
|
476 res.Length() ).AllocL(); |
|
477 } |
|
478 |
|
479 CompressInputBuffer(); |
|
480 |
|
481 ClearBit( EReadingRightsPart ); |
|
482 ClearBit( EGotContentType ); |
|
483 ClearBit( EGotContentEncoding ); |
|
484 |
|
485 SetBit( EGotRightsPart ); |
|
486 SetBit( EReadingHeaderPart ); |
|
487 |
|
488 res.Set( NULL, 0 ); |
|
489 #ifndef __DRM_FULL |
|
490 User::Leave(KErrNotSupported); |
|
491 #endif |
|
492 } |
|
493 else |
|
494 { |
|
495 SetBrokenStateL( KDRMMessageMalformed ); |
|
496 } |
|
497 } |
|
498 else |
|
499 { |
|
500 if ( pos >= 0 ) |
|
501 { |
|
502 SetBrokenStateL( KDRMMessageMalformed ); |
|
503 } |
|
504 } |
|
505 } while ( res.Length() ); |
|
506 } |
|
507 |
|
508 |
|
509 // ----------------------------------------------------------------------------- |
|
510 // CDRMMessageParser::FindBoundaryL |
|
511 // Tries to locate the boundary string from the available data in iInputBuffer. |
|
512 // ----------------------------------------------------------------------------- |
|
513 // |
|
514 void CDRMMessageParser::FindBoundaryL() |
|
515 { |
|
516 TPtrC8 line( NULL, 0 ); |
|
517 |
|
518 FOREVER |
|
519 { |
|
520 line.Set( GetLineL() ); |
|
521 |
|
522 if ( line.Length() > KBoundaryMarkLength ) |
|
523 { |
|
524 TInt size = 0; |
|
525 |
|
526 if ( line.Left( KBoundaryMarkLength ) == KBoundaryMark ) |
|
527 { |
|
528 size = line.Length() - KBoundaryMarkLength - 1; |
|
529 |
|
530 if ( line[ line.Length() - 2 ] == '\r' ) |
|
531 { |
|
532 --size; |
|
533 } |
|
534 |
|
535 iBoundary = line.Mid( KBoundaryMarkLength, size ).AllocL(); |
|
536 |
|
537 SetBit( EGotBoundary ); |
|
538 SetBit( EReadingHeaderPart ); |
|
539 |
|
540 CompressInputBuffer(); |
|
541 |
|
542 return; |
|
543 } |
|
544 } |
|
545 else |
|
546 { |
|
547 if ( line.Length() == 0 ) |
|
548 { |
|
549 return; |
|
550 } |
|
551 } |
|
552 |
|
553 // Something else, not interested. |
|
554 CompressInputBuffer(); |
|
555 } |
|
556 } |
|
557 |
|
558 // ---------------------------------------------------------------------------- |
|
559 // CDRMMessageParser::ReadHeaderL |
|
560 // The boundary is read and the following part is (should be) either a RO part |
|
561 // or content part. The data is kept in iInputBuffer until the whole header |
|
562 // part of the MIME header part is received. After plain "\r\n" line is |
|
563 // received and content-type is defined, iState is updated. |
|
564 // ---------------------------------------------------------------------------- |
|
565 // |
|
566 void CDRMMessageParser::ReadHeaderL() |
|
567 { |
|
568 TPtrC8 line( NULL, 0 ); |
|
569 TPtrC8 ptr( NULL, 0 ); |
|
570 |
|
571 FOREVER |
|
572 { |
|
573 /////////////////////////////////////////////////////////////////// |
|
574 // Process the MIME header line-by-line. Process the lines if they |
|
575 // contain some information that is found useful. Update the |
|
576 // internal state according to findings. |
|
577 /////////////////////////////////////////////////////////////////// |
|
578 line.Set( GetLineL() ); |
|
579 |
|
580 if ( line.Length() ) |
|
581 { |
|
582 if ( line == KEndLine || line == KNewLine ) |
|
583 { |
|
584 /////////////////////////////////////////////// |
|
585 // MIME header is read. Check what to do next. |
|
586 /////////////////////////////////////////////// |
|
587 if ( iState & EGotContentType ) |
|
588 { |
|
589 // Sanity check: Either EReadingRightsPart or |
|
590 // EReadingContentPart must defined. |
|
591 __ASSERT_DEBUG( ( iState & EReadingRightsPart ) || |
|
592 ( iState & EReadingContentPart ), |
|
593 User::Invariant() ); |
|
594 |
|
595 ClearBit( EReadingHeaderPart ); |
|
596 |
|
597 CompressInputBuffer(); |
|
598 |
|
599 // Check which part was read. |
|
600 // If content part is being processed, some checkings |
|
601 // need to be made. |
|
602 if ( iState & EReadingContentPart ) |
|
603 { |
|
604 if ( iContentType->CompareF( KDRMContentType ) == 0 ) |
|
605 { |
|
606 if ( iState & EGotRightsPart ) |
|
607 { |
|
608 // CD DCF. |
|
609 SetBrokenStateL( KErrCANotSupported ); |
|
610 } |
|
611 |
|
612 InitDCFBufferL(); |
|
613 |
|
614 SetBit( EDCFFile ); |
|
615 } |
|
616 else |
|
617 { |
|
618 // Non-DCF FL content or normal CD content. |
|
619 // Create or modify the CID, save the RO. |
|
620 HandleFlContentL(); |
|
621 |
|
622 iDcfCreator->EncryptInitializeL( |
|
623 iOutputStream, |
|
624 *iContentType, |
|
625 iRightsObject ); |
|
626 SetBit( EEncryptStreamOk ); |
|
627 |
|
628 // The RO handle iRightsObject is kept in order |
|
629 // to delete the rights in case of content |
|
630 // encryption error. In that case, this will |
|
631 // generate unnecessary "RO Added / RO Deleted" |
|
632 // notifications, but so what. "More correct" |
|
633 // way of doing would be modifying |
|
634 // EncryptInitialize not to |
|
635 // save the RO, but then the key would have to |
|
636 // be given to it by other means. Since we are |
|
637 // not their "friend" class, we cannot access |
|
638 // their members, and making them to ask our |
|
639 // members when doing EncryptInitialize/Finalize |
|
640 // might cause some problems perhaps. |
|
641 } |
|
642 |
|
643 delete iContentType; |
|
644 iContentType = NULL; |
|
645 } |
|
646 |
|
647 return; |
|
648 } |
|
649 |
|
650 // Empty MIME header. |
|
651 SetBrokenStateL( KDRMMessageMalformed ); |
|
652 } |
|
653 |
|
654 /////////////////////////////////// |
|
655 // Check the line for content-type. |
|
656 /////////////////////////////////// |
|
657 if ( line.Length() > KContentType().Length() && |
|
658 !( line.Left( KContentType().Length() ).CompareF( KContentType ) ) ) |
|
659 { |
|
660 if ( iState & EGotContentType ) |
|
661 { |
|
662 // Content-type given twice. |
|
663 SetBrokenStateL( KDRMMessageMalformed ); |
|
664 } |
|
665 |
|
666 ptr.Set( HeaderValueL( line ) ); |
|
667 |
|
668 SetBit( EGotContentType ); |
|
669 |
|
670 // Which part this is: rights or the actual content? |
|
671 if ( ( ptr.CompareF( KDRMXMLRightsType ) == 0 ) || |
|
672 ( ptr.CompareF( KDRMWBXMLRightsType ) == 0 ) ) |
|
673 { |
|
674 if ( iState & EGotRightsPart ) |
|
675 { |
|
676 // Rights are given twice. |
|
677 SetBrokenStateL( KDRMMessageMalformed ); |
|
678 } |
|
679 |
|
680 SetBit( EReadingRightsPart ); |
|
681 } |
|
682 else |
|
683 { |
|
684 if ( iState & EGotContentPart ) |
|
685 { |
|
686 SetBrokenStateL( KDRMMessageMalformed ); |
|
687 } |
|
688 |
|
689 SetBit( EReadingContentPart ); |
|
690 |
|
691 // Content-type is saved for future use. |
|
692 iContentType = ptr.AllocL(); |
|
693 } |
|
694 } |
|
695 else |
|
696 { |
|
697 //////////////////////////////////////////////// |
|
698 // Check the line for content-transfer-encoding. |
|
699 //////////////////////////////////////////////// |
|
700 if ( line.Length() > KContentTransferEncoding().Length() && |
|
701 !( line.Left( KContentTransferEncoding().Length() ). |
|
702 CompareF( KContentTransferEncoding ) ) ) |
|
703 { |
|
704 if ( iState & EGotContentEncoding ) |
|
705 { |
|
706 // Double line. |
|
707 SetBrokenStateL( KDRMMessageMalformed ); |
|
708 } |
|
709 |
|
710 ptr.Set( HeaderValueL( line ) ); |
|
711 |
|
712 SetBit( EGotContentEncoding ); |
|
713 |
|
714 // Throw an error if content-transfer-encoding |
|
715 // is something we don't support. |
|
716 if ( ptr.CompareF( KEncoding8bit ) && |
|
717 ptr.CompareF( KEncoding7bit) && |
|
718 ptr.CompareF( KEncodingBinary ) ) |
|
719 { |
|
720 if ( ptr.CompareF( KEncodingBase64 ) ) |
|
721 { |
|
722 SetBrokenStateL( KErrCANotSupported ); |
|
723 } |
|
724 |
|
725 // So it has to be Base64. |
|
726 SetBit( EBase64 ); |
|
727 } |
|
728 } |
|
729 else |
|
730 { |
|
731 ////////////////////////////////////////// |
|
732 // Check the line for end boundary marker. |
|
733 ////////////////////////////////////////// |
|
734 TBool final( EFalse ); |
|
735 |
|
736 if ( IsBoundary( line, final ) ) |
|
737 { |
|
738 SetBrokenStateL( KDRMMessageMalformed ); |
|
739 } |
|
740 |
|
741 // Else: some X-field, parameter or something else. |
|
742 // The line is ignored. |
|
743 } |
|
744 } |
|
745 |
|
746 CompressInputBuffer(); |
|
747 } |
|
748 |
|
749 else |
|
750 { |
|
751 // No line available yet. |
|
752 return; |
|
753 } |
|
754 } |
|
755 } |
|
756 |
|
757 // ----------------------------------------------------------------------------- |
|
758 // CDRMMessageParser::GetLineL |
|
759 // Return a descriptor representing a single line ending to \n in iInputBuffer. |
|
760 // ----------------------------------------------------------------------------- |
|
761 // |
|
762 TPtrC8 CDRMMessageParser::GetLineL() |
|
763 { |
|
764 TInt pos = 0; |
|
765 TPtrC8 res( NULL, 0 ); |
|
766 |
|
767 if ( iInputBuffer.Length() > iUsedFromInput ) |
|
768 { |
|
769 pos = iInputBuffer.Mid( iUsedFromInput ).Find( KNewLine ); |
|
770 |
|
771 if ( pos >= 0 ) |
|
772 { |
|
773 res.Set( iInputBuffer.Mid( iUsedFromInput, pos - iUsedFromInput + 1 ) ); |
|
774 iUsedFromInput = pos + 1; |
|
775 } |
|
776 } |
|
777 |
|
778 if ( res.Length() == 0 ) |
|
779 { |
|
780 if ( iInputData.Length() ) |
|
781 { |
|
782 pos = iInputData.Find( KNewLine ); |
|
783 |
|
784 if ( pos < 0 ) |
|
785 { |
|
786 if ( iInputBuffer.MaxSize() - iInputBuffer.Length() < |
|
787 iInputData.Length() ) |
|
788 { |
|
789 SetBrokenStateL( KDRMMessageMalformed ); |
|
790 } |
|
791 |
|
792 iInputBuffer.Append( iInputData ); |
|
793 iInputData.Set( NULL, 0 ); |
|
794 } |
|
795 else |
|
796 { |
|
797 if ( iInputBuffer.MaxSize() - iInputBuffer.Length() < |
|
798 pos + 1 ) |
|
799 { |
|
800 SetBrokenStateL( KDRMMessageMalformed ); |
|
801 } |
|
802 |
|
803 iInputBuffer.Append( iInputData.Left( pos + 1 ) ); |
|
804 res.Set( iInputBuffer.Mid( iUsedFromInput ) ); |
|
805 iUsedFromInput = iInputBuffer.Length(); |
|
806 |
|
807 iInputData.Set( iInputData.Mid( pos + 1 ) ); |
|
808 } |
|
809 } |
|
810 } |
|
811 |
|
812 return res; |
|
813 } |
|
814 |
|
815 // ----------------------------------------------------------------------------- |
|
816 // CDRMMessageParser::HeaderValueL |
|
817 // Return a descriptor representing a header value in aLine. |
|
818 // ----------------------------------------------------------------------------- |
|
819 // |
|
820 TPtrC8 CDRMMessageParser::HeaderValueL( const TDesC8& aLine ) |
|
821 { |
|
822 TInt pos( 0 ); |
|
823 TPtrC8 res( NULL, 0 ); |
|
824 |
|
825 pos = aLine.Find( KColon ); |
|
826 |
|
827 if ( pos <= 0 ) |
|
828 { |
|
829 SetBrokenStateL( KDRMMessageMalformed ); |
|
830 } |
|
831 |
|
832 pos += 1; |
|
833 |
|
834 while ( pos < aLine.Length() && |
|
835 TChar( aLine[ pos ] ).IsSpace() ) |
|
836 { |
|
837 ++pos; |
|
838 } |
|
839 |
|
840 // Don't overindex. |
|
841 if ( pos == aLine.Length() ) |
|
842 { |
|
843 // Full of whitespaces. |
|
844 SetBrokenStateL( KDRMMessageMalformed ); |
|
845 } |
|
846 |
|
847 // Drop possible parameters. |
|
848 res.Set( aLine.Mid( pos ) ); |
|
849 pos = res.Find( KSemiColon ); |
|
850 |
|
851 if ( pos >= 0 ) |
|
852 { |
|
853 res.Set( res.Left( pos ) ); |
|
854 } |
|
855 |
|
856 pos = res.Length(); |
|
857 |
|
858 if ( !pos ) |
|
859 { |
|
860 // Just parameters, no actual value. |
|
861 SetBrokenStateL( KDRMMessageMalformed ); |
|
862 } |
|
863 |
|
864 // This can't underflow, since otherwise there would be only |
|
865 // semicolon & parameters (checked earlier). |
|
866 while( TChar( res[ pos - 1 ] ).IsSpace() ) |
|
867 { |
|
868 --pos; |
|
869 } |
|
870 |
|
871 return res.Left( pos ); |
|
872 } |
|
873 |
|
874 // ----------------------------------------------------------------------------- |
|
875 // CDRMMessageParser::CompressInputBuffer |
|
876 // Compress iInputBuffer. |
|
877 // ----------------------------------------------------------------------------- |
|
878 // |
|
879 void CDRMMessageParser::CompressInputBuffer() |
|
880 { |
|
881 if ( iUsedFromInput ) |
|
882 { |
|
883 const TInt size = iInputBuffer.Length() - iUsedFromInput; |
|
884 |
|
885 Mem::Copy( const_cast< TUint8* >( iInputBuffer.Ptr() ), |
|
886 iInputBuffer.Ptr() + iUsedFromInput, |
|
887 size ); |
|
888 |
|
889 iInputBuffer.SetLength( size ); |
|
890 iUsedFromInput = 0; |
|
891 } |
|
892 } |
|
893 |
|
894 // ----------------------------------------------------------------------------- |
|
895 // CDRMMessageParser::PrepareContentDataL |
|
896 // Fills the iInputBuffer from iInputData. |
|
897 // ----------------------------------------------------------------------------- |
|
898 // |
|
899 void CDRMMessageParser::PrepareContentDataL() |
|
900 { |
|
901 if ( iInputData.Length() ) |
|
902 { |
|
903 if ( iInputBuffer.Length() == iInputBuffer.MaxSize() ) |
|
904 { |
|
905 SetBrokenStateL( KDRMMessageMalformed ); |
|
906 } |
|
907 |
|
908 const TInt size = Min( iInputBuffer.MaxSize() - iInputBuffer.Length(), |
|
909 iInputData.Length() ); |
|
910 |
|
911 iInputBuffer.Append( iInputData.Left( size ) ); |
|
912 |
|
913 iInputData.Set( iInputData.Mid( size ) ); |
|
914 } |
|
915 } |
|
916 |
|
917 // ----------------------------------------------------------------------------- |
|
918 // CDRMMessageParser::HandleBase64DataL |
|
919 // Decode base64 encoded data from and to aData descriptor. |
|
920 // |
|
921 // ----------------------------------------------------------------------------- |
|
922 // |
|
923 TInt CDRMMessageParser::HandleBase64DataL( TPtrC8& aData ) |
|
924 { |
|
925 TUint8* consumed = const_cast< TUint8* >( aData.Ptr() ); |
|
926 TUint32 temp1 = 0; |
|
927 TUint8 temp2 = 0; |
|
928 |
|
929 for ( temp1 = 0, temp2 = 0; ( TInt )temp1 < aData.Length(); ++temp1 ) |
|
930 { |
|
931 if ( ValidB64CharL( *( aData.Ptr() + temp1 ) ) ) |
|
932 { |
|
933 ++temp2; |
|
934 if ( temp2 == 4 ) |
|
935 { |
|
936 consumed = const_cast< TUint8* >( aData.Ptr() ) + temp1; |
|
937 temp2 = 0; |
|
938 } |
|
939 } |
|
940 } |
|
941 |
|
942 if ( consumed != aData.Ptr() ) |
|
943 { |
|
944 User::LeaveIfError( b64decode( const_cast< TUint8* >( aData.Ptr() ), |
|
945 consumed - aData.Ptr() + 1, |
|
946 const_cast< TUint8* >( aData.Ptr() ), |
|
947 &temp1 ) ); |
|
948 |
|
949 aData.Set( aData.Ptr(), temp1 ); |
|
950 |
|
951 temp1 = consumed - aData.Ptr() + 1; |
|
952 } |
|
953 |
|
954 else |
|
955 { |
|
956 aData.Set( aData.Ptr(), 0 ); |
|
957 temp1 = 0; |
|
958 } |
|
959 |
|
960 return static_cast< TInt >( temp1 ); |
|
961 } |
|
962 |
|
963 // ----------------------------------------------------------------------------- |
|
964 // CDRMMessageParser::StripEndLineL |
|
965 // Remove \r\n from the end of the line. Update aBuf accordingly. |
|
966 // It is allowed that only \n exists, since some WAP gateways used to |
|
967 // strip \r's. |
|
968 // ----------------------------------------------------------------------------- |
|
969 // |
|
970 void CDRMMessageParser::StripEndLineL( TPtrC8& aBuf ) |
|
971 { |
|
972 TInt newSize( aBuf.Length() ); |
|
973 |
|
974 if ( aBuf.Right( 1 ) == KNewLine ) |
|
975 { |
|
976 --newSize; |
|
977 |
|
978 if ( ( aBuf.Length() > 1 ) && |
|
979 ( aBuf.Right( 2 ) == KEndLine ) ) |
|
980 { |
|
981 --newSize; |
|
982 } |
|
983 |
|
984 aBuf.Set( aBuf.Left( newSize ) ); |
|
985 } |
|
986 else |
|
987 { |
|
988 SetBrokenStateL( KDRMMessageMalformed ); |
|
989 } |
|
990 } |
|
991 |
|
992 // ----------------------------------------------------------------------------- |
|
993 // CDRMMessageParser::IsBoundary |
|
994 // Check if the given line is a boundary line. Also check if the line is |
|
995 // the end boundary. |
|
996 // ----------------------------------------------------------------------------- |
|
997 // |
|
998 TBool CDRMMessageParser::IsBoundary( const TDesC8& aLine, TBool& aLast ) const |
|
999 { |
|
1000 TBool res = EFalse; |
|
1001 |
|
1002 __ASSERT_DEBUG( iBoundary, User::Invariant() ); |
|
1003 |
|
1004 if ( iState & EGotBoundary ) |
|
1005 { |
|
1006 if ( aLine.Length() > KBoundaryMarkLength + iBoundary->Length() ) |
|
1007 { |
|
1008 TPtrC8 tmp( NULL, 0 ); |
|
1009 |
|
1010 if ( ( aLine.Left( KBoundaryMarkLength ) == KBoundaryMark ) && |
|
1011 ( aLine.Mid( KBoundaryMarkLength, iBoundary->Length() ). |
|
1012 Compare( *iBoundary ) == 0 ) ) |
|
1013 { |
|
1014 res = ETrue; |
|
1015 |
|
1016 tmp.Set( aLine.Right( aLine.Length() - |
|
1017 KBoundaryMarkLength - |
|
1018 iBoundary->Length() ) ); |
|
1019 |
|
1020 if ( ( tmp.Length() >= KBoundaryMarkLength ) && |
|
1021 ( tmp.Left( KBoundaryMarkLength ) == KBoundaryMark ) ) |
|
1022 { |
|
1023 aLast = ETrue; |
|
1024 } |
|
1025 } |
|
1026 } |
|
1027 } |
|
1028 |
|
1029 return res; |
|
1030 } |
|
1031 |
|
1032 // ----------------------------------------------------------------------------- |
|
1033 // CDRMMessageParser::HandleFlContentL |
|
1034 // Process FL/CD rights object. |
|
1035 // ----------------------------------------------------------------------------- |
|
1036 // |
|
1037 void CDRMMessageParser::HandleFlContentL() |
|
1038 { |
|
1039 __ASSERT_DEBUG( !( iState & EDCFFile ), User::Invariant() ); |
|
1040 |
|
1041 if ( iRightsData ) |
|
1042 { |
|
1043 HBufC8* cid( NULL ); |
|
1044 HBufC8* buf( NULL ); |
|
1045 |
|
1046 // RO was found from DRM message. |
|
1047 CreateCDCIDL( cid ); |
|
1048 CleanupStack::PushL( cid ); |
|
1049 |
|
1050 buf = iRightsData; |
|
1051 CleanupStack::PushL( buf ); |
|
1052 iRightsData = NULL; |
|
1053 |
|
1054 ProcessRightsDataL( *cid, |
|
1055 *buf ); |
|
1056 |
|
1057 CleanupStack::PopAndDestroy(); // buf |
|
1058 CleanupStack::PopAndDestroy(); // cid |
|
1059 } |
|
1060 else |
|
1061 { |
|
1062 TInt error = RetrieveFlRights(); |
|
1063 if ( error ) |
|
1064 { |
|
1065 SetBrokenStateL( error ); |
|
1066 } |
|
1067 } |
|
1068 } |
|
1069 |
|
1070 // ----------------------------------------------------------------------------- |
|
1071 // CDRMMessageParser::ProcessRightsData |
|
1072 // Process DRM message -style rights object and fetch it to iRightsObject if |
|
1073 // necessary. |
|
1074 // ----------------------------------------------------------------------------- |
|
1075 // |
|
1076 void CDRMMessageParser::ProcessRightsDataL( |
|
1077 const TDesC8& aCID, |
|
1078 const TDesC8& aData ) |
|
1079 { |
|
1080 __ASSERT_DEBUG( !iRightsObject, User::Invariant() ); |
|
1081 |
|
1082 TInt start = aData.Find(KRightsStartTag); |
|
1083 TInt end = aData.LocateReverse('>'); |
|
1084 |
|
1085 if ( start >= 0 && end > start ) |
|
1086 { |
|
1087 TDRMUniqueID localID( 0 ); |
|
1088 CDrmRightsParser* parser( NULL ); |
|
1089 CDRMAsset* asset( NULL ); |
|
1090 RDRMRightsClient client; |
|
1091 TPtrC8 ptr( &aData[start], end - start + 1 ); |
|
1092 TBuf8< KDCFKeySize > key; |
|
1093 key.SetLength(KDCFKeySize); |
|
1094 RPointerArray< CDRMRights > rights; |
|
1095 |
|
1096 TCleanupItem cleanup( DoResetAndDestroy, &rights ); |
|
1097 CleanupStack::PushL( cleanup ); |
|
1098 |
|
1099 User::LeaveIfError( client.Connect() ); |
|
1100 CleanupClosePushL( client ); |
|
1101 |
|
1102 parser = CDrmRightsParser::NewL(); |
|
1103 CleanupStack::PushL( parser ); |
|
1104 |
|
1105 parser->ParseL( ptr, rights ); |
|
1106 |
|
1107 if (rights.Count()==0) |
|
1108 { |
|
1109 User::Leave(KErrCorrupt); |
|
1110 } |
|
1111 |
|
1112 client.GetRandomDataL(key); |
|
1113 |
|
1114 User::LeaveIfError( client.AddRecord( |
|
1115 key, |
|
1116 rights[0]->GetPermission(), |
|
1117 aCID, |
|
1118 localID) ); |
|
1119 |
|
1120 iRightsObject = CDRMRights::NewL(); |
|
1121 |
|
1122 asset = CDRMAsset::NewLC(); |
|
1123 asset->iUid = aCID.AllocL(); |
|
1124 |
|
1125 iRightsObject->SetAssetL(*asset); |
|
1126 iRightsObject->SetPermissionL(rights[0]->GetPermission()); |
|
1127 |
|
1128 CleanupStack::PopAndDestroy( 4 ); // asset, parser, client, rights |
|
1129 } |
|
1130 else |
|
1131 { |
|
1132 SetBrokenStateL( KErrArgument ); |
|
1133 } |
|
1134 } |
|
1135 |
|
1136 // ----------------------------------------------------------------------------- |
|
1137 // CDRMMessageParser::ProcessContentDataL |
|
1138 // Handle DCF file's CID manipulation in "DCF in DRM message" case. |
|
1139 // Send the data to EncryptUpdateL if encryption is needed. |
|
1140 // ----------------------------------------------------------------------------- |
|
1141 // |
|
1142 void CDRMMessageParser::ProcessContentDataL( TPtrC8& aData ) |
|
1143 { |
|
1144 // First, check if the content is DCF stuff. |
|
1145 if ( iState & EDCFFile ) |
|
1146 { |
|
1147 // Sanity check: DCF File with RO is illegal. |
|
1148 __ASSERT_DEBUG( !iRightsObject, User::Invariant() ); |
|
1149 |
|
1150 ProcessDCFDataL( aData ); |
|
1151 } |
|
1152 else |
|
1153 { |
|
1154 // No, plain FL content. |
|
1155 iDcfCreator->EncryptUpdateL( aData ); |
|
1156 } |
|
1157 } |
|
1158 |
|
1159 // ----------------------------------------------------------------------------- |
|
1160 // CDRMMessageParser::ValidB64CharL |
|
1161 // Determine if the given character is valid base64 character, and leave |
|
1162 // if it is not. |
|
1163 // ----------------------------------------------------------------------------- |
|
1164 // |
|
1165 TBool CDRMMessageParser::ValidB64CharL( const TUint8 aChar ) |
|
1166 { |
|
1167 // Allowed characters are '0'...'9', 'A'...'Z', 'a'...'z', '+', '/', '=' |
|
1168 if ( ( aChar >= 48 && aChar <= 57 ) || |
|
1169 ( aChar >= 65 && aChar <= 90 ) || |
|
1170 ( aChar >= 97 && aChar <= 122 ) || |
|
1171 ( aChar == 43 ) || |
|
1172 ( aChar == 47 ) || |
|
1173 ( aChar == 61 ) ) |
|
1174 { |
|
1175 return ETrue; |
|
1176 } |
|
1177 |
|
1178 if ( ( aChar != 0x0D ) && ( aChar != 0x0A ) ) |
|
1179 { |
|
1180 SetBrokenStateL( KDRMMessageMalformed ); |
|
1181 } |
|
1182 |
|
1183 return EFalse; |
|
1184 } |
|
1185 |
|
1186 // ----------------------------------------------------------------------------- |
|
1187 // DRMCommon::ProcessMessage |
|
1188 // |
|
1189 // ----------------------------------------------------------------------------- |
|
1190 EXPORT_C TInt CDRMMessageParser::ProcessMessage( |
|
1191 HBufC8*& aDRMMessage) |
|
1192 { |
|
1193 TInt error( KErrNone ); |
|
1194 TRAP( error, DoProcessMessageL( aDRMMessage ) ); |
|
1195 |
|
1196 return error; |
|
1197 } |
|
1198 |
|
1199 // ----------------------------------------------------------------------------- |
|
1200 // DRMCommon::ProcessRightsObject |
|
1201 // Processes a rights objects and saves it in the rights database. |
|
1202 // ----------------------------------------------------------------------------- |
|
1203 EXPORT_C TInt CDRMMessageParser::ProcessRightsObject( |
|
1204 const TDesC8& aRightsObject, |
|
1205 RPointerArray<CDRMRights>& aRightsDetail) |
|
1206 { |
|
1207 TInt error( KErrNone ); |
|
1208 TRAP( error, DoProcessRightsObjectL( aRightsObject, |
|
1209 aRightsDetail ) ); |
|
1210 |
|
1211 return error; |
|
1212 } |
|
1213 |
|
1214 void CDRMMessageParser::SetBit( TUint32 aBit ) |
|
1215 { |
|
1216 iState |= aBit; |
|
1217 } |
|
1218 |
|
1219 void CDRMMessageParser::ClearBit( TUint32 aBit ) |
|
1220 { |
|
1221 iState &= ~aBit; |
|
1222 } |
|
1223 |
|
1224 void CDRMMessageParser::Reset() |
|
1225 { |
|
1226 delete iDCFBuffer; |
|
1227 iDCFBuffer = NULL; |
|
1228 |
|
1229 delete iDcfCreator; |
|
1230 iDcfCreator = NULL; |
|
1231 |
|
1232 delete iRightsData; |
|
1233 iRightsData = NULL; |
|
1234 |
|
1235 delete iRightsObject; |
|
1236 iRightsObject = NULL; |
|
1237 |
|
1238 delete iBoundary; |
|
1239 iBoundary = NULL; |
|
1240 |
|
1241 delete iContentType; |
|
1242 iContentType = NULL; |
|
1243 |
|
1244 iInputBuffer.SetLength( 0 ); |
|
1245 |
|
1246 iState = ESearchingBoundary; |
|
1247 iDCFHeaderSize[ 0 ] = KMaxTUint32; |
|
1248 iDCFHeaderSize[ 1 ] = KMaxTUint32; |
|
1249 } |
|
1250 |
|
1251 void CDRMMessageParser::DoProcessMessageL( HBufC8*& aDRMMessage ) |
|
1252 { |
|
1253 TDeleteFileData fileData; |
|
1254 RFileWriteStream output; |
|
1255 RFile file; |
|
1256 TInt size( 0 ); |
|
1257 |
|
1258 User::LeaveIfError( fileData.aFs.Connect() ); |
|
1259 CleanupClosePushL( fileData.aFs ); |
|
1260 |
|
1261 TCleanupItem cleanup( DoDeleteFile, &fileData ); |
|
1262 CleanupStack::PushL( cleanup ); |
|
1263 |
|
1264 #ifndef RD_MULTIPLE_DRIVE |
|
1265 |
|
1266 User::LeaveIfError( output.Temp( fileData.aFs, |
|
1267 KTempPath, |
|
1268 fileData.aName, |
|
1269 EFileWrite ) ); |
|
1270 |
|
1271 #else //RD_MULTIPLE_DRIVE |
|
1272 |
|
1273 TInt driveNumber( -1 ); |
|
1274 TChar driveLetter; |
|
1275 DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); |
|
1276 fileData.aFs.DriveToChar( driveNumber, driveLetter ); |
|
1277 |
|
1278 TFileName tempPath; |
|
1279 tempPath.Format( KTempPath, (TUint)driveLetter ); |
|
1280 |
|
1281 User::LeaveIfError( output.Temp( fileData.aFs, |
|
1282 tempPath, |
|
1283 fileData.aName, |
|
1284 EFileWrite ) ); |
|
1285 |
|
1286 #endif |
|
1287 |
|
1288 CleanupClosePushL( output ); |
|
1289 |
|
1290 InitializeMessageParserL( output ); |
|
1291 ProcessMessageDataL( *aDRMMessage ); |
|
1292 FinalizeMessageParserL(); |
|
1293 |
|
1294 CleanupStack::PopAndDestroy(); // output |
|
1295 |
|
1296 User::LeaveIfError( file.Open( fileData.aFs, fileData.aName, EFileRead ) ); |
|
1297 CleanupClosePushL( file ); |
|
1298 |
|
1299 User::LeaveIfError( file.Size( size ) ); |
|
1300 |
|
1301 if ( size > aDRMMessage->Des().MaxSize() ) |
|
1302 { |
|
1303 HBufC8* tmp( NULL ); |
|
1304 |
|
1305 delete aDRMMessage; |
|
1306 aDRMMessage = NULL; |
|
1307 |
|
1308 tmp = HBufC8::NewLC( size ); |
|
1309 TPtr8 data( tmp->Des() ); |
|
1310 |
|
1311 User::LeaveIfError( file.Read( data ) ); |
|
1312 CleanupStack::Pop(); // tmp |
|
1313 |
|
1314 aDRMMessage = tmp; |
|
1315 } |
|
1316 else |
|
1317 { |
|
1318 TPtr8 data( aDRMMessage->Des() ); |
|
1319 User::LeaveIfError( file.Read( data ) ); |
|
1320 } |
|
1321 |
|
1322 CleanupStack::PopAndDestroy( 3 ); // file, cleanup, fileData.aFs |
|
1323 } |
|
1324 |
|
1325 void CDRMMessageParser::DoProcessRightsObjectL( |
|
1326 const TDesC8& aRightsObject, |
|
1327 RPointerArray<CDRMRights>& aRightsDetail ) |
|
1328 { |
|
1329 CDrmRightsParser* parser = NULL; |
|
1330 TInt start; |
|
1331 TInt end; |
|
1332 TPtrC8 ptr(0, 0); |
|
1333 |
|
1334 start = aRightsObject.Find(KRightsStartTag); |
|
1335 end = aRightsObject.LocateReverse('>'); |
|
1336 |
|
1337 TCleanupItem cleanup( DoResetAndDestroy, &aRightsDetail ); |
|
1338 CleanupStack::PushL( cleanup ); |
|
1339 |
|
1340 if ( start != KErrNotFound && end != KErrNotFound ) |
|
1341 { |
|
1342 // xml |
|
1343 parser = CDrmRightsParser::NewL(); |
|
1344 CleanupStack::PushL(parser); |
|
1345 |
|
1346 ptr.Set(&aRightsObject[start], end - start + 1); |
|
1347 |
|
1348 parser->ParseAndStoreL(ptr, aRightsDetail); |
|
1349 |
|
1350 if (aRightsDetail.Count() == 0) |
|
1351 { |
|
1352 User::Leave( KErrArgument ); |
|
1353 } |
|
1354 |
|
1355 CleanupStack::PopAndDestroy(); // parser |
|
1356 } |
|
1357 else if (start == KErrNotFound ) |
|
1358 { |
|
1359 // wbxml |
|
1360 parser = CDrmRightsParser::NewL(CDrmRightsParser::EWbxmlParser); |
|
1361 CleanupStack::PushL(parser); |
|
1362 |
|
1363 parser->ParseAndStoreL(aRightsObject, aRightsDetail); |
|
1364 if (aRightsDetail.Count() == 0) |
|
1365 { |
|
1366 User::Leave( KErrArgument ); |
|
1367 } |
|
1368 |
|
1369 CleanupStack::PopAndDestroy(); // parser |
|
1370 } |
|
1371 else |
|
1372 { |
|
1373 User::Leave( KErrArgument ); |
|
1374 } |
|
1375 |
|
1376 CleanupStack::Pop(); // cleanup |
|
1377 } |
|
1378 |
|
1379 void CDRMMessageParser::DeletePermission() |
|
1380 { |
|
1381 if ( iRightsObject ) |
|
1382 { |
|
1383 if ( !( iState & EFLContent ) ) |
|
1384 { |
|
1385 HBufC8* URI = NULL; |
|
1386 |
|
1387 if ( !( iRightsObject->GetContentURI( URI ) ) ) |
|
1388 { |
|
1389 __ASSERT_DEBUG( URI, User::Invariant() ); |
|
1390 |
|
1391 RDRMRightsClient client; |
|
1392 |
|
1393 TInt error = client.Connect(); |
|
1394 |
|
1395 if ( !error ) |
|
1396 { |
|
1397 // Don't care if it fails. |
|
1398 client.DeleteDbEntry( *URI, iRightsObject->GetLocalID() ); |
|
1399 |
|
1400 client.Close(); |
|
1401 } |
|
1402 |
|
1403 delete URI; |
|
1404 URI = NULL; |
|
1405 } |
|
1406 } |
|
1407 |
|
1408 delete iRightsObject; |
|
1409 iRightsObject = NULL; |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 void CDRMMessageParser::SetBrokenStateL( const TInt aError ) |
|
1414 { |
|
1415 SetBit( EBroken ); |
|
1416 DeletePermission(); |
|
1417 |
|
1418 User::Leave( aError ); |
|
1419 } |
|
1420 |
|
1421 void CDRMMessageParser::InitDCFBufferL() |
|
1422 { |
|
1423 iDCFBuffer = HBufC8::New( KInitialDCFBufferSize ); |
|
1424 |
|
1425 if ( !iDCFBuffer ) |
|
1426 { |
|
1427 SetBrokenStateL( KErrNoMemory ); |
|
1428 } |
|
1429 } |
|
1430 |
|
1431 void CDRMMessageParser::CreateCDCIDL( HBufC8*& aCID ) |
|
1432 { |
|
1433 aCID = HBufC8::NewL( KCDContentIDLength ); |
|
1434 TPtr8 des( aCID->Des() ); |
|
1435 TBuf8<KCDPlainIDLength> id; |
|
1436 id.SetLength(KCDPlainIDLength); |
|
1437 |
|
1438 RDRMRightsClient client; |
|
1439 CleanupClosePushL(client); |
|
1440 User::LeaveIfError( client.Connect() ); |
|
1441 client.GetRandomDataL(id); |
|
1442 CleanupStack::PopAndDestroy(); |
|
1443 |
|
1444 des = KFLPrefix; |
|
1445 |
|
1446 for (TInt i = 0; i < KCDPlainIDLength; i++) |
|
1447 { |
|
1448 des.AppendNumFixedWidth( id[i], EDecimal, 1 ); |
|
1449 } |
|
1450 |
|
1451 des.Append( KFLSuffix ); |
|
1452 } |
|
1453 |
|
1454 TInt CDRMMessageParser::RetrieveFlRights() |
|
1455 { |
|
1456 __ASSERT_DEBUG( !iRightsObject, User::Invariant() ); |
|
1457 |
|
1458 RDRMRightsClient client; |
|
1459 TInt error( client.Connect() ); |
|
1460 |
|
1461 if ( !error ) |
|
1462 { |
|
1463 TRAP( error, EnsureFLRightsExistL( client, &iRightsObject ) ); |
|
1464 |
|
1465 client.Close(); |
|
1466 } |
|
1467 |
|
1468 return error; |
|
1469 } |
|
1470 |
|
1471 void CDRMMessageParser::ProcessDCFDataL( TPtrC8& aDCFData ) |
|
1472 { |
|
1473 TBool doCommit( EFalse ); |
|
1474 |
|
1475 // Loop until all available data is either cached or processed. |
|
1476 // What happens is |
|
1477 // - modify Content-URI |
|
1478 // - modify DCF header part |
|
1479 // - dump the rest of the available data to output. |
|
1480 while ( iDCFBuffer->Length() || aDCFData.Length() ) |
|
1481 { |
|
1482 if ( !( iState & EDCFURIModified ) ) |
|
1483 { |
|
1484 ////////////////////////////////////////////////////////////////// |
|
1485 // Modify ContentURI. |
|
1486 ////////////////////////////////////////////////////////////////// |
|
1487 FillDCFBufferL( aDCFData ); |
|
1488 |
|
1489 if ( iDCFBuffer->Length() > 3 ) |
|
1490 { |
|
1491 TInt pos = 0; |
|
1492 TUint8* data = const_cast< TUint8* > ( iDCFBuffer->Ptr() ); |
|
1493 |
|
1494 if ( data[ 0 ] != 1 ) |
|
1495 { |
|
1496 SetBrokenStateL( KDRMMessageMalformed ); |
|
1497 } |
|
1498 |
|
1499 // Cache the data until |
|
1500 // - version, |
|
1501 // - ContentTypeLen, |
|
1502 // - ContentURILen, |
|
1503 // - ContentType and |
|
1504 // - ContentURI |
|
1505 // have been received. |
|
1506 pos = data[ 1 ] + 3; |
|
1507 if ( iDCFBuffer->Length() < pos + data[ 2 ] ) |
|
1508 { |
|
1509 return; |
|
1510 } |
|
1511 |
|
1512 // Sanity check. URI has to be more than four ("cid:") octets. |
|
1513 if ( data[ 2 ] < 5 ) |
|
1514 { |
|
1515 SetBrokenStateL( KDRMMessageMalformed ); |
|
1516 } |
|
1517 |
|
1518 if ( Mem::CompareF( &data[ pos ], |
|
1519 KCIDStringLength, |
|
1520 KCIDString().Ptr(), |
|
1521 KCIDStringLength ) == 0 ) |
|
1522 { |
|
1523 // The data length doesn't change, so Mem::Copy() is safe. |
|
1524 Mem::Copy( &data[ pos ], |
|
1525 KFLPrefix().Ptr(), |
|
1526 KFLKPrefixLength ); |
|
1527 |
|
1528 iOutputStream.WriteL( iDCFBuffer->Left( pos + data[ 2 ] ) ); |
|
1529 |
|
1530 doCommit = ETrue; |
|
1531 |
|
1532 CompressDCFBuffer( pos + data[ 2 ] ); |
|
1533 |
|
1534 SetBit( EDCFURIModified ); |
|
1535 } |
|
1536 else |
|
1537 { |
|
1538 // Discard the broken DCF |
|
1539 SetBrokenStateL( KDRMMessageMalformed ); |
|
1540 } |
|
1541 } |
|
1542 else |
|
1543 { |
|
1544 // Not enough data yet. |
|
1545 return; |
|
1546 } |
|
1547 } |
|
1548 else |
|
1549 { |
|
1550 ////////////////////////////////////////////////////////////////// |
|
1551 // URI is now modified. Modify DCF headers if necessary. |
|
1552 ////////////////////////////////////////////////////////////////// |
|
1553 if ( !( iState & EDCFHeadersModified ) ) |
|
1554 { |
|
1555 FillDCFBufferL( aDCFData ); |
|
1556 |
|
1557 // Figure out how much data there is in the header part and/or |
|
1558 // in the data part. |
|
1559 if ( ( iDCFHeaderSize[ 0 ] == KMaxTUint32 ) && |
|
1560 ( iDCFHeaderSize[ 1 ] == KMaxTUint32 ) ) |
|
1561 { |
|
1562 TUint8 used( 0 ); |
|
1563 |
|
1564 // uintvar has 1...5 octets and we need two uintvars before |
|
1565 // anything can be done. Still, there has to be at least |
|
1566 // 12 octets of data in total to make the DCF legal. But here |
|
1567 // we just check the two uintvars. |
|
1568 if ( iDCFBuffer->Length() < 10 ) |
|
1569 { |
|
1570 // Not enough data yet. |
|
1571 // No need to flush aDCFData at this point, since it |
|
1572 // simply cannot contain anything at this point. |
|
1573 __ASSERT_DEBUG( !aDCFData.Length(), User::Invariant() ); |
|
1574 break; |
|
1575 } |
|
1576 |
|
1577 // Read header field length & data length. |
|
1578 for ( TUint8 count = 0; count < 2; ++count ) |
|
1579 { |
|
1580 TInt size( 0 ); |
|
1581 |
|
1582 TWspPrimitiveDecoder decoder( |
|
1583 iDCFBuffer->Mid( used ) ); |
|
1584 size = decoder.UintVar( iDCFHeaderSize[ count ] ); |
|
1585 |
|
1586 // Sanity check. |
|
1587 if ( size < 1 || iDCFHeaderSize[ count ] >= KMaxTInt ) |
|
1588 { |
|
1589 SetBrokenStateL( KDRMMessageMalformed ); |
|
1590 } |
|
1591 |
|
1592 used += size; |
|
1593 } |
|
1594 |
|
1595 CompressDCFBuffer( used ); |
|
1596 } |
|
1597 else |
|
1598 { |
|
1599 // We know the original header size now. |
|
1600 // Wait until the whole header is read. |
|
1601 if ( static_cast< TUint32 >( iDCFBuffer->Length() ) < |
|
1602 iDCFHeaderSize[ 0 ] ) |
|
1603 { |
|
1604 if ( !aDCFData.Length() ) |
|
1605 { |
|
1606 // All available data is now processed. |
|
1607 break; |
|
1608 } |
|
1609 } |
|
1610 else |
|
1611 { |
|
1612 TUint offset( 0 ); |
|
1613 TUint length( 0 ); |
|
1614 HBufC8* newHeader = NULL; |
|
1615 |
|
1616 if ( FindDCFHeader( KRightsIssuer, |
|
1617 offset, |
|
1618 length ) ) |
|
1619 { |
|
1620 // The header field exists. |
|
1621 TInt pos( 0 ); |
|
1622 TPtr8 trim( const_cast< TUint8* >( |
|
1623 iDCFBuffer->Ptr() ) + offset, |
|
1624 length, |
|
1625 length ); |
|
1626 |
|
1627 iDCFHeaderSize[ 0 ] -= length; // remove old data. |
|
1628 |
|
1629 // No colon, no header value. |
|
1630 pos = trim.Find( KColon ); |
|
1631 if ( pos > 0 ) |
|
1632 { |
|
1633 trim.Set( const_cast< TUint8* >( trim.Ptr() ) + pos + 1, |
|
1634 trim.Length() - pos - 1, |
|
1635 trim.Length() - pos - 1 ); |
|
1636 |
|
1637 // Skip whitespaces |
|
1638 trim.TrimLeft(); |
|
1639 trim.TrimRight(); |
|
1640 |
|
1641 if ( trim.Length() ) |
|
1642 { |
|
1643 // Something to process |
|
1644 newHeader = EncryptDCFFieldLC( trim ); |
|
1645 |
|
1646 iDCFHeaderSize[ 0 ] += KRightsIssuer().Length(); |
|
1647 iDCFHeaderSize[ 0 ] += newHeader->Length(); |
|
1648 iDCFHeaderSize[ 0 ] += 3; // ":" and CRLF |
|
1649 } |
|
1650 } |
|
1651 } |
|
1652 |
|
1653 // Write the uintvars to output. |
|
1654 for ( TUint8 loop = 0; loop < 2; ++loop ) |
|
1655 { |
|
1656 TWspPrimitiveEncoder encoder; |
|
1657 HBufC8* var( encoder.UintVarL( iDCFHeaderSize[ loop ] ) ); |
|
1658 |
|
1659 CleanupStack::PushL( var ); |
|
1660 |
|
1661 iOutputStream.WriteL( *var ); |
|
1662 |
|
1663 CleanupStack::PopAndDestroy(); // var |
|
1664 } |
|
1665 |
|
1666 // Dump the header data to output stream. |
|
1667 iOutputStream.WriteL( iDCFBuffer->Left( offset ) ); |
|
1668 |
|
1669 if ( newHeader ) |
|
1670 { |
|
1671 iOutputStream.WriteL( KRightsIssuer ); |
|
1672 iOutputStream.WriteL( KColon ); |
|
1673 iOutputStream.WriteL( *newHeader ); |
|
1674 |
|
1675 CleanupStack::PopAndDestroy(); // newHeader |
|
1676 newHeader = NULL; |
|
1677 |
|
1678 iOutputStream.WriteL( KEndLine ); |
|
1679 } |
|
1680 |
|
1681 iOutputStream.WriteL( |
|
1682 iDCFBuffer->Right( iDCFBuffer->Length() - |
|
1683 offset - |
|
1684 length ) ); |
|
1685 |
|
1686 doCommit = ETrue; |
|
1687 |
|
1688 CompressDCFBuffer( iDCFBuffer->Length() ); |
|
1689 SetBit( EDCFHeadersModified ); |
|
1690 } |
|
1691 } |
|
1692 } |
|
1693 else |
|
1694 { |
|
1695 // Dump the rest of the data. |
|
1696 __ASSERT_DEBUG( !( iDCFBuffer->Length() ), User::Invariant() ); |
|
1697 |
|
1698 iOutputStream.WriteL( aDCFData ); |
|
1699 |
|
1700 aDCFData.Set( NULL, 0 ); |
|
1701 |
|
1702 doCommit = ETrue; |
|
1703 } |
|
1704 } |
|
1705 } |
|
1706 |
|
1707 if ( doCommit ) |
|
1708 { |
|
1709 iOutputStream.CommitL(); |
|
1710 } |
|
1711 } |
|
1712 |
|
1713 void CDRMMessageParser::FillDCFBufferL( TPtrC8& aData ) |
|
1714 { |
|
1715 if ( aData.Length() ) |
|
1716 { |
|
1717 TInt size( 0 ); |
|
1718 |
|
1719 if ( iDCFBuffer->Length() == iDCFBuffer->Des().MaxSize() ) |
|
1720 { |
|
1721 HBufC8* ptr = iDCFBuffer->ReAlloc( iDCFBuffer->Length() + |
|
1722 KDefaultInputBufferSize ); |
|
1723 |
|
1724 if ( !ptr ) |
|
1725 { |
|
1726 SetBrokenStateL( KErrNoMemory ); |
|
1727 } |
|
1728 |
|
1729 iDCFBuffer = ptr; |
|
1730 } |
|
1731 |
|
1732 size = Min( iDCFBuffer->Des().MaxSize() - iDCFBuffer->Length(), |
|
1733 aData.Length() ); |
|
1734 |
|
1735 iDCFBuffer->Des().Append( aData.Left( size ) ); |
|
1736 |
|
1737 aData.Set( aData.Right( aData.Length() - size ) ); |
|
1738 } |
|
1739 } |
|
1740 |
|
1741 void CDRMMessageParser::CompressDCFBuffer( const TInt aHowMuch ) |
|
1742 { |
|
1743 __ASSERT_DEBUG( aHowMuch <= iDCFBuffer->Des().MaxSize(), User::Invariant() ); |
|
1744 |
|
1745 *iDCFBuffer = iDCFBuffer->Des().Mid( aHowMuch ); |
|
1746 } |
|
1747 TBool CDRMMessageParser::FindDCFHeader( const TDesC8& aString, |
|
1748 TUint& aOffset, |
|
1749 TUint& aLength ) |
|
1750 { |
|
1751 TPtrC8 des( const_cast< TUint8* >( iDCFBuffer->Ptr() ), |
|
1752 Min( iDCFBuffer->Length(), iDCFHeaderSize[ 0 ] ) ); |
|
1753 |
|
1754 aOffset = 0; |
|
1755 aLength = 0; |
|
1756 |
|
1757 while ( des.Length() ) |
|
1758 { |
|
1759 TInt pos = des.Find( KEndLine ); |
|
1760 if ( pos < 0 ) |
|
1761 { |
|
1762 // Last header doesn't end to "\r\n" |
|
1763 pos = des.Length(); |
|
1764 if ( pos < 0 ) |
|
1765 { |
|
1766 return EFalse; |
|
1767 } |
|
1768 } |
|
1769 else |
|
1770 { |
|
1771 pos += KEndLineLength; |
|
1772 } |
|
1773 |
|
1774 if ( ( pos < aString.Length() ) || |
|
1775 ( des.Left( aString.Length() ).CompareF( aString ) != 0 ) ) |
|
1776 { |
|
1777 // Skip the line, since this can't be the one we're looking for. |
|
1778 des.Set( des.Right( des.Length() - |
|
1779 pos ) ); |
|
1780 } |
|
1781 else |
|
1782 { |
|
1783 aOffset = des.Ptr() - iDCFBuffer->Ptr(); |
|
1784 aLength = pos; |
|
1785 |
|
1786 return ETrue; |
|
1787 } |
|
1788 } |
|
1789 |
|
1790 // Never reached. |
|
1791 return EFalse; |
|
1792 } |
|
1793 |
|
1794 void CDRMMessageParser::EnsureFLRightsExistL( |
|
1795 RDRMRightsClient& aClient, |
|
1796 CDRMRights** aOutput ) |
|
1797 { |
|
1798 HBufC8* cid( NULL ); |
|
1799 CDRMRights* perm( NULL ); |
|
1800 RPointerArray< CDRMPermission > rights( 1 ); |
|
1801 |
|
1802 TCleanupItem cleanup( DoResetAndDestroy2, &rights ); |
|
1803 CleanupStack::PushL( cleanup ); |
|
1804 |
|
1805 User::LeaveIfError( aClient.ForwardLockURI( cid ) ); |
|
1806 CleanupStack::PushL( cid ); |
|
1807 |
|
1808 TRAPD( error, aClient.GetDBEntriesL( *cid, rights ) ); |
|
1809 |
|
1810 if ( !error ) |
|
1811 { |
|
1812 ConvertPermissionL( perm, *( rights[ 0 ] ), *cid ); |
|
1813 // No need to pushl 'perm' into cleanup stack. |
|
1814 } |
|
1815 else if ( error == KErrCANoRights ) |
|
1816 { |
|
1817 HBufC8* fl( NULL ); |
|
1818 RPointerArray< CDRMRights > rightslist( 1 ); |
|
1819 |
|
1820 TCleanupItem cleanup2( DoResetAndDestroy, &rightslist ); |
|
1821 CleanupStack::PushL( cleanup2 ); |
|
1822 |
|
1823 fl = HBufC8::NewLC( KFLROSize + cid->Length() ); |
|
1824 |
|
1825 *fl = KROPart1; |
|
1826 fl->Des().Append( *cid ); |
|
1827 fl->Des().Append( KROPart2 ); |
|
1828 |
|
1829 User::LeaveIfError( ProcessRightsObject( *fl, rightslist ) ); |
|
1830 |
|
1831 CleanupStack::PopAndDestroy(); // fl |
|
1832 |
|
1833 perm = rightslist[ 0 ]; |
|
1834 rightslist.Remove( 0 ); |
|
1835 |
|
1836 CleanupStack::PopAndDestroy(); // cleanup2 |
|
1837 |
|
1838 error = KErrNone; |
|
1839 } |
|
1840 |
|
1841 CleanupStack::PopAndDestroy(); // cid |
|
1842 |
|
1843 if ( !error ) |
|
1844 { |
|
1845 // There is something. |
|
1846 if ( aOutput ) |
|
1847 { |
|
1848 *aOutput = perm; |
|
1849 } |
|
1850 else |
|
1851 { |
|
1852 delete perm; perm = NULL; |
|
1853 } |
|
1854 } |
|
1855 |
|
1856 CleanupStack::PopAndDestroy(); // cleanup |
|
1857 } |
|
1858 |
|
1859 |
|
1860 HBufC8* CDRMMessageParser::EncryptDCFFieldLC( const TDesC8& aOldHeader ) |
|
1861 { |
|
1862 HBufC8* res = NULL; |
|
1863 RDRMRightsClient client; |
|
1864 |
|
1865 User::LeaveIfError( client.Connect() ); |
|
1866 CleanupClosePushL( client ); |
|
1867 |
|
1868 // Make sure FL rights exists. |
|
1869 EnsureFLRightsExistL( client, NULL ); |
|
1870 |
|
1871 User::LeaveIfError( |
|
1872 client.EncodeRightsIssuerField( aOldHeader, res ) ); |
|
1873 |
|
1874 CleanupStack::PopAndDestroy(); // client |
|
1875 |
|
1876 CleanupStack::PushL( res ); |
|
1877 |
|
1878 return res; |
|
1879 } |
|
1880 |
|
1881 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
1882 |
|
1883 // End of File |