//****************************************************************************************
// IMCVRECV.H
//
// Copyright (c) 1998 Symbian Ltd.  All rights reserved.
//****************************************************************************************

#if !defined (__IMCVRECV_H__)
#define __IMCVRECV_H__

#if !defined (__S32MEM_H__)
#include <s32mem.h>
#endif

#if !defined (__BADESCA_H__)
#include <BADESCA.H> // required for CBufSeg
#endif

#if !defined (__IMCVTEXT_H__)
#include "imcvtext.h"
#endif

#if !defined (__IMCVFILT_H__)
#include "imcvfilt.h"
#endif

#if !defined (__IMCVCONV_H__)
#include "imcvconv.h"
#endif

// Oyster includes
#if !defined(__MSVSTD_H__)
#include <msvstd.h>
#endif

#if !defined(__MSVENTRY_H__)
#include <msventry.h>
#endif

#if !defined(__MSVSTORE_H__)
#include <msvstore.h>
#endif

#if !defined(__MSVUIDS_H__)
#include <MSVUIDS.H>
#endif

#if !defined(__MSVIDS_H__)
#include <MSVIDS.H>
#endif


class CImHeader;
class CRichText;
class CMimeParser;
class CImRecvConvert;
class RFs;
class TImConvert;
class TImAttachmentFile;

const TInt KHeaderBufferLength = 100;

// Max filename length
const TInt MaxMimeParameterValueLength = 256;

//priorities
const TInt KPriorityHigh	=1;
const TInt KPriorityNormal	=3; 
const TInt KPriorityLow		=5;

//boundary stuff
const KBoundaryNotFound		=0;
const KBoundaryFound		=1;
const KBoundaryError		=2;

//----------------------------------------------------------------------------------------
class CRfc822Token : public CBase
//----------------------------------------------------------------------------------------
	{
public:
	enum THeaderPart { EUnknown, ENotFinished, EFrom, EReplyTo, ETo, ECc, EBcc, ESubject, EDate, EMessageId, EPriority, EXPriority, EPrecedence, EImportance, EReturnReceiptTo, EEndOfHeader };
	THeaderPart iHeaderPart;
	TBool iLastToken;
	TBool iFirstLine;

	IMPORT_C static CRfc822Token* NewLC();
	IMPORT_C void Reset();
	inline HBufC8* OutputLine();
	IMPORT_C void ParseNextLineL( const TDesC8& aSourceLine );
	IMPORT_C ~CRfc822Token();
	inline TBool LastToken();

	inline void SetImRecvConvert( CImRecvConvert* );
private:
	TBool MatchAndRemoveL( const TDesC8& );
	CRfc822Token();
	void ConstructL();

private:
	TBuf8<KMaxIMailHeaderReadLineLength+1> iInputLine;
	TBuf8<KMaxIMailHeaderReadLineLength+1> iBufferedInput;
	HBufC8* iOutputLine;
	CImRecvConvert* iImRecvConvert;
	};


//----------------------------------------------------------------------------------------
class CImRecvConvert : public CBase
//----------------------------------------------------------------------------------------	
	{
friend class CMimeParser;
public:
	IMPORT_C static CImRecvConvert* NewLC( RFs& anFs, CMsvServerEntry* aServerEntry, 
												TUid aMsgType, TMsvId aEmailServiceId);
	IMPORT_C static CImRecvConvert* NewL( RFs& anFs, CMsvServerEntry* aServerEntry,
												TUid aMsgType, TMsvId aEmailServiceId);
	IMPORT_C ~CImRecvConvert();

	IMPORT_C void ResetL();
	IMPORT_C void ResetForHeadersL();

	inline void SetAttachmentPathL(const TDesC& aFullPath);	// attachment path, if not set then IMCV will reject attachments
	inline void SetMsvId(TMsvId aId);

	IMPORT_C TInt ParseNextFieldL(const TDesC8& aSourceLine);
	IMPORT_C void MessageCompleteL();
	IMPORT_C void MessageCompleteL(TMsvEmailEntry aEmailEntry);
	IMPORT_C TMsvEmailEntry MessageEntryDetailsL();

	enum TValidEntryType {EMessageEntry, EFolderEntry, EAttachmentEntry, ETextEntry};

	inline const TTime Date() const;	// return RFC822 date
	inline const TMsvPriority Priority() const;
	inline void SaveAllAttachments(TBool aSave);
	inline const TInt ReceiveError() const;
	inline CMsvServerEntry& ServerEntry();
	inline const CImHeader& Header() const;
	inline const TBool ValidCompleteHeader() const;
	inline const TMsvId EntryId() const;	
	inline CImQPDecode& QPDecoder();
	inline TBool NotFinishedRfc822Header();
	
private:
	CImRecvConvert(RFs& anFs, CMsvServerEntry* aServerEntry, 
							TUid aMsgType, TMsvId aEmailServiceId);
	void ConstructL(RFs& anFs);

	void ParseNextLineL(const TDesC8& aSourceLine);
	void ParseBodyLineL(const TDesC8& aSourceLine);
	void ParseMimeLineL(const TDesC8& aSourceLine);
	void DecodeAndStoreLineL(const TDesC8& aSourceLine);

	void ParseRecipientListL(CDesCArray& aRecipientList);
	void PrepareDecoder();

	void WriteToBodyL(const TDesC8& text);
#if defined (_UNICODE)
	void WriteToBodyL(const TDesC16& text);
#endif	

	void SetDefaultFilename();
	void ExtractFilename(TLex& aLex, TDes& rFileName);
	
	TBool CheckUUEStartL(const TDesC8& aSourceLine);
	TBool IsIllegalChar(const TUint aChar);
	void BeautifyWrapping(const TDesC8& aSourceLine, HBufC8& aConvertedLine);
	// returns numeric value of text up to next delimiter
	TInt Value(const TUint8*&);
	void Whitespace(const TUint8*&);
	TBool LineIsAllWhitespace();	

	void EvaluateImPriority();
	TInt ConvertPriorityIntoNumber(const TDesC8& aPriority);
	void ReadPrecedence(const TDesC8& aPriority);
	void ReadImportance(const TDesC8& aPriority);

	void CreateAttachmentL();
	void WriteToAttachmentL(const TDesC8& text);
	void CloseAttachmentFileL();

	// Message Entry specific functions
	void ResetForNewEntryL();
	void ResetForNonMimeEntryL();
	void MoveToParentEntryL();
	TBool StoreEntryDataL(CMsvStore& aStore);
	void StoreEntryStreamsL();
	void CreateEntryL();

private:
	TBool iMessageEntryCalled;
	TBool iReceivingHeadersOnly;
	TInt iReceiveError; // indicates if any anomalies were observed whilst the message was received
	TInt iLeaveError; // keeps any errors that have caused a leave (ie Out of memory, Corrupt file, Server error)

	TMsvId iOriginalMsvServerId;
	TMsvId iTopMessagePart;

	TImAttachmentFile iAttachmentFile;	// attachment file object
	CMsvServerEntry* iServerEntry;
	TUid iNewMsgType;

	CRfc822Token* iRfc822Token;

	TValidEntryType iEntryType;

	TMsvEmailEntry* iEmailEntry;
	CImHeader* iOutputHeader;
	CParaFormatLayer* iParaLayer;
	CCharFormatLayer* iCharLayer;
	CRichText* iOutputBody;
	CImMultipartData* iMultipartData;
	
	CImConvertCharconv* iCharConv;
	CCnvCharacterSetConverter* iConverter;
	
	TBool iParentPart;
	TBool iRfc822Part;
	
	TInt iEmptyHeaderSize;

	TImBodyConvAlgorithm iAlgorithm;

	TBool iCommitLine;	
	TBool iFinalLine;	
	TBool iPrepared;
	TBool iFinishedHeader;
	TBool iNotFinishedRfc822Header;

	CImQPDecode* iBodyDecoder;
	CCnvCharacterSetConverter* iCharacterConverter;
	CImConvertHeader* iHeaderConverter;

	TImRfc822DateField iRfc822Date;

	RFs* iFsSession;  

	TBool iSkipData;

	TBool iCurrentPartIsRichText;	//indicates if current body part is RichText, set on every Close Attachment()
	TImConvert iDecoder;
	TPtrC8 iThisLine;
	
	HBufC* iRemovedAttachmentTag;		// resource text which is put into the body in place of a removed MIME attachment
	HBufC* iRetainedAttachmentTag;		// resource text which is put into the body next to a retained MIME attachment
	HBufC* iDefaultAttachmentName;		// used when no name found	
	HBufC* iAttachmentFullPath;			// full path to current message file

	TBool iSavingAttachments;			// Turn on/off saving of attachments

	TBuf8<KMaxBoundaryTextLength> iSeekBoundary;
	
	TBool iFirstBodyLine;
	TInt iGlobalIndent;
	TInt iPreviousLineLength;
	TInt iPreviousTrailingWhitespace;
	TUint8 iLastChar;
	TInt iLongestLine;
	TBool iNewEntry;

	TImAttachmentFileState iAttachmentFileState;
	TUint32 iEntryDataSize;

	TBool	iLogFileExists;
	RFile	iLogFile;
	TLex8	iLineLex;
	TTime   iTimeDate;

	//priorities   //vk
	TInt iPriority;		//{1..5}
	TInt iXPriority;   // {1..5} 1,2-high, 3-normal, 4,5-low
	TBuf8<KMaxPriorityTextLength> iPrecedence;  //   {bulk-low, list-normal,first class,special delivery-0}
	TBuf8<KMaxPriorityTextLength> iImportance;  // {high, low, normal}
	TMsvPriority iImPriority;

	TMsvId iEmailServiceId;
public:
	TFileName iAttachmentName;
	CMimeParser* iMimeParser;
	};


//----------------------------------------------------------------------------------------
class CMimeParser : public CBase
//----------------------------------------------------------------------------------------
	{
public:
	IMPORT_C static CMimeParser* NewLC(CImRecvConvert& aImRecvConvert);
	IMPORT_C static CMimeParser* NewL(CImRecvConvert& aImRecvConvert);
	IMPORT_C ~CMimeParser();
	void Reset();
	void ResetForNewEntry();
	void ParseLineL(const TDesC8& aSourceLine);

	void SetBoundaryL(const TDesC8& aBoundaryText);
	TBool IsBoundary(const TDesC8& aSourceLine);
	void RemoveBoundary();
	
	inline void StoreMimeHeaderL(CMsvStore& entryStore);
	inline void RestoreMimeHeaderL(CMsvStore& entryStore);

	inline TImEncodingType ContentEncoding();
	inline TMimeContentType ContentType();
	TPtrC8 ContentSubType() const;
	TPtrC8 CurrentCharset() const;

	inline const TBool MessageIsMime() const;
	inline const TBool IsTerminatingBoundary() const;
	inline const TBool BoundaryExists() const;
	inline const TBool BoundaryFound() const;
	inline const TInt MimeHeaderSize() const;
	inline const TInt ReceiveError() const;
	inline const TDesC& ContentDescription() const;
	inline const TPtrC8 ContentLocation() const;
	inline const TPtrC8 ContentId() const;
	const TBool VCard() const;
	const TBool VCalendar() const;
	const TImEmailFolderType MessageFolderType() const;
	const TBool StartPart() const;
	void RestoreMimeParser(CMsvStore& entryStore);

private:
	CMimeParser(CImRecvConvert& aImRecvConvert);
	void ConstructL();

	// String scanning functions
	TBool IsSpecialChar(const TUint8 aChar);
	TBool MatchAndRemoveToken(const TDesC8& aToken);
	void ExtractParameterInfoL(const TDesC8& aTag, TPtr8& rBuffer);	

	// MIME token recognition functions
	void DoMimeVersion();
	void DoContentTypeL();
	void DoContentLocationL();
	void DoContentBaseL();
	void DoContentIdL();
	void DoEncodingL();
	void DoDescriptionL();
	void DoDispositionL();

	// MIME Content-Type type recognition functions
	void DoTextTypeL();
	void DoMultipartTypeL();
	void DoMessageTypeL();
	void DoAttachmentTypeL();

	// Will be moved to MIUT, but for now ..
	const TPtrC8 GetContentTypeValue(const TDesC8& aContentTypeParameter) const;

private:
	CImRecvConvert& iImRecvConvert;
	
	CImMimeHeader* iMimeHeader;
	TInt iEmptyMimeHeaderSize;
	
	TBool isMime;
	TBool iCorrectMimeVersion;
	TImEncodingType iContentEncoding;
	TMimeContentType iContentType;
	TFileName iContentDescription;
	TBool iVCard;
	TBool iVCalendar;
	TBool iStartPart;
	TImEmailFolderType iMessageFolderType;
	HBufC8* iCharset;
	HBufC8* iStartId;

	// Boundary stuff
	CDesC8ArrayFlat* iBoundaryText;
	TInt iBoundaryIndex;
	TInt iBoundaryLength;
	TBool iTerminatingBoundary;
	TBool iBoundaryFound;
	TInt iReceiveError; // Indicates if any anomalies were observed whilst the message was received
						// Can be accessed via the inline ReceiveError()
	TPtrC8 iTestLine;

	HBufC8* iMimeHeaderLine;
	TLexMark8 iMark;
	TLex8 iLex;
	TLex8 iTestLex;	
	};

#include "imcvrecv.inl"

#endif 