/*
* Copyright (c) 2002-2007 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:   Decoding of binary multimedia message
*
*/



#ifndef CMMSDECODE_H
#define CMMSDECODE_H

//  INCLUDES
#include    <mentact.h>
#include    <cmsvattachment.h>

#include    "mmsservercommon.h"
#include    "mmscodecdatasink.h"

// CONSTANTS
// We cannot save unlimited number of attachments.
// We use a "sanity" limit which is actually insanely high, but should be safe.
const TInt KMmsMaxAttachments = 500;

// FUNCTION PROTOTYPES

// FORWARD DECLARATIONS
class MMmsEntryWrapper;
class RBufReadStream;
class CMmsHeaders;
class CMsvMimeHeaders;
class CMmsSettings;

// CLASS DECLARATION

/**
* Decoding of binary multimedia message.
*
* @lib mmscodec.lib
* @since V2.1
*/
class CMmsDecode :public CMsgActive, public MMmsCodecDataSink
    {
    
public:
        
    /** Lookup for file extension */
    typedef struct
        {
        const TText8* tag;
        const TText16* extension;
        }TMmsExtensionLookup;

    /** Lookup for extension header assigned values */
    typedef struct MmsExtensionHeaderLookup
        {
        const TText8* extensionHeader;
        const TUint8* assignedValue;
        }TMmsExtensionHeaderLookup;

    /**
     * @param aFs file system handle.
     */
    IMPORT_C static CMmsDecode* NewL( RFs& aFs );
    
    virtual ~CMmsDecode();

public:
    
    /**
     * Start the state machine.
     * @param aEntryWrapper entry class for message access
     * @param aMmsHeadders reference to CMmsHeaders class.
     * @param aDecodeBuffer buffer holding the data to be decoded.
     * @param aStatus status of calling active object
     * @param aStartPosition the starting point in the buffer.
     *     Default = 0, start from beginning.
     * @param aLength length of the data to be decoded.
     *     Default = 0, decode whole buffer
     * If memory runs out before state machine is started, leaves with error code.
     */
    IMPORT_C void StartL(
        MMmsEntryWrapper& aEntryWrapper,
        CMmsHeaders& aMmsHeaders,
        CBufFlat& aDecodeBuffer,
        TRequestStatus& aStatus,
        TInt aStartPosition = 0,
        TInt aLength = 0 );

    /**
     * Synchronous decoding function.
     * To be used for messages that have only headers and no body.
     * For example MMS notifications and delivery reports.
     * @param aEntryWrapper entry class for message access
     * @param aMmsHeaders reference to CMmsHeaders class.
     * @param aDecodeBuffer buffer holding the data to be decoded.
     * @param aStartPosition the starting point in the buffer.
     *     Default = 0, start from beginning.
     * @param aLength length of the data to be decoded.
     *     Default = 0, decode whole buffer
     * @param aNumberofAttachments pointer to a variable that will contain
     *     the number of attachments on return.
     *     Default = 0, no attachment number requested
     * @param aDataStart pointer to a variable that will contain the
     *     starting position of data in this MMS message.
     *     Will point to start of first multipart entry or start of
     *     monoblock data. If data type is WSP multipart, the assigned
     *     number of the multipart has been stored in aMmsHeaders.
     *     Default = 0, data part start not requested.
     * leaves with error code.
     */
    IMPORT_C void DecodeHeadersL(
        MMmsEntryWrapper& aEntryWrapper,
        CMmsHeaders& aMmsHeaders,
        CBufFlat& aDecodeBuffer,
        TInt aStartPosition = 0,
        TInt aLength = 0,
        TInt* aNumberOfAttachments = 0,
        TInt* aDataStart = 0 );

    /**
     * Decode attachments separately
     * @since 2.6
     * @param aEntryWrapper entry class for message access
     * @param aMmsHeaders reference to CMmsHeaders class.
     * @param aDecodeBuffer buffer holding the data to be decoded.
     * @param aNumberOfAttachments number of attachments to be decoded.
     * @param aStartPosition start position of the data to be decoded.
     *     On return this is updated to point to next data part.
     *     If this was the last data part, aStartPosition will point
     *     past the end of the buffer.
     * @param aStatus status of calling active object.
     * @param aDoNotUpdateParentEntry should the parent entry be updated with 
     *     attachment info.
     *     The parent entry should be updated only when the last attachment
     *     has been handled.
     *     Default EFalse = update parent entry.
     * @param aLength length of the data to be decoded.
     *     Default = 0, decode whole buffer.
     * If aNumberOfAttachments is the actual number of attachments, and
     * aDoNotUpdateParentEntry and aLength have their default values, the whole
     * attachment buffer is decoded and the result is the same as it were
     * if the headers and attachments had been decoded together.
     * If the attachments are handled one by one, aDoNotUpdateParentEntry should
     * be false only when the last attachment has been reached.
     */
    IMPORT_C void DecodeAttachmentsL(
        MMmsEntryWrapper& aEntryWrapper,
        CMmsHeaders& aMmsHeaders,
        CBufFlat& aDecodeBuffer,
        TInt aNumberOfAttachments,
        TInt& aStartPosition,
        TRequestStatus& aStatus,
        TBool aDoNotUpdateParentEntry = EFalse,
        TInt aLength = 0 );

    /**
     * Extract starting position and length of data content from WSP multipart
     * @since 2.6
     * @param aDecodeBuffer buffer holding the data to be decoded.
     * @param aStartPosition start position of the data to be decoded.
     *     On return this is updated to point to next data part.
     *     If this was the last data part, aStartPosition will point
     *     past the end of the buffer.
     * @param aStartOfData On return start of the actual data content in multipart entry
     * @param aLengthOfData On return the length of the data content.
     * @return Mime headers containing content type and content type parameters
     *     of the data part. The structure will be valid only until next call to 
     *     some function of CMmsDecode.
     */
    IMPORT_C CMsvMimeHeaders& ExtractNextDataPartL(
        CBufFlat& aDecodeBuffer,
        TInt& aStartPosition,
        TInt& aStartOfData,
        TInt& aLengthOfData);
        
    /*
     * Commit the store.
     * This function must be called to commit the store if attachments are decoded
     *     and stored individually without allowing the parent entry to be updated
     *     after last attachment.
     * This function can also be called to commit the store after each attachment.
     * This function does not delete the store. The store is deleted when headers
     *     are reseted to start decoding a new entry.
     */            
    IMPORT_C void CommitStoreL();
    
    
    /**
     * Initialize the decoder for work in chunked decoding mode.
     *
     * @since v3.1
     * Only chunked decoding of headers or incoming messages is supported.
     * Chunked decoding of MMBox descriptions is not supported.
     * Needed variables are initialized.
     * Data will be provided later through the MmsCodecDataSink API
     * @param aEntryWrapper entry class for message access.
     *     Must be initialized to point to created message entry to receive the data.
     * @param aMmsHeaders reference to CMmsHeaders class.
     * @param aDecodeBuffer buffer. Given only to ensure that the buffer is always defined.
     *     During initialization buffer contains no data and it can be changed by NextDataPart
     *     function. Normally the buffer given here is the same as given in NextDataPart,
     *     only content will change.
     *
     */
    IMPORT_C void InitializeChunkedMode(
        MMmsEntryWrapper& aEntryWrapper,
        CMmsHeaders& aMmsHeaders,
        CBufFlat& aDecodeBuffer
        );

// from base class MMmsCodecDataSink

    /**
     * From MMmsCodecDataSink.
     * Gives the next data part to be decoded.
     * Decoding is synchronous. When the code returns, data can be released.
     *
     * @since v3.1
     * @param aBuffer flat buffer containing the data to be decoded.
     * @param aPosition start of data to be decoded.
     *     Decoding will start from aPosition.
     *     At return aPosition will point to the data that has not been
     *     decoded yet (in case data ends with an incomplete header) or
     *     past the end of data if everything has been decoded.
     *     The caller can discard the beginning of data up to aPosition.
     *     If there is data left in the buffer it must be shifted to the
     *     beginning of buffer and new data appended to the end to allow
     *     an incomplete header to be decoded at next round.
     * @param aLastChunk ETrue if the data chunk in the buffer is the last one.
     * @return error code, KErrNone if decoding succeeds
     *     If returns some other error, transaction must be cancelled.
     */
    TInt NextDataPart(
        CBufFlat& aBuffer,
        TInt& aPosition,
        TBool aLastDataChunk );
        
    /**
     * From MMmsCodecDataSink.
     * Release data sink and free any resources
     * This funktion must be called after last data chunk has been processed.
     * This funktion must also be called if the process is terminated by an error.
     *
     * @since v3.1
     */
    void RelaseDataSink();
    
    /**
     * Reset data sink.
     * Delete all attachments from current message.
     * Reset MMS headers
     * Start message decoding from the beginning
     * 
     * This function must be called if transaction is interrupted and restarted
     *
     * @since v3.1
     */
    void ResetDataSink();
    
          
private:

    CMmsDecode();

    /**
     * @param aFs file system handle.
     */
    void ConstructL( RFs& aFs );

    /**
     * Active object completion.
     */
    void DoRunL();

    /**
     * Cleanup
     * @param aStatus the completion code
     */
    void DoComplete( TInt& aStatus );

    /**
     * Select next state for state machine.
     */
    void SelectNextState();

    /**
     * Switch states.
     */
    void ChangeStateL();

    /**
     * Initialize members to allow several entry points.
     * We have at least one service that does not preceed
     * in stages, but completes in one shot.
     */
    void Reset();
    
    /**
     * Header decode stage for chunked decoding
     * @param aLastDataChunk is the data chunk the last one
     * @return
     * - ETrue if more data is needed to finish decoding the headers
     * - EFalse if no more data is needed
     */
    TBool SinkHeaders( TBool aLastDataChunk );

    /**
     * Attachment header decode stage for chunked decoding
     * @param aLastDataChunk is the data chunk the last one
     * @return
     * - ETrue if more data is needed to finish decoding the headers
     * - EFalse if no more data is needed
     */
    TBool SinkAttachmentHeaders( TBool aLastDataChunk );
    
    /**
     * Attachment data start stage for chunked decoding
     */
    void SinkAttachmentDataStart();
    
    /**
     * Attachment data stage for chunked decoding
     */
    void SinkAttachmentData();
    
    /**
     * Attachment data finished for chunked decoding
     * @param aLastDataChunk is the data chunk the last one
     */
    void FinishSinkingAttachment( TBool aLastDataChunk );
    
    /**
     * Last chunk postamble for chunked decoding
     */
    void FinalizeSinkingLastChunk();
    
    /**
     * Do headers
     */
    void DecodeHeadersL();

    /**
     * Save the MMS headers
     */
    void SaveMMSHeadersL(); 

    /**
     * Decode one header
     */
    void DecodeOneHeaderL();
    
    /**
     * Get one header.
     * iPosition is advanced to point to the start of value. <br>
     *     (value coding depends on header.) <br>
     * If header name is unknown, pointer is advanced to point
     *     beyond parameters.
     * MMS headers only, assigned numbers only
     * @return -1, if unknown header assignment
     */
    TInt GetHeaderName();

    /**
     * Skip an unknown header name.
     */
// no longer used     
/*     
    void SkipTextString();
*/    

    /**
     * Skip field value (needed for unknown fields).
     */ 
    void SkipFieldValue();

    /**
     * Skip parameter name (needed for unsupported parameters).
     */ 
    void SkipParameterName();

    /**
     * Get uintvar that tells how many bytes will follow.
     * @return decoded number according to WSP uintvar specs
     */
    TUint32 GetUintvar();

    /**
     * Decode From field.
     * Caller must delete returned TDes16*
     * @return descriptor holding the address in unicode
     * (type has been removed)
     * from is different from rest of addresses, as there 
     * will be the "address present" token
     */
    HBufC16* DecodeFromL();
    
    /**
     * Decode address.
     * Caller must delete returned TDes16*
     * @return descriptor holding the address in unicode
     * (type has been removed)
     */
    HBufC16* DecodeAddressL();

    /**
     * Get simple text string.
     * ASCII into unicode.
     * @param aKeepQuote retain quote in the beginning of string.
     *      Needed only when caled from GetEncodedTextStringL.
     * @return descriptor holding unicode version of ASCII string
     */
    HBufC16* GetSimpleTextStringL( TBool aKeepQuote = EFalse );

    /**
     * Get encoded text string.
     * Convert to unicode from character set specified.
     * @return descriptor holding unicode version of string
     */
    HBufC16* GetEncodedTextStringL();

    /**
     * Get a text string as bytes (no conversions).
     * Data is not copied! The result is valid only as long as the
     *     source stays alive. The pointer will point to our
     *     decoding buffer, so it is valid as long as we stay alive.
     * @return descriptor pointing to byte string
     */
    TPtrC8 GetByteString();

    /**
     * Get a text string as bytes (no conversions).
     * Data is not copied! The result is valid only as long as the
     *     source stays alive. The pointer will point to our
     *     decoding buffer, so it is valid as long as we stay alive.
     * Leading 0x7F is removed, but characters from 0x80 to 0x8f are valid
     * @return descriptor pointing to byte string
     */
    TPtrC8 GetUtf8String();

    /**
     * Get short integer or a long integer that is no longer than 32 bits.
     * @return 32 bit integer
     * If the length of the integer is more than 4 bytes, the field is skipped
     */
    TUint32 GetLongOrShortInteger();

    /**
     * Get an integer that may be up to 64 bits long (for example date).
     * @return 64 bit integer
     */
    TInt64 GetVeryLongInteger();

    /**
     * Get a well known header assignment, skip field value if unknown coding.
     * @return token value, 0 if unknown coding (text string etc.)
     */
    TUint8 GetWellKnownFieldValueOrSkip();

    /**
     * Get token and date or interval value for time fields that have alternate coding.
     * @param aTime reference to 64 bit integer that receives
     *     the time.
     * @return absolute or reltive token, KMmsAbsoluteToken or
     *     KMmsRelativeToken. Returns 0, if cannot interpret field.
     */
    TUint8 GetRelativeOrAbsoluteTime( TInt64& aTime );

    /**
     * Get field length and skip the bytes that indicate the length.
     * If field is one-byte token, it is skipped and 0 is returned.
     * If field is text string, the length of the string (including 
     * terminating zero) is returned.
     * The field can be skipped by adding the indicated number of bytes to
     * current postition
     * @return the length of the value. 0 if not enough data
     */
    TUint GetValueLength();
    
    /**
     * Check if there is enough data in the buffer to decode a whole header
     *
     * @since v3.1
     * iPosition is always restored to its original value.
     *
     * @return ETrue if a whole header and its value is in the buffer.
     *     EFalse if not enough data and more should be obtained from the data source
     */
    TBool CheckHeaderLength();
    
    /**
     * Check if there is enough data in the buffer to decode a whole value
     *
     * @since v3.1
     *
     * @param aCheckUintvarData ETrue if routine must check that enough data bytes
     *     follow uintvar.
     *     This is needed when uintvar specifies the length of a header
     *     EFalse if only the integrity of the uintvar itself must be checked
     * @return ETrue if a whole value is in the buffer.
     *     EFalse if not enough data and more should be obtained from the data source
     */
    TBool CheckValueLength( TBool aCheckUintvarData );
    
    /**
     * See if there are enough bytes in the buffer to define a legal uintvar
     *
     * @since v3.1
     *
     * @return ETrue if a whole value is in the buffer.
     *     EFalse if not enough data and more should be obtained from the data source
     *     After check iPosition still points to the beginning of the Uintvar checked
     */
    TBool CheckUintvarLength();

    /**
     * Get attachment mime type.
     * @return pointer (with length) to the mime type string
     */
    TPtrC8 GetContentTypeL();

    /**
     * Get multipart content type.
     * Also gets parameters for the multipart type (start).
     * Root content type parameter is discarded (not used).
     * Start-info parameter is discarded (unless we know how to use it!).
     * @return assigned number for multipart content type,
     *   0 if not multipart (monoblock body)   
     */
    TUint8 GetMultipartContentTypeL();

    /**
     * Get content type and content type parameters for one attachment
     */
    void GetAttachmentContentTypeL();

    /**
     * Decode one content header from multipart headers.
     */
    void DecodeOneContentHeaderL();

    /**
     * Get one content header.
     * iPosition is advanced to point to the start of value.
     *     (value coding depends on header.)
     * @param atextHeader pointer set to header in text form
     * @return assigned number of header
     *      -1, if unknown header assignment
     *      0x7f if textual header (to handle X-type headers)
     */
    TInt GetContentHeaderName( TPtrC8& aTextHeader );

    /**
     * Decode one attachment.
     */
    void DecodeOneAttachmentL();
    
    /**
     * Decode attachment headers
     */
    void DecodeAttachmentHeadersL();
     
    /**
     * Extract parameters that are separated by semicolons.
     * Extracted parameters are stored to MIME headers.
     * @param aBuffer content parameter string ( actual content type string removed already)
     *     this should be of the form:
     *     parameter1=value1;parameter2=value2;parameter3=value3
     */
    void ExtractContentTypeParametersL( const TPtrC8& aBuffer );

    /**
     * Try to form filename from possibly MIME-encoded string
     * @param aSource suggestion for filename, may be MIME encoded
     * @param aDestination full path and filename, if aSource is valid name.
     * @param aPath path for the file.
     * @return ETrue if aSource forms a valid filename, EFalse if not.
     */
    TBool MakeFilenameL( TPtrC8& aSource, TParse& aDestination, const TFileName& aPath );

    /**
     * Cleanup (close streams etc.).
     */
    void FinishL();
    /**
    * check DRM contents.
    */
    TBool CheckDRMContentL();
    /**
     * Dump binary data into file.
     */
    void DumpL();
    
    /**
     * Dump smil part into separate file if needed
     @param aDataLength length of smil part
     */
    void DumpSmil(TInt aDataLength);

    /**
     * Log value yes/no
     * @param aTitle title text
     * @param aValue value that maps to KMmsYes or KMmsNo
     */
    void LogYesNo( TRefByValue<const TDesC> aTitle, TInt aValue );

    /**
     * Decode X-Mms-MM-Flags header and store value
     */
    void GetKeywordL();
    
    /** 
     * Get active and complete own status with error code.
     * To be used when state machine loop must be terminated with error
     */
    void CompleteSelf( TInt aError );
    
    /**
     * Check if string contains only US-ASCII characters.
     * @param aString the string to be checked
     * @return ETrue = ASCII, EFalse = contains characters >= 0x80
     */
    TBool IsStringSafe( const TDesC8& aString );
    
    /**
    * decode FROM header
    */
    void DecodeFromHeaderL();
    
    /**
    * decode TO header
    */
    void DecodeToL();
    
    /**
    * decode CC header
    */
    void DecodeCcL();
    
    /**
    * decode BCC header
    */
    void DecodeBccL();
    
    /**
    * decode content location header
    */
    void DecodeContentLocationHeaderL();
    
    /**
    * Decode message date header
    */
    void DecodeDateHeaderL();
    
    /**
    * Decode delivery report wanted header
    */
    void DecodeDeliveryReportHeader();
    
    /**
    * Decode message delivery time header
    */
    void DecodeDeliveryTimeL();
    
    /**
    * Decode message expiration header
    */
    void DecodeExpiryL();
    
    /**
    * Decode Message Class header
    */
    void DecodeMessageClass();
    
    /**
    * Decode message Id header
    */
    void DecodeMessageIdL();
    
    /**
    * Decode Message Type Header
    */
    void DecodeMessageType();
    
    /**
    * Decode MMS encapsulation version header
    */
    void DecodeMmsVersion();
    
    /**
    * Decode message size header
    */
    void DecodeMessageSize();
    
    /**
    * Decode priority header
    */
    void DecodePriority();
    
    /**
    * Decode Read Reply wanted header
    */
    void DecodeReadReply();
    
    /**
    * Decode delivery report sending allowed header
    */
    void DecodeReportAllowed();
    
    /**
    * decode response status or retrieve status header
    * @param aHeader tells if this is a response status or retrieve status
    */
    void DecodeResponseStatusL( TInt aHeader );
    
    /**
    * decode response text or retrieve text header
    */
    void DecodeResponseTextL( TInt aHeader );
    
    /**
    * Decode sender visibility header
    */
    void DecodeSenderVisibility();
    
    /**
    * decode message status header
    */
    void DecodeStatus();
    
    /**
    * decode subject header
    */
    void DecodeSubjectL();
    
    /**
    * decode Transaction ID
    */
    void DecodeTidL();
    
    /**
    * decode content type header
    */
    void DecodeContentTypeL();
    
    /**
    * Decode read status header
    */
    void DecodeReadStatus();
    
    /**
    * Decode Reply charging header
    */
    void DecodeReplyCharging();
    
    /**
    * Decode reply charging deadline header
    */
    void DecodeReplyChargingDeadlineL();
    
    /**
    * Decode Reply charging id header
    */
    void DecodeReplyChargingIdL();
    
    /**
    * Decode Reply charging size header
    */
    void DecodeReplyChargingSize();
    
    /**
    * Decode Previously-sent-by header
    */
    void DecodePreviousSenderL();
    
    /**
    * Decode Previously sent date header
    */
    void DecodePreviouslySentDateL();
    
    /**
    * Decode store-to-MMBox header
    */
    void DecodeStoreHeaderL();
    
    /**
    * Decode State in MMBox
    */
    void DecodeMMBoxStateL();
    
    /**
    * Decode MMBox Store status header
    */
    void DecodeMMBoxStoreStatusL();
    
    /**
    * Decode MMBox Store status text header
    */
    void DecodeMMBoxStoreStatusTextL();
    
    /**
    * Decode stored in MMBox header
    */
    void DecodeStoredInMMBoxHeaderL();
    
    /**
    * Decode attributes header in MMBox View
    */
    void DecodeAttributesHeaderL();
    
    /**
    * Decode Totals header in MMBox view
    */
    void DecodeTotalsL();
    
    /**
    * Decode totals header in MMBox view
    */
    void DecodeMboxTotalsL();
    
    /**
    * Decode MMBox View Quota header
    */
    void DecodeQuotaHeaderL();
    
    /**
    * Decode MMBox Quota header
    */
    void DecodeMBoxQuotasL();
    
    /**
    * Decode message count header in MMBox View
    */
    void DecodeMessageCountL();
    
    /**
    * Decode start header in MMBox View
    */
    void DecodeStartInMMBoxViewL();
    
    /**
    * Decode Distribution Indicator header
    */
    void DecodeDistributionIndicator();
    
    /**
    * Decode Element descriptor header
    */
    void DecodeElementDescriptorL();
    
    /**
    * Decode the limit header in MMBox view (max number of messages)
    */
    void DecodeMessageLimitL();
    
    /**
    * Decode the extended notification header
    */
    void DecodeExtNotifTextL();

    /**
    * Decode the extended notification end of string indicator
    */
    void DecodeExtNotifEolL();
    
    /**
    * Decode Content Class header
    */
    void DecodeContentClass();
    
    /**
    * Decode DRM Content header
    */
    void DecodeDrmContentHeader();
    
    /**
    * Decode Adaptation allowed header
    */
    void DecodeAdaptationAllowed();
    
    /**
    * Decode application id header
    */
    void DecodeApplicationIdL();
    
    /**
    * Decode reply to application id header 
    */
    void DecodeReplyApplicationIdL();
    
    /**
    * Decode application info header
    */
    void DecodeApplicationInfoL();
    
    /**
    * Decode recommended retrieval mode
    */
    void DecodeRecommendedRetrievalMode();

    /**
    * Decode explanation for the recommended retrieval mode
    */
    void DecodeRecommendedRetrievalModeTextL();
    
    /**
    * Decode id of a message to be cancelled or replaced
    */
    void DecodeCancelReplaceIdL( TInt aHeader );
    
    /**
    * Decode status of cancel operation
    */
    void DecodeCancelStatus();

#ifndef _NO_MMSS_LOGGING_
    /**
     * log date
     * @param aDate date to be logged
     */
    void LogDateL( const TInt64& aDate );
#endif

private:    // Data
    RFs                 iFs; // file system
    TInt                iError;
    TInt                iState;
    MMmsEntryWrapper*   iEntryWrapper;
    CMmsHeaders*        iMmsHeaders;
    CMsvMimeHeaders*    iMimeHeaders;

    CBufFlat*           iDecodeBuffer;
    TUint               iPosition;  // pointer to decode buffer
    TUint               iLength;    // total length of the message to be encoded
    TUint               iDataStart; // starting point of multipart data
    TUint               iNextStart; // starting point of next multipart
    TUint               iNumberOfAttachments;
    TUint               iTotalSize;
    // pointer to start of first text/plain part to be used to generate
    // a description in case actual subject is missing
    TUint               iFakeSubject;
    TUint               iTextPlainLength; // length of the data
    // IANA MIBEnum value of the first text/plain part
    TUint               iCharacterSet;
    // Assigned number for multipart body type.
    // If not multipart, iMultipartType will be 0.
    TUint8              iMultipartType;
    TPtrC8              iRootContentId;
    HBufC8*             iRootContentIdBuffer;
    TMsvAttachmentId    iRootAttachmentId;
    TMsvAttachmentId    iFirstAttachmentId; // if multipart/related,
                        // and root not defined, first attachment is root
    // Counter to generate filenames atta1, atta2, etc.
    // Also keeps track of total number of attachments to support audio messaging
    TInt                iAttaNumber;
    TInt                iSmilCount; // counts the number of SMIL parts
    TInt                iAudioCount; // counts the number of audio(amr) parts
    
    TInt32              iDRMFlags;

    // iLogAllDecoded is obsolete - everything is logged in debug version
    TBool               iLogAllDecoded;
    TBool               iDumpIncoming;

    TPtrC8              iMultipartRootType; // for logging only
    TParse              iParse;     // parse buffer stores current atta filename
    TBufC8<18>          iTempBuffer;
    TInt                iPlainTexts; // number of plain text attachments
    // if caller wants to know where position is, this pointer is non-zero
    TInt*               iUpdatedPosition;
    TBool               iDoNotUpdateParentEntry;
    CMsvStore*          iStore; // store kept open to save several attachments
    
    TInt                iDecodingStage; // stage for chunked encoding
    TInt                iCurrentAttaLength; // data length for current attachment
    TInt                iAttaDataWritten; // data that has already been written to atta file
    TInt                iOldData; // the amount of data left undecoded
    TMsvAttachmentId    iCurrentAttachment;
    TMsvAttachmentId    iFirstTextPlain;
    TBool               iUseForSubject;
    TBool               iRemoveDrm; // remove DRM atta (not really an error)
    // Emergency brake to detect when last header has been decoded
    // Needed when receiving a message that has no attachments from a server
    // that always sends an empty last chunk
    TBool               iLastHeader; 
    
        
#ifndef _NO_MMSS_LOGGING_
// iFilename is only needed when logging and dumping
    TFileName           iFileName ; // filename buffer as member to save stack space
#endif

    };

#endif      // CMMSDECODE_H
            
// End of File
