javaextensions/wma/mms/src.s60/cjavammsmessagehandler.cpp
branchRCL_3
changeset 14 04becd199f91
child 24 6c158198356e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/wma/mms/src.s60/cjavammsmessagehandler.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1018 @@
+/*
+* Copyright (c) 2008 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:  ?Description
+ *
+*/
+
+
+#include <apmstd.h>
+#include <s32stor.h>
+#include <badesca.h>  //to use descriptor arrays
+#include <eikenv.h>
+#include <eikdef.h>
+#include <driveinfo.h>
+#include <DocumentHandler.h>
+
+#include "logger.h"
+#include "s60commonutils.h"
+#include "javasymbianoslayer.h"
+#include "cjavammsmessagehandler.h"
+
+namespace java
+{
+namespace wma
+{
+
+const TInt KMmsMapLength = 7;
+const TInt KReplyToAppIDFieldIndex = 0;
+const TInt KAppIDFieldIndex = 1;
+const TInt KSubjectFieldIndex = 2;
+const TInt KFromFieldIndex = 3;
+const TInt KToFieldIndex = 4;
+const TInt KBccFieldIndex = 5;
+const TInt KCcFieldIndex = 6;
+const TInt KBufFlatGranularity = 10;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::CJavaMMSMessageHandler
+ * C++ default constructor
+ * -----------------------------------------------------------------------------
+ */
+CJavaMMSMessageHandler::CJavaMMSMessageHandler(RFs aRFs) :
+        mRFs(aRFs)
+{
+    JELOG2(EWMA);
+}
+
+/* -----------------------------------------------------------------------------
+ * Destructor
+ * -----------------------------------------------------------------------------
+ */
+CJavaMMSMessageHandler::~CJavaMMSMessageHandler()
+{
+    JELOG2(EWMA);
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::NewL
+ * Two-phased constructor.
+ * -----------------------------------------------------------------------------
+ */
+CJavaMMSMessageHandler* CJavaMMSMessageHandler::NewL(RFs aFs)
+{
+    JELOG2(EWMA);
+    CJavaMMSMessageHandler* self = new CJavaMMSMessageHandler(aFs);
+    return self;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::SerializeLC
+ * This method serializes an MMS (as it is received from the MMS engine) into
+ * a byte array which will be sent to java.
+ * The format of the serialized MMS is according to the following scheme:
+ *     ----------------------------------------------------------------------------------------------------------
+ *     | Map | HeaderLengths | AttachmentsCount | AttachmentsLengths | StartContentFlag | Headers | Attachments |
+ *     ----------------------------------------------------------------------------------------------------------
+ *
+ * where Map                 Represents the decimal value of a binary
+ *                          representation of MMS header fields
+ *                          (applicationID, Subject, From, To, Bcc, Cc)
+ *                          Ex: 52 = 110101 means that 'applicationID'
+ *                          is present, 'Subject' is present, 'From' is
+ *                          not present,'To' is present, 'Bcc' is not
+ *                          present and 'Cc' is present
+ *                          The lengths of each of the MMS header
+ *                          fields which are present
+ *      AttachmentsCount    The number of attachments
+ *      AttachmentsLengths  The lengths of each of the attachments
+ *      StartContentFlag    A boolean indicating if the first
+ *                          attachment should be interpreted as
+ *                          startContent or not
+ *      Headers             The MMS header fields
+ *      Attachments         The attachments
+ * -----------------------------------------------------------------------------
+ */
+CBufFlat& CJavaMMSMessageHandler::SerializeLC(CMMSMessageInformation& aMMS)
+{
+    JELOG2(EWMA);
+    // mms fields
+    TDesC8& replyToAppID = aMMS.ReplyToApplicationIdL();
+    TDesC8& appID = aMMS.ApplicationIdL();
+    TDesC8& subject = aMMS.MessageSubjectL();
+    TDesC8& from = aMMS.MessageFromAddressL();
+    // the address is on the cleanup stack
+    HBufC8& to = BuildAddressLC(EMsvRecipientTo, aMMS);
+    // the address is on the cleanup stack
+    HBufC8& bcc = BuildAddressLC(EMsvRecipientBcc, aMMS);
+    // the address is on the cleanup stack
+    HBufC8& cc = BuildAddressLC(EMsvRecipientCc, aMMS);
+
+    // calculate the mms Map
+    TInt mmsMap = 0;
+    mmsMap += CalculateMap(replyToAppID, appID, subject, from, to, bcc, cc);
+
+    // The serialized buffer
+    CBufFlat* buffer = CBufFlat::NewL(KBufFlatGranularity);
+    CleanupStack::PushL(buffer);
+    CCnvCharacterSetConverter* cConv = CCnvCharacterSetConverter::NewL();
+    CleanupStack::PushL(cConv);
+    RBufWriteStream writeStream(*buffer, 0);
+
+    // add the mmsMap
+    writeStream.WriteUint8L(mmsMap);
+
+    // add the mms fields lengths
+    WriteDes8LengthL(writeStream, replyToAppID);
+    WriteDes8LengthL(writeStream, appID);
+    WriteDes8LengthL(writeStream, subject);
+    WriteDes8LengthL(writeStream, from);
+    WriteDes8LengthL(writeStream, to);
+    WriteDes8LengthL(writeStream, bcc);
+    WriteDes8LengthL(writeStream, cc);
+
+    // add the attachments count
+    TInt8 attchmts = aMMS.AttachmentCount();
+    writeStream.WriteUint8L(attchmts);
+
+    // add the attachments lenghts
+    TInt firstAttchmt = WriteAttachmentsLengthsL(writeStream, aMMS, *cConv);
+
+    // add the starterCID indicator
+    if (attchmts > 0)
+    {
+        if (firstAttchmt >= 0)
+        {
+            writeStream.WriteUint8L(1);
+        }
+        else
+        {
+            writeStream.WriteUint8L(0);
+        }
+    }
+
+    // add the priority
+    TMmsMessagePriority priority = aMMS.MessagePriority();
+    switch (priority)
+    {
+    case EMmsPriorityLow:
+        writeStream.WriteUint8L(KPriorityLow);
+        break;
+    case EMmsPriorityNormal:
+        writeStream.WriteUint8L(KPriorityNormal);
+        break;
+    case EMmsPriorityHigh:
+        writeStream.WriteUint8L(KPriorityHigh);
+        break;
+    default:
+        writeStream.WriteUint8L(KPriorityNormal);
+        break;
+    }
+
+    // add the date
+    WriteInt64L(writeStream, aMMS.MessageTime());
+
+    // add the mms fields
+    WriteDes8L(writeStream, replyToAppID);
+    WriteDes8L(writeStream, appID);
+    WriteDes8L(writeStream, subject);
+    WriteDes8L(writeStream, from);
+    WriteDes8L(writeStream, to);
+    WriteDes8L(writeStream, bcc);
+    WriteDes8L(writeStream, cc);
+
+    // add the attachments
+    WriteAttachmentsL(writeStream, aMMS, *cConv, firstAttchmt);
+
+    // cleanup
+    CleanupStack::PopAndDestroy(cConv);
+    CleanupStack::Pop(buffer);
+    CleanupStack::PopAndDestroy(&cc);
+    CleanupStack::PopAndDestroy(&bcc);
+    CleanupStack::PopAndDestroy(&to);
+    CleanupStack::PushL(buffer);
+
+    return *buffer;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteAttachmentsL
+ * Writes all the attachments into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteAttachmentsL(RBufWriteStream& aWriteStream,
+        CMMSMessageInformation& aMMS, CCnvCharacterSetConverter& aCharConv,
+        TInt firstAttchmt)
+{
+    JELOG2(EWMA);
+    TInt8 attchmts = aMMS.AttachmentCount();
+    if (firstAttchmt >= 0)
+    {
+        WriteAttachmentL(aWriteStream, aMMS.Attachment(firstAttchmt), aCharConv);
+    }
+    for (TInt i = 0; i < attchmts; i++)
+    {
+        if (i != firstAttchmt)
+        {
+            WriteAttachmentL(aWriteStream, aMMS.Attachment(i), aCharConv);
+        }
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteAttachmentL
+ * Writes an attachment into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteAttachmentL(RBufWriteStream& aWriteStream,
+        CMMSMessageAttachment& aAttch, CCnvCharacterSetConverter& aCharConv)
+{
+    JELOG2(EWMA);
+    // mime type
+    WriteDes8L(aWriteStream, aAttch.AttachmentType());
+    // content ID
+    WriteDes8L(aWriteStream, aAttch.ContentIdL());
+    // content location
+    WriteDes8L(aWriteStream, aAttch.ContentLocationL());
+    // content encoding
+    TUint charSetID = aCharConv.ConvertMibEnumOfCharacterSetToIdentifierL(
+                          aAttch.Encoding(), mRFs);
+    HBufC8* encoding = aCharConv.ConvertCharacterSetIdentifierToStandardNameL(
+                           charSetID, mRFs);
+    CleanupStack::PushL(encoding);
+    if (encoding)
+    {
+        aWriteStream.WriteL(*(encoding));
+    }
+    CleanupStack::PopAndDestroy(encoding);
+    // content
+    WriteDes8L(aWriteStream, aAttch.AttachmentData());
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteAttachmentsLengthsL
+ * Writes all attachments lengths (one by one) into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+TInt CJavaMMSMessageHandler::WriteAttachmentsLengthsL(RBufWriteStream& aWriteStream,
+        CMMSMessageInformation& aMMS, CCnvCharacterSetConverter& aCharConv)
+{
+    JELOG2(EWMA);
+    TInt firstAttchmt = -1;
+    TInt8 attchmts = aMMS.AttachmentCount();
+    if (attchmts > 0)
+    {
+        // quick browse through the attachments to see if the starterCID is used
+        for (TInt i = 0; i < attchmts; i++)
+        {
+            CMMSMessageAttachment& attch = aMMS.Attachment(i);
+            if (attch.IsStarterContentId())
+            {
+                // put the starterCID first
+                WriteAttachmentLengthsL(aWriteStream, attch, aCharConv);
+                firstAttchmt = i;
+                break;
+            }
+        }
+    }
+    for (TInt i = 0; i < attchmts; i++)
+    {
+        if (i != firstAttchmt)
+        {
+            WriteAttachmentLengthsL(aWriteStream, aMMS.Attachment(i), aCharConv);
+        }
+    }
+    return firstAttchmt;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteAttachmentLengthsL
+ * Writes an attachment lengths into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteAttachmentLengthsL(RBufWriteStream& aWriteStream,
+        CMMSMessageAttachment& aAttch, CCnvCharacterSetConverter& aCharConv)
+{
+    JELOG2(EWMA);
+    // mime type length
+    WriteDesLengthOrZeroL(aWriteStream, aAttch.AttachmentType());
+    // content ID length
+    WriteDesLengthOrZeroL(aWriteStream, aAttch.ContentIdL());
+    // content location length
+    WriteDesLengthOrZeroL(aWriteStream, aAttch.ContentLocationL());
+    // content encoding length
+    TUint charSetID = aCharConv.ConvertMibEnumOfCharacterSetToIdentifierL(
+                          aAttch.Encoding(), mRFs);
+    HBufC8* encoding = aCharConv.ConvertCharacterSetIdentifierToStandardNameL(
+                           charSetID, mRFs);
+    CleanupStack::PushL(encoding);
+    if (encoding)
+    {
+        WriteIntL(aWriteStream, encoding->Length());
+    }
+    else
+    {
+        WriteIntL(aWriteStream, 0);
+    }
+    CleanupStack::PopAndDestroy(encoding);
+    // content size
+    WriteDesLengthOrZeroL(aWriteStream, aAttch.AttachmentData());
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::BuildAddressLC
+ * Concatenates all the addresses/recipients into a ";" separated
+ * string/descriptor.
+ * -----------------------------------------------------------------------------
+ */
+HBufC8& CJavaMMSMessageHandler::BuildAddressLC(
+    TMsvRecipientTypeValues aAddressType, CMMSMessageInformation& aMMS)
+{
+    JELOG2(EWMA);
+    _LIT(KAddressSep, ";");
+    HBufC8* address = HBufC8::NewLC(0);
+    TPtr8 AddressPtr(address->Des());
+    for (int i = 0; i < aMMS.AddressesCount(aAddressType); i++)
+    {
+        TDesC& currentAddress = aMMS.MessageAddressL(aAddressType, i);
+        HBufC8* tmp = NULL;
+        if (i < aMMS.AddressesCount(aAddressType) - 1)
+        {
+            tmp = address->ReAllocL(address->Length() + currentAddress.Length()
+                                    + 1);
+        }
+        else
+        {
+            tmp
+            = address->ReAllocL(address->Length()
+                                + currentAddress.Length());
+        }
+        CleanupStack::Pop(address);
+        address = tmp;
+        CleanupStack::PushL(address);
+        AddressPtr.Set(address->Des());
+        AddressPtr.Append(currentAddress);
+        if (i < aMMS.AddressesCount(aAddressType) - 1)
+        {
+            AddressPtr.Append(KAddressSep);
+        }
+    }
+    return *address;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::CalculateMap
+ * Calculates the mms map.
+ * -----------------------------------------------------------------------------
+ */
+TInt CJavaMMSMessageHandler::CalculateMap(TDesC8& aReplyToAppID, TDesC8& aAppID,
+        TDesC8& aSubject, TDesC8& aFrom,
+        HBufC8& aTo, HBufC8& aBcc, HBufC8& aCc)
+{
+    JELOG2(EWMA);
+    TInt mmsMap = 0;
+    if (&aReplyToAppID)
+    {
+        mmsMap += K64BitsMask;
+    }
+    if (&aAppID)
+    {
+        mmsMap += K32BitsMask;
+    }
+    if (&aSubject)
+    {
+        mmsMap += K16BitsMask;
+    }
+    if (&aFrom)
+    {
+        mmsMap += K8BitsMask;
+    }
+    if (&aTo)
+    {
+        mmsMap += K4BitsMask;
+    }
+    if (&aBcc)
+    {
+        mmsMap += K2BitsMask;
+    }
+    if (&aCc)
+    {
+        mmsMap += 1;
+    }
+    return mmsMap;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteInt64L
+ * Writes an integer as 8 bytes into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteInt64L(RBufWriteStream& aWriteStream,
+        const TInt64 aInteger)
+{
+    JELOG2(EWMA);
+    aWriteStream.WriteInt8L(aInteger >> K56BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K48BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K40BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K32BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K24BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K16BitsMask);
+    aWriteStream.WriteInt8L(aInteger >> K8BitsMask);
+    aWriteStream.WriteInt8L(aInteger);
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteIntL
+ * Writes an integer as 4 bytes into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteIntL(RBufWriteStream& aWriteStream,
+                                       const TInt32 aInteger)
+{
+    JELOG2(EWMA);
+    aWriteStream.WriteUint8L(aInteger >> K24BitsMask);
+    aWriteStream.WriteUint8L(aInteger >> K16BitsMask);
+    aWriteStream.WriteUint8L(aInteger >> K8BitsMask);
+    aWriteStream.WriteUint8L(aInteger);
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteDes8L
+ * Writes a descriptor (if not NULL) into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteDes8L(RBufWriteStream& aWriteStream,
+                                        const TDesC8& aDes)
+{
+    JELOG2(EWMA);
+    if (&aDes)
+    {
+        aWriteStream.WriteL(aDes);
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteDes8LengthL
+ * Writes a descriptor's length (if not NULL) into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteDes8LengthL(RBufWriteStream& aWriteStream,
+        const TDesC8& aDes)
+{
+    JELOG2(EWMA);
+    if (&aDes)
+    {
+        WriteIntL(aWriteStream, aDes.Length());
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteDes8LengthOrZeroL
+ * Writes a descriptor's length (if descriptor is not NULL) or zero (if
+ * descriptor is NULL) into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteDes8LengthOrZeroL(RBufWriteStream& aWriteStream,
+        const TDesC8& aDes)
+{
+    JELOG2(EWMA);
+    if (&aDes)
+    {
+        aWriteStream.WriteUint8L(aDes.Length());
+    }
+    else
+    {
+        aWriteStream.WriteUint8L(0);
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::WriteDesLengthOrZeroL
+ * Writes a descriptor's length (if descriptor is not NULL) or zero (if
+ * descriptor is NULL) into the write stream.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::WriteDesLengthOrZeroL(RBufWriteStream& aWriteStream,
+        const TDesC8& aDes)
+{
+    JELOG2(EWMA);
+    if (&aDes)
+    {
+        WriteIntL(aWriteStream, aDes.Length());
+    }
+    else
+    {
+        WriteIntL(aWriteStream, 0);
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::DeSerializeL
+ * This method de-serializes an MMS (as it is received java) into
+ * an internal representation (used by the MMS engine proxy).
+ * The format of the serialized MMS is according to the following scheme:
+ *     ----------------------------------------------------------------------------------------------------------
+ *     | Map | HeaderLengths | AttachmentsCount | AttachmentsLengths | StartContentFlag | Headers | Attachments |
+ *     ----------------------------------------------------------------------------------------------------------
+ *
+ * where Map                 Represents the decimal value of a binary
+ *                          representation of MMS header fields
+ *                          (applicationID, Subject, From, To, Bcc, Cc)
+ *                          Ex: 52 = 110101 means that 'applicationID'
+ *                          is present, 'Subject' is present, 'From' is
+ *                          not present,'To' is present, 'Bcc' is not
+ *                          present and 'Cc' is present
+ *                          The lengths of each of the MMS header
+ *                          fields which are present
+ *      AttachmentsCount    The number of attachments
+ *      AttachmentsLengths  The lengths of each of the attachments
+ *      StartContentFlag    A boolean indicating if the first
+ *                          attachment should be interpreted as
+ *                          startContent or not
+ *      Headers             The MMS header fields
+ *      Attachments         The attachments
+ * -----------------------------------------------------------------------------
+ */
+CMMSMessageInformation& CJavaMMSMessageHandler::DeSerializeL(CBufFlat& aMMS)
+{
+    JELOG2(EWMA);
+    RBufReadStream rStream(aMMS, 0);
+
+    // get the raw mms map
+    TInt32 headerLengths[KMmsMapLength] =
+        { 0, 0, 0, 0, 0, 0 };
+
+    ResolveMapL(rStream, headerLengths);
+    // get the attachments count
+    TInt8 attchmts = rStream.ReadUint8L();
+
+    // get the attachments lenghts
+    RArray<TInt> mimeLengths(1);
+    CleanupClosePushL(mimeLengths);
+    RArray<TInt> cidLengths(1);
+    CleanupClosePushL(cidLengths);
+    RArray<TInt> cLocationLengths(1);
+    CleanupClosePushL(cLocationLengths);
+    RArray<TInt> cEncodingLengths(1);
+    CleanupClosePushL(cEncodingLengths);
+    RArray<TInt32> contentLengths(1);
+    CleanupClosePushL(contentLengths);
+    for (TInt i = 0; i < attchmts; i++)
+    {
+        // read the mime length
+        mimeLengths.InsertL(ReadIntL(rStream), i);
+        // read the content ID length
+        cidLengths.InsertL(ReadIntL(rStream), i);
+        // read the content Location length
+        cLocationLengths.InsertL(ReadIntL(rStream), i);
+        // read the content Encoding length
+        cEncodingLengths.InsertL(ReadIntL(rStream), i);
+        // read the content length
+        contentLengths.InsertL(ReadIntL(rStream), i);
+    }
+
+    // get the startContentId flag
+    TInt8 startCID = 0;
+    if (attchmts > 0)
+    {
+        startCID = rStream.ReadUint8L();
+    }
+
+    CMMSMessageInformation& msg = ResolveHeadersLC(rStream, headerLengths);
+    // msg is on the cleanup stack
+
+    // read the attachments
+    CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewL();
+    CleanupStack::PushL(charConv);
+    for (TInt i = 0; i < attchmts; i++)
+    {
+        HBufC8* mime = HBufC8::NewL(mimeLengths[i]);
+        CleanupStack::PushL(mime);
+        TPtr8 mimePtr(mime->Des());
+        HBufC8* cid = HBufC8::NewL(cidLengths[i]);
+        CleanupStack::PushL(cid);
+        TPtr8 cidPtr(cid->Des());
+        HBufC8* cLocation = HBufC8::NewL(cLocationLengths[i]);
+        CleanupStack::PushL(cLocation);
+        TPtr8 cLocationPtr(cLocation->Des());
+        HBufC8* cEncoding = HBufC8::NewL(cEncodingLengths[i]);
+        CleanupStack::PushL(cEncoding);
+        TPtr8 cEncodingPtr(cEncoding->Des());
+        HBufC8* content = HBufC8::NewL(contentLengths[i]);
+        CleanupStack::PushL(content);
+        TPtr8 contentPtr(content->Des());
+        // read the mime
+        rStream.ReadL(mimePtr, mimeLengths[i]);
+        // read the content ID
+        rStream.ReadL(cidPtr, cidLengths[i]);
+        // read the content Location
+        rStream.ReadL(cLocationPtr, cLocationLengths[i]);
+        // read the content Encoding
+        rStream.ReadL(cEncodingPtr, cEncodingLengths[i]);
+        // read the content
+        rStream.ReadL(contentPtr, contentLengths[i]);
+
+        // Save the contentPtr in the file and later add the fileName
+        TDesC8* attachmentName = NULL;
+        SaveDataToFileL(contentPtr, attachmentName, *mime);
+        CMMSMessageAttachment* attch = CMMSMessageAttachment::NewL(mRFs,
+                                       *attachmentName, mimePtr, cidPtr, cLocationPtr);
+        delete attachmentName;
+        attachmentName = NULL;
+        TUint charSetID = charConv->ConvertStandardNameOfCharacterSetToIdentifierL
+                          (cEncodingPtr, mRFs);
+        TUint mibEnum = charConv->ConvertCharacterSetIdentifierToMibEnumL(
+                            charSetID, mRFs);
+        attch->SetEncoding(mibEnum);
+        CleanupStack::PushL(attch);
+        if (i == 0 && startCID == 1)
+        {
+            attch->SetStarterContentId(TRUE);
+        }
+        else
+        {
+            attch->SetStarterContentId(FALSE);
+        }
+        msg.InsertAttachmentL(attch);
+        CleanupStack::Pop(attch);
+        CleanupStack::PopAndDestroy(content);
+        CleanupStack::PopAndDestroy(cEncoding);
+        CleanupStack::PopAndDestroy(cLocation);
+        CleanupStack::PopAndDestroy(cid);
+        CleanupStack::PopAndDestroy(mime);
+    }
+    CleanupStack::PopAndDestroy(charConv);
+    CleanupStack::Pop(&msg); // msg
+
+    // deallocate the dynamic arrays
+    CleanupStack::PopAndDestroy(&contentLengths);
+    CleanupStack::PopAndDestroy(&cEncodingLengths);
+    CleanupStack::PopAndDestroy(&cLocationLengths);
+    CleanupStack::PopAndDestroy(&cidLengths);
+    CleanupStack::PopAndDestroy(&mimeLengths);
+    return msg;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::Divide
+ * This method returns what's left from dividing aNum1 with aNum2.
+ * It is used in serialization/deserialization, when calculating the mmsMap
+ * -----------------------------------------------------------------------------
+ */
+TInt CJavaMMSMessageHandler::Divide(TInt aNum1, TInt aNum2)
+{
+    JELOG2(EWMA);
+    if (aNum1 / aNum2 > 0)
+    {
+        return (aNum1 - (aNum2 *(aNum1 / aNum2)));
+    }
+    return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::ReadIntL
+ * Reads an integer as 4 bytes
+ * -----------------------------------------------------------------------------
+ */
+TInt32 CJavaMMSMessageHandler::ReadIntL(RBufReadStream& aReadStream)
+{
+    JELOG2(EWMA);
+    TInt32 byte1 = aReadStream.ReadUint8L();
+    TInt32 byte2 = aReadStream.ReadUint8L();
+    TInt32 byte3 = aReadStream.ReadUint8L();
+    TInt32 byte4 = aReadStream.ReadUint8L();
+    return (byte1 << K24BitsMask) + (byte2 << K16BitsMask) + (byte3
+            << K8BitsMask) + byte4;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::ReadInt64L
+ * Reads an integer as 8 bytes
+ * -----------------------------------------------------------------------------
+ */
+TInt64 CJavaMMSMessageHandler::ReadInt64L(RBufReadStream& aReadStream)
+{
+    JELOG2(EWMA);
+    TInt64 byte1 = aReadStream.ReadUint8L();
+    TInt64 byte2 = aReadStream.ReadUint8L();
+    TInt64 byte3 = aReadStream.ReadUint8L();
+    TInt64 byte4 = aReadStream.ReadUint8L();
+    TInt64 byte5 = aReadStream.ReadUint8L();
+    TInt64 byte6 = aReadStream.ReadUint8L();
+    TInt64 byte7 = aReadStream.ReadUint8L();
+    TInt64 byte8 = aReadStream.ReadUint8L();
+    return (byte1 << K56BitsMask) + (byte2 << K48BitsMask) + (byte3
+            << K40BitsMask) + (byte4 << K32BitsMask) + (byte5 << K24BitsMask)
+           + (byte6 << K16BitsMask) + (byte7 << K8BitsMask) + byte8;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::ResolveMapL
+ * Resolves the map of the multimedia message. The map of the multimedia
+ * message consists of a byte whose bits indicate which of the
+ * multimedia message headers are present. See comments of 'DeSerialize' method
+ * for more details about the mms map.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::ResolveMapL(RBufReadStream& aReadStream,
+        TInt32 aHeaderLengths[])
+{
+    JELOG2(EWMA);
+    TInt8 mmsMap = aReadStream.ReadUint8L();
+
+    // resolve the mms map
+    while (true)
+    {
+        TInt div = Divide(mmsMap, K64BitsMask);
+        if (div >= 0)
+        {
+            // get reply to app id length
+            aHeaderLengths[KReplyToAppIDFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        div = Divide(mmsMap, K32BitsMask);
+        if (div >= 0)
+        {
+            // get appID length
+            aHeaderLengths[KAppIDFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        div = Divide(mmsMap, K16BitsMask);
+        if (div >= 0)
+        {
+            // get subject length
+            aHeaderLengths[KSubjectFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        div = Divide(mmsMap, K8BitsMask);
+        if (div >= 0)
+        {
+            // get the from length
+            aHeaderLengths[KFromFieldIndex] = ReadIntL(aReadStream);
+        }
+        div = Divide(mmsMap, K4BitsMask);
+        if (div >= 0)
+        {
+            // get to length
+            aHeaderLengths[KToFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        div = Divide(mmsMap, K2BitsMask);
+        if (div >= 0)
+        {
+            // get bcc length
+            aHeaderLengths[KBccFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        if (mmsMap >= 0)
+        {
+            // get cc length
+            aHeaderLengths[KCcFieldIndex] = ReadIntL(aReadStream);
+            if (div == 0)
+                break;
+            mmsMap = div;
+        }
+        break;
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::ResolveHeadersLC
+ * Resolves/reads the headers of the multimedia message from the stream
+ * and sets them to the internal representation of the multimedia
+ * message
+ * -----------------------------------------------------------------------------
+ */
+CMMSMessageInformation& CJavaMMSMessageHandler::ResolveHeadersLC(
+    RBufReadStream& aReadStream, TInt32 aHeaderLengths[])
+{
+    JELOG2(EWMA);
+    // priority
+    TInt8 prio = aReadStream.ReadUint8L();
+    // date
+    TInt64 date = ReadInt64L(aReadStream);
+    CMMSMessageInformation* msg = CMMSMessageInformation::NewL(KNullDesC, date,
+                                  KNullDesC8, NULL);
+    CleanupStack::PushL(msg);
+    // reply to appID
+    HBufC8* replyToAppID =HBufC8::NewL(aHeaderLengths[KReplyToAppIDFieldIndex]);
+    CleanupStack::PushL(replyToAppID);
+    TPtr8 replyToAppIDPtr(replyToAppID->Des());
+    // appID
+    HBufC8* appID = HBufC8::NewL(aHeaderLengths[KAppIDFieldIndex]);
+    CleanupStack::PushL(appID);
+    TPtr8 appIDPtr(appID->Des());
+    // subject
+    HBufC8* subject = HBufC8::New(aHeaderLengths[KSubjectFieldIndex]);
+    CleanupStack::PushL(subject);
+    TPtr8 subjectPtr(subject->Des());
+    // from
+    HBufC8* from = HBufC8::NewL(aHeaderLengths[KFromFieldIndex]);
+    CleanupStack::PushL(from);
+    TPtr8 fromPtr(from->Des());
+    // to
+    HBufC8* to = HBufC8::NewL(aHeaderLengths[KToFieldIndex]);
+    CleanupStack::PushL(to);
+    TPtr8 toPtr(to->Des());
+    // bcc
+    HBufC8* bcc = HBufC8::NewL(aHeaderLengths[KBccFieldIndex]);
+    CleanupStack::PushL(bcc);
+    TPtr8 bccPtr(bcc->Des());
+    // cc
+    HBufC8* cc = HBufC8::NewL(aHeaderLengths[KCcFieldIndex]);
+    CleanupStack::PushL(cc);
+    TPtr8 ccPtr(cc->Des());
+    for (TInt i = 0; i < KMmsMapLength; i++)
+    {
+        if (aHeaderLengths[i] > 0)
+        {
+            // read the first aHeaderLengths[i] bytes
+            switch (i)
+            {
+            case(KReplyToAppIDFieldIndex):
+                // reply to app ID
+                aReadStream.ReadL(replyToAppIDPtr, aHeaderLengths[i]);
+                break;
+            case(KAppIDFieldIndex):
+                // app ID
+                aReadStream.ReadL(appIDPtr, aHeaderLengths[i]);
+                break;
+            case(KSubjectFieldIndex):
+                // subject
+                aReadStream.ReadL(subjectPtr, aHeaderLengths[i]);
+                break;
+            case(KFromFieldIndex):
+                // from
+                aReadStream.ReadL(fromPtr, aHeaderLengths[i]);
+                break;
+            case(KToFieldIndex):
+                // to
+                aReadStream.ReadL(toPtr, aHeaderLengths[i]);
+                break;
+            case(KBccFieldIndex):
+                // bcc
+                aReadStream.ReadL(bccPtr, aHeaderLengths[i]);
+                break;
+            case(KCcFieldIndex):
+                // cc
+                aReadStream.ReadL(ccPtr, aHeaderLengths[i]);
+                break;
+            default:
+                // Nothing to do
+                break;
+            }
+        }
+    }
+    // create the CMMSMessageInformation
+    msg->SetApplicationIdL(appIDPtr);
+    msg->SetReplyToApplicationIdL(replyToAppIDPtr);
+    msg->SetMessageSubjectL(subjectPtr);
+    switch (prio)
+    {
+    case KPriorityLow:
+        //low
+        msg->SetMessagePriority(EMmsPriorityLow);
+        break;
+    case KPriorityNormal:
+        //normal
+        msg->SetMessagePriority(EMmsPriorityNormal);
+        break;
+    case KPriorityHigh:
+        //high
+        msg->SetMessagePriority(EMmsPriorityHigh);
+        break;
+    default:
+        // Nothing to do
+        break;
+    }
+    // parse the addresses and set them to the message
+    ParseAndSetAddressL(EMsvRecipientTo, toPtr, *msg);
+    ParseAndSetAddressL(EMsvRecipientBcc, bccPtr, *msg);
+    ParseAndSetAddressL(EMsvRecipientCc, ccPtr, *msg);
+    // pop the pointers before deleting them
+    CleanupStack::PopAndDestroy(cc);
+    CleanupStack::PopAndDestroy(bcc);
+    CleanupStack::PopAndDestroy(to);
+    CleanupStack::PopAndDestroy(from);
+    CleanupStack::PopAndDestroy(subject);
+    CleanupStack::PopAndDestroy(appID);
+    CleanupStack::PopAndDestroy(replyToAppID);
+    return *msg;
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::ParseAndSetAddressL
+ * Splits the concatenated addresses (";" separated string/descriptor)
+ * into sepparate tokens and sets them individually to the internal
+ * representation of the multimedia message.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::ParseAndSetAddressL(
+    TMsvRecipientTypeValues aAddressType,
+    TDes8& aAddr,
+    CMMSMessageInformation& aMsg)
+{
+    JELOG2(EWMA);
+    if (aAddr.Length() == 0)
+    {
+        return;
+    }
+    else
+    {
+        while (true)
+        {
+            TInt off = aAddr.Locate(';');
+            if (off != KErrNotFound)
+            {
+                TPtrC8 left = aAddr.Left(off);
+                aMsg.AddAddressL(aAddressType, left);
+                TPtrC8 right = aAddr.Right(aAddr.Length() - off - 1);
+                aAddr.Copy(right);
+            }
+            else
+            {
+                aMsg.AddAddressL(aAddressType, aAddr);
+                break;
+            }
+        }
+    }
+}
+
+/* -----------------------------------------------------------------------------
+ * CJavaMMSMessageHandler::SaveDataToFileL
+ * Save data to the D-drive. MMS engine assume that attachments are
+ * always files. It also help us to use less RAM.
+ * -----------------------------------------------------------------------------
+ */
+void CJavaMMSMessageHandler::SaveDataToFileL(const TDesC8& aDataArray,
+        TDesC8*& aFileName,
+        const TDesC8& aDataType)
+{
+    JELOG2(EWMA);
+    //// create a dummy attached file here on the D (temp) drive
+    RFile attachementFile;
+    TInt err = 0;
+    TBuf<KMaxFileName> fileName;
+    int i = 1;
+    CDocumentHandler* docHandler = CDocumentHandler::NewLC();
+    do
+    {
+        fileName.SetLength(0);
+        //fileName.Append(KTempDrive); // Add the drive name
+        TChar driveInfo;
+        DriveInfo::GetDefaultDrive(DriveInfo::EDefaultRam, driveInfo);
+        fileName.Append(driveInfo);
+        fileName.Append(KTempDriveExt);
+        fileName.Append(KTempMmsAttachmentName); // Add the drive name
+        fileName.AppendNum((int) this);
+        fileName.AppendNum(i++);
+        // we delegate the DocHandler to append the file extension
+        TDataType mimeType(aDataType);
+        docHandler->CheckFileNameExtension(fileName, mimeType);
+        err = attachementFile.Create(mRFs, fileName, EFileWrite
+                                     | EFileShareExclusive);
+    }
+    while (KErrAlreadyExists == err);
+    CleanupStack::PopAndDestroy(docHandler);
+    if (err != KErrNone)
+    {
+        User::LeaveIfError(err);
+    }
+    else
+    {
+        // Get the file name, so that we can delete it later
+        java::util::S60CommonUtils::ConvertWiderToNarrowL(fileName,
+                (TDesC8*&) aFileName);
+
+        // add data to the newly created attached file.
+        attachementFile.Write(aDataArray);
+        attachementFile.Flush();
+        attachementFile.Close();
+    }
+}
+
+} //namespace wma
+} //namespace java
+