simpleengine/xmlutils/src/simpledocument.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:05:17 +0200
changeset 0 c8caa15ef882
child 18 52d91a16fec3
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2006 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:    Simple Engine
*
*/




// INCLUDE FILES

#include <e32def.h>           // First to avoid NULL redefine warning (no #ifndef NULL).
#include <e32std.h>
#include <string.h>

#include <imcvcodc.h>

// #include <e32std.h>
#include <s32strm.h>
#include <SenBaseElement.h>
#include <SenBaseAttribute.h>
#include <SenXmlUtils.h>
#include <SenXmlReader.h>
#include <SenDomFragment.h>

#include <multipartparser.h>
#include <bodypart.h>

// own simple
#include "simplecommon.h"
#include "simpleelement.h"
#include "simplenamespace.h"
#include "simpleattribute.h"
#include "simpledocument.h"
#include "simplebasedocument.h"
#include "simpleutils.h"
#include "simplecontent.h"


_LIT8 ( KSimpleEntity, "entity");

// Multipart CONSTANTS

const char Multipart_CRLF_Text[] = {"\r\n"};
const char Multipart_DoubleCRLF_Text[] = {"\r\n\r\n"};

// MACROS
#define MULTIPART_CONTENT_LOCATION_LENGTH           17
#define MULTIPART_CONTENT_TYPE_LENGTH               13
#define MULTIPART_CONTENT_TRANSFER_ENCODING_LENGTH  26
// violates RFC2045; but upon vodafone request
#define MULTIPART_CONTENT_ENCODING_LENGTH           17
#define MULTIPART_CONTENT_LENGTH_LENGTH             15
#define MULTIPART_LAST_MODIFIED_LENGTH              14
#define MULTIPART_CONTENT_ID_LENGTH                 11

#define MULTIPART_CONTENT_LOCATION           2
#define MULTIPART_CONTENT_TRANSFER_ENCODING  3
#define MULTIPART_CONTENT_TYPE               4
#define MULTIPART_CONTENT_ID                 5

#define MULTIPART_INTERNET_DATE_STRING_LENGTH       29

#define SLASH_CHAR    '/'
#define DOT_CHAR      '.'
#define AT_CHAR       '@'
#define COLON_CHAR    ':'
// <scheme>://
// #define SCHEME_SEPARATOR_LENGTH               3
// ================= MEMBER FUNCTIONS =======================
//

// ----------------------------------------------------------
// CSimpleDocument::CSimpleDocument
// ----------------------------------------------------------
//
CSimpleDocument::CSimpleDocument( )
: CSimpleBaseDocument()
    {
    }

// ----------------------------------------------------------
// CSimpleDocument::~CSimpleDocument
// ----------------------------------------------------------
//
CSimpleDocument::~CSimpleDocument()
    {
    iContents.ResetAndDestroy();
    iContents.Close();
    }

// ----------------------------------------------------------
// CSimpleDocument::ConstructL
// ----------------------------------------------------------
//
void CSimpleDocument::ConstructL(
    const TDesC8& aNsUri,
    const TDesC8& aLocalName )
    {
    BaseConstructL(aNsUri, aLocalName);
    }
    
// ----------------------------------------------------------
// CSimpleDocument::ConstructMultiPartL
// ----------------------------------------------------------
//
void CSimpleDocument::ConstructMultiPartL(
    const TDesC8& aData, const TDesC8& aBoundary, const TDesC8& aStart )
    {    
    _LIT(KUrl, "http://dummy.com/d1/d.html");
           
    // body part array
    RPointerArray<CBodyPart> bodyPartArray;
    TCleanupItem clItem( ResetAndDestroy, &bodyPartArray  );
    CleanupStack::PushL( clItem );
    
    // remove "..." characters from boundary if needed
    TPtrC8 pUnQuoted = aBoundary;
    TInt quoted = aBoundary.Locate('"');
    if (!quoted)
        {
        pUnQuoted.Set( aBoundary.Mid( 1, aBoundary.Length() - 2 ));
        } 
    // parse
    MultipartParser::ParseL( aData, KSimpleMultipartType, pUnQuoted, KUrl, bodyPartArray  );    
    DoConstructL( bodyPartArray, aStart );
   
    CleanupStack::PopAndDestroy( ); // bodyPartArray     
    }    

// ----------------------------------------------------------
// CSimpleDocument::ConstructL
// ----------------------------------------------------------
//
void CSimpleDocument::ConstructL(
    const TDesC8& aXml )
    {
    BaseConstructL( aXml );
    }

// ----------------------------------------------------------
// CSimpleDocument::NewL
// ----------------------------------------------------------
//
CSimpleDocument* CSimpleDocument::NewL( )
    {
    CSimpleDocument* self = new (ELeave) CSimpleDocument( );
    CleanupStack::PushL( self );
    self->ConstructL( KSimpleNsDefault, KDocumentLocalName );
    CleanupStack::Pop( self );
    return self;
    }

// ----------------------------------------------------------
// CSimpleDocument::NewL
// ----------------------------------------------------------
//
CSimpleDocument* CSimpleDocument::NewL( const TDesC8& aXml )
    {
    CSimpleDocument* self = new (ELeave) CSimpleDocument( );
    CleanupStack::PushL( self );
    self->ConstructL( aXml );
    CleanupStack::Pop( self );
    return self;
    }
    
// ----------------------------------------------------------
// CSimpleDocument::NewInMultiPartL
// ----------------------------------------------------------
//
CSimpleDocument* CSimpleDocument::NewInMultiPartL( 
    const TDesC8& aData, const TDesC8& aBoundary, const TDesC8& aStart )
    {
    CSimpleDocument* self = new (ELeave) CSimpleDocument( );
    CleanupStack::PushL( self );
    self->ConstructMultiPartL( aData, aBoundary, aStart );
    CleanupStack::Pop( self );
    return self;
    } 
    
// ----------------------------------------------------------
// CSimpleDocument::GetDirectContentsL
// ----------------------------------------------------------
//
void CSimpleDocument::GetDirectContentsL( 
    RPointerArray<MSimpleContent>& aContents )
    {
    aContents.Reset();
    TInt myCount = iContents.Count();
    for ( TInt i = 0; i<myCount; i++ )
        {
        User::LeaveIfError( aContents.Append( iContents[i] ));
        }               
    }
    
// ----------------------------------------------------------
// CSimpleDocument::AddDirectContentL
// ----------------------------------------------------------
//    
void CSimpleDocument::AddDirectContentL( 
    MSimpleContent& aContent,
    TBool aCopyContent )
    {
    CSimpleContent* content = CSimpleContent::NewLC(
        aContent.ContentID(), aContent.ContentType());
    User::LeaveIfError( iContents.Append( content ));
    CleanupStack::Pop( content );
    
    if ( aCopyContent )
        {
        content->CopyBodyL( aContent.Body() );
        }
    else
        {
        content->SetBody( aContent.GiveBodyOwnerShip() );
        }                       
    }
    
// ----------------------------------------------------------
// CSimpleDocument::ValidateXmlL
// ----------------------------------------------------------
//
void CSimpleDocument::ValidateXmlL( const TDesC8& aName )
    {
    if ( aName.CompareF( KDocumentLocalName ) )
        {
        User::Leave( KErrCorrupt );
        }
    }

// ----------------------------------------------------------
// CSimpleDocument::EntityURI
// ----------------------------------------------------------
//
const TDesC8* CSimpleDocument::EntityURI()
    {
    return Root()->AttrValue( KSimpleEntity );
    }

// ----------------------------------------------------------
// CSimpleDocument::SetEntityURIL
// ----------------------------------------------------------
//
void CSimpleDocument::SetEntityURIL( const TDesC8& aValue )
    {
    Root()->AddAttr8L( KSimpleEntity, aValue );
    }

// ----------------------------------------------------------
// CSimpleDocument::DefaultNamespace
// ----------------------------------------------------------
//

TPtrC8 CSimpleDocument::DefaultNamespace()
    {
    return CSimpleBaseDocument::DefaultNamespace();
    }


// ----------------------------------------------------------
// CSimpleDocument::AddNamespaceL
// ----------------------------------------------------------
//
void CSimpleDocument::AddNamespaceL(
    const TDesC8& aPrefix,
    const TDesC8& aUri )
    {
    CSimpleBaseDocument::AddNamespaceL( aPrefix, aUri );
    }

// ----------------------------------------------------------
// CSimpleDocument::NamespacesL
// ----------------------------------------------------------
//
RPointerArray<MSimpleNamespace>& CSimpleDocument::NamespacesL()
    {
    return CSimpleBaseDocument::NamespacesL();
    }

// ----------------------------------------------------------
// CSimpleDocument::ExternalizeL
// ----------------------------------------------------------
//
void CSimpleDocument::ExternalizeL( RWriteStream& aStream )
    {
    
    // notice: check the max message size 
    
    if ( !iContents.Count() )
        {            
        // single pidf+xml    
        CSimpleBaseDocument::ExternalizeL( aStream );
        }
    else
        {
        RPointerArray<CBodyPart> bodyPartsArray;
        RPointerArray<HBufC8> bufferArray;
        
        TRAPD( err, DoExternalizeMultiPartL( bodyPartsArray, bufferArray, aStream ) );                      
                               
        bufferArray.ResetAndDestroy();        
        bodyPartsArray.ResetAndDestroy();         
        bufferArray.Close();        
        bodyPartsArray.Close();        
        
        User::LeaveIfError( err );                                                                          
        }                                                
    }

// ----------------------------------------------------------
// CSimpleDocument::Close
// ----------------------------------------------------------
//
void CSimpleDocument::Close()
    {
    CSimpleBaseDocument::Close();
    }

// ----------------------------------------------------------
// CSimpleDocument::LocalName
// ----------------------------------------------------------
//
const TDesC8& CSimpleDocument::LocalName()
    {
    return CSimpleBaseDocument::LocalName();
    }

// ----------------------------------------------------------
// CSimpleDocument::DefNamespaceL
// ----------------------------------------------------------
//
MSimpleNamespace* CSimpleDocument::DefNamespaceL()
    {
    return CSimpleBaseDocument::DefNamespaceL();
    }

// ----------------------------------------------------------
// CSimpleDocument::HasContent
// ----------------------------------------------------------
//
TBool CSimpleDocument::HasContent()
    {
    return CSimpleBaseDocument::HasContent();
    }

// ----------------------------------------------------------
// CSimpleDocument::ContentUnicodeL
// ----------------------------------------------------------
//
HBufC* CSimpleDocument::ContentUnicodeL()
    {
    return CSimpleBaseDocument::ContentUnicodeL();
    }

// ----------------------------------------------------------
// CSimpleDocument::SetContentUnicodeL
// ----------------------------------------------------------
//
void CSimpleDocument::SetContentUnicodeL( const TDesC& aContent )
    {
    CSimpleBaseDocument::SetContentUnicodeL( aContent );
    }

// ----------------------------------------------------------
// CSimpleDocument::SimpleElementsL
// ----------------------------------------------------------
//
TInt CSimpleDocument::SimpleElementsL( RPointerArray<MSimpleElement>& aElementArray )
    {
    return CSimpleBaseDocument::SimpleElementsL( aElementArray );
    }

// ----------------------------------------------------------
// CSimpleDocument::AttrValueLC
// ----------------------------------------------------------
//
HBufC* CSimpleDocument::AttrValueLC( const TDesC8& aName )
    {
    return CSimpleBaseDocument::AttrValueLC( aName );
    }

// ----------------------------------------------------------
// CSimpleDocument::AttrValue
// ----------------------------------------------------------
//
const TDesC8* CSimpleDocument::AttrValue( const TDesC8& aName )
    {
  return CSimpleBaseDocument::AttrValue( aName );
    }

// ----------------------------------------------------------
// CSimpleDocument::AddAttrL
// ----------------------------------------------------------
//
void CSimpleDocument::AddAttrL( const TDesC8& aName, const TDesC& aValue )
    {
    CSimpleBaseDocument::AddAttrL( aName, aValue );
    }

// ----------------------------------------------------------
// CSimpleDocument::SimpleAttributesL
// ----------------------------------------------------------
//
TInt CSimpleDocument::SimpleAttributesL( RPointerArray<MSimpleAttribute>& aArray )
    {
    return CSimpleBaseDocument::SimpleAttributesL( aArray );
    }

// ----------------------------------------------------------
// CSimpleDocument::SimpleParentL
// ----------------------------------------------------------
//
MSimpleElement* CSimpleDocument::SimpleParentL()
    {
    return NULL;
    }

// ----------------------------------------------------------
// CSimpleDocument::DetachSimpleL
// ----------------------------------------------------------
//
void CSimpleDocument::DetachSimpleL()
    {
    User::Leave( KErrNotFound );
    }


// ----------------------------------------------------------
// CSimpleDocument::AddSimpleElementL
// ----------------------------------------------------------
//
MSimpleElement* CSimpleDocument::AddSimpleElementL(
    const TDesC8& aNsUri,
    const TDesC8& aLocalName )
    {
    return CSimpleBaseDocument::AddSimpleElementL( aNsUri, aLocalName );
    }

// ----------------------------------------------------------
// CSimpleDocument::AddSimpleElementL
// ----------------------------------------------------------
//
MSimpleElement* CSimpleDocument::AddSimpleElementL(
    const TDesC8& aLocalName )
    {
    return CSimpleBaseDocument::AddSimpleElementL( aLocalName );
    }


// ----------------------------------------------------------
// CSimpleDocument::RemoveSimpleElement
// ----------------------------------------------------------
//
void CSimpleDocument::RemoveSimpleElement(
    const TDesC8& aNsUri,
    const TDesC8& aLocalName )
    {
    CSimpleBaseDocument::RemoveSimpleElement( aNsUri, aLocalName );
    }
    
// ----------------------------------------------------------
// CSimpleDocument::ResetAndDestroy
// ----------------------------------------------------------
//
void CSimpleDocument::ResetAndDestroy( TAny* aPtrArray )
    {
    RPointerArray<CBodyPart>* array =
    	static_cast<RPointerArray<CBodyPart>*>( aPtrArray );
    array->ResetAndDestroy();
    array->Close();	
    }   
       
// ----------------------------------------------------------
// CSimpleDocument::DoConstructL
// ----------------------------------------------------------
//    
void CSimpleDocument::DoConstructL( 
    RPointerArray<CBodyPart>& aParts, const TDesC8& aStart )
    {
    // Handle body parts one by one
    TInt size = aParts.Count();
    TInt i;
    CBodyPart* cp = NULL;
    TPtrC8 boundary;
    TPtrC8 start;
    
    TBool pidfOk ( EFalse );
    
          
    for (i = 0; i < size; i++)
        {
        cp = aParts[i];      
                                     
        if ( (( aStart.Length() > 0 && !aStart.Compare( cp->ContentID()) ) || 
                !pidfOk ) && 
             !cp->ContentType().Left(sizeof(KSimpleDocumentType)).CompareF( KSimpleDocumentType ))
            {
            // Multipart root is in the pidf+xml format
            BaseConstructL( cp->Body() );
            pidfOk = ETrue;
            }
        else 
            {
            // Direct contents, as a separate MIME multipart parts                           
            CSimpleContent* cd = CSimpleContent::NewL( 
                cp->ContentID(), cp->ContentType() );
            cd->CopyBodyL( cp->Body() );                 
            CleanupStack::PushL( cd );           
            User::LeaveIfError( iContents.Append( cd ) );
            CleanupStack::Pop( cd );           
            }                  
        }   
    }    
            
// ------------------------------------------------------------------------- 
// CSimpleDocument::DoComposeMultiPartL
// ------------------------------------------------------------------------- 
HBufC8* CSimpleDocument::DoComposeMultiPartL( RPointerArray<CBodyPart>& aBodyArray,
                                const TDesC8& aBoundary )
    {
    // --(aBoundary)
    using namespace NSimpleDocument;
    HBufC8* boundary = HBufC8::NewLC( aBoundary.Length() + 4 );
    boundary->Des().Format( KBoundary, &aBoundary );
    
    // CALCULATE the size of this document.
    TInt bodySize = 0;
    //    a. for each CBodyPart
    //       boundaries + CRLF between headers and body (constant addition)
    bodySize += (boundary->Length() + strlen(Multipart_CRLF_Text)) * aBodyArray.Count() ;
    TInt bodyCounter = aBodyArray.Count();
    for (TInt i = 0; i < bodyCounter; i++)
        {
        if (!(aBodyArray[i]->Headers().Length() +
            aBodyArray[i]->Body().Length()))
            {
            // one less boundary
            bodySize -= boundary->Length() + strlen(Multipart_CRLF_Text);
            // skip empty bodypart
            continue;
            }
        bodySize += aBodyArray[i]->Headers().Length();
        //  ensure there are only 2 CRLFs between header and body
        if (aBodyArray[i]->Headers().Length() > 0)
            {
            TPtrC8 bodyHeaders(aBodyArray[i]->Headers().Ptr(), aBodyArray[i]->Headers().Length());
            TUint newEnd = bodyHeaders.Length() - 1;
            while( bodyHeaders[ newEnd ] == '\r' || bodyHeaders[ newEnd ] == '\n' )
                {
                --newEnd;
                --bodySize;
                }
            // two CRLFs
            bodySize += strlen(Multipart_CRLF_Text);
            }
        bodySize += aBodyArray[i]->Body().Length();
        //  CRLF (end of body, add one only if there is body AND does not end with CRLF)
        TPtrC8 bodyBody(aBodyArray[i]->Body().Ptr(), aBodyArray[i]->Body().Length());
        if (bodyBody.Length() > 0 
            && bodyBody.Right(2) != TPtrC8((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text)))
            {
            bodySize += strlen(Multipart_CRLF_Text);
            }
        }
    // end boundary (boundary - '\r\n' + "--")
    bodySize += boundary->Length(); 
    TInt docSize = bodySize; 
    
    // CALCULATE the size of Headers
    using namespace NSimpleDocument::NSimpleMulti;    
       
    // extra CRLF for separating header and body
    docSize += strlen(Multipart_CRLF_Text);
    //  CALCULATION COMPLETE
    //  at this point, bodySize contains the size of bodyparts, i.e. Content-Length:
    //  and docSize contains the size of the entire document (use it to create HBufC8*
    //  of appropriate size)
  
    //  CONSTRUCT MULTIPART DOCUMENT
    HBufC8* document = HBufC8::NewLC(docSize);
        
    TPtr8 docAppend(document->Des());
           
    //  BODYPARTS
    for (TInt i = 0; i < aBodyArray.Count(); i++)
        {
        if (!(aBodyArray[i]->Headers().Length() +
            aBodyArray[i]->Body().Length()))
            {
            // skip empty bodypart
            continue;
            }
        docAppend.Append( *boundary );
        TInt headerLength = aBodyArray[i]->Headers().Length() - 1;
        while ( headerLength > 0 &&
                (aBodyArray[i]->Headers()[headerLength] == '\r'
                || aBodyArray[i]->Headers()[headerLength] == '\n' ))
            {
            --headerLength;
            }
        docAppend.Append( aBodyArray[i]->Headers().Ptr(), headerLength + 1 );

        if ( headerLength > 0 )
            {
            docAppend.Append((TUint8*)Multipart_DoubleCRLF_Text, strlen(Multipart_DoubleCRLF_Text));
            }
        else
            {
            docAppend.Append((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text));
            }
        //  body
        TPtrC8 opa = aBodyArray[i]->Body();
        docAppend.Append(aBodyArray[i]->Body());
        //  CRLF only if body exists and doesn't end with CRLF
        TPtrC8 bodyBody(aBodyArray[i]->Body().Ptr(), aBodyArray[i]->Body().Length());
        if (bodyBody.Length() > 0
            && bodyBody.Right(2) != TPtrC8((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text)))
            {
            docAppend.Append((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text));
            }
        }
    //  end boundary
    docAppend.AppendFormat(KEndBoundary, &aBoundary);
    CleanupStack::Pop( document );
    CleanupStack::PopAndDestroy( boundary );
    return document;
    } 
    
// ------------------------------------------------------------------------- 
// CSimpleDocument::DoExternalizeMultiPartL
// -------------------------------------------------------------------------    
void CSimpleDocument::DoExternalizeMultiPartL( 
        RPointerArray<CBodyPart>& aBodies, 
        RPointerArray<HBufC8>& aBuffers,
        RWriteStream& aStream )
    {
    const TReal KB64Expand = 1.5; // reserve room for Base64 encoding
    const TInt KBufferSize = 500;
        
    // Convert all the multipart into CBodyPart.
           
    // Let's convert first ROOT element into CBodyPart
    CBodyPart* root = CBodyPart::NewL();
    // Add into cleanup array
    aBodies.Append( root );     
    CSenElement* e = Root()->BaseElement();
    
    // externalize the document into stream
    CBufFlat* myBuffer = CBufFlat::NewL( KBufferSize );
    CleanupStack::PushL( myBuffer );        
    myBuffer->Reset();
    
    RBufWriteStream stream( *myBuffer );
    stream.Open( *myBuffer );  
    CSimpleBaseDocument::ExternalizeL( stream );
    stream.Close();
    
    // Add content, no need to transfer encode
    TPtrC8 body ( myBuffer->Ptr(0) );
    root->SetBody( body ); 
    
    // Handle the headers of the ROOT part
    using namespace NSimpleDocument::NSimpleRoot;
    
    // calculate the size of headers
    TInt headerSize = KContentTypeSize + KCIDSize;
    HBufC8* headers = HBufC8::NewL( headerSize );  
    aBuffers.Append( headers );
    TPtr8 pH(headers->Des());
    // append to MIME headers for the root part   
    pH.Append( NSimpleDocument::NSimpleRoot::KContentType );
    pH.Append( NSimpleDocument::NSimpleRoot::KCID );    
    root->SetHeaders( pH );    
                                       
    // handle the direct contents one by one
    TInt contCount = iContents.Count();
    for ( TInt i=0; i<contCount; i++ )
        { 
        // Let's convert next element into CBodyPart
        CBodyPart* cp = CBodyPart::NewL();
        aBodies.Append( cp );                
         
        // Set Headers
        headerSize = NSimpleDocument::NSimpleContent::KContentTypeSize + 
                     NSimpleDocument::NSimpleContent::KCIDSize + 
                     NSimpleDocument::NSimpleContent::KContentEncodingSize;
        headerSize += (iContents[i])->ContentID().Length();
        headerSize += (iContents[i])->ContentType().Length();                 
        
        headers = HBufC8::NewL( headerSize );
        // Append to cleanup array  
        aBuffers.Append( headers );
        pH.Set( headers->Des() );

        // _LIT8( KMyContentType, "Content-Type: %S\r\n"); 
        TPtrC8 myValue = (iContents[i])->ContentType();     
        pH.Format( NSimpleDocument::NSimpleContent::KContentType, &myValue );    
        myValue.Set((iContents[i])->ContentID() );         
        pH.AppendFormat( NSimpleDocument::NSimpleContent::KCID, &myValue );            
        pH.Append( NSimpleDocument::NSimpleContent::KContentEncoding ); 
        // append to MIME headers           
        cp->SetHeaders( pH );
                     
        // Body
                    
        // BASE64 encode
        HBufC8* body64 = HBufC8::NewL( (iContents[i])->Body().Length() * KB64Expand );  
        aBuffers.Append( body64 );        
        TImCodecB64 codec64;
        codec64.Initialise();        
        TPtr8 desti8 = body64->Des();  
        
        // notice: leave if error?
        TInt err = codec64.Encode( (iContents[i])->Body(), desti8 );                                 
        
        cp->SetBody( body64->Des() );                                                                                 
        }
                            
    // Compose the multipart MIME flat data   
    HBufC8* entireMsg = NULL;      
    entireMsg = DoComposeMultiPartL( aBodies, NSimpleDocument::KSimpleBoundary );
    CleanupStack::PushL( entireMsg );
    // Finally stream entireMsg, 
    // Notice: later DoComposeMultiPartL could stream directly?
    aStream.WriteL( entireMsg->Des() ); 
    CleanupStack::PopAndDestroy( entireMsg );  
    CleanupStack::PopAndDestroy( myBuffer );                 
 
    }