--- /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
+