|
1 /* |
|
2 * Copyright (c) 2004-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 * Handles DRM attachments |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 |
|
23 #include "mmsdrm.h" |
|
24 |
|
25 // drm |
|
26 #include <e32base.h> |
|
27 #include <e32std.h> |
|
28 #include <f32file.h> |
|
29 |
|
30 #include <apmstd.h> |
|
31 |
|
32 #include <s32mem.h> |
|
33 #include <cmsvattachment.h> |
|
34 #include <cmsvmimeheaders.h> |
|
35 #include <msvstore.h> |
|
36 #include <DRMRights.h> |
|
37 #include <DrmPermission.h> |
|
38 #include <DrmConstraint.h> |
|
39 #include <DRMTypes.h> |
|
40 |
|
41 // mms private headers |
|
42 #include "mmsconst.h" |
|
43 #include "mmserrors.h" |
|
44 |
|
45 // CONSTANTS |
|
46 |
|
47 const TInt KMms2 = 2; // just get rid of codescammer complaints |
|
48 const TInt KMmsAssetLength = 1024; // just an estimate |
|
49 |
|
50 // LOCAL FUNCTION PROTOTYPES |
|
51 |
|
52 |
|
53 // ================= MEMBER FUNCTIONS ======================= |
|
54 |
|
55 |
|
56 // --------------------------------------------------------- |
|
57 // |
|
58 // --------------------------------------------------------- |
|
59 // |
|
60 CMmsDrmCaf::CMmsDrmCaf() |
|
61 { |
|
62 } |
|
63 |
|
64 // --------------------------------------------------------- |
|
65 // |
|
66 // --------------------------------------------------------- |
|
67 // |
|
68 CMmsDrmCaf* CMmsDrmCaf::NewL() |
|
69 { |
|
70 CMmsDrmCaf* self = new (ELeave) CMmsDrmCaf(); |
|
71 |
|
72 CleanupStack::PushL( self ); |
|
73 self->ConstructL(); |
|
74 CleanupStack::Pop( self ); |
|
75 |
|
76 return self; |
|
77 } |
|
78 |
|
79 // --------------------------------------------------------- |
|
80 // |
|
81 // --------------------------------------------------------- |
|
82 // |
|
83 void CMmsDrmCaf::ConstructL() |
|
84 { |
|
85 } |
|
86 |
|
87 // --------------------------------------------------------- |
|
88 // |
|
89 // --------------------------------------------------------- |
|
90 // |
|
91 CMmsDrmCaf::~CMmsDrmCaf() |
|
92 { |
|
93 delete iAttachmentFilePath; |
|
94 delete iSupplier; |
|
95 delete iImportFile; |
|
96 } |
|
97 |
|
98 // --------------------------------------------------------- |
|
99 // |
|
100 // --------------------------------------------------------- |
|
101 // |
|
102 TBool CMmsDrmCaf::RegisterL( const CMsvMimeHeaders& aMimeHeaders ) |
|
103 { |
|
104 // We allocate the supplier only when needed |
|
105 if( !iSupplier ) |
|
106 { |
|
107 iSupplier = CSupplier::NewL(); |
|
108 } |
|
109 TBool retValue = EFalse; |
|
110 TInt length = Max( aMimeHeaders.ContentType().Length() + |
|
111 aMimeHeaders.ContentSubType().Length() + 1, KMmsImportFileLength ); |
|
112 |
|
113 HBufC8* contentType = HBufC8::NewL( length ); |
|
114 CleanupStack::PushL( contentType ); |
|
115 |
|
116 contentType->Des().Copy( aMimeHeaders.ContentType() ); |
|
117 contentType->Des().Append( KMmsSlash8 ); |
|
118 contentType->Des().Append( aMimeHeaders.ContentSubType() ); |
|
119 contentType->Des().LowerCase(); |
|
120 |
|
121 TInt i = 0; |
|
122 CMetaDataArray* metaData = NULL; |
|
123 |
|
124 for ( i = 0; i < aMimeHeaders.ContentTypeParams().MdcaCount() - 1; i += KMms2 ) |
|
125 { |
|
126 if ( aMimeHeaders.ContentTypeParams().MdcaPoint( i ).CompareF( KMmsForwardHeader ) == 0 |
|
127 && aMimeHeaders.ContentTypeParams().MdcaPoint( i + 1 ).CompareF( KMmsNoHeader ) == 0 ) |
|
128 { |
|
129 metaData = CMetaDataArray::NewL(); |
|
130 CleanupStack::PushL( metaData ); |
|
131 metaData->AddL( KMmsContentTypeHeader , contentType->Des() ); |
|
132 contentType->Des().Copy( KMmsDrmImportFile ); |
|
133 } |
|
134 else if ( aMimeHeaders.ContentTypeParams().MdcaPoint( i ). |
|
135 CompareF( KMmsRingtoneHeader ) == 0 |
|
136 && aMimeHeaders.ContentTypeParams().MdcaPoint( i + 1 ).CompareF( KMmsNoHeader ) == 0 ) |
|
137 { |
|
138 metaData = CMetaDataArray::NewL(); |
|
139 CleanupStack::PushL( metaData ); |
|
140 metaData->AddL( KMmsContentTypeHeader , contentType->Des() ); |
|
141 contentType->Des().Copy( KMmsDrmImportFile ); |
|
142 // Must also generate rights object and stream it into metadata |
|
143 //create rights |
|
144 CDRMRights* rights = CDRMRights::NewL(); |
|
145 CleanupStack::PushL( rights ); |
|
146 |
|
147 TInt size = 0; |
|
148 // Asset contains the content id |
|
149 // DrmAsset.h |
|
150 CDRMAsset* asset = CDRMAsset::NewLC(); |
|
151 asset->iUid = KMmsHutchContentURI().AllocL(); // This will be freed by the assets destructor |
|
152 // Set the asset to the rights class, it will duplicate the asset |
|
153 rights->SetAssetL( *asset ); |
|
154 size += KMmsAssetLength; // This is a guess, we don't know asset length. |
|
155 |
|
156 CleanupStack::PopAndDestroy( asset ); // Asset |
|
157 |
|
158 // DRMPermission.h |
|
159 CDRMPermission* permission = CDRMPermission::NewLC(); |
|
160 // DRMConstraint.h |
|
161 // DRMTypes.h |
|
162 permission->iPlay = CDRMConstraint::NewL(); |
|
163 permission->iDisplay = CDRMConstraint::NewL(); |
|
164 permission->iExecute = CDRMConstraint::NewL(); |
|
165 permission->iPrint = CDRMConstraint::NewL(); |
|
166 permission->iAvailableRights = ERightsPlay | ERightsDisplay | |
|
167 ERightsExecute | ERightsPrint; |
|
168 // major version for Oma 1 Rights Objects |
|
169 permission->iRightsObjectVersion.iVersionMain = 1; |
|
170 |
|
171 // "ringtone=no" present |
|
172 permission->iInfoBits = ENoRingingTone; |
|
173 permission->iOriginalInsertTime.UniversalTime(); |
|
174 // Set top level and export to empty ones |
|
175 permission->iTopLevel = CDRMConstraint::NewL(); |
|
176 permission->iExport = CDRMConstraint::NewL(); |
|
177 |
|
178 // Set the permission to the rights class, it will duplicate the permission |
|
179 rights->SetPermissionL( *permission ); |
|
180 |
|
181 size += permission->Size(); |
|
182 |
|
183 CleanupStack::PopAndDestroy( permission ); // Permission |
|
184 |
|
185 // stream the rights into metadata |
|
186 |
|
187 HBufC8* data = HBufC8::NewMaxLC( size ); |
|
188 |
|
189 RMemWriteStream stream( (TAny*)( data->Ptr() ), size ); |
|
190 CleanupClosePushL( stream ); |
|
191 |
|
192 rights->ExternalizeL( stream ); |
|
193 metaData->AddL( KOmaImportRightsField(), data->Des() ); |
|
194 |
|
195 CleanupStack::PopAndDestroy( &stream ); // close stream |
|
196 CleanupStack::PopAndDestroy( data ); |
|
197 |
|
198 CleanupStack::PopAndDestroy( rights ); |
|
199 } |
|
200 } |
|
201 |
|
202 if ( iSupplier->IsImportSupported( contentType->Des() ) ) |
|
203 { |
|
204 if ( !metaData ) |
|
205 { |
|
206 metaData = CMetaDataArray::NewL(); |
|
207 CleanupStack::PushL( metaData ); |
|
208 } |
|
209 for ( i = 0; i < aMimeHeaders.XTypeParams().MdcaCount() - 1; i+= KMms2 ) |
|
210 { |
|
211 metaData->AddL( aMimeHeaders.XTypeParams().MdcaPoint( i ), |
|
212 aMimeHeaders.XTypeParams().MdcaPoint( i + 1 ) ); |
|
213 } |
|
214 // Prepare agent for writing data |
|
215 if ( iImportFile ) |
|
216 { |
|
217 // invalid state, previous process not finished |
|
218 User::Leave( KErrArgument ); |
|
219 } |
|
220 iImportFile = iSupplier->ImportFileL( contentType->Des(), *metaData ); |
|
221 retValue = ETrue; |
|
222 } |
|
223 |
|
224 if ( metaData ) |
|
225 { |
|
226 CleanupStack::PopAndDestroy( metaData ); |
|
227 } |
|
228 CleanupStack::PopAndDestroy( contentType ); |
|
229 return retValue; |
|
230 |
|
231 } |
|
232 |
|
233 // --------------------------------------------------------- |
|
234 // |
|
235 // --------------------------------------------------------- |
|
236 // |
|
237 void CMmsDrmCaf::StartProcessingL( |
|
238 RFile& aStartFile, const TDesC& aAttachmentFilePath, CMsvStore& aStore ) |
|
239 { |
|
240 delete iAttachmentFilePath; // just in case the processing has been terminated incorreclty |
|
241 iAttachmentFilePath = NULL; |
|
242 iAttachmentFilePath = HBufC::NewL( aAttachmentFilePath.Length() ); |
|
243 iAttachmentFilePath->Des().Copy( aAttachmentFilePath ); |
|
244 iStore = &aStore; |
|
245 // We duplicate the handle, the caller may close its own copy |
|
246 iAttachmentFile.Duplicate( aStartFile ); |
|
247 } |
|
248 |
|
249 |
|
250 // --------------------------------------------------------- |
|
251 // |
|
252 // --------------------------------------------------------- |
|
253 // |
|
254 TInt CMmsDrmCaf::WriteData( const TDesC8& aData ) |
|
255 { |
|
256 TInt error = KErrNone; |
|
257 |
|
258 error = iImportFile->WriteData( aData ); |
|
259 if ( error != KErrCANewFileHandleRequired ) |
|
260 { |
|
261 // either all went well or the data was corrupted |
|
262 return error; |
|
263 } |
|
264 |
|
265 // We need a new file handle (error == KErrCANewFileHandleRequired) |
|
266 if ( iAttachmentFile.SubSessionHandle() ) |
|
267 { |
|
268 // Caller provided open file handle |
|
269 error = iImportFile->ContinueWithNewOutputFile( iAttachmentFile, |
|
270 iAttachmentFilePath->Des() ); |
|
271 // Close the caller's file handle as CAF has made a copy |
|
272 iAttachmentFile.Close(); |
|
273 if ( error == KErrCANewFileHandleRequired ) |
|
274 { |
|
275 TRAP( error, NewFileL() ); |
|
276 } |
|
277 } |
|
278 else |
|
279 { |
|
280 TRAP( error, NewFileL() ); |
|
281 } |
|
282 // We hope all went well |
|
283 return error; |
|
284 } |
|
285 |
|
286 // --------------------------------------------------------- |
|
287 // |
|
288 // --------------------------------------------------------- |
|
289 // |
|
290 void CMmsDrmCaf::EndProcessingL() |
|
291 { |
|
292 TInt error = KErrNone; |
|
293 |
|
294 error = iImportFile->WriteDataComplete(); |
|
295 if ( error == KErrCANewFileHandleRequired ) |
|
296 { |
|
297 // CAF framework requires another file handle to finish the session |
|
298 TRAP( error, NewFileL() ); |
|
299 } |
|
300 |
|
301 // We clean everything even in case of error |
|
302 delete iAttachmentFilePath; |
|
303 iAttachmentFilePath = NULL; |
|
304 // Terminate the session |
|
305 delete iImportFile; |
|
306 iImportFile = NULL; |
|
307 |
|
308 User::LeaveIfError( error ); |
|
309 } |
|
310 |
|
311 // --------------------------------------------------------- |
|
312 // |
|
313 // --------------------------------------------------------- |
|
314 // |
|
315 void CMmsDrmCaf::NewFileL() |
|
316 { |
|
317 TInt error = KErrNone; |
|
318 TFileName* filename = new( ELeave )TFileName; |
|
319 CleanupStack::PushL( filename ); |
|
320 |
|
321 do |
|
322 { |
|
323 if ( iImportFile->GetSuggestedOutputFileName( *filename ) != KErrNone ) |
|
324 { |
|
325 TFileName* extension = new( ELeave )TFileName; |
|
326 CleanupStack::PushL( extension ); |
|
327 _LIT( KDefAttName, "drmatt"); |
|
328 *filename = KDefAttName; |
|
329 if ( iImportFile->GetSuggestedOutputFileExtension( *extension ) == KErrNone ) |
|
330 { |
|
331 (*filename).Append( *extension ); |
|
332 } |
|
333 CleanupStack::PopAndDestroy( extension ); |
|
334 } |
|
335 CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); |
|
336 RFile file; |
|
337 iStore->CreateShareProtectedAttachmentL( *(filename), file, attachment ); |
|
338 error = iImportFile->ContinueWithNewOutputFile( file, attachment->FilePath() ); |
|
339 // import file duplicates the handle |
|
340 file.Close(); |
|
341 } while ( error == KErrCANewFileHandleRequired ); |
|
342 |
|
343 CleanupStack::PopAndDestroy( filename ); |
|
344 User::LeaveIfError( error ); |
|
345 } |
|
346 |
|
347 |
|
348 // End of File |
|
349 |