omaprovisioning/provisioning/ProvisioningHandler/Src/CWPMessage.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 21:00:49 +0200
changeset 2 5594fba90824
parent 0 b497e44ab2fc
child 25 b183ec05bd8c
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2002-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:  Main class for handling provisioning message
*
*/



// INCLUDE FILES
#include <biodb.h>      // BIO Message Database and message query methods
#include <msvuids.h>    // KUidMsvMessageEntry const
#include <biouids.h>    // KUidBioMessageTypeMtm const
#include <msvapi.h>
#include <msvids.h>
#include <txtfmlyr.h>
#include <txtrich.h>
#include <smut.h>
#include <smuthdr.h>
#include <provisioninghandlerresource.rsg>
#include <pushmessage.h>
#include <CWPEngine.h>
#include <WPAdapterUtil.h>
#include <data_caging_path_literals.hrh>
#include <centralrepository.h>
#include <csmsgetdetdescinterface.h>
#include "MWPPhone.h"
#include "WPPhoneFactory.h"
#include "CWPBootstrap.h"
#include "CWPMessage.h"
#include "CWPPushMessage.h"
#include "WPHandlerDebug.h"
#include "WPHandlerUtil.h"
#include "ProvisioningDebug.h"
#include "ProvisioningInternalCRKeys.h"


// CONSTANTS
_LIT(KResourceName, "ProvisioningHandler");

_LIT(KDirAndFile,"z:ProvisioningHandler.rsc");


// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CWPMessage::CWPMessage
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CWPMessage::CWPMessage()
    {
    }

// -----------------------------------------------------------------------------
// CWPMessage::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CWPMessage::ConstructL( CPushMessage& aMessage )
    {
    FLOG( _L( "CWPMessage::ConstructL: Opening msg session" ) );

    iSession = CMsvSession::OpenSyncL(*this);

    FLOG( _L( "CWPMessage::ConstructL: Constructing push message" ) );
    iMessage = CWPPushMessage::NewL();

    TPtrC8 bodyValue;
    TPtrC8 headerValue;
    if (aMessage.GetMessageBody(bodyValue)
        && aMessage.GetHeader(headerValue) )
        {
        iMessage->SetL( headerValue, bodyValue );
        }

    TPtrC8 serverValue;
    if( aMessage.GetServerAddress( serverValue ) )
        {
        FLOG( _L( "CWPMessage::Begin originator" ) );
        DHEX( serverValue );
        FLOG( _L( "CWPMessage::End originator" ) );
        iMessage->SetOriginatorL( serverValue );
        iSender = serverValue.AllocL();
        }

    FLOG( _L( "CWPMessage::Begin header" ));
    DHEX( iMessage->Header() );
    FLOG( _L( "CWPMessage::Begin message body" ) );
    DHEX( iMessage->Body() );
    FLOG( _L( "CWPMessage::End message" ) );

    FLOG( _L( "CWPMessage::ConstructL: Retrieving BIO message type" ) );
    BioMessageTypeL( aMessage );

    FLOG( _L( "CWPMessage::ConstructL: Finished" ) );
    }

// -----------------------------------------------------------------------------
// CWPMessage::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CWPMessage* CWPMessage::NewL( CPushMessage& aMessage )
    {
    CWPMessage* self = new(ELeave) CWPMessage; 
    CleanupStack::PushL(self);
    self->ConstructL( aMessage );
    CleanupStack::Pop(self);
    return self;
    }

// Destructor
CWPMessage::~CWPMessage()
    {
    delete iPhone;
    delete iSession;
    delete iSender;
    delete iMessage;
    }

// -----------------------------------------------------------------------------
// CWPMessage::HandleSessionEventL
// -----------------------------------------------------------------------------
//
void CWPMessage::HandleSessionEventL(TMsvSessionEvent /*aEvent*/, 
    TAny* /*aArg1*/, TAny* /*aArg2*/, TAny* /*aArg3*/)
    {
    }

// -----------------------------------------------------------------------------
// CWPMessage::ProcessL
// -----------------------------------------------------------------------------
//
void CWPMessage::ProcessL()
    {
    FLOG( _L( "CWPMessage::ProcessL: Started" ) );

    // Create a phone if one does not already exist
    if( !iPhone )
        {
        iPhone = WPPhoneFactory::CreateL();
        }

    FLOG( _L( "CWPMessage::ProcessL: Creating engine" ) );

    // Read the message into the engine
    CWPEngine* engine = CWPEngine::NewLC(); // on CS

    FLOG( _L( "CWPMessage::ProcessL: Importing document" ) );
    engine->ImportDocumentL( iMessage->Body() );

    FLOG( _L( "CWPMessage::ProcessL: Populating adapters" ) );
    engine->PopulateL();

    FTRACE(RDebug::Print(_L(" WPMessage::ProcessL: Number of settings: (%d)"), engine->ItemCount()));
    // Check if the sender can be trusted
    TPtrC8 orig8( iMessage->Originator() );
    HBufC* originator = HBufC::NewLC( orig8.Length() );
    TPtr orig16( originator->Des() );
    orig16.Copy( orig8 );
    if( engine->ContextExistsL( orig16 ) )
        {
        iMessage->SetAuthenticated( ETrue );
        }
    CleanupStack::PopAndDestroy(); // originator
    
    // Try bootstrapping
    FLOG( _L( "CWPMessage::ProcessL: Bootstrapping" ) );
    CWPBootstrap* bootstrap = CWPBootstrap::NewL( iPhone->SubscriberId() );
    CleanupStack::PushL( bootstrap );

    CWPBootstrap::TBootstrapResult result( 
        bootstrap->BootstrapL( *iMessage, *engine, KNullDesC ) );
    CleanupStack::PopAndDestroy(); // bootstrap

    FTRACE(RDebug::Print(_L(" WPMessage::ProcessL: Bootstrap result: (%d)"), result));
        // See UI specs figure 1 
    TBool haveSettings( engine->ItemCount() > 0 );
    switch( result )
        {
        case CWPBootstrap::ENoBootstrap:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping ENoBootstrap" ) );
            // If there's no bootstrap, just save the message
            if( haveSettings )
                {
                StoreMsgL();
                }
            else
                {
                User::Leave( KErrCorrupt );
                }
            break;
            }

        case CWPBootstrap::ENotAuthenticated:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping ENotAuthenticated" ) );
            if( haveSettings )
                {
                StoreMsgL();
                }
            else
            {
                
            // Message is ignored and an information SMs is put to Inbox.
            //Information SMs can be Class0,  based on operator requirement.
            TInt auth_value;
            CRepository * rep = 0;
            TRAPD( err, rep = CRepository::NewL( KCRUidOMAProvisioningLV ));
            if(err == KErrNone)
            {
            	rep->Get( KOMAProvAuthFailMsgHandling, auth_value );
            	delete rep;
            	
            	if(auth_value == 1)
            	StoreMsgclass0L(R_TEXT_AUTHENTICATION_FAILED);
            	else
            	StoreMsgL(R_TEXT_AUTHENTICATION_FAILED);
            	
            	User::Leave( KErrAccessDenied ); 
            }
            else
            {
            StoreMsgL(R_TEXT_AUTHENTICATION_FAILED);
            User::Leave( KErrAccessDenied );                         
            }
                }
            break;
            }

        case CWPBootstrap::EPinRequired:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping EPinRequired" ) );
            
            // If PIN is required, defer authentication to ProvisioningBC
            if( haveSettings )
                {
                StoreMsgL();
                }
            else
                {
                User::Leave( KErrCorrupt );
                }
            break;
            }

        case CWPBootstrap::EAuthenticationFailed:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping EAuthenticationFailed" ) );
            
            // Bootstrap is ignored and an information SMS is put to Inbox.
            //Information SMs can be Class0,  based on operator requirement.
            TInt auth_value;
            CRepository * rep = 0;
            TRAPD( err, rep = CRepository::NewL( KCRUidOMAProvisioningLV ));
            if(err == KErrNone)
            {
            	rep->Get( KOMAProvAuthFailMsgHandling, auth_value );
            	delete rep;
            	
            	if(auth_value == 1)
            	StoreMsgclass0L(R_TEXT_AUTHENTICATION_FAILED);
            	else
            	StoreMsgL(R_TEXT_AUTHENTICATION_FAILED);
            	
            	User::Leave( KErrAccessDenied );
            	
            }
            else
            {
            StoreMsgL(R_TEXT_AUTHENTICATION_FAILED);
            User::Leave( KErrAccessDenied );
            }
            break;
            }

        case CWPBootstrap::EBootstrapExists:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping EBootstrapExists" ) );
            
            if( haveSettings )
                {
                StoreMsgL();
                }
            else
                {
                // Bootstrap is ignored and an information SMS is put to Inbox
                StoreMsgL( R_TEXT_BOOTSTRAP_EXISTS );
                User::Leave( KErrAlreadyExists );
                }
            break;
            }

        case CWPBootstrap::ESucceeded:
            {
            FLOG( _L( "CWPMessage::ProcessL: Bootstrapping ESucceeded" ) );
            
            if( haveSettings )
                {
                StoreMsgL();
                }
            else
                {
                StoreMsgL( R_TEXT_BOOTSTRAPPED );
                }
            break;
            }

        default:
            {
            break;
            }
        }

    CleanupStack::PopAndDestroy(); // engine

    FLOG( _L( "CWPMessage::ProcessL: Finished" ) );
    }

// -----------------------------------------------------------------------------
// CWPMessage::BioMessageTypeL
// -----------------------------------------------------------------------------
//
void CWPMessage::BioMessageTypeL( CPushMessage& aMessage )
    {
    FLOG( _L( "CWPMessage::BioMessageTypeL" ) );
    
    // need to create local RFs for BIO otherwise raises exception
    RFs localFS;
    User::LeaveIfError(localFS.Connect());
    CleanupClosePushL(localFS);
    CBIODatabase* bioDB = CBIODatabase::NewLC(localFS);

    TPtrC contentTypePtr;
    aMessage.GetContentType(contentTypePtr);
    
    iBioUID = KNullUid;
    // IsBioMessageL returns KErrNone if found or KErrNotFound if not found 
    TInt retVal = bioDB->IsBioMessageL(EBioMsgIdIana, contentTypePtr, NULL, iBioUID);
    FTRACE(RDebug::Print(_L(" CWPMessage::BioMessageTypeL (%d)"), retVal));
    CleanupStack::PopAndDestroy(2); // bioDB, localFS
    }

// -----------------------------------------------------------------------------
// CWPMessage::StoreMsgL
// -----------------------------------------------------------------------------
//
void CWPMessage::StoreMsgL()
    {
    FLOG( _L( "CWPMessage::StoreMsgL" ) );
    
    // create an invisible blank entry 
    TMsvEntry entry;
    PrepareEntryLC( entry ); // details on cleanup stack
    entry.iBioType = iBioUID.iUid;
    entry.iMtm = KUidBIOMessageTypeMtm;
    
    // Look up and set the description
    FLOG( _L( "CWPMessage::StoreMsgL 1" ) );
    
    TInt index;
    CBIODatabase* bioDB = CBIODatabase::NewLC( iSession->FileSession() );
    FLOG( _L( "CWPMessage::StoreMsgL 2" ) );
    TRAPD( err, bioDB->GetBioIndexWithMsgIDL( iBioUID, index ) );
    if (err ==KErrNone)
        {
        FLOG( _L( "CWPMessage::StoreMsgL 3" ) );
        HBufC* description = bioDB->BifReader(index).Description().AllocL();
        FLOG( _L( "CWPMessage::StoreMsgL 4" ) );
        entry.iDescription.Set(*description);
        FLOG( _L( "CWPMessage::StoreMsgL 5" ) );
        CleanupStack::PopAndDestroy();  // bioDB
        CleanupStack::PushL( description );
        }
    else
        {
        FTRACE(RDebug::Print(_L(" CWPMessage::StoreMsgL err (%d)"), err));
        CleanupStack::PopAndDestroy();  // bioDB
        }
        
    FLOG( _L( "CWPMessage::StoreMsgL 6" ) );
    // Store entry in inbox
    CMsvEntry* msvEntry = iSession->GetEntryL( KMsvGlobalInBoxIndexEntryId );
    FLOG( _L( "CWPMessage::StoreMsgL 7" ) );
    CleanupStack::PushL(msvEntry);
    msvEntry->CreateL(entry);
    msvEntry->Session().CleanupEntryPushL(entry.Id());
    msvEntry->SetEntryL(entry.Id());
    FLOG( _L( "CWPMessage::StoreMsgL 8" ) );
    // Save the message
    CMsvStore* store = msvEntry->EditStoreL();
    CleanupStack::PushL(store);
    FLOG( _L( "CWPMessage::StoreMsgL 9" ) );
    iMessage->StoreL( *store );
    store->CommitL();
    
    // Complete processing the message
    PostprocessEntryL( *msvEntry, entry );

    CleanupStack::PopAndDestroy(); //store
    msvEntry->Session().CleanupEntryPop(); //entry
    CleanupStack::PopAndDestroy(3); //description, details, msvEntry
    FLOG( _L( "CWPMessage::StoreMsgL Done" ) );
    }

// -----------------------------------------------------------------------------
// CWPMessage::StoreMsgL
// -----------------------------------------------------------------------------
//
void CWPMessage::StoreMsgL( TInt aResource )
    {
    FLOG( _L( "CWPMessage::StoreMsgL(aResource)" ) );
    
    // create an invisible blank entry 
    TMsvEntry entry;
    PrepareEntryLC( entry ); // details on cleanup stack
    entry.iMtm = KUidMsgTypeSMS;     

    // Store entry in inbox
    CMsvEntry* msvEntry = iSession->GetEntryL(KMsvGlobalInBoxIndexEntryId);
    CleanupStack::PushL(msvEntry);
    msvEntry->CreateL(entry);
    msvEntry->Session().CleanupEntryPushL(entry.Id());
    msvEntry->SetEntryL(entry.Id());

    // Save the message body
    CMsvStore* store = msvEntry->EditStoreL();
    CleanupStack::PushL(store);
    CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
    CleanupStack::PushL( paraFormat );
    CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
    CleanupStack::PushL( charFormat );
    CRichText* body = CRichText::NewL( paraFormat, charFormat );
    CleanupStack::PushL( body );
    HBufC* text = LoadStringLC( aResource );
    body->InsertL( body->DocumentLength(), *text );
    store->StoreBodyTextL( *body );

    // Store the actual message for post-mortem analysis
    iMessage->StoreL( *store );

    // Save the SMS header and create a description field
    CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, *body );
    CleanupStack::PushL( header );
    TBuf<KSmsDescriptionLength> description;

    CSmsGetDetDescInterface* smsPlugin = CSmsGetDetDescInterface::NewL();
    CleanupStack::PushL( smsPlugin );
    smsPlugin->GetDescription( header->Message(), description );
    CleanupStack::PopAndDestroy( smsPlugin );

    entry.iDescription.Set( description );
    header->StoreL( *store );
    store->CommitL();
    CleanupStack::PopAndDestroy( 5 ); // header, text, body, charformat, paraFormat

    // Complete processing the message
    PostprocessEntryL( *msvEntry, entry );

    CleanupStack::PopAndDestroy(); //store
    msvEntry->Session().CleanupEntryPop(); //entry
    CleanupStack::PopAndDestroy(2); //details, msvEntry
    }
    
// -----------------------------------------------------------------------------
// CWPMessage::StoreMsgclass0L
// -----------------------------------------------------------------------------
//
void CWPMessage::StoreMsgclass0L( TInt aResource )
    {
    FLOG( _L( "CWPMessage::StoreMsgL(aResource)" ) );
    
    // create an invisible blank entry 
    TMsvEntry entry;
    PrepareEntryLC( entry ); // details on cleanup stack
    entry.iMtm = KUidMsgTypeSMS;     

    // Store entry in inbox
    CMsvEntry* msvEntry = iSession->GetEntryL(KMsvGlobalInBoxIndexEntryId);
    CleanupStack::PushL(msvEntry);
    msvEntry->CreateL(entry);
    msvEntry->Session().CleanupEntryPushL(entry.Id());
    msvEntry->SetEntryL(entry.Id());

    // Save the message body
    CMsvStore* store = msvEntry->EditStoreL();
    CleanupStack::PushL(store);
    CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
    CleanupStack::PushL( paraFormat );
    CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
    CleanupStack::PushL( charFormat );
    CRichText* body = CRichText::NewL( paraFormat, charFormat );
    CleanupStack::PushL( body );
    HBufC* text = LoadStringLC( aResource );
    body->InsertL( body->DocumentLength(), *text );
    store->StoreBodyTextL( *body );

    // Store the actual message for post-mortem analysis
    iMessage->StoreL( *store );

    
   
    
    // Save the SMS header and create a description field
    CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, *body );
    
    
    CleanupStack::PushL( header );
    TBuf<KSmsDescriptionLength> description;

    
    //class 0 Implementation
    CSmsMessage &msg = header->Message();
	CSmsPDU &pdu = msg.SmsPDU(); 
	pdu.SetClass(ETrue,TSmsDataCodingScheme::ESmsClass0);

 	CSmsGetDetDescInterface* smsPlugin = CSmsGetDetDescInterface::NewL();
    CleanupStack::PushL( smsPlugin );
    smsPlugin->GetDescription( msg , description );
    CleanupStack::PopAndDestroy( smsPlugin );

    entry.iDescription.Set( description );
    header->StoreL( *store );
    store->CommitL();
    CleanupStack::PopAndDestroy( 5 ); // header, text, body, charformat, paraFormat

    // Complete processing the message
    PostprocessEntryL( *msvEntry, entry );

    CleanupStack::PopAndDestroy(); //store
    msvEntry->Session().CleanupEntryPop(); //entry
    CleanupStack::PopAndDestroy(2); //details, msvEntry
    }

// -----------------------------------------------------------------------------
// CWPMessage::PrepareEntry
// -----------------------------------------------------------------------------
//
void CWPMessage::PrepareEntryLC( TMsvEntry& aEntry )
    {
    FLOG( _L( "CWPMessage::PrepareEntryLC" ) );
    
    // Current time
    TTime time;

	// Get Universal time
	time.UniversalTime();

	FLOG( _L( "CWPMessage::PrepareEntryLC create an invisible blank entry" ) );	
    // create an invisible blank entry 
    aEntry.iType = KUidMsvMessageEntry;
    aEntry.SetVisible(EFalse);
    aEntry.SetInPreparation(ETrue);
    aEntry.SetReadOnly(EFalse);
    aEntry.SetUnread(ETrue);
    aEntry.iDate = time;
    aEntry.iServiceId = KMsvLocalServiceIndexEntryId;
    aEntry.iError = KErrNone;
    // iMtmData1 is been used/reserved for count, please don't use for any other purpose.
    aEntry.SetMtmData1(3);
    FLOG( _L( "CWPMessage::PrepareEntryLC create an invisible blank entry done" ) );
    // Look up the details
    HBufC* details = NULL;
    if( iMessage->Authenticated() )
        {
        FLOG( _L( "CWPMessage::PrepareEntryLC iMessage->Authenticated() true" ) );
        details = LoadStringLC( R_FROM_SERVICEPROVIDER );
        FLOG( _L( "CWPMessage::PrepareEntryLC LoadString done" ) );
        }
    else
        {
        FLOG( _L( "CWPMessage::PrepareEntryLC iMessage->Authenticated() false" ) );
        if( iSender )
            {
            FLOG( _L( "CWPMessage::PrepareEntryLC iSender true" ) );
            details = HBufC::NewLC( iSender->Length() );
            details->Des().Copy( *iSender );
            }
        else
            {
            FLOG( _L( "CWPMessage::PrepareEntryLC iSender false" ) );
            details = KNullDesC().AllocLC();
            }
        }
    FLOG( _L( "CWPMessage::PrepareEntryLC iDetails.Set" ) );
    aEntry.iDetails.Set( *details );
    FLOG( _L( "CWPMessage::PrepareEntryLC Done" ) );
    }

// -----------------------------------------------------------------------------
// CWPMessage::PostprocessEntryL
// -----------------------------------------------------------------------------
//
void CWPMessage::PostprocessEntryL( CMsvEntry& aCEntry, TMsvEntry& aTEntry )
    {
    FLOG( _L( "CWPMessage::PostprocessEntryL" ) );
    
    aTEntry.SetReadOnly(EFalse);
    aTEntry.SetVisible(ETrue);
    aTEntry.SetInPreparation(EFalse);
    aCEntry.ChangeL(aTEntry);
    }

// -----------------------------------------------------------------------------
// CWPMessage::LoadStringLC
// -----------------------------------------------------------------------------
//
HBufC* CWPMessage::LoadStringLC( TInt aResourceId )
    {
    FLOG( _L( "CWPMessage::LoadStringLC" ) );

	TParse parse;
    FLOG( _L( "CWPMessage::LoadStringLC2" ) );
    parse.Set(KDirAndFile, &KDC_RESOURCE_FILES_DIR, NULL); 

    FLOG( _L( "CWPMessage::LoadStringLC3" ) );
    HBufC* result = WPAdapterUtil::ReadHBufCL( parse.FullName(), KResourceName, aResourceId );
    CleanupStack::PushL( result );
    
    FLOG( _L( "CWPMessage::LoadStringLC done" ) );
    
    return result;
    }

//  End of File