wlansecuritysettings/wpasecuritysettingsui/src/WPASecuritySettingsImpl.cpp
branchRCL_3
changeset 46 c74b3d9f6b9e
child 55 9c2aa05919d9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlansecuritysettings/wpasecuritysettingsui/src/WPASecuritySettingsImpl.cpp	Wed Sep 01 12:23:57 2010 +0100
@@ -0,0 +1,879 @@
+/*
+* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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 class CWPASecuritySettingsImpl.     
+*
+*/
+
+/*
+* %version: tr1cfwln#29 %
+*/
+
+// INCLUDE FILES
+
+#include "WPASecuritySettingsUiPanic.h"
+
+#include "WPASecuritySettingsUI.hrh"
+
+#include <WPASecuritySettingsUI.h>
+#include <commdb.h>
+#include <EAPPluginConfigurationIf.h>
+#include "WPASecuritySettingsImpl.h"
+
+#include <commsdattypesv1_1.h>
+#include <cmmanagertablefields.h>
+#include <wlancontainer.h>
+
+
+// CONSTANTS
+LOCAL_D const TUint32 KUidNone = 0;     // Invalid id
+LOCAL_D const TUint32 E8021X = 4;       // 802.1X security mode
+LOCAL_D const TUint32 EWpa = 8;         // Wpa security mode
+LOCAL_D const TUint32 EWpa2 = 16;       // Wpa2 only security mode
+
+LOCAL_D const TUint32 KExpEapTypeLength = 8;    // expanded EAP type length
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::NewL
+// ---------------------------------------------------------
+//
+CWPASecuritySettingsImpl* CWPASecuritySettingsImpl::NewL( 
+                                                TSecurityMode aSecurityMode )
+    {
+    CWPASecuritySettingsImpl* settings = new ( ELeave ) 
+                                    CWPASecuritySettingsImpl( aSecurityMode );
+    CleanupStack::PushL( settings );
+    settings->ConstructL();
+    CleanupStack::Pop( settings ); 
+    return settings;    
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::CWPASecuritySettingsImpl
+// ---------------------------------------------------------
+//
+CWPASecuritySettingsImpl::CWPASecuritySettingsImpl( 
+                                                TSecurityMode aSecurityMode )
+: iSecurityMode( aSecurityMode ),
+  iWPAMode( EFalse ),
+  iWpa2Only( EFalse ),
+  iWPAUnencryptedConn( EFalse )
+    {
+    iWPAEAPPlugin.Zero();
+    iWPAPreSharedKey.Zero();
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::ConstructL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::ConstructL()
+    {
+    _LIT8( KMatchString, "EAPPConfig" );
+	TRAPD( err, iPlugin = CEAPPluginConfigurationIf::NewL( KMatchString ) );
+    if ( err != KErrNone && err != KEComErrNoInterfaceIdentified )
+        {
+        User::Leave( err );
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::~CWPASecuritySettingsImpl
+// ---------------------------------------------------------
+//
+CWPASecuritySettingsImpl::~CWPASecuritySettingsImpl()
+    {
+    delete iWPAEnabledEAPPlugin;
+    delete iWPADisabledEAPPlugin;
+    delete iPlugin;
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::LoadL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::LoadL( TUint32 aIapId, 
+                                      CCommsDatabase& aCommsDb )
+    {
+    if ( aIapId == KUidNone )
+        {
+        return;
+        }
+
+    CCommsDbTableView* wLanServiceTable;
+        
+    wLanServiceTable = aCommsDb.OpenViewMatchingUintLC(
+                    TPtrC( WLAN_SERVICE ), TPtrC( WLAN_SERVICE_ID ), aIapId );
+
+    TInt errorCode = wLanServiceTable->GotoFirstRecord();
+    if ( errorCode == KErrNone )
+        {
+        if ( iSecurityMode == ESecurityMode8021x )
+            {
+            // in 802.1x PSK mode is not supported
+            iWPAMode = EFalse;
+            }
+        else
+            {
+            // Get WPA Mode
+            TRAPD( err, wLanServiceTable->ReadUintL( TPtrC( WLAN_ENABLE_WPA_PSK ),
+                                                    ( TUint32& ) iWPAMode ) );
+            if ( err != KErrNone )
+                { // do not leave if value is not present in table...
+                if ( err != KErrUnknown )
+                    User::Leave( err );
+                }
+            }
+        
+        TUint32 secMode = 0;
+        // Get WPA2 Only Mode
+        TRAPD( err, wLanServiceTable->ReadUintL( TPtrC( WLAN_SECURITY_MODE ),
+                                                 secMode ) );
+        if ( err != KErrNone )
+            { // do not leave if value is not present in table...
+            if ( err != KErrUnknown )
+                User::Leave( err );
+            }
+
+        iWpa2Only = secMode == EWpa2;
+
+        // Get Unencrypted Connection mode for 802.1x
+        if ( iSecurityMode == ESecurityMode8021x )
+            {
+            // WLAN_WPA_KEY_LENGTH is used also for Unencrypted Connection mode
+            TRAPD( err2, wLanServiceTable->ReadUintL( TPtrC( WLAN_WPA_KEY_LENGTH ),
+                                                ( TUint32& ) iWPAUnencryptedConn ) );
+            if ( err2 != KErrNone )
+                { // do not leave if value is not present in table...
+                if ( err2 != KErrUnknown )
+                    User::Leave( err2 );
+                }
+            }
+
+        // Get EAP list
+    	iWPAEAPPlugin.Copy( *wLanServiceTable->ReadLongTextLC( 
+                                                        TPtrC( WLAN_EAPS ) ) );
+	    CleanupStack::PopAndDestroy();
+	    
+	    if ( !iWPAEAPPlugin.Length() )
+	        {
+	        // no data found in the old column, use the new ones
+
+	        // enabled EAP types
+	        HBufC *data = wLanServiceTable->ReadLongTextLC( 
+	                                              TPtrC( WLAN_ENABLED_EAPS ) );
+
+            TPtrC8 reint( reinterpret_cast<const TUint8*>( data->Ptr() ), 
+	                                                       data->Size() );
+            
+        	delete iWPAEnabledEAPPlugin; iWPAEnabledEAPPlugin = NULL;
+        	iWPAEnabledEAPPlugin = reint.AllocL();
+
+            CleanupStack::PopAndDestroy( data );
+            
+            
+            // 2. disabled EAP types
+            data = wLanServiceTable->ReadLongTextLC( 
+	                                             TPtrC( WLAN_DISABLED_EAPS ) );
+            
+            reint.Set( reinterpret_cast<const TUint8*>( data->Ptr() ), 
+	                                                    data->Size() );
+	                                                    
+        	delete iWPADisabledEAPPlugin; iWPADisabledEAPPlugin = NULL;
+        	iWPADisabledEAPPlugin = reint.AllocL();
+
+	        CleanupStack::PopAndDestroy( data );
+	        }
+	    else
+	        {
+	        // generate appropriate entries in the new enabled and disabled list,
+	        // overwriting those values 
+	        
+	        // count the + and - signs to determine the size of enabled and 
+	        // disabled descriptors
+	        TLex lex( iWPAEAPPlugin );
+            
+	        TInt numPlus = 0;
+	        TInt numMinus = 0;
+	        TChar ch;
+	        while ( !lex.Eos() )
+	            {
+	            ch = lex.Get();
+	            if ( ch == '+' ) ++numPlus;
+	            else if ( ch == '-' ) ++numMinus;
+	            }
+	            
+            // each entry consumes 8 bytes in binary format
+            delete iWPAEnabledEAPPlugin; iWPAEnabledEAPPlugin = NULL;
+            iWPAEnabledEAPPlugin = HBufC8::NewL( 8 * numPlus );
+            
+            delete iWPADisabledEAPPlugin; iWPADisabledEAPPlugin = NULL;
+            iWPADisabledEAPPlugin = HBufC8::NewL( 8 * numMinus );
+
+            lex.Assign( iWPAEAPPlugin );
+            
+            while ( !lex.Eos() )
+                {
+                // beginning of implementation UID
+                TInt16 implUid = 0;
+                
+                if ( lex.Val( implUid ) != KErrNone || !implUid )
+                    {
+                    // if the old string is corrupted, null out both lists
+                    iWPAEnabledEAPPlugin->Des().Zero();
+                    iWPADisabledEAPPlugin->Des().Zero();
+                    break;
+                    }
+
+                // append it to the appropriate list ('+' enabled, '-' disabled)
+                _LIT8( KPadding, "\xFE\0\0\0\0\0\0" );
+                _LIT8( KMsChapV2Padding, "\xFE\xFF\xFF\xFF\0\0\0");
+                const TInt KPlainMsChapV2ImplUid = 99;
+                
+                if ( implUid > 0 )
+                    {
+                    iWPAEnabledEAPPlugin->Des().Append( 
+                                        Abs( implUid ) == KPlainMsChapV2ImplUid? 
+                                                    KMsChapV2Padding: KPadding );
+                    iWPAEnabledEAPPlugin->Des().Append( Abs( implUid ) );
+                    }
+                else if (implUid < 0 )
+                    {
+                    iWPADisabledEAPPlugin->Des().Append( 
+                                        Abs( implUid ) == KPlainMsChapV2ImplUid? 
+                                                    KMsChapV2Padding: KPadding );
+                    iWPADisabledEAPPlugin->Des().Append( Abs( implUid ) );
+                    }
+                
+                // swallow the delimiter (',')
+                lex.Get();
+                }
+                
+            // finally, wipe old column data
+            iWPAEAPPlugin.Zero();
+	        }
+	        
+        // Get PreShared Key
+	    if ( iSecurityMode != ESecurityMode8021x )
+	        {
+            wLanServiceTable->ReadTextL( TPtrC( WLAN_WPA_PRE_SHARED_KEY ), 
+                                    iWPAPreSharedKey );
+	        }
+
+        if ( !IsValidPsk( iWPAPreSharedKey ) )
+            {       
+            // invalid key format
+            iWPAPreSharedKey.Zero();
+            }
+        }
+
+    CleanupStack::PopAndDestroy( wLanServiceTable );  // wLanServiceTable
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::SaveL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::SaveL( TUint32 aIapId, 
+                                      CCommsDatabase& aCommsDb,
+                                      TTypeOfSaving aTypeOfSaving,
+                                      TUint32 aOldIapId )
+    {
+    CCommsDbTableView* wLanServiceTable;
+
+    // Caller MUST initiate a transaction, WE WILL NOT.
+
+    wLanServiceTable = aCommsDb.OpenViewMatchingUintLC( 
+                    TPtrC( WLAN_SERVICE ), TPtrC( WLAN_SERVICE_ID ), aIapId );
+    TInt errorCode = wLanServiceTable->GotoFirstRecord();
+
+    if ( errorCode == KErrNone )
+        {
+        wLanServiceTable->UpdateRecord();
+        }
+    else
+        {
+        TUint32 dummyUid( KUidNone );
+        User::LeaveIfError( wLanServiceTable->InsertRecord( dummyUid ) );
+
+        // Save link to LAN service
+        wLanServiceTable->WriteUintL( TPtrC( WLAN_SERVICE_ID ), aIapId );
+        }
+
+    // Save WPA Mode
+    if ( iSecurityMode != ESecurityMode8021x )
+        {
+        wLanServiceTable->WriteUintL( TPtrC( WLAN_ENABLE_WPA_PSK ), 
+                                  ( TUint32& ) iWPAMode );
+        }
+
+    TUint32 secMode;
+
+    if ( iSecurityMode == ESecurityMode8021x )
+        {
+        secMode = E8021X;
+        }
+    else if ( iWpa2Only )
+        {
+        secMode = EWpa2;
+        }
+    else
+        {
+        secMode = EWpa;
+        }
+
+    // Save security mode
+    wLanServiceTable->WriteUintL( TPtrC( WLAN_SECURITY_MODE ), secMode );
+
+    // With expanded EAP types allowed we no longer need the old column
+    iWPAEAPPlugin.Zero(); 
+
+    // Save EAP list
+    wLanServiceTable->WriteLongTextL( TPtrC( WLAN_EAPS ), iWPAEAPPlugin );
+
+
+    // Save the expanded EAPs
+    wLanServiceTable->WriteTextL( TPtrC( WLAN_ENABLED_EAPS ), 
+                                  iWPAEnabledEAPPlugin? 
+                                        (const TDesC8&)*iWPAEnabledEAPPlugin: 
+                                        (const TDesC8&)KNullDesC8 );
+
+    wLanServiceTable->WriteTextL( TPtrC( WLAN_DISABLED_EAPS ), 
+                                  iWPADisabledEAPPlugin? 
+                                        (const TDesC8&)*iWPADisabledEAPPlugin: 
+                                        (const TDesC8&)KNullDesC8 );
+ 
+
+
+    if ( iSecurityMode == ESecurityMode8021x )
+        {
+        // In 802.1x WpaKeyLength is not used 
+        // and the field is reused to save UnencryptedConn mode
+        wLanServiceTable->WriteUintL( TPtrC( WLAN_WPA_KEY_LENGTH ), 
+                                      ( TUint32& ) iWPAUnencryptedConn );
+        }
+    else
+        {
+        // Save PreShared Key
+        wLanServiceTable->WriteTextL( TPtrC( WLAN_WPA_PRE_SHARED_KEY ), 
+                                  iWPAPreSharedKey );
+    
+        // Save PreShared Key Length
+        wLanServiceTable->WriteUintL( TPtrC( WLAN_WPA_KEY_LENGTH ), 
+                                        iWPAPreSharedKey.Length() );
+        }
+
+    wLanServiceTable->PutRecordChanges();
+
+    if ( iPlugin )
+        {
+        if ( aTypeOfSaving == ESavingBrandNewAP )
+            {
+            iPlugin->ChangeIapIDL( aOldIapId, aIapId );
+            }
+        else if ( aTypeOfSaving == ESavingNewAPAsACopy )
+            {
+            iPlugin->CopySettingsL( aOldIapId, aIapId );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( wLanServiceTable );  // wLanServiceTable
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::DeleteL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::DeleteL( TUint32 aIapId )
+    {
+    if ( iPlugin )
+        {
+        iPlugin->DeleteSettingsL( aIapId );
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::IsValid
+// ---------------------------------------------------------
+//
+TBool CWPASecuritySettingsImpl::IsValid()
+    {
+    TBool retval = ETrue;
+    if ( iWPAMode || !iPlugin )
+        {
+        retval = IsValidPsk( iWPAPreSharedKey );
+        }
+
+    return retval;
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::IsValidPsk
+// ---------------------------------------------------------
+//
+TBool CWPASecuritySettingsImpl::IsValidPsk( const TDesC8& aPsk )
+    {
+    TBool ret( EFalse );
+
+    TInt len = aPsk.Length();
+    
+    ret = ( len >= EMinLengthOfPreSharedKeyAscii && 
+            len <= EMaxLengthOfPreSharedKeyAscii );
+               
+    if ( !ret && len == ELengthOfPreSharedKeyHex )
+        {
+        // perhaps it is hex
+        ret = ETrue;
+        
+        for ( TInt i = 0; i < len; ++i )
+            {
+            TChar ch( aPsk[i] );
+            if ( !ch.IsHexDigit() )
+                {
+                // got a bad character
+                ret = EFalse;
+                break;
+                }
+            }
+        }
+    
+    return ret;
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::SetWPAPreSharedKey
+// ---------------------------------------------------------
+//
+TInt CWPASecuritySettingsImpl::SetWPAPreSharedKey( 
+                                                const TDesC& aPreSharedKey )
+    {
+    TInt ret( KErrNone );
+    
+    HBufC8* buf8 = HBufC8::New( aPreSharedKey.Length() );
+    
+    if ( buf8 )
+        {
+        TPtr8 pskPtr( buf8->Des() );
+        pskPtr.Copy( aPreSharedKey ); 
+
+        if ( IsValidPsk( pskPtr ) )
+            {
+            SetWPAPreSharedKey( pskPtr );
+            SetWPAMode( ETrue );
+            }
+        else
+            {
+            ret = KErrArgument;
+            }
+
+        delete buf8;
+        }
+    else
+        {
+        ret = KErrNoMemory;
+        }
+    
+    return ret;
+    }
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::SetWPAEnabledEAPPlugin
+// ---------------------------------------------------------
+//
+TInt CWPASecuritySettingsImpl::SetWPAEnabledEAPPlugin( 
+                                             const TDesC8& aEnabledPluginList )
+	{
+	delete iWPAEnabledEAPPlugin; iWPAEnabledEAPPlugin = NULL;
+
+    if ( aEnabledPluginList.Length() % KExpEapTypeLength )
+        {
+        // valid expanded EAP types occupy 8 bytes each
+        return KErrArgument;
+        }
+
+	if ( aEnabledPluginList.Length() )
+	    {
+	    iWPAEnabledEAPPlugin = aEnabledPluginList.Alloc();
+	    if ( !iWPAEnabledEAPPlugin )
+	        {
+	        return KErrNoMemory;
+	        }
+	    }
+	
+	return KErrNone;
+	}
+
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::SetWPADisabledEAPPlugin
+// ---------------------------------------------------------
+//
+TInt CWPASecuritySettingsImpl::SetWPADisabledEAPPlugin( 
+                                            const TDesC8& aDisabledPluginList )
+	{
+	delete iWPADisabledEAPPlugin; iWPADisabledEAPPlugin = NULL;
+
+    if ( aDisabledPluginList.Length() % KExpEapTypeLength )
+        {
+        // valid expanded EAP types occupy 8 bytes each
+        return KErrArgument;
+        }
+        
+	if ( aDisabledPluginList.Length() )
+	    {
+	    iWPADisabledEAPPlugin = aDisabledPluginList.Alloc();
+	    if ( !iWPADisabledEAPPlugin )
+	        {
+	        return KErrNoMemory;
+	        }
+	    }
+	
+	return KErrNone;
+	}
+	
+
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::LoadL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::LoadL( TUint32 aIapId, 
+                                      CMDBSession& aSession )
+    {
+    if ( aIapId == KUidNone )
+        {
+        return;
+        }
+        
+    // Load WLAN service table        
+    // first get WLAN table id
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );    
+    generic->InitializeL( TPtrC( WLAN_SERVICE ), NULL );
+    generic->LoadL( aSession );
+    TMDBElementId wlanTableId = generic->TableId();
+    
+    CMDBField<TUint32>* sidField = static_cast<CMDBField<TUint32>*>
+                             ( generic->GetFieldByIdL( KCDTIdWlanServiceId ) );
+                                    
+    // prime with service id                
+    *sidField = aIapId;
+
+    if( generic->FindL( aSession) )
+        {
+        if ( iSecurityMode == ESecurityMode8021x )
+            {
+            // in 802.1x PSK mode is not supported
+            iWPAMode = EFalse;
+            }
+        else
+            {
+            // Get WPA mode
+            CMDBField<TUint>* enableWpaPskField = static_cast<CMDBField<TUint>*>
+                          ( generic->GetFieldByIdL( KCDTIdWlanEnableWpaPsk ) );
+            iWPAMode = *enableWpaPskField;
+            }
+        
+        // Get WPA2 Only Mode
+        CMDBField<TUint>* secModeField = static_cast<CMDBField<TUint>*>
+                               ( generic->GetFieldByIdL( KCDTIdWlanSecMode ) );
+        TUint32 secMode = *secModeField;
+        iWpa2Only = secMode == EWpa2;
+ 
+        // Get 802.1x Unencrypted Connection saved in reused WpaKeyLengthField
+        if ( iSecurityMode == ESecurityMode8021x )
+            {
+            CMDBField<TUint>* WpaKeyLengthField = static_cast<CMDBField<TUint>*>
+                          ( generic->GetFieldByIdL( KCDTIdWlanWpaKeyLength ) );
+            iWPAUnencryptedConn = *WpaKeyLengthField;
+            }
+        
+        // Get EAP plugins
+        CMDBField<TDesC>* wlanEapsField = static_cast<CMDBField<TDesC>*>
+                                  ( generic->GetFieldByIdL( KCDTIdWlanEaps ) );
+        iWPAEAPPlugin = *wlanEapsField;
+        
+	    if ( !iWPAEAPPlugin.Length() )
+	        {
+	        // no data found in the old column, use the new ones
+
+	        // enabled EAP types
+            CMDBField<TDesC8>* wlanEnabledEapsField = 
+                          static_cast<CMDBField<TDesC8>*>
+                          ( generic->GetFieldByIdL( KCDTIdWlanEnabledEaps ) );
+
+        	delete iWPAEnabledEAPPlugin; iWPAEnabledEAPPlugin = NULL;
+        	iWPAEnabledEAPPlugin = 
+        	             ( ( const TDesC8& ) *wlanEnabledEapsField ).AllocL();
+
+            
+            // disabled EAP types
+            CMDBField<TDesC8>* wlanDisabledEapsField = 
+                          static_cast<CMDBField<TDesC8>*>
+                          ( generic->GetFieldByIdL( KCDTIdWlanDisabledEaps ) );
+            
+        	delete iWPADisabledEAPPlugin; iWPADisabledEAPPlugin = NULL;
+        	iWPADisabledEAPPlugin = 
+        	             ( ( const TDesC8& ) *wlanDisabledEapsField ).AllocL();
+
+	        }
+	    else
+	        {
+	        // generate appropriate entries in the new enabled and disabled list,
+	        // overwriting those values 
+	        
+	        // count the + and - signs to determine the size of enabled and 
+	        // disabled descriptors
+	        TLex lex( iWPAEAPPlugin );
+            
+	        TInt numPlus = 0;
+	        TInt numMinus = 0;
+	        TChar ch;
+	        while ( !lex.Eos() )
+	            {
+	            ch = lex.Get();
+	            if ( ch == '+' ) ++numPlus;
+	            else if ( ch == '-' ) ++numMinus;
+	            }
+	            
+            // each entry consumes 8 bytes in binary format
+            delete iWPAEnabledEAPPlugin; iWPAEnabledEAPPlugin = NULL;
+            iWPAEnabledEAPPlugin = HBufC8::NewL( 8 * numPlus );
+            
+            delete iWPADisabledEAPPlugin; iWPADisabledEAPPlugin = NULL;
+            iWPADisabledEAPPlugin = HBufC8::NewL( 8 * numMinus );
+
+            lex.Assign( iWPAEAPPlugin );
+            
+            while ( !lex.Eos() )
+                {
+                // beginning of implementation UID
+                TInt16 implUid = 0;
+                
+                if ( lex.Val( implUid ) != KErrNone || !implUid )
+                    {
+                    // if the old string is corrupted, null out both lists
+                    iWPAEnabledEAPPlugin->Des().Zero();
+                    iWPADisabledEAPPlugin->Des().Zero();
+                    break;
+                    }
+
+                // append it to the appropriate list ('+' enabled, '-' disabled)
+                _LIT8( KPadding, "\xFE\0\0\0\0\0\0" );
+                _LIT8( KMsChapV2Padding, "\xFE\xFF\xFF\xFF\0\0\0");
+                const TInt KPlainMsChapV2ImplUid = 99;
+                
+                if ( implUid > 0 )
+                    {
+                    iWPAEnabledEAPPlugin->Des().Append( 
+                                        Abs( implUid ) == KPlainMsChapV2ImplUid? 
+                                                    KMsChapV2Padding: KPadding );
+                    iWPAEnabledEAPPlugin->Des().Append( Abs( implUid ) );
+                    }
+                else if (implUid < 0 )
+                    {
+                    iWPADisabledEAPPlugin->Des().Append( 
+                                        Abs( implUid ) == KPlainMsChapV2ImplUid? 
+                                                    KMsChapV2Padding: KPadding );
+                    iWPADisabledEAPPlugin->Des().Append( Abs( implUid ) );
+                    }
+                
+                // swallow the delimiter (',')
+                lex.Get();
+                }
+                
+            // finally, wipe old column data
+            iWPAEAPPlugin.Zero();
+	        }
+
+        // GetWPA preshared key
+	    if ( iSecurityMode != ESecurityMode8021x )
+	        {
+            CMDBField<TDesC8>* wpaPskField = static_cast<CMDBField<TDesC8>*>
+                       ( generic->GetFieldByIdL( KCDTIdWlanWpaPreSharedKey ) );
+            iWPAPreSharedKey = *wpaPskField;
+	        }
+	    
+        if ( !IsValidPsk( iWPAPreSharedKey ) )
+            {       
+            // invalid key format
+            iWPAPreSharedKey.Zero();
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( generic );
+    }
+    
+    
+// ---------------------------------------------------------
+// CWPASecuritySettingsImpl::SaveL
+// ---------------------------------------------------------
+//
+void CWPASecuritySettingsImpl::SaveL( TUint32 aIapId, 
+                                      CMDBSession& aSession,
+                                      TTypeOfSaving aTypeOfSaving,
+                                      TUint32 aOldIapId )
+    {
+    const TInt KRetryWait = 100000;    // Wait time between retries in TTimeIntervalMicroSeconds32
+    const TInt KRetryCount = 50;       // Max retry count
+
+    // Load WLAN service table
+    // first get WLAN table id
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );    
+    generic->InitializeL( TPtrC( WLAN_SERVICE ), NULL );
+    generic->LoadL( aSession );
+    TMDBElementId wlanTableId = generic->TableId();
+    
+    CMDBField<TUint32>* sidField = static_cast<CMDBField<TUint32>*>
+                             ( generic->GetFieldByIdL( KCDTIdWlanServiceId ) );
+    
+    // prime with service id                
+    *sidField = aIapId;
+    
+    TBool found = generic->FindL( aSession);
+   
+    // If loading failed, WLAN service record will be 
+    // created and StoreL()-d, otherwise, ModifyL()
+
+    if ( iSecurityMode != ESecurityMode8021x )
+        {
+        // Set WPA mode
+        CMDBField<TUint>* enableWpaPskField = static_cast<CMDBField<TUint>*>
+                ( generic->GetFieldByIdL( KCDTIdWlanEnableWpaPsk ) );
+        enableWpaPskField->SetL( iWPAMode );
+        }
+    
+    // Set security mode
+    TUint32 secMode;
+    if ( iSecurityMode == ESecurityMode8021x )
+        {
+        secMode = E8021X;
+        }
+    else if ( iWpa2Only )
+        {
+        secMode = EWpa2;
+        }
+    else
+        {
+        secMode = EWpa;
+        }
+    CMDBField<TUint>* secModeField = static_cast<CMDBField<TUint>*>
+                        ( generic->GetFieldByIdL( KCDTIdWlanSecMode ) );
+    secModeField->SetL( secMode );
+    
+    // Save EAP list
+    CMDBField<TDesC>* wlanEapsField = static_cast<CMDBField<TDesC>*>
+                                ( generic->GetFieldByIdL( KCDTIdWlanEaps ) );
+
+    // when using the expanded EAP types, wipe out data in the old column
+    iWPAEAPPlugin.Zero();
+
+    wlanEapsField->SetL( iWPAEAPPlugin );
+
+    // Save the expanded EAPs
+    CMDBField<TDesC8>* wlanEnabledEapsField = static_cast<CMDBField<TDesC8>*>
+                           ( generic->GetFieldByIdL( KCDTIdWlanEnabledEaps ) );
+    wlanEnabledEapsField->SetL( iWPAEnabledEAPPlugin? 
+                                    (const TDesC8&)*iWPAEnabledEAPPlugin: 
+                                    (const TDesC8&)KNullDesC8 );
+
+
+    CMDBField<TDesC8>* wlanDisabledEapsField = static_cast<CMDBField<TDesC8>*>
+                          ( generic->GetFieldByIdL( KCDTIdWlanDisabledEaps ) );
+    wlanDisabledEapsField->SetL( iWPADisabledEAPPlugin? 
+                                    (const TDesC8&)*iWPADisabledEAPPlugin: 
+                                    (const TDesC8&)KNullDesC8 );
+
+    // Save PreShared Key length
+    CMDBField<TUint>* keyLengthField = static_cast<CMDBField<TUint>*>
+                        ( generic->GetFieldByIdL( KCDTIdWlanWpaKeyLength ) );
+    if ( iSecurityMode == ESecurityMode8021x )
+        {
+        // In 802.1x keyLengthField is reused to contain Unencrypted Connection info
+        keyLengthField->SetL( iWPAUnencryptedConn );
+        }
+    else
+        {
+        keyLengthField->SetL( iWPAPreSharedKey.Length() );
+        
+        // Save PreShared Key
+        CMDBField<TDesC8>* wpaPskField = static_cast<CMDBField<TDesC8>*>
+                           ( generic->GetFieldByIdL( KCDTIdWlanWpaPreSharedKey ) );
+        wpaPskField->SetL( iWPAPreSharedKey );
+        }
+    
+    TInt error( KErrNone );
+    
+    // Saving changes
+    for ( TInt i( 0 ); i < KRetryCount; i++ )
+        {
+        
+        // If table existed modify it
+        if( found )
+            {
+            TRAP( error, generic->ModifyL( aSession ) );
+            }
+                   
+        // Otherwise store a new record
+        else
+            {
+            generic->SetRecordId( KCDNewRecordRequest );
+            TRAP( error, generic->StoreL( aSession ) );
+            }
+                  
+        // If operation failed with KErrLocked, we'll retry.
+        if ( KErrLocked == error )
+            {
+            User::After( KRetryWait );
+            }
+        
+        // Otherwise break the retry loop.
+        else 
+            {
+            break;        
+            }
+        }
+    
+    // If the save operation failed, leave now. 
+    User::LeaveIfError( error );
+
+    CleanupStack::PopAndDestroy( generic );
+            
+    if ( iPlugin )
+        {
+        if ( aTypeOfSaving == ESavingBrandNewAP )
+            {
+            iPlugin->ChangeIapIDL( aOldIapId, aIapId );
+            }
+        else if ( aTypeOfSaving == ESavingNewAPAsACopy )
+            {
+            iPlugin->CopySettingsL( aOldIapId, aIapId );
+            }
+        }
+    }
+
+// End of File