|
1 /* |
|
2 * Copyright (c) 2003-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: |
|
15 * Entry wrapper for server side components using CMmsEncode and CMmsDecode |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 #include <msventry.h> |
|
23 #include <msvstd.h> |
|
24 #include <msvapi.h> |
|
25 #include <apparc.h> |
|
26 #include <badesca.h> |
|
27 #include <msvstore.h> |
|
28 #include <cmsvmimeheaders.h> |
|
29 #include <mmsvattachmentmanager.h> |
|
30 #include <mmsvattachmentmanagersync.h> |
|
31 #include <centralrepository.h> |
|
32 |
|
33 #include "mmsconst.h" |
|
34 #include "mmsservercommon.h" |
|
35 #include "mmsserverentry.h" |
|
36 #include "mmsheaders.h" |
|
37 #include "mmssettings.h" |
|
38 #include "mmsdrm.h" |
|
39 #include "mmserrors.h" |
|
40 #include "MmsEnginePrivateCRKeys.h" |
|
41 #include "mmsattachmenthandler.h" |
|
42 #include "mmsgenutils.h" |
|
43 |
|
44 // EXTERNAL DATA STRUCTURES |
|
45 |
|
46 // EXTERNAL FUNCTION PROTOTYPES |
|
47 |
|
48 // CONSTANTS |
|
49 #ifdef __MMS_HUTC_FWD_NO |
|
50 const TInt KMms2 = 2; // just get rid of codescammer complaints |
|
51 #endif |
|
52 |
|
53 // MACROS |
|
54 |
|
55 // LOCAL CONSTANTS AND MACROS |
|
56 |
|
57 // MODULE DATA STRUCTURES |
|
58 |
|
59 // LOCAL FUNCTION PROTOTYPES |
|
60 |
|
61 // ==================== LOCAL FUNCTIONS ==================== |
|
62 |
|
63 // ================= MEMBER FUNCTIONS ======================= |
|
64 |
|
65 // --------------------------------------------------------- |
|
66 // C++ default constructor can NOT contain any code, that |
|
67 // might leave. |
|
68 // |
|
69 // --------------------------------------------------------- |
|
70 // |
|
71 CMmsServerEntry::CMmsServerEntry( |
|
72 RFs& aFs, |
|
73 CMsvServerEntry& aServerEntry ): |
|
74 iFs ( aFs ), |
|
75 iServerEntry ( aServerEntry ), |
|
76 iFileOpen( EFalse ) |
|
77 { |
|
78 } |
|
79 |
|
80 // --------------------------------------------------------- |
|
81 // EPOC default constructor can leave. |
|
82 // --------------------------------------------------------- |
|
83 // |
|
84 void CMmsServerEntry::ConstructL( TMsvId aServiceId ) |
|
85 { |
|
86 iServiceId = aServiceId; |
|
87 if ( iServerEntry.Entry().Id() != aServiceId ) |
|
88 { |
|
89 // this is a message entry, we are supposed to handle it. |
|
90 iMessageEntry = iServerEntry.Entry().Id(); |
|
91 } |
|
92 else |
|
93 { |
|
94 iMessageEntry = KMsvNullIndexEntryId; |
|
95 } |
|
96 |
|
97 iMessageDrive = MessageServer::CurrentDriveL( iFs ); |
|
98 |
|
99 TMmsGenUtils::GetLoggingSettings( iLogAllDecoded, iDump ); |
|
100 |
|
101 // The context stays on the message entry, but service entry is freed |
|
102 // The entry we got is only a reference. |
|
103 // If the caller changes the entry, he must call SetCurrentEntry() to |
|
104 // update the message entry. |
|
105 iServerEntry.SetEntry( iMessageEntry ); |
|
106 } |
|
107 |
|
108 // --------------------------------------------------------- |
|
109 // Two-phased constructor. |
|
110 // --------------------------------------------------------- |
|
111 // |
|
112 EXPORT_C CMmsServerEntry* CMmsServerEntry::NewL( |
|
113 RFs& aFs, |
|
114 CMsvServerEntry& aServerEntry, |
|
115 TMsvId aServiceId) |
|
116 { |
|
117 CMmsServerEntry* self = new (ELeave) CMmsServerEntry( aFs, aServerEntry ); |
|
118 |
|
119 CleanupStack::PushL( self ); |
|
120 self->ConstructL( aServiceId ); |
|
121 CleanupStack::Pop( self ); |
|
122 |
|
123 return self; |
|
124 } |
|
125 |
|
126 |
|
127 // --------------------------------------------------------- |
|
128 // Destructor. |
|
129 // --------------------------------------------------------- |
|
130 // |
|
131 CMmsServerEntry::~CMmsServerEntry() |
|
132 { |
|
133 // release any entry we might be holding |
|
134 Reset(); |
|
135 |
|
136 iServerEntry.SetEntry( KMsvNullIndexEntryId ); |
|
137 } |
|
138 |
|
139 // --------------------------------------------------------- |
|
140 // CMmsServerEntry::EditStoreL |
|
141 // --------------------------------------------------------- |
|
142 // |
|
143 CMsvStore* CMmsServerEntry::EditStoreL() |
|
144 { |
|
145 return iServerEntry.EditStoreL(); |
|
146 } |
|
147 |
|
148 // --------------------------------------------------------- |
|
149 // CMmsServerEntry::ReadStoreL |
|
150 // --------------------------------------------------------- |
|
151 // |
|
152 CMsvStore* CMmsServerEntry::ReadStoreL() |
|
153 { |
|
154 return iServerEntry.ReadStoreL(); |
|
155 } |
|
156 |
|
157 // --------------------------------------------------------- |
|
158 // CMmsServerEntry::GetIndexEntry |
|
159 // --------------------------------------------------------- |
|
160 // |
|
161 TInt CMmsServerEntry::GetIndexEntry( TMsvEntry& aTMsvEntry ) |
|
162 { |
|
163 if ( iMessageEntry == KMsvNullIndexEntryId ) |
|
164 { |
|
165 return KErrNotFound; |
|
166 } |
|
167 aTMsvEntry = iServerEntry.Entry(); |
|
168 return KErrNone; |
|
169 } |
|
170 |
|
171 // --------------------------------------------------------- |
|
172 // CMmsServerEntry::ChangeIndexEntry |
|
173 // --------------------------------------------------------- |
|
174 // |
|
175 TInt CMmsServerEntry::ChangeIndexEntry( TMsvEntry& aTMsvEntry ) |
|
176 { |
|
177 TInt error = KErrNone; |
|
178 if ( iMessageEntry == KMsvNullIndexEntryId ) |
|
179 { |
|
180 return KErrNotFound; |
|
181 } |
|
182 error = iServerEntry.ChangeEntry( aTMsvEntry ); |
|
183 return error; |
|
184 } |
|
185 |
|
186 // --------------------------------------------------------- |
|
187 // CMmsServerEntry::SetCurrentEntry |
|
188 // --------------------------------------------------------- |
|
189 // |
|
190 TInt CMmsServerEntry::SetCurrentEntry( TMsvId aId ) |
|
191 { |
|
192 TInt error = KErrNone; |
|
193 if ( iMessageEntry == aId && iServerEntry.Entry().Id() == aId ) |
|
194 { |
|
195 // we already have the context |
|
196 return error; |
|
197 } |
|
198 error = iServerEntry.SetEntry ( aId ); |
|
199 if ( error == KErrNone ) |
|
200 { |
|
201 iMessageEntry = aId; |
|
202 } |
|
203 else |
|
204 { |
|
205 iMessageEntry = KMsvNullIndexEntryId; |
|
206 } |
|
207 return error; |
|
208 } |
|
209 |
|
210 // --------------------------------------------------------- |
|
211 // CMmsServerEntry::AttachmentsSizeL |
|
212 // --------------------------------------------------------- |
|
213 // |
|
214 TInt CMmsServerEntry::AttachmentsSizeL( CMsvStore& aStore ) |
|
215 { |
|
216 return CMmsAttachmentHandler::AttachmentsSizeL( aStore ); |
|
217 } |
|
218 |
|
219 // --------------------------------------------------------- |
|
220 // CMmsServerEntry::DiskSpaceBelowCriticalLevelL |
|
221 // --------------------------------------------------------- |
|
222 // |
|
223 TInt CMmsServerEntry::DiskSpaceBelowCriticalLevelL( TInt aDataSize ) |
|
224 { |
|
225 TInt error = KErrNone; |
|
226 |
|
227 if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( |
|
228 &iFs, aDataSize, iMessageDrive ) ) |
|
229 { |
|
230 error = KErrDiskFull; |
|
231 } |
|
232 |
|
233 return error; |
|
234 } |
|
235 |
|
236 |
|
237 // --------------------------------------------------------- |
|
238 // CMmsServerEntry::StoreMmsHeadersL |
|
239 // --------------------------------------------------------- |
|
240 // |
|
241 TInt CMmsServerEntry::StoreMmsHeadersL( CMmsHeaders& aMmsHeaders, CMsvStore* aStore ) |
|
242 { |
|
243 // The entry must be kept pointing to the message entry |
|
244 // As all attachment are stored to the message enrty, it is |
|
245 // no longer necessary to switch the context between message |
|
246 // entry and attachment entry. |
|
247 TInt error = KErrNone; |
|
248 if ( DiskSpaceBelowCriticalLevelL( aMmsHeaders.Size() ) ) |
|
249 { |
|
250 error = KErrDiskFull; |
|
251 } |
|
252 |
|
253 if ( error == KErrNone ) |
|
254 { |
|
255 CMsvStore* store = aStore; |
|
256 if ( !aStore ) |
|
257 { |
|
258 store = iServerEntry.EditStoreL(); |
|
259 CleanupStack::PushL(store); |
|
260 } |
|
261 aMmsHeaders.StoreL(*store); |
|
262 if ( !aStore ) |
|
263 { |
|
264 store->CommitL(); |
|
265 CleanupStack::PopAndDestroy( store ); |
|
266 } |
|
267 } |
|
268 |
|
269 return error; |
|
270 } |
|
271 |
|
272 // --------------------------------------------------------- |
|
273 // CMmsServerEntry::RestoreMmsHeadersL |
|
274 // --------------------------------------------------------- |
|
275 // |
|
276 void CMmsServerEntry::RestoreMmsHeadersL( CMmsHeaders& aMmsHeaders, CMsvStore* aStore ) |
|
277 { |
|
278 // The entry must be kept pointing to the message entry |
|
279 // As all attachment are stored to the message enrty, it is |
|
280 // no longer necessary to switch the context between message |
|
281 // entry and attachment entry. |
|
282 CMsvStore* store = aStore; |
|
283 if ( !aStore ) |
|
284 { |
|
285 store = iServerEntry.ReadStoreL(); |
|
286 CleanupStack::PushL( store ); |
|
287 } |
|
288 aMmsHeaders.RestoreL( *store ); |
|
289 if ( !aStore ) |
|
290 { |
|
291 CleanupStack::PopAndDestroy( store ); |
|
292 } |
|
293 } |
|
294 |
|
295 // --------------------------------------------------------- |
|
296 // CMmsServerEntry::CreateFileAttachmentL |
|
297 // --------------------------------------------------------- |
|
298 // |
|
299 TInt CMmsServerEntry::CreateFileAttachmentL( |
|
300 CMsvStore& aStore, |
|
301 const TDesC& aFileName, |
|
302 const TPtrC8& aAttachmentData, |
|
303 CMsvMimeHeaders& aMimeHeaders, |
|
304 TMsvAttachmentId& aAttachment, |
|
305 TInt& aAttachmentSize, |
|
306 TInt32& aDRMFlags) |
|
307 { |
|
308 |
|
309 TInt error = KErrNone; |
|
310 CreateEmptyFileAttachmentL( |
|
311 aStore, |
|
312 aFileName, |
|
313 aMimeHeaders, |
|
314 aAttachment ); |
|
315 |
|
316 error = ProcessAttachmentDataL( aAttachmentData, aDRMFlags ); |
|
317 |
|
318 TInt error2 = KErrNone; |
|
319 error2 = FinalizeAttachmentL( aStore, aAttachmentSize, aDRMFlags ); |
|
320 |
|
321 if ( error == KErrNone ) |
|
322 { |
|
323 error = error2; |
|
324 } |
|
325 |
|
326 return error; |
|
327 } |
|
328 |
|
329 // --------------------------------------------------------- |
|
330 // CMmsServerEntry::DeleteEntry |
|
331 // --------------------------------------------------------- |
|
332 // |
|
333 TInt CMmsServerEntry::DeleteEntry( TMsvId aEntryIndex ) |
|
334 { |
|
335 TInt error = iServerEntry.SetEntry( aEntryIndex ); |
|
336 if ( error == KErrNone ) |
|
337 { |
|
338 error = iServerEntry.SetEntry( iServerEntry.Entry().Parent() ); |
|
339 if ( error == KErrNone ) |
|
340 { |
|
341 error = iServerEntry.DeleteEntry( aEntryIndex ); |
|
342 } |
|
343 } |
|
344 iServerEntry.SetEntry( KMsvNullIndexEntryId ); |
|
345 iMessageEntry = KMsvNullIndexEntryId; |
|
346 return error; |
|
347 |
|
348 } |
|
349 |
|
350 // --------------------------------------------------------- |
|
351 // CMmsServerEntry::IsValidFilename |
|
352 // --------------------------------------------------------- |
|
353 // |
|
354 TBool CMmsServerEntry::IsValidFilename( const TPtrC& aFileName ) |
|
355 { |
|
356 return CMmsAttachmentHandler::IsValidFilename( iFs, aFileName ); |
|
357 } |
|
358 |
|
359 // --------------------------------------------------------- |
|
360 // CMmsServerEntry::GetDecodingFlag |
|
361 // --------------------------------------------------------- |
|
362 // |
|
363 TBool CMmsServerEntry::GetDecodingFlag() |
|
364 { |
|
365 return iLogAllDecoded; |
|
366 } |
|
367 |
|
368 // --------------------------------------------------------- |
|
369 // CMmsServerEntry::GetDumpFlag |
|
370 // --------------------------------------------------------- |
|
371 // |
|
372 TBool CMmsServerEntry::GetDumpFlag() |
|
373 { |
|
374 return iDump; |
|
375 } |
|
376 |
|
377 // --------------------------------------------------------- |
|
378 // CMmsServerEntry:: |
|
379 // --------------------------------------------------------- |
|
380 // |
|
381 void CMmsServerEntry::CreateEmptyFileAttachmentL( |
|
382 CMsvStore& aStore, |
|
383 const TDesC& aFileName, |
|
384 CMsvMimeHeaders& aMimeHeaders, |
|
385 TMsvAttachmentId& aAttachment ) |
|
386 { |
|
387 iAttaId = 0; |
|
388 Reset(); |
|
389 iRemoveDRM = EFalse; |
|
390 |
|
391 TBool noForward = EFalse; |
|
392 // Hutch parameter handling disabled because there is a bug in DRM Asset |
|
393 #ifdef __MMS_HUTC_FWD_NO |
|
394 // Test for H. fwd=no parameter handling |
|
395 // Also ringtone=no |
|
396 // MMS DRM will eventually take care of both |
|
397 TInt i = 0; |
|
398 for ( i = 0; i < aMimeHeaders.ContentTypeParams().MdcaCount() - 1; i += KMms2 ) |
|
399 { |
|
400 if ( ( aMimeHeaders.ContentTypeParams().MdcaPoint( i ).CompareF( KMmsForwardHeader ) == 0 |
|
401 || aMimeHeaders.ContentTypeParams().MdcaPoint( i ). |
|
402 CompareF( KMmsRingtoneHeader ) == 0 ) |
|
403 && aMimeHeaders.ContentTypeParams().MdcaPoint( i + 1 ).CompareF( KMmsNoHeader ) == 0 ) |
|
404 { |
|
405 noForward = ETrue; |
|
406 } |
|
407 } |
|
408 #endif |
|
409 |
|
410 if ( aMimeHeaders.ContentSubType().FindF( KMmsDrmMessageCT ) != KErrNotFound || noForward ) |
|
411 { |
|
412 // This is a drm message. |
|
413 if ( !iDrmHandler ) |
|
414 { |
|
415 iDrmHandler = CMmsDrmCaf::NewL(); |
|
416 } |
|
417 iDRMNeeded = iDrmHandler->RegisterL( aMimeHeaders ); |
|
418 } |
|
419 // We try to continue in any case if we did not run out of memory |
|
420 // If check within MmsDrm fails, iDRMNeeded is set to true, and we will try |
|
421 // DRM handling later. |
|
422 |
|
423 // store must be created before attachmentInfo because attachment info ownership |
|
424 // will be transferred to attachment manager |
|
425 |
|
426 CMsvAttachment* attachmentInfo = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); |
|
427 CleanupStack::PushL( attachmentInfo ); |
|
428 |
|
429 attachmentInfo->SetAttachmentNameL( aFileName ); |
|
430 // We must set size after the data has been saved |
|
431 attachmentInfo->SetComplete( ETrue ); |
|
432 |
|
433 // take type from mime headers |
|
434 HBufC8* tempContentType = HBufC8::NewL( aMimeHeaders.ContentType().Length() + |
|
435 aMimeHeaders.ContentSubType().Length() + 1 ); |
|
436 CleanupStack::PushL( tempContentType ); |
|
437 tempContentType->Des().Copy( aMimeHeaders.ContentType() ); |
|
438 tempContentType->Des().Append( KMmsSlash8 ); |
|
439 tempContentType->Des().Append( aMimeHeaders.ContentSubType() ); |
|
440 attachmentInfo->SetMimeTypeL( tempContentType->Des() ); |
|
441 CleanupStack::PopAndDestroy( tempContentType ); |
|
442 |
|
443 aMimeHeaders.StoreL( *attachmentInfo ); // Mime headers are streamed into atta info |
|
444 |
|
445 if ( DiskSpaceBelowCriticalLevelL( aMimeHeaders.Size() ) ) |
|
446 { |
|
447 CleanupStack::PopAndDestroy( attachmentInfo ); |
|
448 User::Leave( KErrDiskFull ); |
|
449 } |
|
450 |
|
451 MMsvAttachmentManagerSync& attaMan = aStore.AttachmentManagerExtensionsL(); |
|
452 attaMan.CreateAttachmentL( aFileName, iAttaFile, attachmentInfo ); |
|
453 CleanupStack::Pop( attachmentInfo ); |
|
454 aAttachment = attachmentInfo->Id(); |
|
455 iAttaId = aAttachment; |
|
456 iFileOpen = ETrue; |
|
457 |
|
458 if ( iDRMNeeded ) |
|
459 { |
|
460 iDrmHandler->StartProcessingL( iAttaFile, attachmentInfo->FilePath(), aStore ); |
|
461 // the atta file can now be closed |
|
462 iAttaFile.Close(); |
|
463 } |
|
464 |
|
465 } |
|
466 |
|
467 // --------------------------------------------------------- |
|
468 // CMmsServerEntry:: |
|
469 // --------------------------------------------------------- |
|
470 // |
|
471 TInt CMmsServerEntry::ProcessAttachmentDataL( |
|
472 const TPtrC8& aAttachmentData, |
|
473 TInt32& aDRMFlags ) |
|
474 { |
|
475 TInt error = KErrNone; |
|
476 |
|
477 if ( DiskSpaceBelowCriticalLevelL( aAttachmentData.Size() ) ) |
|
478 { |
|
479 return KErrDiskFull; |
|
480 } |
|
481 |
|
482 if ( !iDRMNeeded ) |
|
483 { |
|
484 error = iAttaFile.Write( aAttachmentData ); |
|
485 } |
|
486 else |
|
487 { |
|
488 // if we have iDRMNeeded, we must also have the handler |
|
489 error = iDrmHandler->WriteData( aAttachmentData ); |
|
490 if ( error != KErrNone ) |
|
491 { |
|
492 error = KMmsErrorRemoveDRM; |
|
493 iRemoveDRM = ETrue; |
|
494 aDRMFlags |= EMmsDrmCorruptedAttachment; |
|
495 } |
|
496 } |
|
497 |
|
498 return error; |
|
499 } |
|
500 |
|
501 // --------------------------------------------------------- |
|
502 // CMmsServerEntry:: |
|
503 // --------------------------------------------------------- |
|
504 // |
|
505 TInt CMmsServerEntry::FinalizeAttachmentL( |
|
506 CMsvStore& aStore, |
|
507 TInt& aAttachmentSize, |
|
508 TInt32& aDRMFlags ) |
|
509 { |
|
510 TInt error = KErrNone; |
|
511 |
|
512 TInt size = 0; |
|
513 if ( iFileOpen ) |
|
514 { |
|
515 if ( iDRMNeeded ) |
|
516 { |
|
517 // If DRM is needed, we have the handler |
|
518 TRAP( error, iDrmHandler->EndProcessingL() ); |
|
519 iFileOpen = EFalse; |
|
520 if ( error != KErrNone ) |
|
521 { |
|
522 error = KMmsErrorRemoveDRM; |
|
523 } |
|
524 } |
|
525 else |
|
526 { |
|
527 error = iAttaFile.Flush(); |
|
528 iAttaFile.Size( size ); |
|
529 } |
|
530 } |
|
531 aAttachmentSize = size; |
|
532 |
|
533 // reset closes the file and stream |
|
534 Reset(); |
|
535 |
|
536 MMsvAttachmentManager& attaMan = aStore.AttachmentManagerL(); |
|
537 MMsvAttachmentManagerSync& attaManSync = aStore.AttachmentManagerExtensionsL(); |
|
538 |
|
539 if ( iRemoveDRM || error == KMmsErrorRemoveDRM ) |
|
540 { |
|
541 error = KMmsErrorRemoveDRM; |
|
542 aDRMFlags |= EMmsDrmCorruptedAttachment; |
|
543 // can only remove synchronously if index is known. |
|
544 TInt count = attaMan.AttachmentCount(); |
|
545 TInt i = count - 1; |
|
546 TBool found = EFalse; |
|
547 while ( i >= 0 && !found ) |
|
548 { |
|
549 CMsvAttachment* attachmentInfo = attaMan.GetAttachmentInfoL( i ); |
|
550 if ( attachmentInfo->Id() == iAttaId ) |
|
551 { |
|
552 found = ETrue; |
|
553 } |
|
554 else |
|
555 { |
|
556 i--; |
|
557 } |
|
558 delete attachmentInfo; |
|
559 attachmentInfo = NULL; |
|
560 } |
|
561 if ( i >= 0 && found ) |
|
562 { |
|
563 attaManSync.RemoveAttachmentL( i ); |
|
564 } |
|
565 } |
|
566 else |
|
567 { |
|
568 if ( size == 0 ) |
|
569 { |
|
570 // If the file was encrypted, te size could not be obtained before. |
|
571 // See if we can get it now |
|
572 RFile handle = attaMan.GetAttachmentFileL( iAttaId ); |
|
573 handle.Size( size ); |
|
574 handle.Close(); |
|
575 } |
|
576 CMsvAttachment* attachmentInfo = attaMan.GetAttachmentInfoL( iAttaId ); |
|
577 CleanupStack::PushL( attachmentInfo ); |
|
578 attachmentInfo->SetSize( size ); |
|
579 TRAPD( error2, attaManSync.ModifyAttachmentInfoL( attachmentInfo ) ); |
|
580 if ( error2 == KErrNone ) |
|
581 { |
|
582 CleanupStack::Pop( attachmentInfo ); |
|
583 } |
|
584 else |
|
585 { |
|
586 // if error, attachmentinfo ownership was not transferred |
|
587 CleanupStack::PopAndDestroy( attachmentInfo ); |
|
588 } |
|
589 } |
|
590 // Error about unsuccessful attachment info modification is not returned to caller. |
|
591 // The attachment size info is unreliable anyway, actual file size should always be called |
|
592 |
|
593 iRemoveDRM = EFalse; |
|
594 return error; |
|
595 } |
|
596 |
|
597 // --------------------------------------------------------- |
|
598 // CMmsServerEntry:: |
|
599 // --------------------------------------------------------- |
|
600 // |
|
601 void CMmsServerEntry::Reset() |
|
602 { |
|
603 if ( iFileOpen ) |
|
604 { |
|
605 iAttaFile.Close(); |
|
606 iFileOpen = EFalse; |
|
607 } |
|
608 |
|
609 delete iDrmHandler; |
|
610 iDrmHandler = NULL; |
|
611 iDRMNeeded = EFalse; |
|
612 |
|
613 } |
|
614 |
|
615 |
|
616 // ================= OTHER EXPORTED FUNCTIONS ============== |
|
617 |
|
618 // End of File |