messagingfw/msgsrvnstore/server/src/MSVSTORE.CPP
changeset 0 8e480a14352b
child 44 7c176670643f
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 1998-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 // MSVSTORE.CPP
       
    15 //
       
    16 
       
    17 #include <txtrich.h>
       
    18 
       
    19 
       
    20 #include "MSVSTD.H"
       
    21 #include "MSVSTORE.H"
       
    22 #include "MSVPANIC.H"
       
    23 #include "CMsvCachedStore.h"
       
    24 #include "cmsvbodytext.h"
       
    25 #include <cmsvplainbodytext.h>
       
    26 #include "CMsvAttachmentManager.h"
       
    27 #include <cmsvattachment.h>
       
    28 #include <charconv.h>
       
    29 #include <escapeutils.h>
       
    30 #include <mmsvstoremanager.h>
       
    31 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
       
    32 #include "msvconsts.h"
       
    33 #endif
       
    34 
       
    35 
       
    36 //
       
    37 // CMsvStore
       
    38 //
       
    39 const TUint8 KCarriageReturn = 0x0D;
       
    40 const TUint8 KLineFeed       = 0x0A;
       
    41 
       
    42 EXPORT_C CMsvStore::~CMsvStore()
       
    43 //
       
    44 //
       
    45 //
       
    46 /** Destructor.
       
    47 
       
    48 If the message store is currently locked, the destructor releases it before 
       
    49 deleting the object. */
       
    50 	{
       
    51 	// tell the observer that this store is being released/closed
       
    52 	if (iConstructed)
       
    53 		{
       
    54 		// only inform server if the store was successfully opened
       
    55 		if (iLockStatus==EMsvStoreLocked)
       
    56 			iObserver.HandleStoreEvent(MMsvStoreObserver::EMsvEditStoreClosed, iId);
       
    57 		else
       
    58 			iObserver.HandleStoreEvent(MMsvStoreObserver::EMsvReadStoreClosed, iId);
       
    59 		}
       
    60 
       
    61 	delete iAttachmentManager;
       
    62 
       
    63 	delete iStore;
       
    64 	delete iBodyText;
       
    65 	}
       
    66 
       
    67 EXPORT_C void CMsvStore::StoreBodyTextL(const CRichText& aRichTextBody)
       
    68 //
       
    69 // stores and commits body text to the file store, overwriting any existing data
       
    70 // will panic if the store is unlocked and will leave if no store is found
       
    71 //
       
    72 /** Stores the body text stream of the message store. Any existing 
       
    73 data is overwritten. Write access is needed for this function. A commit must be done
       
    74 following this function for the new data to be retained.
       
    75 
       
    76 @param aRichTextBody The body data to be externalised 
       
    77 @leave KErrAccessDenied Store is not open for writing 
       
    78 @leave Other Standard streaming leave codes */
       
    79 	{
       
    80 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
    81 		User::Leave(KErrAccessDenied);
       
    82 
       
    83 	iBodyText->RemoveL(*this);
       
    84 	
       
    85 	// Remove the body text data if stored in KMsvPlainBodyText8 or KMsvPlainBodyText16 format.
       
    86 	if (IsPresentL(KMsvPlainBodyText8))
       
    87 		{
       
    88 		RemoveL(KMsvPlainBodyText8);
       
    89 		}
       
    90 	if (IsPresentL(KMsvPlainBodyText16))
       
    91 		{
       
    92 		RemoveL(KMsvPlainBodyText16);
       
    93 		}
       
    94 	
       
    95 	RMsvWriteStream out;
       
    96 	out.AssignL(*this,KMsvEntryRichTextBody);
       
    97 	CEmbeddedStore* embeddedStore=CEmbeddedStore::NewLC(out);
       
    98 	TStreamId streamId=aRichTextBody.StoreL(*embeddedStore);
       
    99 	embeddedStore->SetRootL(streamId);
       
   100 	embeddedStore->CommitL();
       
   101 	CleanupStack::PopAndDestroy(); //embeddedstore
       
   102 	}
       
   103 
       
   104 void CMsvStore::Lock()
       
   105 	{
       
   106 	iLockStatus=EMsvStoreLocked;
       
   107 	}
       
   108 
       
   109 EXPORT_C TBool CMsvStore::IsNullL() const
       
   110 /** Tests whether the message store contains any streams.
       
   111 @return ETrue if the store has no streams, else EFalse
       
   112 */
       
   113 	{
       
   114 	return iStore->IsNullL();		
       
   115 	}
       
   116 
       
   117 EXPORT_C TBool CMsvStore::IsPresentL(TUid aUid) const
       
   118 /** Tests whether the message store contains a stream identifier.
       
   119 Do not use to check if there is a body text part stored with the email;
       
   120 use CMsvStore::HasBodyTextL() instead.
       
   121 @param aUid Identifier of stream 
       
   122 @return ETrue if the store has a stream aUid, else EFalse 
       
   123  */
       
   124 	{
       
   125 	return iStore->IsPresentL(aUid);
       
   126 	}
       
   127 	
       
   128 
       
   129 EXPORT_C TBool CMsvStore::HasBodyTextL() const
       
   130 /** Checks if the store has a body text stream; IsPresentL(KMsvEntryRichTextBody)
       
   131 will always return EFalse when the store_8bit_flag in imcm.rss is enabled.
       
   132 @return ETrue if the store has a body text stream, else EFalse 
       
   133 */
       
   134 	{
       
   135 	return iStore->IsPresentL(KMsvEntryRichTextBody) || iBodyText->IsPresentL(*this)|| iStore->IsPresentL(KMsvPlainBodyText8)|| iStore->IsPresentL(KMsvPlainBodyText16);
       
   136 	}
       
   137 
       
   138 /**
       
   139 Restores body text into the given rich text object - doesnt matter if store is locked or not
       
   140 will leave if the file store doesn't exist, the body text does not exist, and also propagate store leaves
       
   141 Reads the body text stream from the message store into the given rich text 
       
   142 object. 
       
   143 @param aRichTextBody 	On return, the message store's body text is inserted 
       
   144 						into this object. Any previously existing contents is lost. 
       
   145 @leave KErrNotFound 	There is no body text stream in the store 
       
   146 @leave Other Standard streaming leave codes 
       
   147 */
       
   148 EXPORT_C void CMsvStore::RestoreBodyTextL(CRichText& aRichTextBody)
       
   149 	{
       
   150 	// Charset set to 0 so that RestoreBodyTextL works as per existing published behaviour.
       
   151 	RestoreBodyTextL(aRichTextBody, 0);
       
   152 	}
       
   153 
       
   154 /**
       
   155 Restores body text into the given rich text object - doesnt matter if store is locked or not.
       
   156 Reads the body text stream from the message store into the given rich text 
       
   157 object.
       
   158 @param aRichTextBody 		On return, the message store's body text is inserted 
       
   159 							into this object. Any previously existing contents is lost. 
       
   160 @param aCharsetOverride   	The charset with which to override the existing charset 
       
   161 							when data is stored a 8 bit format. 
       
   162 @leave KErrNotFound 		There is no body text stream in the store 
       
   163 @leave Other Standard streaming leave codes 
       
   164 */
       
   165 EXPORT_C void CMsvStore::RestoreBodyTextL(CRichText& aRichTextBody, TUint aCharsetOverride)
       
   166 	{
       
   167 	if (iStore==NULL )
       
   168 		{
       
   169 		User::Leave(KErrNotFound);
       
   170 		}
       
   171 
       
   172 	if (IsPresentL(KMsvEntryRichTextBody))
       
   173 		{
       
   174 		RMsvReadStream inputStream;
       
   175 		inputStream.OpenL(*this, KMsvEntryRichTextBody); // CEmbeddedStore::FromLC() take ownership
       
   176 		CEmbeddedStore* embeddedStore = CEmbeddedStore::FromLC(inputStream);
       
   177 		aRichTextBody.RestoreL(*embeddedStore, embeddedStore->Root());
       
   178 		CleanupStack::PopAndDestroy();	// embeddedStore
       
   179 		}
       
   180 	else if(iBodyText->IsPresentL(*this))
       
   181 		{
       
   182 		iBodyText->RestoreL(*this);
       
   183 		// If a new charset was set, override the  restored charset
       
   184 		// so that data is converted using new charset.
       
   185 		if(aCharsetOverride != 0)
       
   186 			{
       
   187 			iBodyText->SetCharacterSet(aCharsetOverride);
       
   188 			}
       
   189 		iBodyText->GetBodyTextL(iFs, *this, aRichTextBody);
       
   190 		}
       
   191 	else
       
   192 		{
       
   193 		if(IsPresentL(KMsvPlainBodyText8) || IsPresentL(KMsvPlainBodyText16))
       
   194 			{
       
   195 			RestorePlainBodyTextL (aRichTextBody, aCharsetOverride);
       
   196 			}
       
   197 		else		
       
   198 			{
       
   199 			User::Leave(KErrNotFound);
       
   200 			}
       
   201 		}
       
   202 	}
       
   203 
       
   204 
       
   205 
       
   206 
       
   207 /**
       
   208 Restores a CRichText object from the plain body text file.
       
   209 @param aRichText 			On completion this contains the plain body text.
       
   210 @param aCharsetOverride 	The new charset with which to override the existing charset 
       
   211 							when data is stored a 8 bit plain text format. 
       
   212 @return void.
       
   213 */
       
   214 void CMsvStore::RestorePlainBodyTextL(CRichText& aRichText, TUint aCharsetOverride)
       
   215 	{
       
   216 	RMsvReadStream inputStream;
       
   217 	TBool is8Bit = EFalse;
       
   218 	TUint charSet = 0;
       
   219 	TUint defaultCharSet = 0;
       
   220 	if(IsPresentL(KMsvPlainBodyText8))
       
   221 		{
       
   222 		inputStream.OpenLC(*this, KMsvPlainBodyText8);
       
   223 		charSet = inputStream.ReadUint32L();
       
   224 		defaultCharSet = inputStream.ReadUint32L();
       
   225 		is8Bit = ETrue;
       
   226 		}
       
   227 	else
       
   228 		{
       
   229 		inputStream.OpenLC(*this, KMsvPlainBodyText16);
       
   230 		}
       
   231 	// If a new charset was set, override the  restored charset so that 
       
   232 	// data is converted using new charset.
       
   233 	if(aCharsetOverride!=0)
       
   234 		{
       
   235 		charSet = aCharsetOverride;
       
   236 		}
       
   237 	
       
   238 	TBool committed = inputStream.ReadUint32L();
       
   239 	TFileName filePath;
       
   240 	HBufC* fileName = HBufC::NewLC(inputStream, KMaxFileName);	
       
   241 	RFile bodyTextFile;
       
   242 	CleanupClosePushL(bodyTextFile);
       
   243 	
       
   244 	iStoreManager.BodyTextFilePathL(iId, filePath);
       
   245 
       
   246 	filePath.Append(*fileName);
       
   247 	iStoreManager.OpenBodyTextFileForReadL(bodyTextFile, iId, filePath);
       
   248 	if(is8Bit)
       
   249 		{
       
   250 		GetRichTextFrom8BitL(bodyTextFile, aRichText, charSet, defaultCharSet);
       
   251 		}
       
   252 	else
       
   253 		{
       
   254 		GetRichTextFrom16BitL(bodyTextFile, aRichText);
       
   255 		}
       
   256 
       
   257 	CleanupStack::PopAndDestroy(3, &inputStream);//bodyTextFile,fileName,in
       
   258 	}
       
   259 /**	
       
   260 Restores 8 bit body text from the Message Store
       
   261 @param aInputStream		on completion the RFileReadStream contains the message body text stream.
       
   262 */
       
   263 void CMsvStore::Restore8BitBodyTextL(RFileReadStream& aInputStream)
       
   264 	{
       
   265 	RMsvReadStream in;
       
   266 	in.OpenLC(*this, KMsvPlainBodyText8);
       
   267 	in.ReadUint32L();	// reads charset
       
   268 	in.ReadUint32L();	// read default charset
       
   269 	in.ReadUint32L();	// returns ETrue if committed to message store else EFalse
       
   270 	TFileName filePath;
       
   271 	HBufC* fileName = HBufC::NewLC(in, KMaxFileName);
       
   272 	RFile bodyTextFile;
       
   273 	CleanupClosePushL(bodyTextFile);
       
   274 	iStoreManager.BodyTextFilePathL(iId, filePath);
       
   275 	filePath.Append(*fileName);
       
   276 	iStoreManager.OpenBodyTextFileForReadL(bodyTextFile, iId, filePath);
       
   277 	aInputStream.Attach(bodyTextFile, 0);
       
   278 	CleanupStack::PopAndDestroy(3, &in);	// bodyTextFile, fileName, in
       
   279 	}	
       
   280 	
       
   281 /**
       
   282 Gets CRichText from plain body text file if data stored as 8 bit.
       
   283 @param aFile 			The file containing the plain body text.
       
   284 @param aRichText 		The CRichText object that will be filled on return.
       
   285 @param aCharSet 		The charset of the body part.
       
   286 @param aDefaultCharSet  The default charset of the system.
       
   287 @return void.
       
   288 */	
       
   289 void CMsvStore::GetRichTextFrom8BitL(RFile& aBodyTextFile, CRichText& aRichText, TUint aCharSet, TUint aDefaultCharSet)
       
   290 	{
       
   291 	Convert8BitToRichTextL(aBodyTextFile, aRichText, aCharSet, aDefaultCharSet);
       
   292 	}
       
   293 
       
   294 
       
   295 /**
       
   296 Gets CRichText from plain body text file if data stored as 16 bit.
       
   297 @param aFile 	  The file containing the plain body text.
       
   298 @param aRichText  The CRichText object that will be filled on return.
       
   299 @return void.
       
   300 */
       
   301 void CMsvStore::GetRichTextFrom16BitL(RFile& aBodyTextFile, CRichText& aRichText)
       
   302 	{
       
   303 	TInt size = 0;
       
   304 	aBodyTextFile.Size(size);
       
   305 	TBuf8<KMsvDecodeChunkLength> buf;
       
   306 	TBool carriageReturn = EFalse;
       
   307 	while(size > 0)
       
   308 		{
       
   309 		aBodyTextFile.Read(buf);
       
   310 		// Divide by 2 since the 16-bit buffer was stored using 8-bit pointer.
       
   311 		TPtrC16 bodyTextPtr((TUint16*)(buf.Ptr()), buf.Length()/2); 
       
   312 
       
   313 		// Was the last character of the last block a carriage return.
       
   314 		// If so we need to check for the specific condition where the carriage
       
   315 		// return / line feed has been split across blocks in which case the line
       
   316 		// feed should be discarded and the special character ELineBreak inserted
       
   317 		// instead. If the first character of this new block is not line feed
       
   318 		// then we should insert the carriage return as it is required in the
       
   319 		// output data and has not been added yet.
       
   320 		if (carriageReturn)
       
   321 			{
       
   322 			if (bodyTextPtr[0] == KLineFeed)
       
   323 				{
       
   324 				aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
       
   325 				bodyTextPtr.Set(bodyTextPtr.Mid(1));
       
   326 				}
       
   327 			else
       
   328 				{
       
   329 				aRichText.InsertL(aRichText.DocumentLength(), TChar(KCarriageReturn));
       
   330 				}
       
   331 
       
   332 			carriageReturn = EFalse;
       
   333 			}
       
   334 
       
   335 		TInt start = 0;
       
   336 		TInt len = bodyTextPtr.Length();
       
   337 		TInt i = 0;
       
   338 			
       
   339 		// Insert the data read from the RFile to CRichText.If there is CRLF insert 
       
   340 		// CEditableText::ELineBreak  
       
   341 		for(i=1; i<len; ++i)
       
   342 			{
       
   343 			// This will get data from RFile line by line and insert it to CRichText.
       
   344 			if(bodyTextPtr[i-1] == KCarriageReturn && bodyTextPtr[i] == KLineFeed)
       
   345 				{
       
   346 				TPtrC ptr = bodyTextPtr.Mid(start, (i-1)-start);
       
   347 				aRichText.InsertL(aRichText.DocumentLength(), ptr);
       
   348 				aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
       
   349 				start = i+1;
       
   350 				}
       
   351 			}
       
   352 		// We have inserted a line to the CRichText object, there were some more data left in
       
   353 		// bodyTextPtr, so insert rest of it to CRichText.
       
   354 		if (start != i)
       
   355 			{
       
   356 			// If last character is KCarriageReturn.
       
   357 			if(bodyTextPtr[len - 1] == KCarriageReturn)
       
   358 				{
       
   359 				carriageReturn = ETrue;
       
   360 				TPtrC ptr1 = bodyTextPtr.Mid(start, (i-1)-start);
       
   361 		    	aRichText.InsertL(aRichText.DocumentLength(), ptr1);
       
   362 				}
       
   363 			else
       
   364 				{
       
   365 				TPtrC ptr2 = bodyTextPtr.Mid(start, i-start);
       
   366 		    	aRichText.InsertL(aRichText.DocumentLength(), ptr2);
       
   367 				}
       
   368 			
       
   369 			}
       
   370 		size -= buf.Length();
       
   371 		}
       
   372 
       
   373 	// If the last character of the text was a carriage return, then we won't
       
   374 	// have added it because we were waiting to check what the start of the next
       
   375 	// block was. As there are no more blocks, the carriage return needs to be 
       
   376 	// added now.
       
   377 	if (carriageReturn)
       
   378 		{
       
   379 		aRichText.InsertL(aRichText.DocumentLength(), TChar(KCarriageReturn));
       
   380 		}
       
   381 	}
       
   382 
       
   383 /**
       
   384 Converts 8 bit data to Unicode and inserts to the CRichText object.
       
   385 @param aFile 			The file containing the plain body text.
       
   386 @param aRichText 		The CRichText object that will be filled on return.
       
   387 @param aCharSet 		The charset of the body part.
       
   388 @param aDefaultCharSet  The default charset of the system.
       
   389 @return void.
       
   390 */
       
   391 void CMsvStore::Convert8BitToRichTextL(RFile& aBodyTextFile, CRichText& aRichText, TUint aCharSet, TUint aDefaultCharSet)
       
   392 	{
       
   393 	RFileReadStream inputStream(aBodyTextFile);
       
   394 	inputStream.PushL();
       
   395 	MStreamBuf* sourceStream = inputStream.Source();
       
   396 	
       
   397 	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewL();
       
   398 	CleanupStack::PushL(converter);
       
   399 	
       
   400 	CCnvCharacterSetConverter::TAvailability available = CCnvCharacterSetConverter::ENotAvailable;
       
   401 
       
   402 	if (aCharSet != 0)
       
   403 		{
       
   404 		available = converter->PrepareToConvertToOrFromL(aCharSet, iFs);
       
   405 		} 
       
   406 	if (available == CCnvCharacterSetConverter::ENotAvailable)
       
   407 		{
       
   408 		available = converter->PrepareToConvertToOrFromL(aDefaultCharSet, iFs);
       
   409 		}
       
   410 	if (available != CCnvCharacterSetConverter::EAvailable)
       
   411 		{
       
   412 		User::Leave(KErrNotSupported);
       
   413 		}	
       
   414 		
       
   415 	HBufC8* inBuf = HBufC8::NewLC(KMsvDecodeChunkLength);
       
   416 	HBufC16* outBuf = HBufC16::NewLC(KMsvDecodeChunkLength);
       
   417 	TPtr8 inPtr = inBuf->Des();
       
   418 	TPtr16 outPtr = outBuf->Des();
       
   419 	
       
   420 	// Used to preserve state across multiple calls to ConvertToUnicode.
       
   421 	TInt state = CCnvCharacterSetConverter::KStateDefault; 
       
   422 	TBool newLine = EFalse;
       
   423 	TBool newPara = EFalse;
       
   424 	TInt bytesRemaining = sourceStream->SizeL();
       
   425 
       
   426 	while(bytesRemaining > 0)
       
   427 		{
       
   428 		// Set the buffer length to the smaller of the number of bytes remaining,
       
   429 		// or the chunk length.
       
   430 		inPtr.SetLength(bytesRemaining < KMsvDecodeChunkLength ? bytesRemaining : KMsvDecodeChunkLength);
       
   431 		// Read data from stream up to and including the 1st LF encountered.
       
   432 		TRAPD(err, inputStream.ReadL(inPtr,TChar(KLineFeed)));
       
   433 		if (err != KErrEof)
       
   434 			{
       
   435 			User::LeaveIfError(err);
       
   436 			}
       
   437 		
       
   438 		TInt inBufLength = inPtr.Length();
       
   439 		__ASSERT_DEBUG(inBufLength > 0, PanicServer(EMsvInputBufferEmpty));
       
   440 		bytesRemaining -= inBufLength;
       
   441 		
       
   442 		// If the data read is terminated with an LF or CRLF, remove it and mark it for
       
   443 		// appending a rich text line end or paragraph delimiter. 
       
   444 		TInt bytesTruncated = 0;
       
   445 		if (inPtr[inBufLength - 1] != KLineFeed)
       
   446 			{
       
   447 			// The data read does not contain any new line or paragraph delimters.
       
   448 			newLine = EFalse;
       
   449 			newPara = EFalse;
       
   450 			}
       
   451 		else
       
   452 			{
       
   453 			// Data read is terminated with LF.  Truncate length of data to ignore LF or CRLF bytes.
       
   454 			if (inBufLength > 1 && inPtr[inBufLength - 2] == KCarriageReturn)
       
   455 				{
       
   456 				bytesTruncated = 2;
       
   457 				inBufLength -= bytesTruncated;
       
   458 				inPtr.SetLength(inBufLength);  // Remove CRLF.
       
   459 				}
       
   460 			else
       
   461 				{
       
   462 				bytesTruncated = 1;
       
   463 				inBufLength -= bytesTruncated;
       
   464 				inPtr.SetLength(inBufLength);  // Remove LF.
       
   465 				}
       
   466 			
       
   467 			// Work out if it should be a new line or new paragraph.
       
   468 			if (inBufLength == 0)
       
   469 				{
       
   470 				if (newLine)
       
   471 					{
       
   472 					// There are more than two new line delimiters in a row with no data
       
   473 					// between them - new paragraph.
       
   474 					newLine = EFalse;
       
   475 					newPara = ETrue;
       
   476 					}
       
   477 				else
       
   478 					{
       
   479 					newLine = ETrue;
       
   480 					newPara = EFalse;
       
   481 					}
       
   482 				}
       
   483 			else
       
   484 				{
       
   485 				// It's a new line.
       
   486 				newLine = ETrue;
       
   487 				newPara = EFalse;
       
   488 				}
       
   489 			}
       
   490 		
       
   491 		// Convert the 8 bit data to unicode.
       
   492 		TInt bytesUnconverted = converter->ConvertToUnicode(outPtr, inPtr, state);
       
   493 		User::LeaveIfError(bytesUnconverted);
       
   494 		if (bytesUnconverted > 0)
       
   495 			{
       
   496 			// Some bytes could not be converted because the output buffer was too small.
       
   497 			// Seek back to the position of the 1st unconverted byte and recalculate the bytes remaining.  
       
   498 			TInt bytesSeekBack = bytesUnconverted + bytesTruncated;
       
   499 			sourceStream->SeekL(MStreamBuf::ERead, EStreamMark, -bytesSeekBack);
       
   500 			bytesRemaining += bytesSeekBack;
       
   501 			newLine = EFalse;
       
   502 			newPara = EFalse;
       
   503 			}
       
   504 		
       
   505 		// There is no AppendL method for CRichText.  Insert decoded text at end of document instead.
       
   506 		aRichText.InsertL(aRichText.DocumentLength(), outPtr);
       
   507 
       
   508 		// Insert a new line or paragraph delimiter if necessary.
       
   509 		if (newLine)
       
   510 			{
       
   511 			aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
       
   512 			}
       
   513 			
       
   514 		if (newPara)
       
   515 			{
       
   516 			aRichText.InsertL(aRichText.DocumentLength(), CEditableText::EParagraphDelimiter);
       
   517 			}
       
   518 		}
       
   519 	CleanupStack::PopAndDestroy(4, &inputStream); //outBuf,inBuf,converter,inputStream
       
   520 	}
       
   521 
       
   522 
       
   523 EXPORT_C void CMsvStore::DeleteBodyTextL()
       
   524 //
       
   525 // Deletes the body text stream
       
   526 //
       
   527 /** Deletes the stream that contains the body text. Write access is needed for 
       
   528 this function.
       
   529 
       
   530 @leave KErrAccessDenied Store is not open for writing 
       
   531 @leave Other Standard streaming leave codes */
       
   532 	{
       
   533 	if (IsPresentL(KMsvEntryRichTextBody))
       
   534 		RemoveL(KMsvEntryRichTextBody);
       
   535 	
       
   536 	// Remove the body text data if stored in KMsvPlainBodyText8 or KMsvPlainBodyText16 format.
       
   537 	if (IsPresentL(KMsvPlainBodyText8))
       
   538 		{
       
   539 		RemoveL(KMsvPlainBodyText8);
       
   540 		}
       
   541 	if (IsPresentL(KMsvPlainBodyText16))
       
   542 		{
       
   543 		RemoveL(KMsvPlainBodyText16);
       
   544 		}
       
   545 		
       
   546 	iBodyText->RemoveL(*this);
       
   547 	}
       
   548 
       
   549 
       
   550 EXPORT_C void CMsvStore::DeleteL()
       
   551 //
       
   552 // Deletes the file store
       
   553 //
       
   554 /** Deletes the message store. After a delete, the behaviour of the object is undefined: 
       
   555 it can only be deleted.
       
   556 
       
   557 Write access is needed for this function.
       
   558 
       
   559 @leave KErrAccessDenied The store is read only 
       
   560 @leave Other Standard file store error codes */
       
   561 	{
       
   562 	if (iStore==NULL)
       
   563 		return;
       
   564 
       
   565 	if (iLockStatus==EMsvStoreUnlocked)
       
   566 		User::Leave(KErrAccessDenied);
       
   567 	
       
   568 	iStore->DeleteL();
       
   569 	delete iStore;
       
   570 	iStore=NULL;
       
   571 	}
       
   572 
       
   573 
       
   574 EXPORT_C TInt CMsvStore::Commit()
       
   575 //
       
   576 //
       
   577 //
       
   578 /** Commits changes to the message store, returning any error code.
       
   579 
       
   580 Committing changes makes these changes permanent, and means that the store 
       
   581 cannot be rolled back to a state before the changes were begun. 
       
   582 
       
   583 You should use this function before deleting a CMsvStore, if you have made 
       
   584 changes to it through RMsvWriteStream . Note that StoreBodyTextL() performs 
       
   585 a commit itself, so an additional commit is not required after its use.
       
   586 
       
   587 The functions is identical to the following one, except that it returns an 
       
   588 error code if an error occurs.
       
   589 
       
   590 Write access is needed.
       
   591 
       
   592 @return Changes committed successfully 
       
   593 @return Store open for read only 
       
   594 @return Unable to commit changes */
       
   595 	{
       
   596 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
   597 		return KErrAccessDenied;
       
   598 	
       
   599 	TInt error = KErrNone;
       
   600 
       
   601 	// Save the attachment information if there is any...
       
   602 	if( iAttachmentManager != NULL )
       
   603 		{
       
   604 		TRAP(error, iAttachmentManager->StoreL());
       
   605 		if( error < KErrNone )
       
   606 			{
       
   607 			// error occured trying to save the attachments
       
   608 			return error;
       
   609 			}
       
   610 		}
       
   611 	// commit the store
       
   612 	error = iStore->Commit();
       
   613 	if( iAttachmentManager != NULL && error==KErrNone )
       
   614 		{
       
   615 		iAttachmentManager->HandleCommitComplete();
       
   616 		}
       
   617 	return error;
       
   618 	}
       
   619 
       
   620 
       
   621 EXPORT_C void CMsvStore::CommitL()
       
   622 //
       
   623 //
       
   624 //
       
   625 /** Commits changes to the message store, leaving if an error occurs.
       
   626 
       
   627 Committing changes makes these changes permanent, and means that the store 
       
   628 cannot be rolled back to a state before the changes were begun. 
       
   629 
       
   630 You should use this function before deleting a CMsvStore, if you have made 
       
   631 changes to it through RMsvWriteStream . Note that StoreBodyTextL() performs 
       
   632 a commit itself, so an additional commit is not required after its use.
       
   633 
       
   634 The functions is identical to the previous one, except that it leaves with 
       
   635 the error code if an error occurs.
       
   636 
       
   637 Write access is needed.
       
   638 
       
   639 @leave KErrAccessDenied Store open for read only 
       
   640 @leave Standard streaming error codes Unable to commit changes */
       
   641 	{
       
   642 	User::LeaveIfError(Commit());
       
   643 	}
       
   644 
       
   645 
       
   646 EXPORT_C void CMsvStore::Remove(TUid aUid)
       
   647 //
       
   648 //
       
   649 //
       
   650 /** Deletes the identified stream from the store. The function returns, whether 
       
   651 or not it completes successfully.
       
   652 
       
   653 Write access is needed for this function.
       
   654 
       
   655 @param aUid The UID of the stream to delete */
       
   656 	{
       
   657 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   658 	TRAP_IGNORE(RemoveL(aUid));
       
   659 #else
       
   660 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
   661 		return;
       
   662 	
       
   663 	if((aUid == KMsvPlainBodyText16)|| aUid == (KMsvPlainBodyText16))
       
   664 		{
       
   665 		TRAP_IGNORE(iStoreManager.DeletePlainTextFileL(iId));
       
   666 		}
       
   667 	
       
   668 	iStore->Remove(aUid);
       
   669 #endif
       
   670 	}
       
   671 
       
   672 
       
   673 
       
   674 
       
   675 EXPORT_C void CMsvStore::RemoveL(TUid aUid)
       
   676 //
       
   677 //
       
   678 //
       
   679 /** Deletes the identified stream from the store. It leaves if it cannot complete 
       
   680 successfully.
       
   681 
       
   682 Write access is needed for this function.
       
   683 
       
   684 @param aUid The UID of the stream to delete 
       
   685 @leave KErrAccessDenied The store is read only 
       
   686 @leave Other Standard streaming error codes */
       
   687 	{
       
   688 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
   689 		User::Leave(KErrAccessDenied);
       
   690 	if((aUid == KMsvPlainBodyText16)|| aUid == (KMsvPlainBodyText16))
       
   691 		{
       
   692 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   693 		TRAP_IGNORE(iStoreManager.DeletePlainTextFileL(iId));
       
   694 #else
       
   695 		iStoreManager.DeletePlainTextFileL(iId);
       
   696 #endif
       
   697 		}
       
   698 
       
   699 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   700 	iStore->Remove(aUid);
       
   701 #else	
       
   702 	iStore->RemoveL(aUid);
       
   703 #endif
       
   704 	}
       
   705 
       
   706 
       
   707 
       
   708 
       
   709 EXPORT_C void CMsvStore::Revert()
       
   710 //
       
   711 //
       
   712 //
       
   713 /** Reverts the store to the previous commit level. This removes all changes that 
       
   714 have been made to the store since the last commit. 
       
   715 
       
   716 The function cannot leave: it returns, whether or not it completes successfully.
       
   717 
       
   718 Write access is needed for this function. */
       
   719 	{
       
   720 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
   721 		return;
       
   722 
       
   723 	iStore->Revert();		// Check this for 2073
       
   724 	
       
   725 	// load the attachment infomation if already loaded
       
   726 	if( iAttachmentManager != NULL )
       
   727 		{
       
   728 		TRAP_IGNORE(iAttachmentManager->RestoreL()); // ignore any errors
       
   729 		}
       
   730 	}
       
   731 
       
   732 
       
   733 
       
   734 EXPORT_C void CMsvStore::RevertL()
       
   735 //
       
   736 //
       
   737 //
       
   738 /** Reverts the store to the previous commit level. This removes all changes that 
       
   739 have been made to the store since the last commit. 
       
   740 
       
   741 The function leaves if it cannot complete successfully.
       
   742 
       
   743 Write access is needed for this function.
       
   744 
       
   745 @leave KErrAccessDenied The store is read only 
       
   746 @leave Other Standard streaming error codes */
       
   747 	{
       
   748 	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
       
   749 		User::Leave(KErrAccessDenied);
       
   750 	
       
   751 	iStore->RevertL(); 
       
   752 
       
   753 	// load the attachment infomation if already loaded
       
   754 	if( iAttachmentManager != NULL )
       
   755 		{
       
   756 		iAttachmentManager->RestoreL();
       
   757 		}
       
   758 	}
       
   759 
       
   760 EXPORT_C TInt CMsvStore::SizeL()
       
   761 //
       
   762 // Returns the size of the store, or zero if the file doesn't exist
       
   763 //
       
   764 /** Gets the size of the message store.
       
   765 
       
   766 @return Size of the message store in bytes */
       
   767 	{
       
   768 	if (iStore==NULL)
       
   769 		User::Leave(KErrNotFound);
       
   770 	
       
   771 	return iStore->Size();
       
   772 	}
       
   773 
       
   774 
       
   775 
       
   776 /**
       
   777 @internalComponent
       
   778 */
       
   779 EXPORT_C CMsvStore* CMsvStore::OpenForReadL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId)
       
   780 	{
       
   781 	CMsvStore* store=new(ELeave) CMsvStore(aObserver, aFs, aId, aStoreManager);
       
   782 	CleanupStack::PushL(store);
       
   783 	store->ConstructL(ETrue);
       
   784 	CleanupStack::Pop(store);
       
   785 	return store;
       
   786 	}
       
   787 
       
   788 /**
       
   789 @internalComponent
       
   790 */
       
   791 EXPORT_C CMsvStore* CMsvStore::OpenForWriteL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId)
       
   792 	{
       
   793 	CMsvStore* store=new(ELeave) CMsvStore(aObserver, aFs, aId, aStoreManager);
       
   794 	CleanupStack::PushL(store);
       
   795 	store->Lock();
       
   796 	store->ConstructL(EFalse);
       
   797 	CleanupStack::Pop(store);
       
   798 	return store;
       
   799 	}
       
   800 
       
   801 /**
       
   802 @internalComponent
       
   803 */
       
   804 EXPORT_C CMsvStore::CMsvStore(MMsvStoreObserver& aObserver, RFs& aFs, TMsvId aId, MMsvStoreManager& aStoreManager)
       
   805 : iLockStatus(EMsvStoreUnlocked), iFs(aFs), iObserver(aObserver), iId(aId), iConstructed(EFalse), iStoreManager(aStoreManager)
       
   806 	{}
       
   807 
       
   808 
       
   809 
       
   810 
       
   811 void CMsvStore::ConstructL(TBool aReadOnly)
       
   812 	{
       
   813 	iStore=CMsvCachedStore::OpenL(iId, iStoreManager, aReadOnly);
       
   814 	iBodyText = CMsvBodyText::NewL();
       
   815 	iConstructed=ETrue;
       
   816 	}
       
   817 
       
   818 
       
   819 /**
       
   820 Returns an interface for the Attachment Manager.
       
   821 
       
   822 This methods returns an interface that can be used to provided attachment
       
   823 management functionality for each message entry.
       
   824 
       
   825 @return A reference to the Attachment Manager interface
       
   826 @see MMsvAttachmentManager
       
   827 */
       
   828 EXPORT_C MMsvAttachmentManager& CMsvStore::AttachmentManagerL()
       
   829 	{
       
   830 	if( iAttachmentManager==NULL )
       
   831 		{
       
   832 		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
       
   833 		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
       
   834 		}
       
   835 		
       
   836 	MMsvAttachmentManager& attachmentAPI = *iAttachmentManager;
       
   837 	return attachmentAPI;
       
   838 	}
       
   839 	
       
   840 EXPORT_C MMsvAttachmentManagerSync& CMsvStore::AttachmentManagerExtensionsL()
       
   841 	{
       
   842 	if( iAttachmentManager==NULL )
       
   843 		{
       
   844 		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
       
   845 		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
       
   846 		}
       
   847 		
       
   848 	return (MMsvAttachmentManagerSync&) *iAttachmentManager;
       
   849 	}
       
   850 
       
   851 /**
       
   852 @internalTechnology
       
   853 @released
       
   854 */
       
   855 EXPORT_C void CMsvStore::CreateShareProtectedAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
       
   856 	{
       
   857 	if (iAttachmentManager == NULL)
       
   858 		{
       
   859 		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
       
   860 		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
       
   861 		}
       
   862 
       
   863 	iAttachmentManager->CreateShareProtectedAttachmentL(aFileName, aAttachmentFile, aAttachmentInfo);
       
   864 	}
       
   865 
       
   866 
       
   867 /**
       
   868 Intialise and return the CMsvPlainBodyText object that can be used for reading/writing plain body text.
       
   869 @param aIs8Bit				TBool indicating whether to store bdy text as 8/16 bit.
       
   870 @param aCharsetId			The charset of the body part.
       
   871 @param aDefaultCharsetId    The default charset of the system.
       
   872 @leave KErrAccessDenied		If Store is opened in Read mode.
       
   873 @return CMsvPlainBodyText.
       
   874 */
       
   875 EXPORT_C CMsvPlainBodyText* CMsvStore::InitialisePlainBodyTextForWriteL(TBool aIs8Bit, TUint aCharsetId, TUint aDefaultCharsetId)
       
   876 	{
       
   877 	if(iLockStatus != EMsvStoreLocked)
       
   878 		{
       
   879 		User::Leave(KErrAccessDenied);
       
   880 		}
       
   881 	return CMsvPlainBodyText::NewL(iStoreManager, *this, aIs8Bit, aCharsetId, aDefaultCharsetId, iId, iFs);
       
   882 	}
       
   883 
       
   884 
       
   885 /**
       
   886 Intialise and return the CMsvPlainBodyText object that can be used for reading plain body text.
       
   887 @param aChunkLength		The length of the chunk that will be processed while reading.
       
   888 @leave KErrAccessDenied	If Store is opened in Write mode.
       
   889 @return CMsvPlainBodyText.
       
   890 */
       
   891 EXPORT_C CMsvPlainBodyText* CMsvStore::InitialisePlainBodyTextForReadL(TInt aChunkLength)
       
   892 	{
       
   893 	if(iLockStatus == EMsvStoreLocked)
       
   894 		{
       
   895 		User::Leave(KErrAccessDenied);
       
   896 		}
       
   897 	return CMsvPlainBodyText::NewL(iStoreManager, *this, iId, iFs, aChunkLength);
       
   898 	}
       
   899 
       
   900 
       
   901 
       
   902 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   903 
       
   904 /**
       
   905 Construct the CacheEntry.
       
   906 @param aMtmId  A TUid.
       
   907 @param aIsBodyEntry A TEntryStoreType.
       
   908 @return None.
       
   909 @internalComponent
       
   910 */
       
   911 
       
   912 void CMsvStore::ConstructDbL(TUid aMtmId,TBool aReadOnly)
       
   913 	{
       
   914 	iStore=CMsvCachedStore::OpenL(iId, iStoreManager, aReadOnly,aMtmId);
       
   915 	iStore->iMtmId = aMtmId;
       
   916 	iBodyText = CMsvBodyText::NewL();	
       
   917 	iConstructed=ETrue;
       
   918 	}
       
   919 
       
   920 /**
       
   921 Open the Store for read.
       
   922 @param aObserver A MMsvStoreObserver as reference.
       
   923 @param aFs A RFs as reference.
       
   924 @param aStoreManager A MMsvStoreManager as reference.
       
   925 @param aId A TMsvId
       
   926 @param aMtmId A TUid.
       
   927 @param aIsBodyEntry A TEntryStoreType
       
   928 @return CMsvStore*
       
   929 @internalComponent
       
   930 */
       
   931 
       
   932 EXPORT_C CMsvStore* CMsvStore::OpenForReadL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId, TUid aMtmId)
       
   933 	{
       
   934 	CMsvStore* store=new(ELeave)CMsvStore(aObserver, aFs, aId, aStoreManager);
       
   935 	CleanupStack::PushL(store);
       
   936 	store->ConstructDbL(aMtmId,ETrue);
       
   937 	CleanupStack::Pop(store);
       
   938 	return store;	
       
   939 	}
       
   940 
       
   941 
       
   942 /**
       
   943 Open the Store for write.
       
   944 @param aObserver A MMsvStoreObserver as reference.
       
   945 @param aFs A RFs as reference.
       
   946 @param aStoreManager A MMsvStoreManager as reference.
       
   947 @param aId A TMsvId
       
   948 @param aMtmId A TUid.
       
   949 @param aIsBodyEntry A TEntryStoreType
       
   950 @return CMsvStore*
       
   951 @internalComponent
       
   952 */
       
   953 
       
   954 EXPORT_C CMsvStore* CMsvStore::OpenForWriteL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId, TUid aMtmId)
       
   955 	{
       
   956 	CMsvStore* store=new(ELeave)CMsvStore(aObserver, aFs, aId, aStoreManager);
       
   957 	CleanupStack::PushL(store);
       
   958 	store->ConstructDbL(aMtmId,EFalse);
       
   959 	store->Lock();
       
   960 	CleanupStack::Pop(store);
       
   961 	return store;
       
   962 	}
       
   963 
       
   964 /**
       
   965 Restore the Header entry.
       
   966 @param None.
       
   967 @return None.
       
   968 @internalComponent
       
   969 */
       
   970 void CMsvStore::RestoreL()
       
   971 	{
       
   972 	if (iStore==NULL )
       
   973 		{
       
   974 		User::Leave(KErrNotFound);
       
   975 		}
       
   976 
       
   977 	iStoreManager.LoadHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList);	
       
   978 	}
       
   979 
       
   980 
       
   981 /**
       
   982 Create or Update the Header entry.
       
   983 @param None.
       
   984 @return None.
       
   985 @internalComponent
       
   986 */
       
   987 void CMsvStore::CommitHeaderL()
       
   988 	{
       
   989 	TInt error = KErrNone;
       
   990 	if(!iStore->isNewEntry)
       
   991 		{
       
   992 		TRAP(error, iStoreManager.UpdateHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList));
       
   993 		}
       
   994 	else
       
   995 		{
       
   996 		TRAP(error, iStoreManager.CreateHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList));
       
   997 		iStore->isNewEntry = EFalse;
       
   998 		}
       
   999 	User::LeaveIfError(error);	
       
  1000 	}
       
  1001 
       
  1002 /**
       
  1003 Returns ETrue if entries stored in database
       
  1004 */
       
  1005 EXPORT_C TBool CMsvStore::IsDbStore()
       
  1006 	{
       
  1007 	return 	iStore->isDbStore;
       
  1008 	}
       
  1009 
       
  1010 
       
  1011 /** Create TMsvWriteStore to read message store.
       
  1012 
       
  1013 @param aMsvStore The aMsvStore as reference. 
       
  1014 @return TMsvWriteStore  write sore.
       
  1015  */
       
  1016 EXPORT_C TMsvWriteStore::TMsvWriteStore(CMsvStore& aMsvStore):iMsvStore(aMsvStore)
       
  1017 	{
       
  1018 	}
       
  1019 
       
  1020 /**
       
  1021 Assign the  header Fields in to header Field list.
       
  1022 @param aHeaderFields : CHeaderFields*
       
  1023 @return None.
       
  1024 */
       
  1025 
       
  1026 EXPORT_C void TMsvWriteStore::AssignL(CHeaderFields* aHeaderFields)
       
  1027 	{
       
  1028 	iMsvStore.iStore->AssignL(aHeaderFields);
       
  1029 	}
       
  1030 	
       
  1031 /**
       
  1032 Commit the header entry to message store 
       
  1033 
       
  1034 @param None.
       
  1035 @return None.
       
  1036 */	
       
  1037 	
       
  1038 EXPORT_C void TMsvWriteStore::CommitL()
       
  1039 	{
       
  1040 	iMsvStore.CommitHeaderL();
       
  1041 	}
       
  1042 	
       
  1043 
       
  1044 /** Create TMsvReadStore to read message store.
       
  1045 
       
  1046 @param aMsvStore The aMsvStore as reference. 
       
  1047 @param aUid The UID.
       
  1048 @return TMsvReadStore  read sore.
       
  1049  */
       
  1050 
       
  1051 
       
  1052 EXPORT_C TMsvReadStore::TMsvReadStore(CMsvStore& aMsvStore, TUid aUid):
       
  1053 iMsvStore(aMsvStore), iUid(aUid)
       
  1054 	{	
       
  1055 	}
       
  1056 	
       
  1057 
       
  1058 /** Load the Header entry from message store.
       
  1059 
       
  1060 @param aHeaderFields The CHeaderFields as pointer reference. 
       
  1061 @return None.
       
  1062  */
       
  1063 	
       
  1064 	
       
  1065 EXPORT_C void TMsvReadStore::LoadL(CHeaderFields*& aHeaderFields)
       
  1066 	{
       
  1067 	iMsvStore.RestoreL();
       
  1068 	iMsvStore.iStore->GetHeaderL(iUid, aHeaderFields);
       
  1069 	}
       
  1070 	
       
  1071 
       
  1072 /** Read the Header entry from message store.
       
  1073 
       
  1074 @param aHeaderFields The CHeaderFields as pointer reference. 
       
  1075 @return None.
       
  1076  */
       
  1077 
       
  1078 	
       
  1079 EXPORT_C void TMsvReadStore::ReadL(CHeaderFields*& aHeaderFields)
       
  1080 	{
       
  1081 	iMsvStore.iStore->GetHeaderL(iUid, aHeaderFields);
       
  1082 	}
       
  1083 		
       
  1084 
       
  1085 #endif //#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)