javaextensions/wma/mms/src.s60/cjavammsmessagehandler.cpp
branchRCL_3
changeset 19 04becd199f91
child 47 f40128debb5d
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include <apmstd.h>
       
    20 #include <s32stor.h>
       
    21 #include <badesca.h>  //to use descriptor arrays
       
    22 #include <eikenv.h>
       
    23 #include <eikdef.h>
       
    24 #include <driveinfo.h>
       
    25 #include <DocumentHandler.h>
       
    26 
       
    27 #include "logger.h"
       
    28 #include "s60commonutils.h"
       
    29 #include "javasymbianoslayer.h"
       
    30 #include "cjavammsmessagehandler.h"
       
    31 
       
    32 namespace java
       
    33 {
       
    34 namespace wma
       
    35 {
       
    36 
       
    37 const TInt KMmsMapLength = 7;
       
    38 const TInt KReplyToAppIDFieldIndex = 0;
       
    39 const TInt KAppIDFieldIndex = 1;
       
    40 const TInt KSubjectFieldIndex = 2;
       
    41 const TInt KFromFieldIndex = 3;
       
    42 const TInt KToFieldIndex = 4;
       
    43 const TInt KBccFieldIndex = 5;
       
    44 const TInt KCcFieldIndex = 6;
       
    45 const TInt KBufFlatGranularity = 10;
       
    46 
       
    47 // ============================ MEMBER FUNCTIONS ===============================
       
    48 
       
    49 /* -----------------------------------------------------------------------------
       
    50  * CJavaMMSMessageHandler::CJavaMMSMessageHandler
       
    51  * C++ default constructor
       
    52  * -----------------------------------------------------------------------------
       
    53  */
       
    54 CJavaMMSMessageHandler::CJavaMMSMessageHandler(RFs aRFs) :
       
    55         mRFs(aRFs)
       
    56 {
       
    57     JELOG2(EWMA);
       
    58 }
       
    59 
       
    60 /* -----------------------------------------------------------------------------
       
    61  * Destructor
       
    62  * -----------------------------------------------------------------------------
       
    63  */
       
    64 CJavaMMSMessageHandler::~CJavaMMSMessageHandler()
       
    65 {
       
    66     JELOG2(EWMA);
       
    67 }
       
    68 
       
    69 /* -----------------------------------------------------------------------------
       
    70  * CJavaMMSMessageHandler::NewL
       
    71  * Two-phased constructor.
       
    72  * -----------------------------------------------------------------------------
       
    73  */
       
    74 CJavaMMSMessageHandler* CJavaMMSMessageHandler::NewL(RFs aFs)
       
    75 {
       
    76     JELOG2(EWMA);
       
    77     CJavaMMSMessageHandler* self = new CJavaMMSMessageHandler(aFs);
       
    78     return self;
       
    79 }
       
    80 
       
    81 /* -----------------------------------------------------------------------------
       
    82  * CJavaMMSMessageHandler::SerializeLC
       
    83  * This method serializes an MMS (as it is received from the MMS engine) into
       
    84  * a byte array which will be sent to java.
       
    85  * The format of the serialized MMS is according to the following scheme:
       
    86  *     ----------------------------------------------------------------------------------------------------------
       
    87  *     | Map | HeaderLengths | AttachmentsCount | AttachmentsLengths | StartContentFlag | Headers | Attachments |
       
    88  *     ----------------------------------------------------------------------------------------------------------
       
    89  *
       
    90  * where Map                 Represents the decimal value of a binary
       
    91  *                          representation of MMS header fields
       
    92  *                          (applicationID, Subject, From, To, Bcc, Cc)
       
    93  *                          Ex: 52 = 110101 means that 'applicationID'
       
    94  *                          is present, 'Subject' is present, 'From' is
       
    95  *                          not present,'To' is present, 'Bcc' is not
       
    96  *                          present and 'Cc' is present
       
    97  *                          The lengths of each of the MMS header
       
    98  *                          fields which are present
       
    99  *      AttachmentsCount    The number of attachments
       
   100  *      AttachmentsLengths  The lengths of each of the attachments
       
   101  *      StartContentFlag    A boolean indicating if the first
       
   102  *                          attachment should be interpreted as
       
   103  *                          startContent or not
       
   104  *      Headers             The MMS header fields
       
   105  *      Attachments         The attachments
       
   106  * -----------------------------------------------------------------------------
       
   107  */
       
   108 CBufFlat& CJavaMMSMessageHandler::SerializeLC(CMMSMessageInformation& aMMS)
       
   109 {
       
   110     JELOG2(EWMA);
       
   111     // mms fields
       
   112     TDesC8& replyToAppID = aMMS.ReplyToApplicationIdL();
       
   113     TDesC8& appID = aMMS.ApplicationIdL();
       
   114     TDesC8& subject = aMMS.MessageSubjectL();
       
   115     TDesC8& from = aMMS.MessageFromAddressL();
       
   116     // the address is on the cleanup stack
       
   117     HBufC8& to = BuildAddressLC(EMsvRecipientTo, aMMS);
       
   118     // the address is on the cleanup stack
       
   119     HBufC8& bcc = BuildAddressLC(EMsvRecipientBcc, aMMS);
       
   120     // the address is on the cleanup stack
       
   121     HBufC8& cc = BuildAddressLC(EMsvRecipientCc, aMMS);
       
   122 
       
   123     // calculate the mms Map
       
   124     TInt mmsMap = 0;
       
   125     mmsMap += CalculateMap(replyToAppID, appID, subject, from, to, bcc, cc);
       
   126 
       
   127     // The serialized buffer
       
   128     CBufFlat* buffer = CBufFlat::NewL(KBufFlatGranularity);
       
   129     CleanupStack::PushL(buffer);
       
   130     CCnvCharacterSetConverter* cConv = CCnvCharacterSetConverter::NewL();
       
   131     CleanupStack::PushL(cConv);
       
   132     RBufWriteStream writeStream(*buffer, 0);
       
   133 
       
   134     // add the mmsMap
       
   135     writeStream.WriteUint8L(mmsMap);
       
   136 
       
   137     // add the mms fields lengths
       
   138     WriteDes8LengthL(writeStream, replyToAppID);
       
   139     WriteDes8LengthL(writeStream, appID);
       
   140     WriteDes8LengthL(writeStream, subject);
       
   141     WriteDes8LengthL(writeStream, from);
       
   142     WriteDes8LengthL(writeStream, to);
       
   143     WriteDes8LengthL(writeStream, bcc);
       
   144     WriteDes8LengthL(writeStream, cc);
       
   145 
       
   146     // add the attachments count
       
   147     TInt8 attchmts = aMMS.AttachmentCount();
       
   148     writeStream.WriteUint8L(attchmts);
       
   149 
       
   150     // add the attachments lenghts
       
   151     TInt firstAttchmt = WriteAttachmentsLengthsL(writeStream, aMMS, *cConv);
       
   152 
       
   153     // add the starterCID indicator
       
   154     if (attchmts > 0)
       
   155     {
       
   156         if (firstAttchmt >= 0)
       
   157         {
       
   158             writeStream.WriteUint8L(1);
       
   159         }
       
   160         else
       
   161         {
       
   162             writeStream.WriteUint8L(0);
       
   163         }
       
   164     }
       
   165 
       
   166     // add the priority
       
   167     TMmsMessagePriority priority = aMMS.MessagePriority();
       
   168     switch (priority)
       
   169     {
       
   170     case EMmsPriorityLow:
       
   171         writeStream.WriteUint8L(KPriorityLow);
       
   172         break;
       
   173     case EMmsPriorityNormal:
       
   174         writeStream.WriteUint8L(KPriorityNormal);
       
   175         break;
       
   176     case EMmsPriorityHigh:
       
   177         writeStream.WriteUint8L(KPriorityHigh);
       
   178         break;
       
   179     default:
       
   180         writeStream.WriteUint8L(KPriorityNormal);
       
   181         break;
       
   182     }
       
   183 
       
   184     // add the date
       
   185     WriteInt64L(writeStream, aMMS.MessageTime());
       
   186 
       
   187     // add the mms fields
       
   188     WriteDes8L(writeStream, replyToAppID);
       
   189     WriteDes8L(writeStream, appID);
       
   190     WriteDes8L(writeStream, subject);
       
   191     WriteDes8L(writeStream, from);
       
   192     WriteDes8L(writeStream, to);
       
   193     WriteDes8L(writeStream, bcc);
       
   194     WriteDes8L(writeStream, cc);
       
   195 
       
   196     // add the attachments
       
   197     WriteAttachmentsL(writeStream, aMMS, *cConv, firstAttchmt);
       
   198 
       
   199     // cleanup
       
   200     CleanupStack::PopAndDestroy(cConv);
       
   201     CleanupStack::Pop(buffer);
       
   202     CleanupStack::PopAndDestroy(&cc);
       
   203     CleanupStack::PopAndDestroy(&bcc);
       
   204     CleanupStack::PopAndDestroy(&to);
       
   205     CleanupStack::PushL(buffer);
       
   206 
       
   207     return *buffer;
       
   208 }
       
   209 
       
   210 /* -----------------------------------------------------------------------------
       
   211  * CJavaMMSMessageHandler::WriteAttachmentsL
       
   212  * Writes all the attachments into the write stream.
       
   213  * -----------------------------------------------------------------------------
       
   214  */
       
   215 void CJavaMMSMessageHandler::WriteAttachmentsL(RBufWriteStream& aWriteStream,
       
   216         CMMSMessageInformation& aMMS, CCnvCharacterSetConverter& aCharConv,
       
   217         TInt firstAttchmt)
       
   218 {
       
   219     JELOG2(EWMA);
       
   220     TInt8 attchmts = aMMS.AttachmentCount();
       
   221     if (firstAttchmt >= 0)
       
   222     {
       
   223         WriteAttachmentL(aWriteStream, aMMS.Attachment(firstAttchmt), aCharConv);
       
   224     }
       
   225     for (TInt i = 0; i < attchmts; i++)
       
   226     {
       
   227         if (i != firstAttchmt)
       
   228         {
       
   229             WriteAttachmentL(aWriteStream, aMMS.Attachment(i), aCharConv);
       
   230         }
       
   231     }
       
   232 }
       
   233 
       
   234 /* -----------------------------------------------------------------------------
       
   235  * CJavaMMSMessageHandler::WriteAttachmentL
       
   236  * Writes an attachment into the write stream.
       
   237  * -----------------------------------------------------------------------------
       
   238  */
       
   239 void CJavaMMSMessageHandler::WriteAttachmentL(RBufWriteStream& aWriteStream,
       
   240         CMMSMessageAttachment& aAttch, CCnvCharacterSetConverter& aCharConv)
       
   241 {
       
   242     JELOG2(EWMA);
       
   243     // mime type
       
   244     WriteDes8L(aWriteStream, aAttch.AttachmentType());
       
   245     // content ID
       
   246     WriteDes8L(aWriteStream, aAttch.ContentIdL());
       
   247     // content location
       
   248     WriteDes8L(aWriteStream, aAttch.ContentLocationL());
       
   249     // content encoding
       
   250     TUint charSetID = aCharConv.ConvertMibEnumOfCharacterSetToIdentifierL(
       
   251                           aAttch.Encoding(), mRFs);
       
   252     HBufC8* encoding = aCharConv.ConvertCharacterSetIdentifierToStandardNameL(
       
   253                            charSetID, mRFs);
       
   254     CleanupStack::PushL(encoding);
       
   255     if (encoding)
       
   256     {
       
   257         aWriteStream.WriteL(*(encoding));
       
   258     }
       
   259     CleanupStack::PopAndDestroy(encoding);
       
   260     // content
       
   261     WriteDes8L(aWriteStream, aAttch.AttachmentData());
       
   262 }
       
   263 
       
   264 /* -----------------------------------------------------------------------------
       
   265  * CJavaMMSMessageHandler::WriteAttachmentsLengthsL
       
   266  * Writes all attachments lengths (one by one) into the write stream.
       
   267  * -----------------------------------------------------------------------------
       
   268  */
       
   269 TInt CJavaMMSMessageHandler::WriteAttachmentsLengthsL(RBufWriteStream& aWriteStream,
       
   270         CMMSMessageInformation& aMMS, CCnvCharacterSetConverter& aCharConv)
       
   271 {
       
   272     JELOG2(EWMA);
       
   273     TInt firstAttchmt = -1;
       
   274     TInt8 attchmts = aMMS.AttachmentCount();
       
   275     if (attchmts > 0)
       
   276     {
       
   277         // quick browse through the attachments to see if the starterCID is used
       
   278         for (TInt i = 0; i < attchmts; i++)
       
   279         {
       
   280             CMMSMessageAttachment& attch = aMMS.Attachment(i);
       
   281             if (attch.IsStarterContentId())
       
   282             {
       
   283                 // put the starterCID first
       
   284                 WriteAttachmentLengthsL(aWriteStream, attch, aCharConv);
       
   285                 firstAttchmt = i;
       
   286                 break;
       
   287             }
       
   288         }
       
   289     }
       
   290     for (TInt i = 0; i < attchmts; i++)
       
   291     {
       
   292         if (i != firstAttchmt)
       
   293         {
       
   294             WriteAttachmentLengthsL(aWriteStream, aMMS.Attachment(i), aCharConv);
       
   295         }
       
   296     }
       
   297     return firstAttchmt;
       
   298 }
       
   299 
       
   300 /* -----------------------------------------------------------------------------
       
   301  * CJavaMMSMessageHandler::WriteAttachmentLengthsL
       
   302  * Writes an attachment lengths into the write stream.
       
   303  * -----------------------------------------------------------------------------
       
   304  */
       
   305 void CJavaMMSMessageHandler::WriteAttachmentLengthsL(RBufWriteStream& aWriteStream,
       
   306         CMMSMessageAttachment& aAttch, CCnvCharacterSetConverter& aCharConv)
       
   307 {
       
   308     JELOG2(EWMA);
       
   309     // mime type length
       
   310     WriteDesLengthOrZeroL(aWriteStream, aAttch.AttachmentType());
       
   311     // content ID length
       
   312     WriteDesLengthOrZeroL(aWriteStream, aAttch.ContentIdL());
       
   313     // content location length
       
   314     WriteDesLengthOrZeroL(aWriteStream, aAttch.ContentLocationL());
       
   315     // content encoding length
       
   316     TUint charSetID = aCharConv.ConvertMibEnumOfCharacterSetToIdentifierL(
       
   317                           aAttch.Encoding(), mRFs);
       
   318     HBufC8* encoding = aCharConv.ConvertCharacterSetIdentifierToStandardNameL(
       
   319                            charSetID, mRFs);
       
   320     CleanupStack::PushL(encoding);
       
   321     if (encoding)
       
   322     {
       
   323         WriteIntL(aWriteStream, encoding->Length());
       
   324     }
       
   325     else
       
   326     {
       
   327         WriteIntL(aWriteStream, 0);
       
   328     }
       
   329     CleanupStack::PopAndDestroy(encoding);
       
   330     // content size
       
   331     WriteDesLengthOrZeroL(aWriteStream, aAttch.AttachmentData());
       
   332 }
       
   333 
       
   334 /* -----------------------------------------------------------------------------
       
   335  * CJavaMMSMessageHandler::BuildAddressLC
       
   336  * Concatenates all the addresses/recipients into a ";" separated
       
   337  * string/descriptor.
       
   338  * -----------------------------------------------------------------------------
       
   339  */
       
   340 HBufC8& CJavaMMSMessageHandler::BuildAddressLC(
       
   341     TMsvRecipientTypeValues aAddressType, CMMSMessageInformation& aMMS)
       
   342 {
       
   343     JELOG2(EWMA);
       
   344     _LIT(KAddressSep, ";");
       
   345     HBufC8* address = HBufC8::NewLC(0);
       
   346     TPtr8 AddressPtr(address->Des());
       
   347     for (int i = 0; i < aMMS.AddressesCount(aAddressType); i++)
       
   348     {
       
   349         TDesC& currentAddress = aMMS.MessageAddressL(aAddressType, i);
       
   350         HBufC8* tmp = NULL;
       
   351         if (i < aMMS.AddressesCount(aAddressType) - 1)
       
   352         {
       
   353             tmp = address->ReAllocL(address->Length() + currentAddress.Length()
       
   354                                     + 1);
       
   355         }
       
   356         else
       
   357         {
       
   358             tmp
       
   359             = address->ReAllocL(address->Length()
       
   360                                 + currentAddress.Length());
       
   361         }
       
   362         CleanupStack::Pop(address);
       
   363         address = tmp;
       
   364         CleanupStack::PushL(address);
       
   365         AddressPtr.Set(address->Des());
       
   366         AddressPtr.Append(currentAddress);
       
   367         if (i < aMMS.AddressesCount(aAddressType) - 1)
       
   368         {
       
   369             AddressPtr.Append(KAddressSep);
       
   370         }
       
   371     }
       
   372     return *address;
       
   373 }
       
   374 
       
   375 /* -----------------------------------------------------------------------------
       
   376  * CJavaMMSMessageHandler::CalculateMap
       
   377  * Calculates the mms map.
       
   378  * -----------------------------------------------------------------------------
       
   379  */
       
   380 TInt CJavaMMSMessageHandler::CalculateMap(TDesC8& aReplyToAppID, TDesC8& aAppID,
       
   381         TDesC8& aSubject, TDesC8& aFrom,
       
   382         HBufC8& aTo, HBufC8& aBcc, HBufC8& aCc)
       
   383 {
       
   384     JELOG2(EWMA);
       
   385     TInt mmsMap = 0;
       
   386     if (&aReplyToAppID)
       
   387     {
       
   388         mmsMap += K64BitsMask;
       
   389     }
       
   390     if (&aAppID)
       
   391     {
       
   392         mmsMap += K32BitsMask;
       
   393     }
       
   394     if (&aSubject)
       
   395     {
       
   396         mmsMap += K16BitsMask;
       
   397     }
       
   398     if (&aFrom)
       
   399     {
       
   400         mmsMap += K8BitsMask;
       
   401     }
       
   402     if (&aTo)
       
   403     {
       
   404         mmsMap += K4BitsMask;
       
   405     }
       
   406     if (&aBcc)
       
   407     {
       
   408         mmsMap += K2BitsMask;
       
   409     }
       
   410     if (&aCc)
       
   411     {
       
   412         mmsMap += 1;
       
   413     }
       
   414     return mmsMap;
       
   415 }
       
   416 
       
   417 /* -----------------------------------------------------------------------------
       
   418  * CJavaMMSMessageHandler::WriteInt64L
       
   419  * Writes an integer as 8 bytes into the write stream.
       
   420  * -----------------------------------------------------------------------------
       
   421  */
       
   422 void CJavaMMSMessageHandler::WriteInt64L(RBufWriteStream& aWriteStream,
       
   423         const TInt64 aInteger)
       
   424 {
       
   425     JELOG2(EWMA);
       
   426     aWriteStream.WriteInt8L(aInteger >> K56BitsMask);
       
   427     aWriteStream.WriteInt8L(aInteger >> K48BitsMask);
       
   428     aWriteStream.WriteInt8L(aInteger >> K40BitsMask);
       
   429     aWriteStream.WriteInt8L(aInteger >> K32BitsMask);
       
   430     aWriteStream.WriteInt8L(aInteger >> K24BitsMask);
       
   431     aWriteStream.WriteInt8L(aInteger >> K16BitsMask);
       
   432     aWriteStream.WriteInt8L(aInteger >> K8BitsMask);
       
   433     aWriteStream.WriteInt8L(aInteger);
       
   434 }
       
   435 
       
   436 /* -----------------------------------------------------------------------------
       
   437  * CJavaMMSMessageHandler::WriteIntL
       
   438  * Writes an integer as 4 bytes into the write stream.
       
   439  * -----------------------------------------------------------------------------
       
   440  */
       
   441 void CJavaMMSMessageHandler::WriteIntL(RBufWriteStream& aWriteStream,
       
   442                                        const TInt32 aInteger)
       
   443 {
       
   444     JELOG2(EWMA);
       
   445     aWriteStream.WriteUint8L(aInteger >> K24BitsMask);
       
   446     aWriteStream.WriteUint8L(aInteger >> K16BitsMask);
       
   447     aWriteStream.WriteUint8L(aInteger >> K8BitsMask);
       
   448     aWriteStream.WriteUint8L(aInteger);
       
   449 }
       
   450 
       
   451 /* -----------------------------------------------------------------------------
       
   452  * CJavaMMSMessageHandler::WriteDes8L
       
   453  * Writes a descriptor (if not NULL) into the write stream.
       
   454  * -----------------------------------------------------------------------------
       
   455  */
       
   456 void CJavaMMSMessageHandler::WriteDes8L(RBufWriteStream& aWriteStream,
       
   457                                         const TDesC8& aDes)
       
   458 {
       
   459     JELOG2(EWMA);
       
   460     if (&aDes)
       
   461     {
       
   462         aWriteStream.WriteL(aDes);
       
   463     }
       
   464 }
       
   465 
       
   466 /* -----------------------------------------------------------------------------
       
   467  * CJavaMMSMessageHandler::WriteDes8LengthL
       
   468  * Writes a descriptor's length (if not NULL) into the write stream.
       
   469  * -----------------------------------------------------------------------------
       
   470  */
       
   471 void CJavaMMSMessageHandler::WriteDes8LengthL(RBufWriteStream& aWriteStream,
       
   472         const TDesC8& aDes)
       
   473 {
       
   474     JELOG2(EWMA);
       
   475     if (&aDes)
       
   476     {
       
   477         WriteIntL(aWriteStream, aDes.Length());
       
   478     }
       
   479 }
       
   480 
       
   481 /* -----------------------------------------------------------------------------
       
   482  * CJavaMMSMessageHandler::WriteDes8LengthOrZeroL
       
   483  * Writes a descriptor's length (if descriptor is not NULL) or zero (if
       
   484  * descriptor is NULL) into the write stream.
       
   485  * -----------------------------------------------------------------------------
       
   486  */
       
   487 void CJavaMMSMessageHandler::WriteDes8LengthOrZeroL(RBufWriteStream& aWriteStream,
       
   488         const TDesC8& aDes)
       
   489 {
       
   490     JELOG2(EWMA);
       
   491     if (&aDes)
       
   492     {
       
   493         aWriteStream.WriteUint8L(aDes.Length());
       
   494     }
       
   495     else
       
   496     {
       
   497         aWriteStream.WriteUint8L(0);
       
   498     }
       
   499 }
       
   500 
       
   501 /* -----------------------------------------------------------------------------
       
   502  * CJavaMMSMessageHandler::WriteDesLengthOrZeroL
       
   503  * Writes a descriptor's length (if descriptor is not NULL) or zero (if
       
   504  * descriptor is NULL) into the write stream.
       
   505  * -----------------------------------------------------------------------------
       
   506  */
       
   507 void CJavaMMSMessageHandler::WriteDesLengthOrZeroL(RBufWriteStream& aWriteStream,
       
   508         const TDesC8& aDes)
       
   509 {
       
   510     JELOG2(EWMA);
       
   511     if (&aDes)
       
   512     {
       
   513         WriteIntL(aWriteStream, aDes.Length());
       
   514     }
       
   515     else
       
   516     {
       
   517         WriteIntL(aWriteStream, 0);
       
   518     }
       
   519 }
       
   520 
       
   521 /* -----------------------------------------------------------------------------
       
   522  * CJavaMMSMessageHandler::DeSerializeL
       
   523  * This method de-serializes an MMS (as it is received java) into
       
   524  * an internal representation (used by the MMS engine proxy).
       
   525  * The format of the serialized MMS is according to the following scheme:
       
   526  *     ----------------------------------------------------------------------------------------------------------
       
   527  *     | Map | HeaderLengths | AttachmentsCount | AttachmentsLengths | StartContentFlag | Headers | Attachments |
       
   528  *     ----------------------------------------------------------------------------------------------------------
       
   529  *
       
   530  * where Map                 Represents the decimal value of a binary
       
   531  *                          representation of MMS header fields
       
   532  *                          (applicationID, Subject, From, To, Bcc, Cc)
       
   533  *                          Ex: 52 = 110101 means that 'applicationID'
       
   534  *                          is present, 'Subject' is present, 'From' is
       
   535  *                          not present,'To' is present, 'Bcc' is not
       
   536  *                          present and 'Cc' is present
       
   537  *                          The lengths of each of the MMS header
       
   538  *                          fields which are present
       
   539  *      AttachmentsCount    The number of attachments
       
   540  *      AttachmentsLengths  The lengths of each of the attachments
       
   541  *      StartContentFlag    A boolean indicating if the first
       
   542  *                          attachment should be interpreted as
       
   543  *                          startContent or not
       
   544  *      Headers             The MMS header fields
       
   545  *      Attachments         The attachments
       
   546  * -----------------------------------------------------------------------------
       
   547  */
       
   548 CMMSMessageInformation& CJavaMMSMessageHandler::DeSerializeL(CBufFlat& aMMS)
       
   549 {
       
   550     JELOG2(EWMA);
       
   551     RBufReadStream rStream(aMMS, 0);
       
   552 
       
   553     // get the raw mms map
       
   554     TInt32 headerLengths[KMmsMapLength] =
       
   555         { 0, 0, 0, 0, 0, 0 };
       
   556 
       
   557     ResolveMapL(rStream, headerLengths);
       
   558     // get the attachments count
       
   559     TInt8 attchmts = rStream.ReadUint8L();
       
   560 
       
   561     // get the attachments lenghts
       
   562     RArray<TInt> mimeLengths(1);
       
   563     CleanupClosePushL(mimeLengths);
       
   564     RArray<TInt> cidLengths(1);
       
   565     CleanupClosePushL(cidLengths);
       
   566     RArray<TInt> cLocationLengths(1);
       
   567     CleanupClosePushL(cLocationLengths);
       
   568     RArray<TInt> cEncodingLengths(1);
       
   569     CleanupClosePushL(cEncodingLengths);
       
   570     RArray<TInt32> contentLengths(1);
       
   571     CleanupClosePushL(contentLengths);
       
   572     for (TInt i = 0; i < attchmts; i++)
       
   573     {
       
   574         // read the mime length
       
   575         mimeLengths.InsertL(ReadIntL(rStream), i);
       
   576         // read the content ID length
       
   577         cidLengths.InsertL(ReadIntL(rStream), i);
       
   578         // read the content Location length
       
   579         cLocationLengths.InsertL(ReadIntL(rStream), i);
       
   580         // read the content Encoding length
       
   581         cEncodingLengths.InsertL(ReadIntL(rStream), i);
       
   582         // read the content length
       
   583         contentLengths.InsertL(ReadIntL(rStream), i);
       
   584     }
       
   585 
       
   586     // get the startContentId flag
       
   587     TInt8 startCID = 0;
       
   588     if (attchmts > 0)
       
   589     {
       
   590         startCID = rStream.ReadUint8L();
       
   591     }
       
   592 
       
   593     CMMSMessageInformation& msg = ResolveHeadersLC(rStream, headerLengths);
       
   594     // msg is on the cleanup stack
       
   595 
       
   596     // read the attachments
       
   597     CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewL();
       
   598     CleanupStack::PushL(charConv);
       
   599     for (TInt i = 0; i < attchmts; i++)
       
   600     {
       
   601         HBufC8* mime = HBufC8::NewL(mimeLengths[i]);
       
   602         CleanupStack::PushL(mime);
       
   603         TPtr8 mimePtr(mime->Des());
       
   604         HBufC8* cid = HBufC8::NewL(cidLengths[i]);
       
   605         CleanupStack::PushL(cid);
       
   606         TPtr8 cidPtr(cid->Des());
       
   607         HBufC8* cLocation = HBufC8::NewL(cLocationLengths[i]);
       
   608         CleanupStack::PushL(cLocation);
       
   609         TPtr8 cLocationPtr(cLocation->Des());
       
   610         HBufC8* cEncoding = HBufC8::NewL(cEncodingLengths[i]);
       
   611         CleanupStack::PushL(cEncoding);
       
   612         TPtr8 cEncodingPtr(cEncoding->Des());
       
   613         HBufC8* content = HBufC8::NewL(contentLengths[i]);
       
   614         CleanupStack::PushL(content);
       
   615         TPtr8 contentPtr(content->Des());
       
   616         // read the mime
       
   617         rStream.ReadL(mimePtr, mimeLengths[i]);
       
   618         // read the content ID
       
   619         rStream.ReadL(cidPtr, cidLengths[i]);
       
   620         // read the content Location
       
   621         rStream.ReadL(cLocationPtr, cLocationLengths[i]);
       
   622         // read the content Encoding
       
   623         rStream.ReadL(cEncodingPtr, cEncodingLengths[i]);
       
   624         // read the content
       
   625         rStream.ReadL(contentPtr, contentLengths[i]);
       
   626 
       
   627         // Save the contentPtr in the file and later add the fileName
       
   628         TDesC8* attachmentName = NULL;
       
   629         SaveDataToFileL(contentPtr, attachmentName, *mime);
       
   630         CMMSMessageAttachment* attch = CMMSMessageAttachment::NewL(mRFs,
       
   631                                        *attachmentName, mimePtr, cidPtr, cLocationPtr);
       
   632         delete attachmentName;
       
   633         attachmentName = NULL;
       
   634         TUint charSetID = charConv->ConvertStandardNameOfCharacterSetToIdentifierL
       
   635                           (cEncodingPtr, mRFs);
       
   636         TUint mibEnum = charConv->ConvertCharacterSetIdentifierToMibEnumL(
       
   637                             charSetID, mRFs);
       
   638         attch->SetEncoding(mibEnum);
       
   639         CleanupStack::PushL(attch);
       
   640         if (i == 0 && startCID == 1)
       
   641         {
       
   642             attch->SetStarterContentId(TRUE);
       
   643         }
       
   644         else
       
   645         {
       
   646             attch->SetStarterContentId(FALSE);
       
   647         }
       
   648         msg.InsertAttachmentL(attch);
       
   649         CleanupStack::Pop(attch);
       
   650         CleanupStack::PopAndDestroy(content);
       
   651         CleanupStack::PopAndDestroy(cEncoding);
       
   652         CleanupStack::PopAndDestroy(cLocation);
       
   653         CleanupStack::PopAndDestroy(cid);
       
   654         CleanupStack::PopAndDestroy(mime);
       
   655     }
       
   656     CleanupStack::PopAndDestroy(charConv);
       
   657     CleanupStack::Pop(&msg); // msg
       
   658 
       
   659     // deallocate the dynamic arrays
       
   660     CleanupStack::PopAndDestroy(&contentLengths);
       
   661     CleanupStack::PopAndDestroy(&cEncodingLengths);
       
   662     CleanupStack::PopAndDestroy(&cLocationLengths);
       
   663     CleanupStack::PopAndDestroy(&cidLengths);
       
   664     CleanupStack::PopAndDestroy(&mimeLengths);
       
   665     return msg;
       
   666 }
       
   667 
       
   668 /* -----------------------------------------------------------------------------
       
   669  * CJavaMMSMessageHandler::Divide
       
   670  * This method returns what's left from dividing aNum1 with aNum2.
       
   671  * It is used in serialization/deserialization, when calculating the mmsMap
       
   672  * -----------------------------------------------------------------------------
       
   673  */
       
   674 TInt CJavaMMSMessageHandler::Divide(TInt aNum1, TInt aNum2)
       
   675 {
       
   676     JELOG2(EWMA);
       
   677     if (aNum1 / aNum2 > 0)
       
   678     {
       
   679         return (aNum1 - (aNum2 *(aNum1 / aNum2)));
       
   680     }
       
   681     return -1;
       
   682 }
       
   683 
       
   684 /* -----------------------------------------------------------------------------
       
   685  * CJavaMMSMessageHandler::ReadIntL
       
   686  * Reads an integer as 4 bytes
       
   687  * -----------------------------------------------------------------------------
       
   688  */
       
   689 TInt32 CJavaMMSMessageHandler::ReadIntL(RBufReadStream& aReadStream)
       
   690 {
       
   691     JELOG2(EWMA);
       
   692     TInt32 byte1 = aReadStream.ReadUint8L();
       
   693     TInt32 byte2 = aReadStream.ReadUint8L();
       
   694     TInt32 byte3 = aReadStream.ReadUint8L();
       
   695     TInt32 byte4 = aReadStream.ReadUint8L();
       
   696     return (byte1 << K24BitsMask) + (byte2 << K16BitsMask) + (byte3
       
   697             << K8BitsMask) + byte4;
       
   698 }
       
   699 
       
   700 /* -----------------------------------------------------------------------------
       
   701  * CJavaMMSMessageHandler::ReadInt64L
       
   702  * Reads an integer as 8 bytes
       
   703  * -----------------------------------------------------------------------------
       
   704  */
       
   705 TInt64 CJavaMMSMessageHandler::ReadInt64L(RBufReadStream& aReadStream)
       
   706 {
       
   707     JELOG2(EWMA);
       
   708     TInt64 byte1 = aReadStream.ReadUint8L();
       
   709     TInt64 byte2 = aReadStream.ReadUint8L();
       
   710     TInt64 byte3 = aReadStream.ReadUint8L();
       
   711     TInt64 byte4 = aReadStream.ReadUint8L();
       
   712     TInt64 byte5 = aReadStream.ReadUint8L();
       
   713     TInt64 byte6 = aReadStream.ReadUint8L();
       
   714     TInt64 byte7 = aReadStream.ReadUint8L();
       
   715     TInt64 byte8 = aReadStream.ReadUint8L();
       
   716     return (byte1 << K56BitsMask) + (byte2 << K48BitsMask) + (byte3
       
   717             << K40BitsMask) + (byte4 << K32BitsMask) + (byte5 << K24BitsMask)
       
   718            + (byte6 << K16BitsMask) + (byte7 << K8BitsMask) + byte8;
       
   719 }
       
   720 
       
   721 /* -----------------------------------------------------------------------------
       
   722  * CJavaMMSMessageHandler::ResolveMapL
       
   723  * Resolves the map of the multimedia message. The map of the multimedia
       
   724  * message consists of a byte whose bits indicate which of the
       
   725  * multimedia message headers are present. See comments of 'DeSerialize' method
       
   726  * for more details about the mms map.
       
   727  * -----------------------------------------------------------------------------
       
   728  */
       
   729 void CJavaMMSMessageHandler::ResolveMapL(RBufReadStream& aReadStream,
       
   730         TInt32 aHeaderLengths[])
       
   731 {
       
   732     JELOG2(EWMA);
       
   733     TInt8 mmsMap = aReadStream.ReadUint8L();
       
   734 
       
   735     // resolve the mms map
       
   736     while (true)
       
   737     {
       
   738         TInt div = Divide(mmsMap, K64BitsMask);
       
   739         if (div >= 0)
       
   740         {
       
   741             // get reply to app id length
       
   742             aHeaderLengths[KReplyToAppIDFieldIndex] = ReadIntL(aReadStream);
       
   743             if (div == 0)
       
   744                 break;
       
   745             mmsMap = div;
       
   746         }
       
   747         div = Divide(mmsMap, K32BitsMask);
       
   748         if (div >= 0)
       
   749         {
       
   750             // get appID length
       
   751             aHeaderLengths[KAppIDFieldIndex] = ReadIntL(aReadStream);
       
   752             if (div == 0)
       
   753                 break;
       
   754             mmsMap = div;
       
   755         }
       
   756         div = Divide(mmsMap, K16BitsMask);
       
   757         if (div >= 0)
       
   758         {
       
   759             // get subject length
       
   760             aHeaderLengths[KSubjectFieldIndex] = ReadIntL(aReadStream);
       
   761             if (div == 0)
       
   762                 break;
       
   763             mmsMap = div;
       
   764         }
       
   765         div = Divide(mmsMap, K8BitsMask);
       
   766         if (div >= 0)
       
   767         {
       
   768             // get the from length
       
   769             aHeaderLengths[KFromFieldIndex] = ReadIntL(aReadStream);
       
   770         }
       
   771         div = Divide(mmsMap, K4BitsMask);
       
   772         if (div >= 0)
       
   773         {
       
   774             // get to length
       
   775             aHeaderLengths[KToFieldIndex] = ReadIntL(aReadStream);
       
   776             if (div == 0)
       
   777                 break;
       
   778             mmsMap = div;
       
   779         }
       
   780         div = Divide(mmsMap, K2BitsMask);
       
   781         if (div >= 0)
       
   782         {
       
   783             // get bcc length
       
   784             aHeaderLengths[KBccFieldIndex] = ReadIntL(aReadStream);
       
   785             if (div == 0)
       
   786                 break;
       
   787             mmsMap = div;
       
   788         }
       
   789         if (mmsMap >= 0)
       
   790         {
       
   791             // get cc length
       
   792             aHeaderLengths[KCcFieldIndex] = ReadIntL(aReadStream);
       
   793             if (div == 0)
       
   794                 break;
       
   795             mmsMap = div;
       
   796         }
       
   797         break;
       
   798     }
       
   799 }
       
   800 
       
   801 /* -----------------------------------------------------------------------------
       
   802  * CJavaMMSMessageHandler::ResolveHeadersLC
       
   803  * Resolves/reads the headers of the multimedia message from the stream
       
   804  * and sets them to the internal representation of the multimedia
       
   805  * message
       
   806  * -----------------------------------------------------------------------------
       
   807  */
       
   808 CMMSMessageInformation& CJavaMMSMessageHandler::ResolveHeadersLC(
       
   809     RBufReadStream& aReadStream, TInt32 aHeaderLengths[])
       
   810 {
       
   811     JELOG2(EWMA);
       
   812     // priority
       
   813     TInt8 prio = aReadStream.ReadUint8L();
       
   814     // date
       
   815     TInt64 date = ReadInt64L(aReadStream);
       
   816     CMMSMessageInformation* msg = CMMSMessageInformation::NewL(KNullDesC, date,
       
   817                                   KNullDesC8, NULL);
       
   818     CleanupStack::PushL(msg);
       
   819     // reply to appID
       
   820     HBufC8* replyToAppID =HBufC8::NewL(aHeaderLengths[KReplyToAppIDFieldIndex]);
       
   821     CleanupStack::PushL(replyToAppID);
       
   822     TPtr8 replyToAppIDPtr(replyToAppID->Des());
       
   823     // appID
       
   824     HBufC8* appID = HBufC8::NewL(aHeaderLengths[KAppIDFieldIndex]);
       
   825     CleanupStack::PushL(appID);
       
   826     TPtr8 appIDPtr(appID->Des());
       
   827     // subject
       
   828     HBufC8* subject = HBufC8::New(aHeaderLengths[KSubjectFieldIndex]);
       
   829     CleanupStack::PushL(subject);
       
   830     TPtr8 subjectPtr(subject->Des());
       
   831     // from
       
   832     HBufC8* from = HBufC8::NewL(aHeaderLengths[KFromFieldIndex]);
       
   833     CleanupStack::PushL(from);
       
   834     TPtr8 fromPtr(from->Des());
       
   835     // to
       
   836     HBufC8* to = HBufC8::NewL(aHeaderLengths[KToFieldIndex]);
       
   837     CleanupStack::PushL(to);
       
   838     TPtr8 toPtr(to->Des());
       
   839     // bcc
       
   840     HBufC8* bcc = HBufC8::NewL(aHeaderLengths[KBccFieldIndex]);
       
   841     CleanupStack::PushL(bcc);
       
   842     TPtr8 bccPtr(bcc->Des());
       
   843     // cc
       
   844     HBufC8* cc = HBufC8::NewL(aHeaderLengths[KCcFieldIndex]);
       
   845     CleanupStack::PushL(cc);
       
   846     TPtr8 ccPtr(cc->Des());
       
   847     for (TInt i = 0; i < KMmsMapLength; i++)
       
   848     {
       
   849         if (aHeaderLengths[i] > 0)
       
   850         {
       
   851             // read the first aHeaderLengths[i] bytes
       
   852             switch (i)
       
   853             {
       
   854             case(KReplyToAppIDFieldIndex):
       
   855                 // reply to app ID
       
   856                 aReadStream.ReadL(replyToAppIDPtr, aHeaderLengths[i]);
       
   857                 break;
       
   858             case(KAppIDFieldIndex):
       
   859                 // app ID
       
   860                 aReadStream.ReadL(appIDPtr, aHeaderLengths[i]);
       
   861                 break;
       
   862             case(KSubjectFieldIndex):
       
   863                 // subject
       
   864                 aReadStream.ReadL(subjectPtr, aHeaderLengths[i]);
       
   865                 break;
       
   866             case(KFromFieldIndex):
       
   867                 // from
       
   868                 aReadStream.ReadL(fromPtr, aHeaderLengths[i]);
       
   869                 break;
       
   870             case(KToFieldIndex):
       
   871                 // to
       
   872                 aReadStream.ReadL(toPtr, aHeaderLengths[i]);
       
   873                 break;
       
   874             case(KBccFieldIndex):
       
   875                 // bcc
       
   876                 aReadStream.ReadL(bccPtr, aHeaderLengths[i]);
       
   877                 break;
       
   878             case(KCcFieldIndex):
       
   879                 // cc
       
   880                 aReadStream.ReadL(ccPtr, aHeaderLengths[i]);
       
   881                 break;
       
   882             default:
       
   883                 // Nothing to do
       
   884                 break;
       
   885             }
       
   886         }
       
   887     }
       
   888     // create the CMMSMessageInformation
       
   889     msg->SetApplicationIdL(appIDPtr);
       
   890     msg->SetReplyToApplicationIdL(replyToAppIDPtr);
       
   891     msg->SetMessageSubjectL(subjectPtr);
       
   892     switch (prio)
       
   893     {
       
   894     case KPriorityLow:
       
   895         //low
       
   896         msg->SetMessagePriority(EMmsPriorityLow);
       
   897         break;
       
   898     case KPriorityNormal:
       
   899         //normal
       
   900         msg->SetMessagePriority(EMmsPriorityNormal);
       
   901         break;
       
   902     case KPriorityHigh:
       
   903         //high
       
   904         msg->SetMessagePriority(EMmsPriorityHigh);
       
   905         break;
       
   906     default:
       
   907         // Nothing to do
       
   908         break;
       
   909     }
       
   910     // parse the addresses and set them to the message
       
   911     ParseAndSetAddressL(EMsvRecipientTo, toPtr, *msg);
       
   912     ParseAndSetAddressL(EMsvRecipientBcc, bccPtr, *msg);
       
   913     ParseAndSetAddressL(EMsvRecipientCc, ccPtr, *msg);
       
   914     // pop the pointers before deleting them
       
   915     CleanupStack::PopAndDestroy(cc);
       
   916     CleanupStack::PopAndDestroy(bcc);
       
   917     CleanupStack::PopAndDestroy(to);
       
   918     CleanupStack::PopAndDestroy(from);
       
   919     CleanupStack::PopAndDestroy(subject);
       
   920     CleanupStack::PopAndDestroy(appID);
       
   921     CleanupStack::PopAndDestroy(replyToAppID);
       
   922     return *msg;
       
   923 }
       
   924 
       
   925 /* -----------------------------------------------------------------------------
       
   926  * CJavaMMSMessageHandler::ParseAndSetAddressL
       
   927  * Splits the concatenated addresses (";" separated string/descriptor)
       
   928  * into sepparate tokens and sets them individually to the internal
       
   929  * representation of the multimedia message.
       
   930  * -----------------------------------------------------------------------------
       
   931  */
       
   932 void CJavaMMSMessageHandler::ParseAndSetAddressL(
       
   933     TMsvRecipientTypeValues aAddressType,
       
   934     TDes8& aAddr,
       
   935     CMMSMessageInformation& aMsg)
       
   936 {
       
   937     JELOG2(EWMA);
       
   938     if (aAddr.Length() == 0)
       
   939     {
       
   940         return;
       
   941     }
       
   942     else
       
   943     {
       
   944         while (true)
       
   945         {
       
   946             TInt off = aAddr.Locate(';');
       
   947             if (off != KErrNotFound)
       
   948             {
       
   949                 TPtrC8 left = aAddr.Left(off);
       
   950                 aMsg.AddAddressL(aAddressType, left);
       
   951                 TPtrC8 right = aAddr.Right(aAddr.Length() - off - 1);
       
   952                 aAddr.Copy(right);
       
   953             }
       
   954             else
       
   955             {
       
   956                 aMsg.AddAddressL(aAddressType, aAddr);
       
   957                 break;
       
   958             }
       
   959         }
       
   960     }
       
   961 }
       
   962 
       
   963 /* -----------------------------------------------------------------------------
       
   964  * CJavaMMSMessageHandler::SaveDataToFileL
       
   965  * Save data to the D-drive. MMS engine assume that attachments are
       
   966  * always files. It also help us to use less RAM.
       
   967  * -----------------------------------------------------------------------------
       
   968  */
       
   969 void CJavaMMSMessageHandler::SaveDataToFileL(const TDesC8& aDataArray,
       
   970         TDesC8*& aFileName,
       
   971         const TDesC8& aDataType)
       
   972 {
       
   973     JELOG2(EWMA);
       
   974     //// create a dummy attached file here on the D (temp) drive
       
   975     RFile attachementFile;
       
   976     TInt err = 0;
       
   977     TBuf<KMaxFileName> fileName;
       
   978     int i = 1;
       
   979     CDocumentHandler* docHandler = CDocumentHandler::NewLC();
       
   980     do
       
   981     {
       
   982         fileName.SetLength(0);
       
   983         //fileName.Append(KTempDrive); // Add the drive name
       
   984         TChar driveInfo;
       
   985         DriveInfo::GetDefaultDrive(DriveInfo::EDefaultRam, driveInfo);
       
   986         fileName.Append(driveInfo);
       
   987         fileName.Append(KTempDriveExt);
       
   988         fileName.Append(KTempMmsAttachmentName); // Add the drive name
       
   989         fileName.AppendNum((int) this);
       
   990         fileName.AppendNum(i++);
       
   991         // we delegate the DocHandler to append the file extension
       
   992         TDataType mimeType(aDataType);
       
   993         docHandler->CheckFileNameExtension(fileName, mimeType);
       
   994         err = attachementFile.Create(mRFs, fileName, EFileWrite
       
   995                                      | EFileShareExclusive);
       
   996     }
       
   997     while (KErrAlreadyExists == err);
       
   998     CleanupStack::PopAndDestroy(docHandler);
       
   999     if (err != KErrNone)
       
  1000     {
       
  1001         User::LeaveIfError(err);
       
  1002     }
       
  1003     else
       
  1004     {
       
  1005         // Get the file name, so that we can delete it later
       
  1006         java::util::S60CommonUtils::ConvertWiderToNarrowL(fileName,
       
  1007                 (TDesC8*&) aFileName);
       
  1008 
       
  1009         // add data to the newly created attached file.
       
  1010         attachementFile.Write(aDataArray);
       
  1011         attachementFile.Flush();
       
  1012         attachementFile.Close();
       
  1013     }
       
  1014 }
       
  1015 
       
  1016 } //namespace wma
       
  1017 } //namespace java
       
  1018