messagingfw/msgsrvnstore/server/src/MSVSTORE.CPP
changeset 22 bde600d88860
parent 0 8e480a14352b
child 44 7c176670643f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/MSVSTORE.CPP	Fri Jun 04 10:32:16 2010 +0100
@@ -0,0 +1,1085 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// MSVSTORE.CPP
+//
+
+#include <txtrich.h>
+
+
+#include "MSVSTD.H"
+#include "MSVSTORE.H"
+#include "MSVPANIC.H"
+#include "CMsvCachedStore.h"
+#include "cmsvbodytext.h"
+#include <cmsvplainbodytext.h>
+#include "CMsvAttachmentManager.h"
+#include <cmsvattachment.h>
+#include <charconv.h>
+#include <escapeutils.h>
+#include <mmsvstoremanager.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
+#include "msvconsts.h"
+#endif
+
+
+//
+// CMsvStore
+//
+const TUint8 KCarriageReturn = 0x0D;
+const TUint8 KLineFeed       = 0x0A;
+
+EXPORT_C CMsvStore::~CMsvStore()
+//
+//
+//
+/** Destructor.
+
+If the message store is currently locked, the destructor releases it before 
+deleting the object. */
+	{
+	// tell the observer that this store is being released/closed
+	if (iConstructed)
+		{
+		// only inform server if the store was successfully opened
+		if (iLockStatus==EMsvStoreLocked)
+			iObserver.HandleStoreEvent(MMsvStoreObserver::EMsvEditStoreClosed, iId);
+		else
+			iObserver.HandleStoreEvent(MMsvStoreObserver::EMsvReadStoreClosed, iId);
+		}
+
+	delete iAttachmentManager;
+
+	delete iStore;
+	delete iBodyText;
+	}
+
+EXPORT_C void CMsvStore::StoreBodyTextL(const CRichText& aRichTextBody)
+//
+// stores and commits body text to the file store, overwriting any existing data
+// will panic if the store is unlocked and will leave if no store is found
+//
+/** Stores the body text stream of the message store. Any existing 
+data is overwritten. Write access is needed for this function. A commit must be done
+following this function for the new data to be retained.
+
+@param aRichTextBody The body data to be externalised 
+@leave KErrAccessDenied Store is not open for writing 
+@leave Other Standard streaming leave codes */
+	{
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		User::Leave(KErrAccessDenied);
+
+	iBodyText->RemoveL(*this);
+	
+	// Remove the body text data if stored in KMsvPlainBodyText8 or KMsvPlainBodyText16 format.
+	if (IsPresentL(KMsvPlainBodyText8))
+		{
+		RemoveL(KMsvPlainBodyText8);
+		}
+	if (IsPresentL(KMsvPlainBodyText16))
+		{
+		RemoveL(KMsvPlainBodyText16);
+		}
+	
+	RMsvWriteStream out;
+	out.AssignL(*this,KMsvEntryRichTextBody);
+	CEmbeddedStore* embeddedStore=CEmbeddedStore::NewLC(out);
+	TStreamId streamId=aRichTextBody.StoreL(*embeddedStore);
+	embeddedStore->SetRootL(streamId);
+	embeddedStore->CommitL();
+	CleanupStack::PopAndDestroy(); //embeddedstore
+	}
+
+void CMsvStore::Lock()
+	{
+	iLockStatus=EMsvStoreLocked;
+	}
+
+EXPORT_C TBool CMsvStore::IsNullL() const
+/** Tests whether the message store contains any streams.
+@return ETrue if the store has no streams, else EFalse
+*/
+	{
+	return iStore->IsNullL();		
+	}
+
+EXPORT_C TBool CMsvStore::IsPresentL(TUid aUid) const
+/** Tests whether the message store contains a stream identifier.
+Do not use to check if there is a body text part stored with the email;
+use CMsvStore::HasBodyTextL() instead.
+@param aUid Identifier of stream 
+@return ETrue if the store has a stream aUid, else EFalse 
+ */
+	{
+	return iStore->IsPresentL(aUid);
+	}
+	
+
+EXPORT_C TBool CMsvStore::HasBodyTextL() const
+/** Checks if the store has a body text stream; IsPresentL(KMsvEntryRichTextBody)
+will always return EFalse when the store_8bit_flag in imcm.rss is enabled.
+@return ETrue if the store has a body text stream, else EFalse 
+*/
+	{
+	return iStore->IsPresentL(KMsvEntryRichTextBody) || iBodyText->IsPresentL(*this)|| iStore->IsPresentL(KMsvPlainBodyText8)|| iStore->IsPresentL(KMsvPlainBodyText16);
+	}
+
+/**
+Restores body text into the given rich text object - doesnt matter if store is locked or not
+will leave if the file store doesn't exist, the body text does not exist, and also propagate store leaves
+Reads the body text stream from the message store into the given rich text 
+object. 
+@param aRichTextBody 	On return, the message store's body text is inserted 
+						into this object. Any previously existing contents is lost. 
+@leave KErrNotFound 	There is no body text stream in the store 
+@leave Other Standard streaming leave codes 
+*/
+EXPORT_C void CMsvStore::RestoreBodyTextL(CRichText& aRichTextBody)
+	{
+	// Charset set to 0 so that RestoreBodyTextL works as per existing published behaviour.
+	RestoreBodyTextL(aRichTextBody, 0);
+	}
+
+/**
+Restores body text into the given rich text object - doesnt matter if store is locked or not.
+Reads the body text stream from the message store into the given rich text 
+object.
+@param aRichTextBody 		On return, the message store's body text is inserted 
+							into this object. Any previously existing contents is lost. 
+@param aCharsetOverride   	The charset with which to override the existing charset 
+							when data is stored a 8 bit format. 
+@leave KErrNotFound 		There is no body text stream in the store 
+@leave Other Standard streaming leave codes 
+*/
+EXPORT_C void CMsvStore::RestoreBodyTextL(CRichText& aRichTextBody, TUint aCharsetOverride)
+	{
+	if (iStore==NULL )
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	if (IsPresentL(KMsvEntryRichTextBody))
+		{
+		RMsvReadStream inputStream;
+		inputStream.OpenL(*this, KMsvEntryRichTextBody); // CEmbeddedStore::FromLC() take ownership
+		CEmbeddedStore* embeddedStore = CEmbeddedStore::FromLC(inputStream);
+		aRichTextBody.RestoreL(*embeddedStore, embeddedStore->Root());
+		CleanupStack::PopAndDestroy();	// embeddedStore
+		}
+	else if(iBodyText->IsPresentL(*this))
+		{
+		iBodyText->RestoreL(*this);
+		// If a new charset was set, override the  restored charset
+		// so that data is converted using new charset.
+		if(aCharsetOverride != 0)
+			{
+			iBodyText->SetCharacterSet(aCharsetOverride);
+			}
+		iBodyText->GetBodyTextL(iFs, *this, aRichTextBody);
+		}
+	else
+		{
+		if(IsPresentL(KMsvPlainBodyText8) || IsPresentL(KMsvPlainBodyText16))
+			{
+			RestorePlainBodyTextL (aRichTextBody, aCharsetOverride);
+			}
+		else		
+			{
+			User::Leave(KErrNotFound);
+			}
+		}
+	}
+
+
+
+
+/**
+Restores a CRichText object from the plain body text file.
+@param aRichText 			On completion this contains the plain body text.
+@param aCharsetOverride 	The new charset with which to override the existing charset 
+							when data is stored a 8 bit plain text format. 
+@return void.
+*/
+void CMsvStore::RestorePlainBodyTextL(CRichText& aRichText, TUint aCharsetOverride)
+	{
+	RMsvReadStream inputStream;
+	TBool is8Bit = EFalse;
+	TUint charSet = 0;
+	TUint defaultCharSet = 0;
+	if(IsPresentL(KMsvPlainBodyText8))
+		{
+		inputStream.OpenLC(*this, KMsvPlainBodyText8);
+		charSet = inputStream.ReadUint32L();
+		defaultCharSet = inputStream.ReadUint32L();
+		is8Bit = ETrue;
+		}
+	else
+		{
+		inputStream.OpenLC(*this, KMsvPlainBodyText16);
+		}
+	// If a new charset was set, override the  restored charset so that 
+	// data is converted using new charset.
+	if(aCharsetOverride!=0)
+		{
+		charSet = aCharsetOverride;
+		}
+	
+	TBool committed = inputStream.ReadUint32L();
+	TFileName filePath;
+	HBufC* fileName = HBufC::NewLC(inputStream, KMaxFileName);	
+	RFile bodyTextFile;
+	CleanupClosePushL(bodyTextFile);
+	
+	iStoreManager.BodyTextFilePathL(iId, filePath);
+
+	filePath.Append(*fileName);
+	iStoreManager.OpenBodyTextFileForReadL(bodyTextFile, iId, filePath);
+	if(is8Bit)
+		{
+		GetRichTextFrom8BitL(bodyTextFile, aRichText, charSet, defaultCharSet);
+		}
+	else
+		{
+		GetRichTextFrom16BitL(bodyTextFile, aRichText);
+		}
+
+	CleanupStack::PopAndDestroy(3, &inputStream);//bodyTextFile,fileName,in
+	}
+/**	
+Restores 8 bit body text from the Message Store
+@param aInputStream		on completion the RFileReadStream contains the message body text stream.
+*/
+void CMsvStore::Restore8BitBodyTextL(RFileReadStream& aInputStream)
+	{
+	RMsvReadStream in;
+	in.OpenLC(*this, KMsvPlainBodyText8);
+	in.ReadUint32L();	// reads charset
+	in.ReadUint32L();	// read default charset
+	in.ReadUint32L();	// returns ETrue if committed to message store else EFalse
+	TFileName filePath;
+	HBufC* fileName = HBufC::NewLC(in, KMaxFileName);
+	RFile bodyTextFile;
+	CleanupClosePushL(bodyTextFile);
+	iStoreManager.BodyTextFilePathL(iId, filePath);
+	filePath.Append(*fileName);
+	iStoreManager.OpenBodyTextFileForReadL(bodyTextFile, iId, filePath);
+	aInputStream.Attach(bodyTextFile, 0);
+	CleanupStack::PopAndDestroy(3, &in);	// bodyTextFile, fileName, in
+	}	
+	
+/**
+Gets CRichText from plain body text file if data stored as 8 bit.
+@param aFile 			The file containing the plain body text.
+@param aRichText 		The CRichText object that will be filled on return.
+@param aCharSet 		The charset of the body part.
+@param aDefaultCharSet  The default charset of the system.
+@return void.
+*/	
+void CMsvStore::GetRichTextFrom8BitL(RFile& aBodyTextFile, CRichText& aRichText, TUint aCharSet, TUint aDefaultCharSet)
+	{
+	Convert8BitToRichTextL(aBodyTextFile, aRichText, aCharSet, aDefaultCharSet);
+	}
+
+
+/**
+Gets CRichText from plain body text file if data stored as 16 bit.
+@param aFile 	  The file containing the plain body text.
+@param aRichText  The CRichText object that will be filled on return.
+@return void.
+*/
+void CMsvStore::GetRichTextFrom16BitL(RFile& aBodyTextFile, CRichText& aRichText)
+	{
+	TInt size = 0;
+	aBodyTextFile.Size(size);
+	TBuf8<KMsvDecodeChunkLength> buf;
+	TBool carriageReturn = EFalse;
+	while(size > 0)
+		{
+		aBodyTextFile.Read(buf);
+		// Divide by 2 since the 16-bit buffer was stored using 8-bit pointer.
+		TPtrC16 bodyTextPtr((TUint16*)(buf.Ptr()), buf.Length()/2); 
+
+		// Was the last character of the last block a carriage return.
+		// If so we need to check for the specific condition where the carriage
+		// return / line feed has been split across blocks in which case the line
+		// feed should be discarded and the special character ELineBreak inserted
+		// instead. If the first character of this new block is not line feed
+		// then we should insert the carriage return as it is required in the
+		// output data and has not been added yet.
+		if (carriageReturn)
+			{
+			if (bodyTextPtr[0] == KLineFeed)
+				{
+				aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
+				bodyTextPtr.Set(bodyTextPtr.Mid(1));
+				}
+			else
+				{
+				aRichText.InsertL(aRichText.DocumentLength(), TChar(KCarriageReturn));
+				}
+
+			carriageReturn = EFalse;
+			}
+
+		TInt start = 0;
+		TInt len = bodyTextPtr.Length();
+		TInt i = 0;
+			
+		// Insert the data read from the RFile to CRichText.If there is CRLF insert 
+		// CEditableText::ELineBreak  
+		for(i=1; i<len; ++i)
+			{
+			// This will get data from RFile line by line and insert it to CRichText.
+			if(bodyTextPtr[i-1] == KCarriageReturn && bodyTextPtr[i] == KLineFeed)
+				{
+				TPtrC ptr = bodyTextPtr.Mid(start, (i-1)-start);
+				aRichText.InsertL(aRichText.DocumentLength(), ptr);
+				aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
+				start = i+1;
+				}
+			}
+		// We have inserted a line to the CRichText object, there were some more data left in
+		// bodyTextPtr, so insert rest of it to CRichText.
+		if (start != i)
+			{
+			// If last character is KCarriageReturn.
+			if(bodyTextPtr[len - 1] == KCarriageReturn)
+				{
+				carriageReturn = ETrue;
+				TPtrC ptr1 = bodyTextPtr.Mid(start, (i-1)-start);
+		    	aRichText.InsertL(aRichText.DocumentLength(), ptr1);
+				}
+			else
+				{
+				TPtrC ptr2 = bodyTextPtr.Mid(start, i-start);
+		    	aRichText.InsertL(aRichText.DocumentLength(), ptr2);
+				}
+			
+			}
+		size -= buf.Length();
+		}
+
+	// If the last character of the text was a carriage return, then we won't
+	// have added it because we were waiting to check what the start of the next
+	// block was. As there are no more blocks, the carriage return needs to be 
+	// added now.
+	if (carriageReturn)
+		{
+		aRichText.InsertL(aRichText.DocumentLength(), TChar(KCarriageReturn));
+		}
+	}
+
+/**
+Converts 8 bit data to Unicode and inserts to the CRichText object.
+@param aFile 			The file containing the plain body text.
+@param aRichText 		The CRichText object that will be filled on return.
+@param aCharSet 		The charset of the body part.
+@param aDefaultCharSet  The default charset of the system.
+@return void.
+*/
+void CMsvStore::Convert8BitToRichTextL(RFile& aBodyTextFile, CRichText& aRichText, TUint aCharSet, TUint aDefaultCharSet)
+	{
+	RFileReadStream inputStream(aBodyTextFile);
+	inputStream.PushL();
+	MStreamBuf* sourceStream = inputStream.Source();
+	
+	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewL();
+	CleanupStack::PushL(converter);
+	
+	CCnvCharacterSetConverter::TAvailability available = CCnvCharacterSetConverter::ENotAvailable;
+
+	if (aCharSet != 0)
+		{
+		available = converter->PrepareToConvertToOrFromL(aCharSet, iFs);
+		} 
+	if (available == CCnvCharacterSetConverter::ENotAvailable)
+		{
+		available = converter->PrepareToConvertToOrFromL(aDefaultCharSet, iFs);
+		}
+	if (available != CCnvCharacterSetConverter::EAvailable)
+		{
+		User::Leave(KErrNotSupported);
+		}	
+		
+	HBufC8* inBuf = HBufC8::NewLC(KMsvDecodeChunkLength);
+	HBufC16* outBuf = HBufC16::NewLC(KMsvDecodeChunkLength);
+	TPtr8 inPtr = inBuf->Des();
+	TPtr16 outPtr = outBuf->Des();
+	
+	// Used to preserve state across multiple calls to ConvertToUnicode.
+	TInt state = CCnvCharacterSetConverter::KStateDefault; 
+	TBool newLine = EFalse;
+	TBool newPara = EFalse;
+	TInt bytesRemaining = sourceStream->SizeL();
+
+	while(bytesRemaining > 0)
+		{
+		// Set the buffer length to the smaller of the number of bytes remaining,
+		// or the chunk length.
+		inPtr.SetLength(bytesRemaining < KMsvDecodeChunkLength ? bytesRemaining : KMsvDecodeChunkLength);
+		// Read data from stream up to and including the 1st LF encountered.
+		TRAPD(err, inputStream.ReadL(inPtr,TChar(KLineFeed)));
+		if (err != KErrEof)
+			{
+			User::LeaveIfError(err);
+			}
+		
+		TInt inBufLength = inPtr.Length();
+		__ASSERT_DEBUG(inBufLength > 0, PanicServer(EMsvInputBufferEmpty));
+		bytesRemaining -= inBufLength;
+		
+		// If the data read is terminated with an LF or CRLF, remove it and mark it for
+		// appending a rich text line end or paragraph delimiter. 
+		TInt bytesTruncated = 0;
+		if (inPtr[inBufLength - 1] != KLineFeed)
+			{
+			// The data read does not contain any new line or paragraph delimters.
+			newLine = EFalse;
+			newPara = EFalse;
+			}
+		else
+			{
+			// Data read is terminated with LF.  Truncate length of data to ignore LF or CRLF bytes.
+			if (inBufLength > 1 && inPtr[inBufLength - 2] == KCarriageReturn)
+				{
+				bytesTruncated = 2;
+				inBufLength -= bytesTruncated;
+				inPtr.SetLength(inBufLength);  // Remove CRLF.
+				}
+			else
+				{
+				bytesTruncated = 1;
+				inBufLength -= bytesTruncated;
+				inPtr.SetLength(inBufLength);  // Remove LF.
+				}
+			
+			// Work out if it should be a new line or new paragraph.
+			if (inBufLength == 0)
+				{
+				if (newLine)
+					{
+					// There are more than two new line delimiters in a row with no data
+					// between them - new paragraph.
+					newLine = EFalse;
+					newPara = ETrue;
+					}
+				else
+					{
+					newLine = ETrue;
+					newPara = EFalse;
+					}
+				}
+			else
+				{
+				// It's a new line.
+				newLine = ETrue;
+				newPara = EFalse;
+				}
+			}
+		
+		// Convert the 8 bit data to unicode.
+		TInt bytesUnconverted = converter->ConvertToUnicode(outPtr, inPtr, state);
+		User::LeaveIfError(bytesUnconverted);
+		if (bytesUnconverted > 0)
+			{
+			// Some bytes could not be converted because the output buffer was too small.
+			// Seek back to the position of the 1st unconverted byte and recalculate the bytes remaining.  
+			TInt bytesSeekBack = bytesUnconverted + bytesTruncated;
+			sourceStream->SeekL(MStreamBuf::ERead, EStreamMark, -bytesSeekBack);
+			bytesRemaining += bytesSeekBack;
+			newLine = EFalse;
+			newPara = EFalse;
+			}
+		
+		// There is no AppendL method for CRichText.  Insert decoded text at end of document instead.
+		aRichText.InsertL(aRichText.DocumentLength(), outPtr);
+
+		// Insert a new line or paragraph delimiter if necessary.
+		if (newLine)
+			{
+			aRichText.InsertL(aRichText.DocumentLength(), CEditableText::ELineBreak);
+			}
+			
+		if (newPara)
+			{
+			aRichText.InsertL(aRichText.DocumentLength(), CEditableText::EParagraphDelimiter);
+			}
+		}
+	CleanupStack::PopAndDestroy(4, &inputStream); //outBuf,inBuf,converter,inputStream
+	}
+
+
+EXPORT_C void CMsvStore::DeleteBodyTextL()
+//
+// Deletes the body text stream
+//
+/** Deletes the stream that contains the body text. Write access is needed for 
+this function.
+
+@leave KErrAccessDenied Store is not open for writing 
+@leave Other Standard streaming leave codes */
+	{
+	if (IsPresentL(KMsvEntryRichTextBody))
+		RemoveL(KMsvEntryRichTextBody);
+	
+	// Remove the body text data if stored in KMsvPlainBodyText8 or KMsvPlainBodyText16 format.
+	if (IsPresentL(KMsvPlainBodyText8))
+		{
+		RemoveL(KMsvPlainBodyText8);
+		}
+	if (IsPresentL(KMsvPlainBodyText16))
+		{
+		RemoveL(KMsvPlainBodyText16);
+		}
+		
+	iBodyText->RemoveL(*this);
+	}
+
+
+EXPORT_C void CMsvStore::DeleteL()
+//
+// Deletes the file store
+//
+/** Deletes the message store. After a delete, the behaviour of the object is undefined: 
+it can only be deleted.
+
+Write access is needed for this function.
+
+@leave KErrAccessDenied The store is read only 
+@leave Other Standard file store error codes */
+	{
+	if (iStore==NULL)
+		return;
+
+	if (iLockStatus==EMsvStoreUnlocked)
+		User::Leave(KErrAccessDenied);
+	
+	iStore->DeleteL();
+	delete iStore;
+	iStore=NULL;
+	}
+
+
+EXPORT_C TInt CMsvStore::Commit()
+//
+//
+//
+/** Commits changes to the message store, returning any error code.
+
+Committing changes makes these changes permanent, and means that the store 
+cannot be rolled back to a state before the changes were begun. 
+
+You should use this function before deleting a CMsvStore, if you have made 
+changes to it through RMsvWriteStream . Note that StoreBodyTextL() performs 
+a commit itself, so an additional commit is not required after its use.
+
+The functions is identical to the following one, except that it returns an 
+error code if an error occurs.
+
+Write access is needed.
+
+@return Changes committed successfully 
+@return Store open for read only 
+@return Unable to commit changes */
+	{
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		return KErrAccessDenied;
+	
+	TInt error = KErrNone;
+
+	// Save the attachment information if there is any...
+	if( iAttachmentManager != NULL )
+		{
+		TRAP(error, iAttachmentManager->StoreL());
+		if( error < KErrNone )
+			{
+			// error occured trying to save the attachments
+			return error;
+			}
+		}
+	// commit the store
+	error = iStore->Commit();
+	if( iAttachmentManager != NULL && error==KErrNone )
+		{
+		iAttachmentManager->HandleCommitComplete();
+		}
+	return error;
+	}
+
+
+EXPORT_C void CMsvStore::CommitL()
+//
+//
+//
+/** Commits changes to the message store, leaving if an error occurs.
+
+Committing changes makes these changes permanent, and means that the store 
+cannot be rolled back to a state before the changes were begun. 
+
+You should use this function before deleting a CMsvStore, if you have made 
+changes to it through RMsvWriteStream . Note that StoreBodyTextL() performs 
+a commit itself, so an additional commit is not required after its use.
+
+The functions is identical to the previous one, except that it leaves with 
+the error code if an error occurs.
+
+Write access is needed.
+
+@leave KErrAccessDenied Store open for read only 
+@leave Standard streaming error codes Unable to commit changes */
+	{
+	User::LeaveIfError(Commit());
+	}
+
+
+EXPORT_C void CMsvStore::Remove(TUid aUid)
+//
+//
+//
+/** Deletes the identified stream from the store. The function returns, whether 
+or not it completes successfully.
+
+Write access is needed for this function.
+
+@param aUid The UID of the stream to delete */
+	{
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	TRAP_IGNORE(RemoveL(aUid));
+#else
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		return;
+	
+	if((aUid == KMsvPlainBodyText16)|| aUid == (KMsvPlainBodyText16))
+		{
+		TRAP_IGNORE(iStoreManager.DeletePlainTextFileL(iId));
+		}
+	
+	iStore->Remove(aUid);
+#endif
+	}
+
+
+
+
+EXPORT_C void CMsvStore::RemoveL(TUid aUid)
+//
+//
+//
+/** Deletes the identified stream from the store. It leaves if it cannot complete 
+successfully.
+
+Write access is needed for this function.
+
+@param aUid The UID of the stream to delete 
+@leave KErrAccessDenied The store is read only 
+@leave Other Standard streaming error codes */
+	{
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		User::Leave(KErrAccessDenied);
+	if((aUid == KMsvPlainBodyText16)|| aUid == (KMsvPlainBodyText16))
+		{
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+		TRAP_IGNORE(iStoreManager.DeletePlainTextFileL(iId));
+#else
+		iStoreManager.DeletePlainTextFileL(iId);
+#endif
+		}
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	iStore->Remove(aUid);
+#else	
+	iStore->RemoveL(aUid);
+#endif
+	}
+
+
+
+
+EXPORT_C void CMsvStore::Revert()
+//
+//
+//
+/** Reverts the store to the previous commit level. This removes all changes that 
+have been made to the store since the last commit. 
+
+The function cannot leave: it returns, whether or not it completes successfully.
+
+Write access is needed for this function. */
+	{
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		return;
+
+	iStore->Revert();		// Check this for 2073
+	
+	// load the attachment infomation if already loaded
+	if( iAttachmentManager != NULL )
+		{
+		TRAP_IGNORE(iAttachmentManager->RestoreL()); // ignore any errors
+		}
+	}
+
+
+
+EXPORT_C void CMsvStore::RevertL()
+//
+//
+//
+/** Reverts the store to the previous commit level. This removes all changes that 
+have been made to the store since the last commit. 
+
+The function leaves if it cannot complete successfully.
+
+Write access is needed for this function.
+
+@leave KErrAccessDenied The store is read only 
+@leave Other Standard streaming error codes */
+	{
+	if (iLockStatus==EMsvStoreUnlocked || iStore==NULL)
+		User::Leave(KErrAccessDenied);
+	
+	iStore->RevertL(); 
+
+	// load the attachment infomation if already loaded
+	if( iAttachmentManager != NULL )
+		{
+		iAttachmentManager->RestoreL();
+		}
+	}
+
+EXPORT_C TInt CMsvStore::SizeL()
+//
+// Returns the size of the store, or zero if the file doesn't exist
+//
+/** Gets the size of the message store.
+
+@return Size of the message store in bytes */
+	{
+	if (iStore==NULL)
+		User::Leave(KErrNotFound);
+	
+	return iStore->Size();
+	}
+
+
+
+/**
+@internalComponent
+*/
+EXPORT_C CMsvStore* CMsvStore::OpenForReadL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId)
+	{
+	CMsvStore* store=new(ELeave) CMsvStore(aObserver, aFs, aId, aStoreManager);
+	CleanupStack::PushL(store);
+	store->ConstructL(ETrue);
+	CleanupStack::Pop(store);
+	return store;
+	}
+
+/**
+@internalComponent
+*/
+EXPORT_C CMsvStore* CMsvStore::OpenForWriteL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId)
+	{
+	CMsvStore* store=new(ELeave) CMsvStore(aObserver, aFs, aId, aStoreManager);
+	CleanupStack::PushL(store);
+	store->Lock();
+	store->ConstructL(EFalse);
+	CleanupStack::Pop(store);
+	return store;
+	}
+
+/**
+@internalComponent
+*/
+EXPORT_C CMsvStore::CMsvStore(MMsvStoreObserver& aObserver, RFs& aFs, TMsvId aId, MMsvStoreManager& aStoreManager)
+: iLockStatus(EMsvStoreUnlocked), iFs(aFs), iObserver(aObserver), iId(aId), iConstructed(EFalse), iStoreManager(aStoreManager)
+	{}
+
+
+
+
+void CMsvStore::ConstructL(TBool aReadOnly)
+	{
+	iStore=CMsvCachedStore::OpenL(iId, iStoreManager, aReadOnly);
+	iBodyText = CMsvBodyText::NewL();
+	iConstructed=ETrue;
+	}
+
+
+/**
+Returns an interface for the Attachment Manager.
+
+This methods returns an interface that can be used to provided attachment
+management functionality for each message entry.
+
+@return A reference to the Attachment Manager interface
+@see MMsvAttachmentManager
+*/
+EXPORT_C MMsvAttachmentManager& CMsvStore::AttachmentManagerL()
+	{
+	if( iAttachmentManager==NULL )
+		{
+		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
+		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
+		}
+		
+	MMsvAttachmentManager& attachmentAPI = *iAttachmentManager;
+	return attachmentAPI;
+	}
+	
+EXPORT_C MMsvAttachmentManagerSync& CMsvStore::AttachmentManagerExtensionsL()
+	{
+	if( iAttachmentManager==NULL )
+		{
+		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
+		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
+		}
+		
+	return (MMsvAttachmentManagerSync&) *iAttachmentManager;
+	}
+
+/**
+@internalTechnology
+@released
+*/
+EXPORT_C void CMsvStore::CreateShareProtectedAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
+	{
+	if (iAttachmentManager == NULL)
+		{
+		TBool isStoreReadOnly = (iLockStatus == EMsvStoreUnlocked ? ETrue : EFalse);
+		iAttachmentManager = CMsvAttachmentManager::NewL(*this, iStoreManager, iId, iFs, isStoreReadOnly);
+		}
+
+	iAttachmentManager->CreateShareProtectedAttachmentL(aFileName, aAttachmentFile, aAttachmentInfo);
+	}
+
+
+/**
+Intialise and return the CMsvPlainBodyText object that can be used for reading/writing plain body text.
+@param aIs8Bit				TBool indicating whether to store bdy text as 8/16 bit.
+@param aCharsetId			The charset of the body part.
+@param aDefaultCharsetId    The default charset of the system.
+@leave KErrAccessDenied		If Store is opened in Read mode.
+@return CMsvPlainBodyText.
+*/
+EXPORT_C CMsvPlainBodyText* CMsvStore::InitialisePlainBodyTextForWriteL(TBool aIs8Bit, TUint aCharsetId, TUint aDefaultCharsetId)
+	{
+	if(iLockStatus != EMsvStoreLocked)
+		{
+		User::Leave(KErrAccessDenied);
+		}
+	return CMsvPlainBodyText::NewL(iStoreManager, *this, aIs8Bit, aCharsetId, aDefaultCharsetId, iId, iFs);
+	}
+
+
+/**
+Intialise and return the CMsvPlainBodyText object that can be used for reading plain body text.
+@param aChunkLength		The length of the chunk that will be processed while reading.
+@leave KErrAccessDenied	If Store is opened in Write mode.
+@return CMsvPlainBodyText.
+*/
+EXPORT_C CMsvPlainBodyText* CMsvStore::InitialisePlainBodyTextForReadL(TInt aChunkLength)
+	{
+	if(iLockStatus == EMsvStoreLocked)
+		{
+		User::Leave(KErrAccessDenied);
+		}
+	return CMsvPlainBodyText::NewL(iStoreManager, *this, iId, iFs, aChunkLength);
+	}
+
+
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+/**
+Construct the CacheEntry.
+@param aMtmId  A TUid.
+@param aIsBodyEntry A TEntryStoreType.
+@return None.
+@internalComponent
+*/
+
+void CMsvStore::ConstructDbL(TUid aMtmId,TBool aReadOnly)
+	{
+	iStore=CMsvCachedStore::OpenL(iId, iStoreManager, aReadOnly,aMtmId);
+	iStore->iMtmId = aMtmId;
+	iBodyText = CMsvBodyText::NewL();	
+	iConstructed=ETrue;
+	}
+
+/**
+Open the Store for read.
+@param aObserver A MMsvStoreObserver as reference.
+@param aFs A RFs as reference.
+@param aStoreManager A MMsvStoreManager as reference.
+@param aId A TMsvId
+@param aMtmId A TUid.
+@param aIsBodyEntry A TEntryStoreType
+@return CMsvStore*
+@internalComponent
+*/
+
+EXPORT_C CMsvStore* CMsvStore::OpenForReadL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId, TUid aMtmId)
+	{
+	CMsvStore* store=new(ELeave)CMsvStore(aObserver, aFs, aId, aStoreManager);
+	CleanupStack::PushL(store);
+	store->ConstructDbL(aMtmId,ETrue);
+	CleanupStack::Pop(store);
+	return store;	
+	}
+
+
+/**
+Open the Store for write.
+@param aObserver A MMsvStoreObserver as reference.
+@param aFs A RFs as reference.
+@param aStoreManager A MMsvStoreManager as reference.
+@param aId A TMsvId
+@param aMtmId A TUid.
+@param aIsBodyEntry A TEntryStoreType
+@return CMsvStore*
+@internalComponent
+*/
+
+EXPORT_C CMsvStore* CMsvStore::OpenForWriteL(MMsvStoreObserver& aObserver, RFs& aFs, MMsvStoreManager& aStoreManager, TMsvId aId, TUid aMtmId)
+	{
+	CMsvStore* store=new(ELeave)CMsvStore(aObserver, aFs, aId, aStoreManager);
+	CleanupStack::PushL(store);
+	store->ConstructDbL(aMtmId,EFalse);
+	store->Lock();
+	CleanupStack::Pop(store);
+	return store;
+	}
+
+/**
+Restore the Header entry.
+@param None.
+@return None.
+@internalComponent
+*/
+void CMsvStore::RestoreL()
+	{
+	if (iStore==NULL )
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	iStoreManager.LoadHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList);	
+	}
+
+
+/**
+Create or Update the Header entry.
+@param None.
+@return None.
+@internalComponent
+*/
+void CMsvStore::CommitHeaderL()
+	{
+	TInt error = KErrNone;
+	if(!iStore->isNewEntry)
+		{
+		TRAP(error, iStoreManager.UpdateHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList));
+		}
+	else
+		{
+		TRAP(error, iStoreManager.CreateHeaderEntryL(iStore->iMtmId, iId, iStore->iHeaderFieldList));
+		iStore->isNewEntry = EFalse;
+		}
+	User::LeaveIfError(error);	
+	}
+
+/**
+Returns ETrue if entries stored in database
+*/
+EXPORT_C TBool CMsvStore::IsDbStore()
+	{
+	return 	iStore->isDbStore;
+	}
+
+
+/** Create TMsvWriteStore to read message store.
+
+@param aMsvStore The aMsvStore as reference. 
+@return TMsvWriteStore  write sore.
+ */
+EXPORT_C TMsvWriteStore::TMsvWriteStore(CMsvStore& aMsvStore):iMsvStore(aMsvStore)
+	{
+	}
+
+/**
+Assign the  header Fields in to header Field list.
+@param aHeaderFields : CHeaderFields*
+@return None.
+*/
+
+EXPORT_C void TMsvWriteStore::AssignL(CHeaderFields* aHeaderFields)
+	{
+	iMsvStore.iStore->AssignL(aHeaderFields);
+	}
+	
+/**
+Commit the header entry to message store 
+
+@param None.
+@return None.
+*/	
+	
+EXPORT_C void TMsvWriteStore::CommitL()
+	{
+	iMsvStore.CommitHeaderL();
+	}
+	
+
+/** Create TMsvReadStore to read message store.
+
+@param aMsvStore The aMsvStore as reference. 
+@param aUid The UID.
+@return TMsvReadStore  read sore.
+ */
+
+
+EXPORT_C TMsvReadStore::TMsvReadStore(CMsvStore& aMsvStore, TUid aUid):
+iMsvStore(aMsvStore), iUid(aUid)
+	{	
+	}
+	
+
+/** Load the Header entry from message store.
+
+@param aHeaderFields The CHeaderFields as pointer reference. 
+@return None.
+ */
+	
+	
+EXPORT_C void TMsvReadStore::LoadL(CHeaderFields*& aHeaderFields)
+	{
+	iMsvStore.RestoreL();
+	iMsvStore.iStore->GetHeaderL(iUid, aHeaderFields);
+	}
+	
+
+/** Read the Header entry from message store.
+
+@param aHeaderFields The CHeaderFields as pointer reference. 
+@return None.
+ */
+
+	
+EXPORT_C void TMsvReadStore::ReadL(CHeaderFields*& aHeaderFields)
+	{
+	iMsvStore.iStore->GetHeaderL(iUid, aHeaderFields);
+	}
+		
+
+#endif //#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)