wlanutilities/wlansniffer/apwizard/src/wsfwlaniapcreator.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:32 +0100
branchRCL_3
changeset 25 f28ada11abbf
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201029 Kit: 201035

/*
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   Implementation of CWsfWlanIapCreator
*
*/




//  EXTERNAL INCLUDES
#include <wlancontainer.h>
#include <EapType.h>
#include <cmdestinationext.h>
#include <utf.h>

//  CLASS HEADER
#include "wsfwlaniapcreator.h"

//  INTERNAL INCLUDES
#include "wsfactivewaiter.h"
#include "wsflogger.h"


using namespace CMManager;


/**
* Order of first WEP key
*/
static const TInt KFirstWepKey = 0;

/**
* WEP authentication modes
*/
static const TInt KWepAuthOpen = 0;        // Open authentication

/**
* Max length of WPA key
*/
static const TUint KWpaKeyMaxLength = 64;
    
/**
* Max length of WEP key
*/
static const TUint KMaxWepKeyLen = 26; 



  

// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::NewL
// ----------------------------------------------------------------------------
//
CWsfWlanIapCreator* CWsfWlanIapCreator::NewL()
    {
    CWsfWlanIapCreator* thisPtr = NewLC();
    CleanupStack::Pop( thisPtr );
    return thisPtr;         
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::NewLC
// ----------------------------------------------------------------------------
//
CWsfWlanIapCreator* CWsfWlanIapCreator::NewLC()
    {
    CWsfWlanIapCreator* thisPtr = new (ELeave) CWsfWlanIapCreator();
    CleanupStack::PushL( thisPtr );
    thisPtr->ConstructL();
    return thisPtr;    
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::~CWsfWlanIapCreator
// ----------------------------------------------------------------------------
//
CWsfWlanIapCreator::~CWsfWlanIapCreator()
    {
    delete iDbSession;
    iCmManagerExt.Close();
    }
    

// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::CWsfWlanIapCreator
// ----------------------------------------------------------------------------
//
CWsfWlanIapCreator::CWsfWlanIapCreator()     
    {
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::ConstructL
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::ConstructL()
    {
    iDbSession = CommsDat::CMDBSession::NewL( CMDBSession::LatestVersion() );
    iCmManagerExt.OpenL();
    iDestinationId = 0;
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::StoreWPADataL
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::StoreWPADataL( const TInt aIapId, 
                                     const TDesC& aPresharedKey, 
                                     const CMManager::TWlanSecMode aSecMode )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::StoreWPADataL" );
    
    CCDIAPRecord *iapRec = static_cast<CCDIAPRecord*>
                          ( CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
    
    CleanupStack::PushL( iapRec );
    
    iapRec->SetRecordId( aIapId );
    iapRec->LoadL( *iDbSession );
        
    TUint32 serviceId = TUint32( iapRec->iService );

    LOG_WRITEF("IAP(%d).serviceID = %d", aIapId, serviceId );
    
    // we have the service id, now we can flush the iap record
    CleanupStack::PopAndDestroy( iapRec );

    // search for the record    
    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>( 
                                          CCDRecordBase::RecordFactoryL( 0 ) );
    CleanupStack::PushL( generic );    
    generic->InitializeL( TPtrC( WLAN_SERVICE ), NULL );
    generic->LoadL( *iDbSession );
    
    CMDBField<TUint32>* sidField = static_cast<CMDBField<TUint32>*>
                             ( generic->GetFieldByIdL( KCDTIdWlanServiceId ) );
    
    // prime with service id                
    *sidField = serviceId;
    
    TBool found = generic->FindL( *iDbSession );

    LOG_WRITE( "saving common WPA settings..." );
    TBool usesPsk( aPresharedKey.Length() > 0 );

    // Save PreShared Key as 8 bit string
    TBuf8<KWpaKeyMaxLength> keyWPA;
    keyWPA.Copy( aPresharedKey );
    TInt len( keyWPA.Length() );
    LOG_WRITEF( "PSK:[%S] len = %d", &aPresharedKey, len );


    CMDBField<TUint>* enableWpaPskField = static_cast<CMDBField<TUint>*>
                          ( generic->GetFieldByIdL( KCDTIdWlanEnableWpaPsk ) );
    enableWpaPskField->SetL( usesPsk );

    CMDBField<TUint>* secModeField = static_cast<CMDBField<TUint>*>
                        ( generic->GetFieldByIdL( KCDTIdWlanSecMode ) );
    secModeField->SetL( aSecMode );

    CMDBField<TDesC8>* wpaPskField = static_cast<CMDBField<TDesC8>*>
                       ( generic->GetFieldByIdL( KCDTIdWlanWpaPreSharedKey ) );
    wpaPskField->SetL( keyWPA );
        
    // Save PreShared Key length
    CMDBField<TUint>* keyLengthField = static_cast<CMDBField<TUint>*>
                        ( generic->GetFieldByIdL( KCDTIdWlanWpaKeyLength ) );
    keyLengthField->SetL( keyWPA.Length() );


    if ( !usesPsk )
        {
        // not PSK -> must be EAP
        LOG_WRITE( "saving EAP info..." );
        RImplInfoPtrArray eapArray;
        REComSession::ListImplementationsL( KEapTypeInterfaceUid, eapArray );
        CleanupClosePushL( eapArray );
        
        for ( TInt i = 0; i < eapArray.Count(); ++i )
            {
            // IsDisallowedOutsidePEAP actually means IsDisallowedOutsideTunnel
            if ( !CEapType::IsDisallowedOutsidePEAP( *eapArray[i] ) )
                {
                CEapType* eapType = CEapType::NewL( eapArray[i]->DataType(), 
                                                    ELan, 
                                                    serviceId );
                CleanupStack::PushL( eapType );
                
                eapType->SetIndexL( ELan, serviceId );
                CleanupStack::PopAndDestroy( eapType );
                }
            }

        eapArray.ResetAndDestroy();
        CleanupStack::PopAndDestroy( &eapArray );
        }

    if ( !found )
        {
        // there wasn't any wlan service record, we have to create it now
        LOG_WRITE("new service record");
        generic->SetRecordId( KCDNewRecordRequest );
        generic->StoreL( *iDbSession );
        }
    else
        {
        // modify existing record
        LOG_WRITE("existing service record");
        generic->ModifyL( *iDbSession );
        }
    
    CleanupStack::PopAndDestroy( generic );
    }
    

// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::StoreWEPDataL
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::StoreWEPDataL( const TInt aIapId, 
                                        const TDesC& aWepKey, 
                                        const TBool aIsHexWep )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::StoreWEPDataL" );
    
    CCDIAPRecord *iapRec = static_cast<CCDIAPRecord*>
                          ( CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
    
    CleanupStack::PushL( iapRec );
    
    iapRec->SetRecordId( aIapId );
    iapRec->LoadL( *iDbSession );

    TUint32 serviceId = TUint32( iapRec->iService );
    LOG_WRITEF("IAP(%d).serviceID = %d", aIapId, serviceId );
    
    CleanupStack::PopAndDestroy( iapRec );


    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
        ( CCDRecordBase::RecordFactoryL( 0 ) );
    CleanupStack::PushL( generic );    
    generic->InitializeL( TPtrC( WLAN_SERVICE ), NULL );
    generic->LoadL( *iDbSession );
    
    CMDBField<TUint32>* sidField = static_cast<CMDBField<TUint32>*>
                             ( generic->GetFieldByIdL( KCDTIdWlanServiceId ) );
    
    // prime with service id                
    *sidField = serviceId;
    
    TBool found = generic->FindL( *iDbSession );
    
    LOG_WRITE( "saving WEP settings..." );


    CMDBField<TUint>* indexField = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanWepIndex ) );
    indexField->SetL( KFirstWepKey );

    // Save authentication mode    
    CMDBField<TUint>* authenticationField = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanAuthMode ) );
    authenticationField->SetL( KWepAuthOpen );
    
    

    // now we need to convert the key to 8bit and to hex
    // and again detect the required bits
    TBuf8<KMaxWepKeyLen> key;
    
    // convert to 8 bit
    key.Copy( aWepKey );

       
    if ( !aIsHexWep )
        {
        // Must be converted to hexa and stored as a hexa
        // Ascii key is half the length of Hex
        HBufC8* buf8Conv = HBufC8::NewLC( key.Length()*2 );
        TPtr8 bufptr( buf8Conv->Des() );
        ConvertAsciiToHex( key, bufptr );
        
        CMDBField<TDesC8>* wepKey1Field = static_cast<CMDBField<TDesC8>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanWepKey1 ) );
        wepKey1Field->SetL( buf8Conv->Des() );

        CleanupStack::PopAndDestroy( buf8Conv );
        }
    else
        {
        // already in hexa format
        CMDBField<TDesC8>* wepKey1Field = static_cast<CMDBField<TDesC8>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanWepKey1 ) );
        wepKey1Field->SetL( key );
        }
        
    
     // write default values to the rest of the columns
    key.Zero();
    
    CMDBField<TDesC8>* wepKey2Field = static_cast<CMDBField<TDesC8>*>
                        ( generic->GetFieldByIdL( KCDTIdWlanWepKey2 ) );
    wepKey2Field->SetL( key );
    CMDBField<TDesC8>* wepKey3Field = static_cast<CMDBField<TDesC8>*>
                        ( generic->GetFieldByIdL( KCDTIdWlanWepKey3 ) );
    wepKey3Field->SetL( key );
    CMDBField<TDesC8>* wepKey4Field = static_cast<CMDBField<TDesC8>*>
                        ( generic->GetFieldByIdL( KCDTIdWlanWepKey4 ) );
    wepKey4Field->SetL( key );


    // write format data
    TUint fmt( aIsHexWep );
    
    CMDBField<TUint>* formatKey1Field = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanFormatKey1 ) );
    formatKey1Field->SetL( fmt );
    CMDBField<TUint>* formatKey2Field = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanFormatKey2 ) );
    formatKey2Field->SetL( fmt );
    CMDBField<TUint>* formatKey3Field = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanFormatKey3 ) );
    formatKey3Field->SetL( fmt );
    CMDBField<TUint>* formatKey4Field = static_cast<CMDBField<TUint>*>
                            ( generic->GetFieldByIdL( KCDTIdWlanFormatKey4 ) );
    formatKey4Field->SetL( fmt );
    
    
    if ( !found )
        {
        // there wasn't any wlan service record, we have to create it now
        LOG_WRITE("new service record");
        generic->SetRecordId( KCDNewRecordRequest );
        generic->StoreL( *iDbSession );
        }
    else
        {
        // modify existing record
        LOG_WRITE("existing service record");
        generic->ModifyL( *iDbSession );
        }
        
    CleanupStack::PopAndDestroy( generic );    
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::ConvertAsciiToHex
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::ConvertAsciiToHex( const TDesC8& aSource, 
                                            TDes8& aDest )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::ConvertAsciiToHex" );
    _LIT8( hex, "0123456789ABCDEF" );
    TInt size = aSource.Size();
    aDest.Zero();
    
    for ( TInt ii = 0; ii < size; ii++ )
        {
        TText8 ch = aSource[ii];
        aDest.Append( hex()[(ch/16)&0x0f] );
        aDest.Append( hex()[ch&0x0f] );
        }
    }
    


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::SetDefaultDestination
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::SetDefaultDestination( const TUint32 aDestinationId )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::SetDefaultDestination" );
    LOG_WRITEF( "destId = %d", aDestinationId );
    iDestinationId = aDestinationId;
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::CreateAccessPointL
// ----------------------------------------------------------------------------
//
void CWsfWlanIapCreator::CreateAccessPointL( TWsfWlanInfo& aWlanInfo, 
                                                const TDesC& aPresharedKey, 
                                                const TBool aIsHex )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::CreateAccessPointL" );
    TUint32 iapId( 0 );

    // create connection method
    iapId = CreateConnectionMethodL( aWlanInfo );
    

    // open a transaction
    const TUint KMaxOpenTransAttempts = 10;
    const TUint KRetryAfter = 100000;

    TInt err( KErrNone );
    TUint attempts( KMaxOpenTransAttempts );
    
    CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewLC();
    RTimer timer;
    timer.CreateLocal();
    CleanupClosePushL( timer );
    
    do
        {
        TRAP( err, iDbSession->OpenTransactionL() );
        if ( err )
            {
            timer.After( waiter->iStatus, 
                         TTimeIntervalMicroSeconds32( KRetryAfter ) );
            waiter->WaitForRequest();
            }
        }
    while ( err && attempts-- );

    User::LeaveIfError( err );

    CleanupStack::PopAndDestroy( &timer );
    CleanupStack::PopAndDestroy( waiter );
    
    CleanupStack::PushL( TCleanupItem( RollbackCommsDat, iDbSession ) );

    
    // now we have a valid transaction, save security settings
    
    switch ( aWlanInfo.iSecurityMode )
        {
        case EWlanSecModeWep:
            {
            StoreWEPDataL( iapId, aPresharedKey, aIsHex );
            break;
            }
        case EWlanSecMode802_1x:
        case EWlanSecModeWpa:
        case EWlanSecModeWpa2:
            {
            StoreWPADataL( iapId, aPresharedKey, aWlanInfo.iSecurityMode );
            break;
            }
        case EWlanSecModeOpen: // fall through on purpose
        default:
            {
            }
        }

    CleanupStack::Pop( 1 ); // transaction rollback popped
    
    // commit changes
    if ( iDbSession->IsInTransaction() )
        {
        iDbSession->CommitTransactionL();
        }
        
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::RollbackCommsDat
// ----------------------------------------------------------------------------
void CWsfWlanIapCreator::RollbackCommsDat( TAny* aDbSession )
    {
    CommsDat::CMDBSession* session = static_cast<CommsDat::CMDBSession*>( 
                                                                 aDbSession );
    TRAP_IGNORE( session->RollbackTransactionL() );
    }


// ----------------------------------------------------------------------------
// CWsfWlanIapCreator::CreateConnectionMethodL
// ----------------------------------------------------------------------------
//
TUint32 CWsfWlanIapCreator::CreateConnectionMethodL( TWsfWlanInfo& aWlanInfo )
    {
    LOG_ENTERFN( "CWsfWlanIapCreator::CreateConnectionMethodL" );
    
    HBufC* name16 = NULL;
    HBufC* ssid16 = NULL;
    
    if ( aWlanInfo.iRawSsid.Length() )
        {
        // ssid is from scan result store it as it is 
        // since the encoding of ssid is unknown
        name16 = HBufC::NewLC( aWlanInfo.iRawSsid.Length() );
        name16->Des().Copy( aWlanInfo.iRawSsid );
        ssid16 = HBufC::NewLC( aWlanInfo.iRawSsid.Length() );
        ssid16->Des().Copy( aWlanInfo.iRawSsid );
        }
    else
        {
        // user has inputted ssid store it to name as unicode since it is utf-8 
        name16 = aWlanInfo.GetSsidAsUnicodeLC();
        ssid16 = HBufC::NewLC( aWlanInfo.iSsid.Length() );
        ssid16->Des().Copy( aWlanInfo.iSsid );
        }
        
    TUint32 iapId( 0 );
    
    if ( !iDestinationId )
        {
        // possibly temporary iap to uncategorized
        LOG_WRITE( "destId not set -> temporary into Uncategorised" );
        
        RCmConnectionMethodExt cm = iCmManagerExt.CreateConnectionMethodL( 
                                                         KUidWlanBearerType );
        CleanupClosePushL( cm );
        
        cm.SetStringAttributeL( ECmName, *name16 );
        cm.SetStringAttributeL( EWlanSSID, *ssid16 );
        cm.SetIntAttributeL( EWlanSecurityMode, aWlanInfo.iSecurityMode );
        cm.SetIntAttributeL( EWlanConnectionMode, aWlanInfo.iNetMode );
        cm.SetBoolAttributeL( EWlanScanSSID, !aWlanInfo.iVisibility );
        
        // commit changes
        cm.UpdateL();

        // get the iap id
        iapId = cm.GetIntAttributeL( ECmId );
        
        // now retrieve the name again to see if it has been changed 
        // (ExistingCmName -> ExistingCmName(01) and alike)
        HBufC* cmName = cm.GetStringAttributeL( ECmName );
        
        TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8( 
                                                        aWlanInfo.iNetworkName, 
                                                        *cmName  );
        if ( error )
            {
            LOG_WRITE( "ConvertFromUnicodeToUtf8 failed");
            aWlanInfo.iNetworkName.Copy( *cmName );
            }

        delete cmName;
        
        CleanupStack::PopAndDestroy( &cm );
        }
    else
        {
        // final iap to the default destination
        LOG_WRITEF( "destId = %d", iDestinationId );
        
        RCmDestinationExt destination = iCmManagerExt.DestinationL( 
                                                            iDestinationId );
        CleanupClosePushL( destination );
        
        RCmConnectionMethodExt cm = destination.CreateConnectionMethodL( 
                                                         KUidWlanBearerType );
        CleanupClosePushL( cm );

        cm.SetStringAttributeL( ECmName, *name16 );
        cm.SetStringAttributeL( EWlanSSID, *ssid16 );
        cm.SetIntAttributeL( EWlanSecurityMode, aWlanInfo.iSecurityMode );
        cm.SetIntAttributeL( EWlanConnectionMode, aWlanInfo.iNetMode );
        cm.SetBoolAttributeL( EWlanScanSSID, !aWlanInfo.iVisibility );
        
        // commit changes
        destination.UpdateL();

        // get the iap id
        iapId = cm.GetIntAttributeL( ECmId );
        
        // now retrieve the name again to see if it has been changed 
        // (ExistingCmName -> ExistingCmName(01) and alike)
        HBufC* cmName = cm.GetStringAttributeL( ECmName );
        TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8( 
                                                         aWlanInfo.iNetworkName, 
                                                         *cmName  );
        if ( error )
            {
            LOG_WRITE( "ConvertFromUnicodeToUtf8 failed");
            aWlanInfo.iNetworkName.Copy( *cmName );
            }
        
        delete cmName;
        
        CleanupStack::PopAndDestroy( &cm );
        CleanupStack::PopAndDestroy( &destination );
        }

    CleanupStack::PopAndDestroy( ssid16 );
    CleanupStack::PopAndDestroy( name16 );

    aWlanInfo.iIapId = iapId;
    LOG_WRITEF( "new iapId = %d", iapId );

    return iapId;
    }