|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <msvstore.h> |
|
17 #include <f32file.h> |
|
18 |
|
19 #include "CMsvAttachmentManager.h" |
|
20 #include <mmsvstoremanager.h> |
|
21 #include "CCopyOneFile.h" |
|
22 #include "CMsvAttachmentRename.h" |
|
23 #include "TMsvServerStoreManager.h" |
|
24 |
|
25 const TUid KMsvEntryAttachmentInfo={0x10202D55}; |
|
26 _LIT(KTxtRenameLockFile, "_Rename_._"); |
|
27 |
|
28 CMsvAttachmentManager* CMsvAttachmentManager::NewL(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly) |
|
29 { |
|
30 CMsvAttachmentManager* me = new(ELeave) CMsvAttachmentManager(aStore, aStoreManager, aEntryId, aFs, aReadOnly); |
|
31 CleanupStack::PushL(me); |
|
32 me->ConstructL(); |
|
33 CleanupStack::Pop(me); |
|
34 return me; |
|
35 } |
|
36 |
|
37 CMsvAttachmentManager::CMsvAttachmentManager(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly) |
|
38 :CActive(EPriorityStandard), iStore(aStore), iStoreManager(aStoreManager), iEntryId(aEntryId), iFs(aFs), iReadOnly(aReadOnly) |
|
39 { |
|
40 CActiveScheduler::Add(this); |
|
41 } |
|
42 |
|
43 void CMsvAttachmentManager::ConstructL() |
|
44 { |
|
45 // Only need the CCopyOneFile if attachment is not readonly |
|
46 if( !iReadOnly ) |
|
47 iCopyOneFile = CCopyOneFile::NewL(iFs); |
|
48 |
|
49 // Populate the array of attachments from store file that contains all of the data |
|
50 RestoreL(); |
|
51 } |
|
52 |
|
53 CMsvAttachmentManager::~CMsvAttachmentManager() |
|
54 { |
|
55 Cancel(); |
|
56 |
|
57 // if we have any added attachments, these must be deleted as they have not been committed |
|
58 TInt addedAttachmentCount = iAddedAttachments.Count(); |
|
59 for( TInt ii=0; ii<addedAttachmentCount; ++ii ) |
|
60 { |
|
61 iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return code |
|
62 } |
|
63 |
|
64 iAddedAttachments.ResetAndDestroy(); |
|
65 iDeletedAttachments.ResetAndDestroy(); |
|
66 iAttachments.ResetAndDestroy(); |
|
67 iRenamed.ResetAndDestroy(); |
|
68 delete iCopyOneFile; |
|
69 } |
|
70 |
|
71 void CMsvAttachmentManager::RunL() |
|
72 { |
|
73 User::LeaveIfError(iStatus.Int()); |
|
74 |
|
75 User::RequestComplete(iReportStatus, KErrNone); |
|
76 } |
|
77 |
|
78 void CMsvAttachmentManager::DoCancel() |
|
79 { |
|
80 __ASSERT_DEBUG(iCopyOneFile!=NULL, User::Invariant()); |
|
81 |
|
82 if( iCopyOneFile->IsActive() ) |
|
83 iCopyOneFile->Cancel(); |
|
84 } |
|
85 |
|
86 TInt CMsvAttachmentManager::RunError(TInt aError) |
|
87 { |
|
88 // Asynchronous request only occur when an attachment is added |
|
89 // so delete the last added attachment |
|
90 TInt count = iAttachments.Count(); |
|
91 --count; |
|
92 if (count > 0) |
|
93 { |
|
94 delete iAttachments[count]; |
|
95 iAttachments.Remove(count); |
|
96 } |
|
97 |
|
98 count = iAddedAttachments.Count(); |
|
99 --count; |
|
100 if (count > 0) |
|
101 { |
|
102 delete iAddedAttachments[count]; |
|
103 iAddedAttachments.Remove(count); |
|
104 } |
|
105 User::RequestComplete(iReportStatus, aError); |
|
106 return KErrNone; |
|
107 } |
|
108 |
|
109 void CMsvAttachmentManager::CompleteSelf() |
|
110 { |
|
111 iStatus=KRequestPending; |
|
112 SetActive(); |
|
113 TRequestStatus* status = &iStatus; |
|
114 User::RequestComplete(status, KErrNone); |
|
115 } |
|
116 |
|
117 void CMsvAttachmentManager::RestoreL() |
|
118 { |
|
119 // Before loading, ensure that array is flushed out, all changes since last |
|
120 // store commit will be lost |
|
121 iAttachments.ResetAndDestroy(); |
|
122 iDeletedAttachments.ResetAndDestroy(); |
|
123 |
|
124 // if any added attachment file were added since the last commit, these must be removed |
|
125 TInt addedAttachmentCount = iAddedAttachments.Count(); |
|
126 for( TInt ii=0; ii<addedAttachmentCount; ++ii ) |
|
127 { |
|
128 iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return error |
|
129 } |
|
130 // All the added attachments have been cleaned up, reset the list |
|
131 iAddedAttachments.ResetAndDestroy(); |
|
132 |
|
133 // Only load the attachment info stream if one exists |
|
134 if(iStore.IsPresentL(KMsvEntryAttachmentInfo)) |
|
135 { |
|
136 RMsvReadStream readStream; |
|
137 readStream.OpenLC(iStore, KMsvEntryAttachmentInfo); |
|
138 |
|
139 // Read the data... |
|
140 // 1. the number of attachments |
|
141 TInt attachmentCount = readStream.ReadInt32L(); |
|
142 |
|
143 TFileName attachmentFilePath; |
|
144 |
|
145 // 2. populate the attachment array contents |
|
146 // for every object create and populate it from the stream |
|
147 for(TInt ii=0; ii<attachmentCount; ++ii) |
|
148 { |
|
149 // create empty attachment object, doesn't matter what type as the |
|
150 // correct attachment type is set when it is internalised |
|
151 CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); |
|
152 CleanupStack::PushL(attachment); |
|
153 readStream >> *attachment; |
|
154 if( attachment->IsPathRequired() ) |
|
155 { |
|
156 // The attachment path needs to be dynamically set, only get the file path if needed |
|
157 if( attachmentFilePath.Length()==0 ) |
|
158 { |
|
159 iStoreManager.AttachmentFilePathL(iEntryId, attachmentFilePath); |
|
160 } |
|
161 |
|
162 TParse fullPath; |
|
163 User::LeaveIfError(fullPath.Set(attachmentFilePath, &attachment->FilePath(), NULL)); |
|
164 attachment->SetFilePathL(fullPath.FullName()); |
|
165 } |
|
166 |
|
167 User::LeaveIfError(iAttachments.Append(attachment)); |
|
168 CleanupStack::Pop(attachment); |
|
169 } |
|
170 |
|
171 // 3. attachment id generator |
|
172 iIdGenerator = readStream.ReadUint32L(); |
|
173 |
|
174 CleanupStack::PopAndDestroy(&readStream); |
|
175 } |
|
176 |
|
177 // Restore any rename info from the rename lock file |
|
178 TInt err = InternaliseRenameLockL(); |
|
179 if( err==KErrNone ) |
|
180 { |
|
181 // lock file exists |
|
182 TInt currentIndex = iRenamed.Count(); |
|
183 while( currentIndex>0 ) |
|
184 { |
|
185 // We have some files that have been renamed and need to |
|
186 // be renamed back to the old name, these are renamed in |
|
187 // reverse order in case any one single attachment was |
|
188 // renamed twice before committing. |
|
189 --currentIndex; |
|
190 CMsvAttachmentRename* renameInfo = iRenamed[currentIndex]; |
|
191 iStoreManager.RenameAttachment(iEntryId, renameInfo->NewName(), renameInfo->OldName()); // ignore errors |
|
192 } |
|
193 |
|
194 iRenamed.ResetAndDestroy(); |
|
195 |
|
196 // delete the lock file as it no longer needed |
|
197 iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error |
|
198 } |
|
199 } |
|
200 |
|
201 void CMsvAttachmentManager::HandleCommitComplete() |
|
202 { |
|
203 // The attachments have been commited, the cache of added files can be removed |
|
204 iAddedAttachments.ResetAndDestroy(); |
|
205 |
|
206 // Any attachment files that are marked for delete, must be deleted from the message store |
|
207 TInt deleteAttachmentCount = iDeletedAttachments.Count(); |
|
208 for( TInt ii=0; ii<deleteAttachmentCount; ++ii ) |
|
209 { |
|
210 iStoreManager.DeleteAttachment(iEntryId, *iDeletedAttachments[ii]); // ignore errors |
|
211 } |
|
212 iDeletedAttachments.ResetAndDestroy(); |
|
213 |
|
214 // Remove the rename info as changes have been committed |
|
215 iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error |
|
216 iRenamed.ResetAndDestroy(); |
|
217 } |
|
218 |
|
219 void CMsvAttachmentManager::StoreL() |
|
220 { |
|
221 __ASSERT_DEBUG(iReadOnly==EFalse, User::Invariant()); |
|
222 |
|
223 TInt attachmentCount = iAttachments.Count(); |
|
224 |
|
225 // If there are no attachments, remove the stream |
|
226 if(attachmentCount==0) |
|
227 { |
|
228 iStore.Remove(KMsvEntryAttachmentInfo); |
|
229 } |
|
230 else |
|
231 { |
|
232 RMsvWriteStream writeStream; |
|
233 writeStream.AssignLC(iStore, KMsvEntryAttachmentInfo); |
|
234 |
|
235 // Write the data... |
|
236 // 1. the number of attachments |
|
237 writeStream.WriteInt32L(attachmentCount); |
|
238 |
|
239 // 2. save the attachment array contents |
|
240 // for every object create and populate it from the stream |
|
241 for(TInt ii=0; ii<attachmentCount; ++ii) |
|
242 { |
|
243 CMsvAttachment* attachment = iAttachments[ii]; |
|
244 writeStream << *attachment; |
|
245 } |
|
246 |
|
247 // 3. attachment id generator |
|
248 writeStream.WriteUint32L(iIdGenerator); |
|
249 |
|
250 writeStream.CommitL(); |
|
251 CleanupStack::PopAndDestroy(&writeStream); |
|
252 } |
|
253 } |
|
254 |
|
255 TMsvAttachmentId CMsvAttachmentManager::GenerateAttachmentId() |
|
256 { |
|
257 return ++iIdGenerator; |
|
258 } |
|
259 |
|
260 void CMsvAttachmentManager::CreateAttachmentInStoreLC(TDes& aFileName, RFile& aFile, CMsvAttachment* aAttachmentInfo, TBool aIsShareProtected) |
|
261 { |
|
262 if( aFileName.CompareF(KTxtRenameLockFile)==0 ) |
|
263 { |
|
264 // Cant add attachments using the same name as the rename lock file |
|
265 User::Leave(KErrBadName); |
|
266 } |
|
267 |
|
268 if(aIsShareProtected) |
|
269 { |
|
270 iStoreManager.CreateShareProtectedAttachmentForWriteL(iEntryId, aFileName, aFile); |
|
271 } |
|
272 else |
|
273 { |
|
274 iStoreManager.CreateAttachmentForWriteL(iEntryId, aFileName, aFile); |
|
275 } |
|
276 |
|
277 CleanupClosePushL(aFile); |
|
278 |
|
279 HBufC* addedFilePath = aFileName.AllocLC(); |
|
280 User::LeaveIfError(iAddedAttachments.Append(addedFilePath)); |
|
281 CleanupStack::Pop(addedFilePath); |
|
282 |
|
283 // initailise attachment info and take ownership |
|
284 aAttachmentInfo->SetFilePathL(aFileName); |
|
285 User::LeaveIfError(iAttachments.Append(aAttachmentInfo)); |
|
286 aAttachmentInfo->SetId(GenerateAttachmentId()); |
|
287 } |
|
288 |
|
289 void CMsvAttachmentManager::AddAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
290 { |
|
291 if(iReadOnly) |
|
292 User::Leave(KErrAccessDenied); |
|
293 |
|
294 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant()); |
|
295 |
|
296 RFile fileToCopy; |
|
297 User::LeaveIfError(fileToCopy.Open(iFs, aFilePath, EFileRead|EFileShareReadersOnly)); |
|
298 CleanupClosePushL(fileToCopy); |
|
299 |
|
300 TFileName fileName; |
|
301 User::LeaveIfError(fileToCopy.Name(fileName)); |
|
302 |
|
303 RFile newFileHandle; |
|
304 CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse); |
|
305 |
|
306 aStatus=KRequestPending; |
|
307 iReportStatus=&aStatus; |
|
308 |
|
309 iCopyOneFile->Copy(fileToCopy, newFileHandle, iStatus); |
|
310 CleanupStack::Pop(2, &fileToCopy); // newFileHandle, fileToCopy |
|
311 SetActive(); |
|
312 } |
|
313 |
|
314 void CMsvAttachmentManager::AddAttachmentL(RFile& aFileHandle, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
315 { |
|
316 if(iReadOnly) |
|
317 User::Leave(KErrAccessDenied); |
|
318 |
|
319 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant()); |
|
320 |
|
321 TFileName fileName; |
|
322 User::LeaveIfError(aFileHandle.Name(fileName)); |
|
323 |
|
324 RFile newFileHandle; |
|
325 CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse); |
|
326 |
|
327 aStatus=KRequestPending; |
|
328 iReportStatus=&aStatus; |
|
329 |
|
330 iCopyOneFile->Copy(aFileHandle, newFileHandle, iStatus); |
|
331 CleanupStack::Pop(&newFileHandle); |
|
332 SetActive(); |
|
333 } |
|
334 |
|
335 void CMsvAttachmentManager::AddLinkedAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
336 { |
|
337 if(iReadOnly) |
|
338 User::Leave(KErrAccessDenied); |
|
339 |
|
340 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvLinkedFile, User::Invariant()); |
|
341 |
|
342 // initailise attachment info and take ownership |
|
343 aAttachmentInfo->SetFilePathL(aFilePath); |
|
344 User::LeaveIfError(iAttachments.Append(aAttachmentInfo)); |
|
345 aAttachmentInfo->SetId(GenerateAttachmentId()); |
|
346 |
|
347 aStatus=KRequestPending; |
|
348 iReportStatus=&aStatus; |
|
349 CompleteSelf(); |
|
350 } |
|
351 |
|
352 void CMsvAttachmentManager::AddEntryAsAttachmentL(TMsvId aEntryId, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
353 { |
|
354 if(iReadOnly) |
|
355 User::Leave(KErrAccessDenied); |
|
356 |
|
357 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvMessageEntry, User::Invariant()); |
|
358 |
|
359 // initailise attachment info and take ownership |
|
360 User::LeaveIfError(iAttachments.Append(aAttachmentInfo)); |
|
361 aAttachmentInfo->SetId(GenerateAttachmentId()); |
|
362 aAttachmentInfo->SetEntryAttachmentId(aEntryId); |
|
363 |
|
364 aStatus=KRequestPending; |
|
365 iReportStatus=&aStatus; |
|
366 User::RequestComplete(iReportStatus, KErrNone); |
|
367 } |
|
368 |
|
369 void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
370 { |
|
371 CreateAttachmentL(aFileName, aAttachmentFile, aAttachmentInfo); |
|
372 |
|
373 aStatus=KRequestPending; |
|
374 iReportStatus=&aStatus; |
|
375 CompleteSelf(); |
|
376 } |
|
377 |
|
378 |
|
379 TInt CMsvAttachmentManager::AttachmentCount() const |
|
380 { |
|
381 return iAttachments.Count(); |
|
382 } |
|
383 |
|
384 CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TInt aIndex) |
|
385 { |
|
386 // Create a deep copy the CMsvAttachment object to pass back to the client |
|
387 CMsvAttachment* currentAttachment = iAttachments[aIndex]; |
|
388 |
|
389 return CMsvAttachment::NewL(*currentAttachment); |
|
390 } |
|
391 |
|
392 CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TMsvAttachmentId aId) |
|
393 { |
|
394 return GetAttachmentInfoL(IndexPositionOfAttachmentL(aId)); |
|
395 } |
|
396 |
|
397 void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo) |
|
398 { |
|
399 if(iReadOnly) |
|
400 User::Leave(KErrAccessDenied); |
|
401 |
|
402 // Get the index position of the attachment info with the same Id |
|
403 TInt attachmentIndex = IndexPositionOfAttachmentL(aAttachmentInfo->Id()); |
|
404 __ASSERT_ALWAYS(aAttachmentInfo->Type()==iAttachments[attachmentIndex]->Type(), User::Invariant()); |
|
405 |
|
406 // Insert the replaced attachment info object into the same position and then |
|
407 // remove the old one |
|
408 User::LeaveIfError(iAttachments.Insert(aAttachmentInfo, attachmentIndex)); |
|
409 ++attachmentIndex; |
|
410 delete iAttachments[attachmentIndex]; |
|
411 iAttachments.Remove(attachmentIndex); |
|
412 } |
|
413 |
|
414 void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) |
|
415 { |
|
416 ModifyAttachmentInfoL(aAttachmentInfo); |
|
417 aStatus=KRequestPending; |
|
418 iReportStatus=&aStatus; |
|
419 CompleteSelf(); |
|
420 } |
|
421 |
|
422 RFile CMsvAttachmentManager::GetAttachmentFileL(TInt aIndex) |
|
423 { |
|
424 CMsvAttachment* attachment = iAttachments[aIndex]; |
|
425 |
|
426 // Make sure that the attachment is a file attachment |
|
427 if( attachment->Type() == CMsvAttachment::EMsvMessageEntry ) |
|
428 User::Leave(KErrNotSupported); |
|
429 |
|
430 RFile attachmentFile; |
|
431 |
|
432 if( attachment->Type() == CMsvAttachment::EMsvFile ) |
|
433 { |
|
434 iStoreManager.OpenAttachmentL(iEntryId, attachment->FilePath(), attachmentFile); |
|
435 } |
|
436 else // attachment->iType == ELinkedFile |
|
437 { |
|
438 RFs fs; |
|
439 fs.Connect(); |
|
440 fs.ShareProtected(); |
|
441 User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileRead | EFileShareReadersOnly)); |
|
442 } |
|
443 |
|
444 // handle to attachment file allocated, return to caller |
|
445 return attachmentFile; |
|
446 } |
|
447 |
|
448 RFile CMsvAttachmentManager::GetAttachmentFileL(TMsvAttachmentId aId) |
|
449 { |
|
450 return GetAttachmentFileL(IndexPositionOfAttachmentL(aId)); |
|
451 } |
|
452 |
|
453 RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TInt aIndex) |
|
454 { |
|
455 if(iReadOnly) |
|
456 User::Leave(KErrAccessDenied); |
|
457 |
|
458 CMsvAttachment* attachment = iAttachments[aIndex]; |
|
459 |
|
460 // Make sure that the attachment is a file attachment |
|
461 if( attachment->Type() == CMsvAttachment::EMsvMessageEntry ) |
|
462 User::Leave(KErrNotSupported); |
|
463 |
|
464 RFile attachmentFile; |
|
465 |
|
466 if( attachment->Type() == CMsvAttachment::EMsvFile ) |
|
467 { |
|
468 iStoreManager.OpenAttachmentForWriteL(iEntryId, attachment->FilePath(), attachmentFile); |
|
469 } |
|
470 else // attachment->iType == ELinkedFile |
|
471 { |
|
472 RFs fs; |
|
473 fs.Connect(); |
|
474 fs.ShareProtected(); |
|
475 User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileWrite)); |
|
476 } |
|
477 |
|
478 // handle to attachment file allocated, return to caller |
|
479 return attachmentFile; |
|
480 } |
|
481 |
|
482 RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TMsvAttachmentId aId) |
|
483 { |
|
484 return GetAttachmentFileForWriteL(IndexPositionOfAttachmentL(aId)); |
|
485 } |
|
486 |
|
487 void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex, TRequestStatus& aStatus) |
|
488 { |
|
489 RemoveAttachmentL(aIndex); |
|
490 |
|
491 aStatus=KRequestPending; |
|
492 iReportStatus=&aStatus; |
|
493 CompleteSelf(); |
|
494 } |
|
495 |
|
496 void CMsvAttachmentManager::RemoveAttachmentL(TMsvAttachmentId aId, TRequestStatus& aStatus) |
|
497 { |
|
498 RemoveAttachmentL(IndexPositionOfAttachmentL(aId), aStatus); |
|
499 } |
|
500 |
|
501 TInt CMsvAttachmentManager::IndexPositionOfAttachmentL(TMsvAttachmentId aId) const |
|
502 { |
|
503 TInt foundPosition = KErrNotFound; |
|
504 TInt attachmentCount = iAttachments.Count(); |
|
505 // Go through the attachment list to find the attachment by its id |
|
506 for( TInt ii=0; ii<attachmentCount; ++ii ) |
|
507 { |
|
508 if( iAttachments[ii]->Id() == aId ) |
|
509 { |
|
510 foundPosition = ii; |
|
511 break; |
|
512 } |
|
513 } |
|
514 |
|
515 // Leave with KErrNotFound if the attachment id is not found |
|
516 User::LeaveIfError(foundPosition); |
|
517 |
|
518 // return the index position of attachment |
|
519 return foundPosition; |
|
520 } |
|
521 |
|
522 void CMsvAttachmentManager::CancelRequest() |
|
523 { |
|
524 Cancel(); |
|
525 User::RequestComplete(iReportStatus, KErrCancel); |
|
526 } |
|
527 |
|
528 void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo) |
|
529 { |
|
530 if(iReadOnly) |
|
531 User::Leave(KErrAccessDenied); |
|
532 |
|
533 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant()); |
|
534 |
|
535 // File name must be provided |
|
536 if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle) |
|
537 User::Leave(KErrArgument); |
|
538 |
|
539 TFileName fileName = aFileName; |
|
540 |
|
541 CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, EFalse); |
|
542 CleanupStack::Pop(&aAttachmentFile); |
|
543 } |
|
544 |
|
545 void CMsvAttachmentManager::CreateShareProtectedAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo) |
|
546 { |
|
547 if(iReadOnly) |
|
548 User::Leave(KErrAccessDenied); |
|
549 |
|
550 __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant()); |
|
551 |
|
552 // File name must be provided |
|
553 if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle) |
|
554 User::Leave(KErrArgument); |
|
555 |
|
556 TFileName fileName = aFileName; |
|
557 |
|
558 CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, ETrue); |
|
559 CleanupStack::Pop(&aAttachmentFile); |
|
560 } |
|
561 |
|
562 TInt CMsvAttachmentManager::InternaliseRenameLockL() |
|
563 { |
|
564 iRenamed.ResetAndDestroy(); |
|
565 |
|
566 // if the rename lock file exists internalise it |
|
567 RFile renameLockFile; |
|
568 TRAPD(err, iStoreManager.OpenAttachmentL(iEntryId, KTxtRenameLockFile, renameLockFile)); |
|
569 if( err==KErrNone ) |
|
570 { |
|
571 // got the rename lock file |
|
572 RFileReadStream renameReadStream(renameLockFile); |
|
573 renameReadStream.PushL(); |
|
574 TInt renamedCount = renameReadStream.ReadInt32L(); |
|
575 for( TInt ii=0; ii<renamedCount; ++ii ) |
|
576 { |
|
577 CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC(); |
|
578 renameReadStream >> *renameInfo; |
|
579 iRenamed.AppendL(renameInfo); |
|
580 CleanupStack::Pop(renameInfo); |
|
581 } |
|
582 CleanupStack::PopAndDestroy(); // renameReadStream |
|
583 } |
|
584 else if( err==KErrNotFound || err==KErrPathNotFound ) |
|
585 { |
|
586 err = KErrNotFound; // rename lock file not found |
|
587 } |
|
588 else |
|
589 { |
|
590 User::Leave(err); |
|
591 } |
|
592 |
|
593 return err; |
|
594 } |
|
595 |
|
596 void CMsvAttachmentManager::ExternaliseRenameLockL() |
|
597 { |
|
598 __ASSERT_DEBUG(iRenamed.Count()>0, User::Invariant()); |
|
599 |
|
600 // Get the rename lock file to store the rename information |
|
601 RFile renameLockFile; |
|
602 TFileName lockFileName(KTxtRenameLockFile()); |
|
603 iStoreManager.ReplaceAttachmentForWriteL(iEntryId, lockFileName, renameLockFile); |
|
604 RFileWriteStream renameWriteStream(renameLockFile); |
|
605 renameWriteStream.PushL(); |
|
606 |
|
607 // Externalise the count and each rename file info object |
|
608 TInt renamedCount = iRenamed.Count(); |
|
609 renameWriteStream.WriteInt32L(renamedCount); |
|
610 for( TInt ii=0; ii<renamedCount; ++ii ) |
|
611 { |
|
612 renameWriteStream << *(iRenamed[ii]); |
|
613 } |
|
614 |
|
615 renameWriteStream.CommitL(); |
|
616 CleanupStack::PopAndDestroy(); // renameWriteStream |
|
617 } |
|
618 |
|
619 void CMsvAttachmentManager::DoAttachmentRenameL(TInt aIndex, const TDesC& aNewName) |
|
620 { |
|
621 if(iReadOnly) |
|
622 { |
|
623 User::Leave(KErrAccessDenied); |
|
624 } |
|
625 |
|
626 CMsvAttachment* renameAttachment = iAttachments[aIndex]; |
|
627 __ASSERT_ALWAYS(renameAttachment->Type() == CMsvAttachment::EMsvFile, User::Invariant()); |
|
628 |
|
629 // Build the attachment rename infomation and store in array |
|
630 TPtrC oldFilePath(renameAttachment->FilePath()); |
|
631 CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC(oldFilePath, aNewName); |
|
632 iRenamed.AppendL(renameInfo); |
|
633 CleanupStack::Pop(renameInfo); |
|
634 |
|
635 // Save the rename infomation |
|
636 ExternaliseRenameLockL(); |
|
637 |
|
638 // Rename and update the attachment info |
|
639 TParse newFilePath; |
|
640 User::LeaveIfError(newFilePath.Set(aNewName, &oldFilePath, NULL)); |
|
641 User::LeaveIfError(iStoreManager.RenameAttachment(iEntryId, oldFilePath, aNewName)); |
|
642 renameAttachment->SetFilePathL(newFilePath.FullName()); |
|
643 } |
|
644 |
|
645 void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName) |
|
646 { |
|
647 DoAttachmentRenameL(aIndex, aNewName); |
|
648 } |
|
649 |
|
650 void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName, TRequestStatus& aStatus) |
|
651 { |
|
652 DoAttachmentRenameL(aIndex, aNewName); |
|
653 |
|
654 aStatus=KRequestPending; |
|
655 iReportStatus=&aStatus; |
|
656 User::RequestComplete(iReportStatus, KErrNone); |
|
657 } |
|
658 |
|
659 void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex) |
|
660 { |
|
661 if(iReadOnly) |
|
662 User::Leave(KErrAccessDenied); |
|
663 |
|
664 // If the attachment is a file attachment, we need remove the attachment object |
|
665 // and mark the file for deletion so that it is deleted only when SaveL is called. |
|
666 // This ensures that if the store is reverted, the attachment files are still in |
|
667 // the message store |
|
668 CMsvAttachment* deleteAttachment = iAttachments[aIndex]; |
|
669 |
|
670 // only need to mark the file for deletion if it is an attachment stored in the |
|
671 // message server, ie. dont delete linked attachments |
|
672 if( deleteAttachment->Type() == CMsvAttachment::EMsvFile ) |
|
673 { |
|
674 HBufC* deleteFilePath = deleteAttachment->FilePath().AllocLC(); |
|
675 User::LeaveIfError(iDeletedAttachments.Append(deleteFilePath)); |
|
676 CleanupStack::Pop(deleteFilePath); |
|
677 } |
|
678 |
|
679 iAttachments.Remove(aIndex); |
|
680 delete deleteAttachment; |
|
681 } |
|
682 |