|
1 /* |
|
2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "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 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <f32file.h> |
|
20 #include <caf/caferr.h> |
|
21 #include "rtaImport.h" |
|
22 #include "drmrights.h" |
|
23 #include "drmrightsparser.h" |
|
24 #include "rtarights.h" |
|
25 #include "rightsobject.h" |
|
26 #include "reftestagentconstants.h" |
|
27 #include "rtapanic.h" |
|
28 #include <cinidata.h> |
|
29 |
|
30 using namespace ReferenceTestAgent; |
|
31 |
|
32 EXPORT_C CRefTestAgentImport* CRefTestAgentImport::NewL(const TDesC& aClientSuggestedFileName, RFs& aFs, const TImportFileMimeType& aMimeType) |
|
33 { |
|
34 CRefTestAgentImport* self = new (ELeave) CRefTestAgentImport(aFs, aMimeType); |
|
35 CleanupStack::PushL(self); |
|
36 self->ConstructL(aClientSuggestedFileName); |
|
37 CleanupStack::Pop(self); |
|
38 return self; |
|
39 } |
|
40 |
|
41 CRefTestAgentImport::CRefTestAgentImport(RFs& aFs, const TImportFileMimeType& aMimeType) |
|
42 : iFs(aFs), iOutputFileOpened(EFalse), |
|
43 iRightsOffsetPckg(iRightsOffset), |
|
44 iDrmFilesOffsetPckg(iDrmFilesOffset), |
|
45 iRightsSizePckg(iRightsSize), |
|
46 iDrmFilesSizePckg(iDrmFilesSize), |
|
47 iMimeType(aMimeType), |
|
48 iOffsetSize(sizeof(TInt)) |
|
49 { |
|
50 // Set the length of the buffers to receive integers to be zero initially |
|
51 iRightsOffsetPckg.Zero(); |
|
52 iRightsSizePckg.Zero(); |
|
53 iDrmFilesOffsetPckg.Zero(); |
|
54 iDrmFilesSizePckg.Zero(); |
|
55 } |
|
56 |
|
57 void CRefTestAgentImport::ConstructL(const TDesC& aClientSuggestedFileName) |
|
58 { |
|
59 iDrmRightsParser = CDrmRightsParser::NewL(); |
|
60 |
|
61 /* |
|
62 * Read KRtaTempOutputDir from the ini file. Set it to c:\\rta\\ if |
|
63 * no value is available |
|
64 */ |
|
65 _LIT(KIniFile, "z:\\rta\\settings.ini"); |
|
66 _LIT(KRtaTempOutDirInScript, "RtaTempOutputDir"); |
|
67 CIniData* iniData = NULL; |
|
68 TPtrC tempOutputDir; |
|
69 |
|
70 iniData = CIniData::NewL(KIniFile()); |
|
71 CleanupStack::PushL(iniData); |
|
72 if(iniData->FindVar(KRtaTempOutDirInScript(), tempOutputDir)) |
|
73 { |
|
74 iRtaTempOutDir = tempOutputDir.AllocL(); |
|
75 } |
|
76 else |
|
77 { |
|
78 _LIT(KDefaultRtaDir, ":\\rta\\"); |
|
79 iRtaTempOutDir = HBufC::NewL(KDefaultRtaDir().Length()+1); |
|
80 TPtr ptr(iRtaTempOutDir->Des()); |
|
81 ptr[0] = RFs::GetSystemDriveChar(); |
|
82 ptr.Append(KDefaultRtaDir); |
|
83 } |
|
84 CleanupStack::PopAndDestroy(iniData); |
|
85 |
|
86 TInt nameLen = aClientSuggestedFileName.Length(); |
|
87 if (nameLen) |
|
88 { |
|
89 iClientSuggestedFileName = HBufC8::NewL(nameLen); |
|
90 iClientSuggestedFileName->Des().Copy(aClientSuggestedFileName); |
|
91 } |
|
92 |
|
93 TInt err = iFs.MkDirAll(*iRtaTempOutDir); |
|
94 if (err != KErrNone && err != KErrAlreadyExists) |
|
95 { |
|
96 User::Leave(err); |
|
97 } |
|
98 } |
|
99 |
|
100 CRefTestAgentImport::~CRefTestAgentImport() |
|
101 { |
|
102 if (iTempOutFileName) |
|
103 { |
|
104 // This means importing failed half way thru |
|
105 iFile.Close(); |
|
106 iFs.Delete(*iTempOutFileName); |
|
107 delete iTempOutFileName; |
|
108 } |
|
109 |
|
110 delete iDrmRightsParser; |
|
111 delete iClientSuggestedFileName; |
|
112 delete iRightObjectCid; |
|
113 delete iRtaTempOutDir; |
|
114 } |
|
115 |
|
116 |
|
117 EXPORT_C void CRefTestAgentImport::WriteL(const TDesC8& aData) |
|
118 { |
|
119 if(iMimeType == EMimeContentOrRights) |
|
120 {//If a file content and its rights object are imported |
|
121 WriteFileDataL(aData); |
|
122 } |
|
123 else |
|
124 {//If a streamed content and its rights object are imported |
|
125 WriteStreamDataL(aData); |
|
126 } |
|
127 } |
|
128 |
|
129 void CRefTestAgentImport::WriteStreamDataL(const TDesC8& aData) |
|
130 { |
|
131 TPtrC8 inputData(aData); |
|
132 |
|
133 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
134 if(EReceivingHeaderMark == iImportStage) |
|
135 { |
|
136 iImportStage = EReceivingRightsOffset; |
|
137 } |
|
138 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
139 |
|
140 if(aData.Length() == 0) |
|
141 { |
|
142 if(iImportStage == EReceivingRightsOffset) |
|
143 {// zero length data is not expected |
|
144 User::Leave(KErrCorrupt); |
|
145 } |
|
146 //If the length of the sent data is zero and the import stage is not EReceivingRightsOffset, |
|
147 //it implies that the streaming data import has finished. |
|
148 if(iImportStage != EFinished) |
|
149 {//Change the state to EFinished and leave |
|
150 iImportStage = EFinished; |
|
151 |
|
152 if(iMimeType == EMimePostAcquisitionContent) |
|
153 {//if the content being imported is post-acquisition, add the constant data part to complete import operation. |
|
154 WriteDescriptorL(KContentXml()); |
|
155 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
156 TInt64 offset = KRTAArchiveHeaderSize + sizeof(TInt64); |
|
157 User::LeaveIfError(iFile.Seek(ESeekStart, offset)); |
|
158 TInt64 drmFileOffset = offset + sizeof(TInt) + |
|
159 KMimeTypeRecordedContent().Length()+ sizeof(TInt) + iRightObjectCid->Length() + |
|
160 sizeof(TInt64) + iBytesReceived + sizeof(TInt64); |
|
161 WriteInt64L(drmFileOffset); |
|
162 User::LeaveIfError(iFile.Seek(ESeekStart, iDataOffset)); |
|
163 WriteInt64L(iBytesReceived); |
|
164 #else |
|
165 TInt intLen = 4; |
|
166 User::LeaveIfError(iFile.Seek(ESeekStart, intLen)); |
|
167 WriteIntL(intLen + intLen + KMimeTypeRecordedContent().Length()+ intLen + iRightObjectCid->Length() + intLen + iBytesReceived + intLen); |
|
168 User::LeaveIfError(iFile.Seek(ESeekStart, iDataOffset)); |
|
169 WriteIntL(iBytesReceived); |
|
170 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
171 } |
|
172 User::Leave(KErrCANewFileHandleRequired); |
|
173 } |
|
174 return; |
|
175 } |
|
176 |
|
177 switch(iImportStage) |
|
178 { |
|
179 case EReceivingRightsOffset: |
|
180 |
|
181 OpenTempOutFileL(); |
|
182 WriteHeaderWithNoRightsL(); |
|
183 |
|
184 if(iMimeType == EMimePostAcquisitionRights) |
|
185 { |
|
186 iImportStage = EReceivingRights; |
|
187 iRightsOffset = 1; //Set this variable to be able to get rights count when it required. |
|
188 } |
|
189 else if(iMimeType == EMimePostAcquisitionContent) |
|
190 { |
|
191 WriteDescriptorL(KMimeTypeRecordedContent()); |
|
192 WriteDescriptorL(*iRightObjectCid); |
|
193 User::LeaveIfError(iFile.Seek(ESeekCurrent, iDataOffset)); |
|
194 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
195 WriteInt64L(0); |
|
196 #else |
|
197 WriteIntL(0); |
|
198 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
199 iImportStage = EReceivingDrmFiles; |
|
200 } |
|
201 |
|
202 WriteStreamDataL(inputData); |
|
203 break; |
|
204 |
|
205 case EReceivingRights: |
|
206 // Parse the Xml data as it's received |
|
207 iDrmRightsParser->ParseL(inputData); |
|
208 iBytesReceived += inputData.Length(); |
|
209 break; |
|
210 |
|
211 case EReceivingDrmFiles: |
|
212 // Write the streaming content as it's received |
|
213 User::LeaveIfError(iFile.Write(inputData)); |
|
214 iBytesReceived += inputData.Length(); |
|
215 break; |
|
216 |
|
217 default: |
|
218 User::Panic(KRtaPanicString(), ERtaPanicImportInvalidState); |
|
219 break; |
|
220 } |
|
221 } |
|
222 |
|
223 |
|
224 |
|
225 void CRefTestAgentImport::WriteFileDataL(const TDesC8& aData) |
|
226 { |
|
227 TPtrC8 rightsOffsetFragment; |
|
228 TPtrC8 drmFilesOffsetFragment; |
|
229 TPtrC8 remainingContentFragment; |
|
230 TPtrC8 drmFilesSizeFragment; |
|
231 TPtrC8 remainingDrmFilesFragment; |
|
232 TPtrC8 rightsSizeFragment; |
|
233 TPtrC8 inputData(aData); |
|
234 |
|
235 if(aData.Length() > 0) |
|
236 { |
|
237 switch(iImportStage) |
|
238 { |
|
239 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
240 case EReceivingHeaderMark: |
|
241 { |
|
242 TUint size = iHeaderBuff.MaxLength() - iHeaderBuff.Length(); |
|
243 if(inputData.Length() < size) |
|
244 { |
|
245 size = inputData.Length(); |
|
246 } |
|
247 iHeaderBuff.Append(inputData.Left(size)); |
|
248 inputData.Set(aData.Right(aData.Length() - size)); |
|
249 iBytesReceived += size; |
|
250 if(iHeaderBuff.Length() == KRTAArchiveHeaderSize) |
|
251 { |
|
252 iImportStage = EReceivingRightsOffset; |
|
253 if(iHeaderBuff.Compare(KRTAArchiveHeader) == 0) |
|
254 { |
|
255 iOffsetSize = sizeof(TInt64); |
|
256 } |
|
257 else |
|
258 { |
|
259 iOffsetSize = sizeof(TInt); |
|
260 // Bytes received in case of header's absence in the archive. |
|
261 iBytesReceived -= KRTAArchiveHeaderSize; |
|
262 WriteFileDataL(iHeaderBuff); |
|
263 } |
|
264 WriteFileDataL(inputData); |
|
265 } |
|
266 |
|
267 break; |
|
268 } |
|
269 #endif //SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
270 case EReceivingRightsOffset: |
|
271 //ASSERT_ALWAYS(iBytesReceived < iRightsOffsetPckg.MaxLength()); |
|
272 |
|
273 // Grab the remaining bytes of the rights offset |
|
274 rightsOffsetFragment.Set(inputData.Left(iOffsetSize - iRightsOffsetPckg.Length())); |
|
275 iRightsOffsetPckg.Append(rightsOffsetFragment); |
|
276 iBytesReceived += rightsOffsetFragment.Length(); |
|
277 |
|
278 // See if we have received the entire iRightsOffset |
|
279 if(iRightsOffsetPckg.Length() == iOffsetSize) |
|
280 { |
|
281 // Continue processing any remaining data in the next stage |
|
282 // by recursively calling WriteData() |
|
283 inputData.Set(aData.Right(aData.Length() - rightsOffsetFragment.Length())); |
|
284 iImportStage = EReceivingDrmFilesOffset; |
|
285 WriteFileDataL(inputData); |
|
286 } |
|
287 break; |
|
288 |
|
289 case EReceivingDrmFilesOffset: |
|
290 //ASSERT_ALWAYS(iBytesReceived >= iRightsOffsetPckg.MaxLength()); |
|
291 //ASSERT_ALWAYS(iBytesReceived < iRightsOffsetPckg.MaxLength() + iDrmFilesOffsetPckg.MaxLength()); |
|
292 |
|
293 // Grab the remaining bytes of the rights offset |
|
294 drmFilesOffsetFragment.Set(inputData.Left(iOffsetSize - iDrmFilesOffsetPckg.Length())); |
|
295 iDrmFilesOffsetPckg.Append(drmFilesOffsetFragment); |
|
296 iBytesReceived += drmFilesOffsetFragment.Length(); |
|
297 |
|
298 // See if we have received the entire iDrmFilesOffset |
|
299 if(iDrmFilesOffsetPckg.Length() == iOffsetSize) |
|
300 { |
|
301 // Continue processing any remaining data in the next stage |
|
302 // by recursively calling WriteData() |
|
303 inputData.Set(aData.Right(aData.Length() - drmFilesOffsetFragment.Length())); |
|
304 |
|
305 OpenTempOutFileL(); |
|
306 WriteHeaderWithNoRightsL(); |
|
307 |
|
308 // Next part of the archive to process is the content. But |
|
309 // if no DRM section then next item is rights size. |
|
310 iImportStage = (iDrmFilesOffset == 0) ? EReceivingRightsSize : EReceivingContent; |
|
311 |
|
312 WriteFileDataL(inputData); |
|
313 } |
|
314 break; |
|
315 |
|
316 case EReceivingContent: |
|
317 // ASSERT_ALWAYS(iBytesReceived < iDrmFilesOffset); |
|
318 if(iBytesReceived + inputData.Length() <= iDrmFilesOffset) |
|
319 { |
|
320 // all the data to receive is just content stuff |
|
321 // write it straight to the output file |
|
322 User::LeaveIfError(iFile.Write(inputData)); |
|
323 iBytesReceived += inputData.Length(); |
|
324 } |
|
325 else |
|
326 { |
|
327 // The data written includes the boundary indicating the |
|
328 // end of the content and the start of the content XML file |
|
329 // ie. the offset given by iDrmFilesOffset |
|
330 |
|
331 // Grab the remaining bytes of the content and write them to the file |
|
332 remainingContentFragment.Set(inputData.Left(iDrmFilesOffset - iBytesReceived)); |
|
333 User::LeaveIfError(iFile.Write(remainingContentFragment)); |
|
334 iBytesReceived += remainingContentFragment.Length(); |
|
335 |
|
336 // the remaining inputData includes the content Xml File size |
|
337 inputData.Set(aData.Right(aData.Length() - remainingContentFragment.Length())); |
|
338 iImportStage = EReceivingDrmFilesSize; |
|
339 WriteFileDataL(inputData); |
|
340 } |
|
341 break; |
|
342 case EReceivingDrmFilesSize: |
|
343 // Grab the remaining bytes of the rights offset |
|
344 drmFilesSizeFragment.Set(inputData.Left(iDrmFilesSizePckg.MaxLength() - iDrmFilesSizePckg.Length())); |
|
345 iDrmFilesSizePckg.Append(drmFilesSizeFragment); |
|
346 iBytesReceived += drmFilesSizeFragment.Length(); |
|
347 |
|
348 // See if we have received the entire iDrmFilesOffset |
|
349 if(iDrmFilesSizePckg.Length() == iDrmFilesSizePckg.MaxLength()) |
|
350 { |
|
351 // Write the DrmFiles size to the output file |
|
352 User::LeaveIfError(iFile.Write(iDrmFilesSizePckg)); |
|
353 |
|
354 // Continue processing any remaining data in the next stage |
|
355 // by recursively calling WriteData() |
|
356 inputData.Set(aData.Right(aData.Length() - drmFilesSizeFragment.Length())); |
|
357 |
|
358 iImportStage = EReceivingDrmFiles; |
|
359 WriteFileDataL(inputData); |
|
360 } |
|
361 break; |
|
362 case EReceivingDrmFiles: |
|
363 // ASSERT_ALWAYS(iBytesReceived < iDrmFilesOffset); |
|
364 if(iBytesReceived + inputData.Length() < iDrmFilesOffset + iDrmFilesSize + iDrmFilesSizePckg.MaxLength()) |
|
365 { |
|
366 // all the data to receive is just drm files xml stuff |
|
367 // write it straight to the output file |
|
368 User::LeaveIfError(iFile.Write(inputData)); |
|
369 iBytesReceived += inputData.Length(); |
|
370 } |
|
371 else |
|
372 { |
|
373 // The data written includes the boundary indicating the |
|
374 // end of the drmFiles and the start of the rights file |
|
375 // ie. the offset given by iDrmRightsOffset |
|
376 |
|
377 // Grab the remaining bytes of the drmFiles XML and write it to the file |
|
378 remainingDrmFilesFragment.Set(inputData.Left(iDrmFilesOffset + iDrmFilesSize + iDrmFilesSizePckg.MaxLength() - iBytesReceived)); |
|
379 User::LeaveIfError(iFile.Write(remainingDrmFilesFragment)); |
|
380 iBytesReceived += remainingDrmFilesFragment.Length(); |
|
381 |
|
382 // any remaining inputData is the rights Xml File |
|
383 inputData.Set(aData.Right(aData.Length() - remainingDrmFilesFragment.Length())); |
|
384 if(iRightsOffset == 0) |
|
385 { |
|
386 iImportStage = EFinished; |
|
387 if(inputData.Length() > 0) |
|
388 { |
|
389 User::Leave(KErrCorrupt); |
|
390 } |
|
391 User::Leave(KErrCANewFileHandleRequired); |
|
392 } |
|
393 else |
|
394 { |
|
395 iImportStage = EReceivingRightsSize; |
|
396 } |
|
397 WriteFileDataL(inputData); |
|
398 } |
|
399 break; |
|
400 case EReceivingRightsSize: |
|
401 // Grab the remaining bytes of the rights offset |
|
402 rightsSizeFragment.Set(inputData.Left(iRightsSizePckg.MaxLength() - iRightsSizePckg.Length())); |
|
403 iRightsSizePckg.Append(rightsSizeFragment); |
|
404 iBytesReceived += rightsSizeFragment.Length(); |
|
405 |
|
406 // See if we have received the entire iDrmFilesOffset |
|
407 if(iRightsSizePckg.Length() == iRightsSizePckg.MaxLength()) |
|
408 { |
|
409 // Don't write the rights size to the output file |
|
410 // Rights are parsed not written to the file |
|
411 |
|
412 // Continue processing any remaining data in the next stage |
|
413 // by recursively calling WriteFileDataL() |
|
414 inputData.Set(aData.Right(aData.Length() - rightsSizeFragment.Length())); |
|
415 |
|
416 iImportStage = EReceivingRights; |
|
417 WriteFileDataL(inputData); |
|
418 } |
|
419 break; |
|
420 case EReceivingRights: |
|
421 if(iBytesReceived + inputData.Length() <= iRightsOffset + iRightsSize + iRightsSizePckg.MaxLength()) |
|
422 { |
|
423 // Parse the Xml data as it's received |
|
424 iDrmRightsParser->ParseL(inputData); |
|
425 iBytesReceived += inputData.Length(); |
|
426 } |
|
427 else |
|
428 { |
|
429 // unexpected data after the rights |
|
430 User::Leave(KErrCorrupt); |
|
431 } |
|
432 |
|
433 // See if all the rights have been received |
|
434 if(iBytesReceived == iRightsOffset + iRightsSize + iRightsSizePckg.MaxLength()) |
|
435 { |
|
436 iImportStage = EFinished; |
|
437 User::Leave(KErrCANewFileHandleRequired); |
|
438 } |
|
439 break; |
|
440 |
|
441 case EFinished: |
|
442 // not expecting any more data |
|
443 User::Leave(KErrCorrupt); |
|
444 break; |
|
445 default: |
|
446 User::Panic(KRtaPanicString(), ERtaPanicImportInvalidState); |
|
447 break; |
|
448 } |
|
449 } |
|
450 } |
|
451 |
|
452 |
|
453 EXPORT_C void CRefTestAgentImport::ContinueWithNewOutputFileL(RFile& aFile, const TDesC& aFileName) |
|
454 { |
|
455 if(iImportStage != EFinished) |
|
456 { |
|
457 User::Panic(KRtaPanicString(), ERtaPanicImportInvalidState); |
|
458 } |
|
459 |
|
460 if (! iOutputFileOpened) |
|
461 { |
|
462 __ASSERT_DEBUG(iTempOutFileName, User::Invariant() ); |
|
463 |
|
464 // If OutputContentL leaves, do not want to do it again. |
|
465 iOutputFileOpened = ETrue; |
|
466 OutputContentL(aFile); |
|
467 |
|
468 if (NULL == iClientSuggestedFileName) |
|
469 { |
|
470 iClientSuggestedFileName = HBufC8::NewL(aFileName.Length()); |
|
471 iClientSuggestedFileName->Des().Copy(aFileName); |
|
472 } |
|
473 } |
|
474 else |
|
475 { |
|
476 ProcessRightsL(aFile); |
|
477 } |
|
478 } |
|
479 |
|
480 |
|
481 void CRefTestAgentImport::WriteHeaderWithNoRightsL() |
|
482 { |
|
483 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
484 iFile.Write(KRTAArchiveHeader); |
|
485 TInt64 zero = 0; |
|
486 TPckg <TInt64> zeroPckg(zero); |
|
487 #else |
|
488 TInt zero = 0; |
|
489 TPckg <TInt> zeroPckg(zero); |
|
490 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
491 // Write a zero to the file in place of the rights offset |
|
492 // since we are removing rights as the file is processed |
|
493 User::LeaveIfError(iFile.Write(zeroPckg)); |
|
494 |
|
495 if(iMimeType == EMimeContentOrRights) |
|
496 {// Write the DrmFiles Offset to the output file |
|
497 User::LeaveIfError(iFile.Write(iDrmFilesOffsetPckg)); |
|
498 } |
|
499 else |
|
500 {// Write a zero to the file in place of the drm files offset |
|
501 User::LeaveIfError(iFile.Write(zeroPckg)); |
|
502 } |
|
503 } |
|
504 |
|
505 _LIT(KReceiptFileExtension, ".TXT"); |
|
506 |
|
507 EXPORT_C TInt CRefTestAgentImport::GetSuggestedOutputFileExtension(TDes& aFileExtension) |
|
508 { |
|
509 if(! iOutputFileOpened) |
|
510 { |
|
511 aFileExtension.Copy(KRtaExtensionContent()); |
|
512 } |
|
513 else |
|
514 { |
|
515 // Use ".txt", not .receipt because there are testcases |
|
516 // out there which use CAF's DeleteFile API to delete receipts. |
|
517 // When using RTA's manager's DeleteFile on a "cid.receipt", |
|
518 // it means delete rights with the given cid. |
|
519 aFileExtension.Copy(KReceiptFileExtension()); |
|
520 } |
|
521 return KErrNone; |
|
522 } |
|
523 |
|
524 EXPORT_C TInt CRefTestAgentImport::GetSuggestedOutputFileName(TDes& aFileName) |
|
525 { |
|
526 TRAPD( err, GetSuggestedOutputFileNameL(aFileName) ); |
|
527 return err; |
|
528 } |
|
529 |
|
530 void CRefTestAgentImport::GetSuggestedOutputFileNameL(TDes& aFileName) |
|
531 { |
|
532 if(iImportStage != EFinished) |
|
533 { |
|
534 User::Leave(KErrNotReady); |
|
535 } |
|
536 |
|
537 TInt rightsCount = (iRightsOffset == 0) ? 0 : iDrmRightsParser->DrmRightsL().RightsCount(); |
|
538 |
|
539 if (! iOutputFileOpened) |
|
540 { |
|
541 if (iClientSuggestedFileName) |
|
542 { |
|
543 TChar slash(KPathDelimiter); |
|
544 // If LocateReverse returns a negative number, TDesC8::Right |
|
545 // will return the entire des anyway. |
|
546 TInt n = iClientSuggestedFileName->Length() - iClientSuggestedFileName->LocateReverse(slash) - 1; |
|
547 aFileName.Copy(iClientSuggestedFileName->Right(n)); |
|
548 } |
|
549 else if(rightsCount) |
|
550 { |
|
551 // Use first rights object's cid as output filename. |
|
552 aFileName.Copy(iDrmRightsParser->DrmRightsL().Rights(0).Cid()); |
|
553 if(iMimeType == EMimePostAcquisitionRights) |
|
554 { |
|
555 aFileName.Append(KRtaExtensionPostAcquisitionRights); |
|
556 } |
|
557 else |
|
558 { |
|
559 aFileName.Append(KRtaExtensionContent); |
|
560 } |
|
561 } |
|
562 else |
|
563 { |
|
564 aFileName.Copy(KNullDesC); |
|
565 } |
|
566 } |
|
567 else if(rightsCount) |
|
568 { |
|
569 aFileName.Copy(iDrmRightsParser->DrmRightsL().Rights(0).Cid()); |
|
570 // Use ".txt", not .receipt because there are testcases |
|
571 // out there which use CAF's DeleteFile API to delete receipts. |
|
572 // When using RTA's manager's DeleteFile on a "cid.receipt", |
|
573 // it means delete rights with the given cid. |
|
574 aFileName.Append(KReceiptFileExtension()); |
|
575 } |
|
576 else |
|
577 { |
|
578 // All rights have been processed. |
|
579 User::Leave(KErrCompletion); |
|
580 } |
|
581 } |
|
582 |
|
583 EXPORT_C TInt CRefTestAgentImport::WriteComplete() |
|
584 { |
|
585 TRAPD( err, WriteCompleteL() ); |
|
586 return err; |
|
587 } |
|
588 |
|
589 void CRefTestAgentImport::WriteCompleteL() |
|
590 { |
|
591 if(iImportStage != EFinished) |
|
592 { |
|
593 User::Leave( KErrCorrupt ); |
|
594 } |
|
595 |
|
596 TInt rightsCount = (iRightsOffset) ? iDrmRightsParser->DrmRightsL().RightsCount() : 0; |
|
597 if(rightsCount > 0) |
|
598 { |
|
599 // Erase the client suggested filename from db before adding |
|
600 // the imported rights. This way the client who uses the |
|
601 // feature of DeleteFile(suggestedFileName) will not |
|
602 // touch other's rights. And clients who do not know |
|
603 // about this feature are not affected. They can just |
|
604 // keep using the default suggested filename and tests |
|
605 // continue to pass. |
|
606 RRtaRights rightsServer; |
|
607 User::LeaveIfError(rightsServer.Connect()); |
|
608 CleanupClosePushL(rightsServer); |
|
609 if (iClientSuggestedFileName) |
|
610 { |
|
611 rightsServer.EraseDeleteKeyL(*iClientSuggestedFileName); |
|
612 } |
|
613 CleanupStack::PopAndDestroy(&rightsServer); |
|
614 |
|
615 // This will start a loop where all the rights are processed |
|
616 // Through Continue with new output fileL |
|
617 User::Leave(KErrCANewFileHandleRequired); |
|
618 } |
|
619 } |
|
620 |
|
621 void CRefTestAgentImport::ProcessRightsL(RFile& aFile) |
|
622 { |
|
623 RRtaRights rightsServer; |
|
624 |
|
625 // Just process one rights object at a time |
|
626 if(iDrmRightsParser->DrmRightsL().RightsCount() > 0) |
|
627 { |
|
628 User::LeaveIfError(rightsServer.Connect()); |
|
629 CleanupClosePushL(rightsServer); |
|
630 |
|
631 CRightsObject& ro = iDrmRightsParser->DrmRightsL().Rights(0); |
|
632 // A client (JMI) requested that the DeleteFile API doubles |
|
633 // as API to delete rights objects. Clients will pass the |
|
634 // suggested output filename at rights import time to specify |
|
635 // the rights to delete. |
|
636 if (iClientSuggestedFileName == NULL) |
|
637 { |
|
638 ro.SetDeleteKeyL(KNullDesC8); |
|
639 } |
|
640 else |
|
641 { |
|
642 ro.SetDeleteKeyL(*iClientSuggestedFileName); |
|
643 } |
|
644 rightsServer.AddRightsL(ro); |
|
645 |
|
646 // write the receipt file |
|
647 iDrmRightsParser->DrmRightsL().Rights(0).WriteDescription(aFile); |
|
648 |
|
649 // Remove the rights object from our array |
|
650 iDrmRightsParser->DrmRightsL().Remove(0); |
|
651 CleanupStack::PopAndDestroy(&rightsServer); |
|
652 |
|
653 if(iDrmRightsParser->DrmRightsL().RightsCount() > 0) |
|
654 { |
|
655 User::Leave(KErrCANewFileHandleRequired); |
|
656 } |
|
657 } |
|
658 else |
|
659 { |
|
660 User::Leave(KErrNotFound); |
|
661 } |
|
662 } |
|
663 |
|
664 void CRefTestAgentImport::OutputContentL(RFile& aFile) |
|
665 { |
|
666 const TInt KBufSize = 512; |
|
667 HBufC8* hbuf = HBufC8::NewLC(KBufSize); |
|
668 TPtr8 bufptr = hbuf->Des(); |
|
669 |
|
670 // The content to output has been buffered in iFile. |
|
671 // Thus rewind iFile and then copy the contents of |
|
672 // iFile to aFile. |
|
673 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
674 TInt64 pos = 0; |
|
675 #else |
|
676 TInt pos = 0; |
|
677 #endif //SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
678 User::LeaveIfError( iFile.Seek(ESeekStart,pos) ); |
|
679 |
|
680 do |
|
681 { |
|
682 User::LeaveIfError(iFile.Read(bufptr)); |
|
683 User::LeaveIfError(aFile.Write(bufptr)); |
|
684 } |
|
685 while (bufptr.Length() == bufptr.MaxLength()); |
|
686 |
|
687 CleanupStack::PopAndDestroy(hbuf); |
|
688 aFile.Close(); |
|
689 iFile.Close(); |
|
690 |
|
691 iFs.Delete(*iTempOutFileName); |
|
692 delete iTempOutFileName; |
|
693 iTempOutFileName = NULL; |
|
694 } |
|
695 |
|
696 void CRefTestAgentImport::OpenTempOutFileL() |
|
697 { |
|
698 const TInt KMaxTry = 2048; |
|
699 _LIT(KRtaTempFileNameFmt, "%S%S%x%S"); |
|
700 |
|
701 TInt namelength = (*iRtaTempOutDir).Length() + |
|
702 KRtaTempOutFileName().Length() + |
|
703 4 + |
|
704 KRtaExtensionContent().Length(); |
|
705 |
|
706 delete iTempOutFileName; |
|
707 User::LeaveIfNull( iTempOutFileName = HBufC::New(namelength) ); |
|
708 |
|
709 TPtr des = iTempOutFileName->Des(); |
|
710 TInt ret = KErrAlreadyExists; |
|
711 |
|
712 for (TInt i = 1; (i <= KMaxTry) && (KErrAlreadyExists == ret); i++) |
|
713 { |
|
714 des.Format(KRtaTempFileNameFmt, iRtaTempOutDir, &KRtaTempOutFileName, i, &KRtaExtensionContent); |
|
715 ret = iFile.Create(iFs, des, EFileStream | EFileWrite); |
|
716 if (ret == KErrNone) |
|
717 { |
|
718 return; |
|
719 } |
|
720 } |
|
721 |
|
722 // C:\rta\tmpout1.content to C:\rta\tmpout800.content all exist! |
|
723 delete iTempOutFileName; |
|
724 iTempOutFileName = NULL; |
|
725 User::Leave(ret); |
|
726 } |
|
727 |
|
728 void CRefTestAgentImport::WriteIntL(TInt aLen) |
|
729 { |
|
730 TPckg<TInt> lengthPckg(aLen); |
|
731 User::LeaveIfError(iFile.Write(lengthPckg,lengthPckg.Length())); |
|
732 } |
|
733 |
|
734 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
735 void CRefTestAgentImport::WriteInt64L(TInt64 aLen) |
|
736 { |
|
737 TPckg<TInt64> lengthPckg(aLen); |
|
738 User::LeaveIfError(iFile.Write(lengthPckg,lengthPckg.Length())); |
|
739 } |
|
740 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
741 |
|
742 void CRefTestAgentImport::WriteDescriptorL(const TDesC8& aBuffer) |
|
743 { |
|
744 TInt length = aBuffer.Length(); |
|
745 WriteIntL(length); |
|
746 User::LeaveIfError(iFile.Write(aBuffer, length)); |
|
747 } |
|
748 |
|
749 |
|
750 EXPORT_C void CRefTestAgentImport::SetMetaDataL(const ContentAccess::CMetaDataArray& aMetaDataArray) |
|
751 { |
|
752 iRightObjectCid = aMetaDataArray.SearchL(_L8("Cid")).AllocL(); |
|
753 } |
|
754 |
|
755 EXPORT_C void CRefTestAgentImport::GetCurrentFileNameAndBuffer(TDes& aFileName, TDes8& aBuffer) |
|
756 { |
|
757 iFile.FullName(aFileName); |
|
758 ReadBuffer(aBuffer); |
|
759 } |
|
760 |
|
761 void CRefTestAgentImport::ReadBuffer(TDes8& aBuffer) |
|
762 { |
|
763 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
764 TInt64 originalPos = 0, startOffset = 0; |
|
765 #else |
|
766 TInt originalPos = 0, startOffset = 0; |
|
767 #endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API |
|
768 iFile.Seek(ESeekCurrent, originalPos); |
|
769 iFile.Seek(ESeekStart, startOffset); |
|
770 iFile.Read(aBuffer); |
|
771 iFile.Seek(ESeekStart, originalPos); |
|
772 } |
|
773 |
|
774 |