// IMCVCONV.H
//
// Copyright (c) 1998 Symbian Ltd.  All rights reserved. 
//

#ifndef __IMCVCONV_H__
#define __IMCVCONV_H__

#include <e32base.h>

#if !defined (__MIUTHDR_H_)
#include <miuthdr.h>
#endif

#if !defined (__CHARCONV_H_)
#include <charconv.h>
#endif

#if !defined (__UTF_H_)
#include <utf.h>
#endif


class CImQPDecode;
class CImQPEncode;

#define KBase64 _L("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
#define KCharFormat _L("%c")

const KImCvFinished=(-1);


 // Maximum length allowed for an 'encoded-word' rfc2047
const TInt KEncodedWordMaxLength = 75;
const TInt KMaxCharsetNameLength = 256;
const TInt KMaxEncodedTypeLength = 1; // Length of encoding character

// All encoding information except data and charset name length.
const TInt KMaxEncodedInformationLength = KMaxEncodedTypeLength+6;

// Length of the field name, eg "Subject: ". This may change as other fields are processed.  
const TInt KMaxHeaderFieldNameLength = 10;


//----------------------------------------------------------------------------------------
class TImConvert
//----------------------------------------------------------------------------------------
	{
private:
	// base64 and UU coding defines
	enum EMaskValues{ ESixBitMask = 0x3F, EEightBitMask = 0xFF };
	enum EMaskShiftValues{ ESix = 6, EFour = 4, ETwo = 2, EZero = 0 };

	// base64 coding defines
	enum{ EPadChar = 64 };

	// UU coding defines
	enum{ ESpace = 32, EBackQuote = 96 };

public:
	IMPORT_C TImConvert();
	IMPORT_C ~TImConvert();

	// base64 coding functions
	IMPORT_C TBool DecodeB64(const TDesC8& aSrcString, TDes8& rDestString); // Line by line decoder
	// returns 1 if aSrcString is not long enough to decode fully, resulting in the storage of the
	// last character and requiring another aSrcString (poss 0 length) to be passed to it to clear
	// this character.
	// returns 0 if the line was decoded OK or the end of the encoded file is reached ie "="

	IMPORT_C void EncodeB64(const TDesC8& aSrcString, TDes8& rDestString); // TDes8* must be 33% larger than the string to be converted

	// uu coding functions
	IMPORT_C TBool DecodeUU(const TDesC8& aSrcString, TDes8& rDestString); // Line by line decoder
	// returns 1 if aSrcString is not long enough (determined by the 1st char in the string)
	// or if an invalid UU encoded character is found.
	// returns 0 if the line was decoded OK

	IMPORT_C void EncodeUU(const TDesC8& aSrcString, TDes8& rDestString); // TDes8* must be 33% larger than the string to be converted

private:
	TInt iShiftStored;
	TInt iMaskShiftStored;

	};


//----------------------------------------------------------------------------------------
class CImCharsetNameMatching : public CBase
//----------------------------------------------------------------------------------------
	{
public:
	IMPORT_C static CImCharsetNameMatching* NewL(RFs& anFs,
			 CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* aCharsetsAvailable);
	IMPORT_C ~CImCharsetNameMatching( );

	IMPORT_C TUint GetMimeCharsetUid(const TDesC& aBufIn) const;
private:
	CImCharsetNameMatching(RFs& anFs,
			 CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* aCharsetsAvailable);
	void ConstructL();
	void ReadResourceFileL();
private:
	RFs& iFsSession;
	CDesCArray* iCharsetNamesList;
	CArrayFixFlat<TUint>* iCharsetPositionList;
	CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* iCharsetsAvailable; 
	};




// Wrapper class for CHARCONV.
// 'Our' charset dependant on build, UNICODE or CodePage 1252.
//----------------------------------------------------------------------------------------
class CImConvertCharconv : public CBase
//----------------------------------------------------------------------------------------
	{
public:	
	IMPORT_C static CImConvertCharconv* NewL(CCnvCharacterSetConverter& aConverter, RFs& anFs);
	~CImConvertCharconv();

	IMPORT_C TInt ConvertToOurCharsetL(const TDesC8& aBufIn, TDes& rBufOut, TDesC8& aCharset);
	IMPORT_C TInt ConvertFromOurCharsetL(const TDesC& aBufIn, TDes8& rBufOut, TDesC8& aCharset);

	// MUST call prepare function first.
	IMPORT_C TInt ConvertToOurCharsetL(const TDesC8& aBufIn, TDes& rBufOut, const TUint& aUid);
	IMPORT_C TInt ConvertFromOurCharsetL(const TDesC& aBufIn, TDes8& rBufOut, const TUint& aUid);

	IMPORT_C TUint PrepareToConvertToFromOurCharsetL(const TDesC8& aCharset);
	IMPORT_C TUint PrepareToConvertToFromOurCharsetL(const TUint aUid);

	IMPORT_C TBool GetMimeCharsetUid(const TDesC8& aBufIn, TUint& rUid) const;
private:
	void ConstructL();
	CImConvertCharconv(CCnvCharacterSetConverter& aConverter, RFs& anFs);
	TInt StraightCopy( const TDesC8& aBufIn, TDes& rBufOut);
#if defined (_UNICODE)
	TInt StraightCopy( const TDesC& aBufIn, TDes8& rBufOut);
#endif
private:
	CCnvCharacterSetConverter& iConverter;
	CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* iCharsetsAvailable; 
	CnvUtfConverter iUtfConverter;

	RFs& iFs;
	CImCharsetNameMatching* iMatching;
	TUint iCharsetUid;
	};


// For converting a text string to/from encoded form
// Note: 'Word' here has special meaning derived from the one defined in rfc2047.
// It refers to one encoding instance.

//----------------------------------------------------------------------------------------
class CImConvertHeader : public CBase
//----------------------------------------------------------------------------------------
	{
public:
	IMPORT_C static CImConvertHeader* NewL(CImConvertCharconv& aConverter);
	~CImConvertHeader();

	IMPORT_C void DecodeAllHeaderFieldsL(CImHeader& rHeader); 

	// coder/decoder for single descriptors	
	IMPORT_C void DecodeHeaderFieldL(const TDesC& aBufIn, TDes& rBufOut); 

	IMPORT_C void EncodeHeaderFieldL(const TDesC& aBufIn, TDes8& rBufOut);
	IMPORT_C void EncodeHeaderFieldL(const TDesC& aBufIn, TDes8& rBufOut, 
		const TDesC8& aCharset, const CImHeaderEncodingInfo::TEncodingType aType);
	
	// Header needed for retrieving encoding information, used in Send code.
	IMPORT_C void EncodeHeaderFieldL(const TDesC& aBufIn, TDes8& rBufOut, 
								CImHeader& rHeader, TInt aState, TInt aArrayVal = 0);

	IMPORT_C TBool FindEncodedWord(TPtrC8& aData, TInt& aInit,TInt& rStart, TInt& rEnd);

private:
	void ConstructL();
	CImConvertHeader(CImConvertCharconv&);

	// Functions dealing only with single 'encoded-word's
	void EncodeWordL(const TDesC& aBufIn, TDes8& rBufOut, CImHeaderEncodingInfo& aInfo);
	TInt DecodeWordL(const TDesC8& aBufIn, TDes& rBufOut); // Returns num of unconverted elements

	void DecodeRecipientListL( CDesCArray& aArray);
	void DecodeFieldL(const TDesC& aField);

	TBool EncodeWordDataL(const TDesC& aBufIn, TDes8& rBufOut, CImHeaderEncodingInfo& aInfo);
	TInt AddEncodedWordInfo(const TDesC8& aBufIn, TDes8& rBufOut, CImHeaderEncodingInfo& aInfo);

	void Append(TDes& aBuffer, TDesC8& aAddition);
	TBool IsAscii( TUint aChar );
private:
	CImHeaderEncodingInfo* iEncodingInfo;
	CImConvertCharconv& iCharConv;

	// Get access to QP/ Base64 encoding/decoding functions
	TImConvert	 iDecoder;
	CImQPDecode* iQPDecode;
	CImQPEncode* iQPEncode;

	// Need in the narrow build, to check if possible to convert to/from
	// the machines character set.
	TUint iCharacterSetId; 

	CImHeader* iHeader;	

	// Converted static variables used in EncodeWordL()
	HBufC8* iBuf;
	TInt iRecurse;

	};



#endif

