wvsettings20/IMPSSrc/CIMPSSAPCenRep.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvsettings20/IMPSSrc/CIMPSSAPCenRep.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1244 @@
+/*
+* Copyright (c) 2005 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:  IMPS SAP Settings Store implementation.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include 	<e32std.h>
+#include    <centralrepository.h>
+//#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+//#include <centralrepositoryinternal.h>
+//#endif
+#include    "CIMPSSAPCenRep.h"
+#include	"cimpssapsettings.h"
+#include	"CIMPSSAPSettingsBody.h"
+#include	"cimpssapsettingslist.h"
+#include	"CIMPSSAPKeyValuePairs.h"
+#include	"CIMPSSAPKeyValuePair.h"
+#include	"CIMPSSAPNotifier.h"
+
+#include	"IMPSSAPSettingsStoreCenRepUids.h"
+#include    "IMPSSAPSettingsStoreDebugPrint.h"
+#include    "IMPSSAPSettingsStorePanics.h"
+
+#include	"RIMPSReleaseArray.h"
+
+#include 	"TIMPSSAPSettingsListItemNameKey.h"
+#include	"TIMPSCenRepOperations.h"
+
+// This implementation uses the following way of dividing the
+// central repository id range for storing
+// SAP Settings data:
+//
+// - 6 bits for base id(defines the SAP access group)
+// - 10 bits for sap uid(unique within all groups)
+// - 16 bits for settings, which is further divided into 256
+// subsets each containing 256 items. Currently 2 subsets are in use.
+// First of the subsets contains settings that have fixed identifiers
+// and the second one key-value pairs.
+
+
+/*
+Example:
+------------------------------
+
+cenrep entry: 3221356546 int 8081 0
+
+=
+
+110000 		| 0000000010 	| 0000000000000010
+------ 		  ----------   	  ----------------
+SAP			| SAP Uid    	| Setting Id
+Base
+
+6 bits, 	  10 bits	  	  16 bits
+110000		 ..010 = 	 	 (10 = 2 dec = ESAPPort in TFixedSAPSetting)
+(0x30)		   2 dec
+PEC base
+id
+
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::CIMPSSAPCenRep
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CIMPSSAPCenRep::CIMPSSAPCenRep()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CIMPSSAPCenRep::ConstructL( TInt aPriority )
+    {
+    iRepository = CRepository::NewL( KCRUidIMPSStore );
+    iNotifier = CIMPSSAPNotifier::NewL( aPriority, KCRUidIMPSStore );
+    iCommsDatabase = CCommsDatabase::NewL( EDatabaseTypeIAP );
+    SetUpDefaultsL();
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIMPSSAPCenRep* CIMPSSAPCenRep::NewL( TInt aPriority )
+    {
+    CIMPSSAPCenRep* self = CIMPSSAPCenRep::NewLC( aPriority );
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIMPSSAPCenRep* CIMPSSAPCenRep::NewLC( TInt aPriority )
+    {
+    CIMPSSAPCenRep* self = new( ELeave ) CIMPSSAPCenRep();
+
+    CleanupStack::PushL( self );
+    self->ConstructL( aPriority );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::~CIMPSSAPCenRep
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CIMPSSAPCenRep::~CIMPSSAPCenRep()
+    {
+    delete iRepository;
+    delete iNotifier;
+    delete iCommsDatabase;
+    }
+
+// HELPER FUNCTIONS
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::MaskedId()
+// Calculates masked central repository id for setting
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint32 CIMPSSAPCenRep::MaskedId( TInt aSetting, TUint32 aUid,
+                                  TIMPSAccessGroup aGroup )
+    {
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+    TUint32 maskBase( 0 );
+    if ( aGroup & EIMPSIMAccessGroup )
+        {
+        maskBase += KSAPSettingsIMBaseId << KBaseOffset;
+        }
+    else
+        {
+        maskBase += KSAPSettingsPECBaseId << KBaseOffset;
+        }
+    maskBase += aUid << KSAPOffset;
+    maskBase += aSetting;
+
+    return maskBase;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SAPNameExistsL()
+// Checks if SAP with given name already exists in given access group.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CIMPSSAPCenRep::SAPNameExistsL( const TDesC& aSAPName, TUint32 aUid,
+                                      TIMPSAccessGroup aGroup )
+    {
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+    CIMPSSAPSettingsList* list = CIMPSSAPSettingsList::NewLC();
+
+    PopulateSAPSettingsListL( *list, aGroup );
+
+    TInt count( list->Count() );
+    TBool alreadyExists( EFalse );
+    TInt index( 0 );
+    if ( list->FindNameL( aSAPName, index ) == 0 )
+        {
+        if ( list->UidForIndex( index ) != aUid )
+            {
+            alreadyExists = ETrue;
+            }
+        }
+
+
+    CleanupStack::PopAndDestroy( list );
+    return alreadyExists;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SAPProtectionL()
+// Checks SAP protection level.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TIMPSSAPProtection CIMPSSAPCenRep::SAPProtectionL( TUint32 aUid,
+                                                   TIMPSAccessGroup aGroup )
+    {
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+    TInt ret( ESAPNoProtection );
+    User::LeaveIfError( iRepository->Get( EProtection + aUid, ret ) );
+    return static_cast< TIMPSSAPProtection >( ret );
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::NewUidL()
+// Gets new Uid for new SAP
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TUint32 CIMPSSAPCenRep::NewUidL()
+    {
+    TInt newUid;
+    TInt ret;
+    ret = iRepository->Get( KSAPHighestUid, newUid );
+    if ( ret == KErrNotFound ) // Highest uid not found, create it
+        {
+        // Check if we have existing SAPs despite not having the highest uid.
+        // This may happen if we have older settings.
+        if ( SAPCountL( EIMPSAccessFilterAll ) > 0 ) // existing SAPs
+            {
+            RArray<TUint32> foundSAPs;
+            CleanupClosePushL( foundSAPs );
+            // FindL return value is currently undocumented,
+            // thus silently consumed for now
+            iRepository->FindL( ESAPName, KSAPPopulateAllMask, foundSAPs );
+            TInt count( foundSAPs.Count() );
+            for ( TInt i( 0 ); i < count; ++i )
+                {
+                //transform found cenrep uids to SAP uids
+                foundSAPs[i] &= KSAPUidMask;
+                foundSAPs[i] = foundSAPs[i] >> KSAPOffset;
+                }
+            foundSAPs.SortUnsigned();
+            // Find the highest existing uid
+            for ( TUint32 i( KLastSAPId ); i >= KFirstSAPId;i-- )
+                {
+                if ( foundSAPs.Find( i ) == KErrNone )
+                    {
+                    if ( i < KLastSAPId )
+                        {
+                        newUid = i + 1;
+                        }
+                    else
+                        {
+                        newUid = KFirstSAPId;
+                        }
+                    break;
+                    }
+                }
+            CleanupStack::PopAndDestroy(); // foundSAPs
+            }
+        else // No existing SAPs
+            {
+            newUid = KFirstSAPId;
+            }
+        User::LeaveIfError( iRepository->Create( KSAPHighestUid, newUid ) );
+        }
+
+    else // Otherwise if it's an error situation
+        {
+        User::LeaveIfError( ret );
+        }
+
+    if ( newUid < KFirstSAPId )
+        {
+        // Something is wrong if we get here
+        User::Leave( KErrGeneral );
+        }
+    else if ( newUid >= KLastSAPId ) // If at the end of the range
+        {
+        // start from the beginning
+        newUid = KFirstSAPId;
+        }
+    // Check if there are ANY free uids
+    if ( ( KLastSAPId - KFirstSAPId ) <= SAPCountL( EIMPSAccessFilterAll ) )
+        {
+        User::Leave( KErrInUse ); // All UIDs in use
+        }
+
+    // Check if there is the next uid is unused.
+    TBool okId( EFalse );
+    TInt err( KErrNone );
+    while ( !okId )
+        {
+        newUid++;
+        TUint32 maskedUid = newUid << KSAPOffset;
+        RArray<TUint32> foundSAPs;
+        CleanupClosePushL( foundSAPs );
+        err = iRepository->FindL( maskedUid, KSAPExistsMask, foundSAPs );
+        if ( err == KErrNotFound ) // The uid is free
+            {
+            okId = ETrue;
+            }
+        else if ( err == KErrNone ) // There was a SAP with that uid
+            {
+            // Check range
+            if ( newUid >= KLastSAPId )
+                {
+                newUid = KFirstSAPId; // Start from the beginning.
+                }
+            }
+        else
+            {
+            User::Leave( err );
+            }
+        CleanupStack::PopAndDestroy(); //foundSAPs
+        }
+    // Save the new highest
+    User::LeaveIfError( iRepository->Set( KSAPHighestUid, newUid ) );
+    return newUid; // return the new uid
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SAPTypeL()
+// Gets SAP type
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TIMPSAccessGroup CIMPSSAPCenRep::SAPTypeL( TUint32 aUid )
+    {
+    TIMPSAccessGroup type( EIMPSNoAccessGroup );
+    aUid &= KSAPBaseMask;
+    aUid = aUid >> KBaseOffset;
+    if ( aUid == KSAPSettingsPECBaseId )
+        {
+        type = EIMPSPECAccessGroup;
+        }
+    else if ( aUid == KSAPSettingsIMBaseId )
+        {
+        type = EIMPSIMAccessGroup;
+        }
+    else
+        {
+        // aUid was found in unknown access group. Should not happen.
+        User::Leave( KErrGeneral );
+        }
+    return type;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SAPExistsL()
+// Checks if SAP exists in central repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::SAPExistsL( TUint32 aUid )
+    {
+    RArray<TUint32> foundSAPs;
+    CleanupClosePushL( foundSAPs );
+    // FindL return value is currently undocumented,
+    // thus silently consumed for now
+    iRepository->FindL( aUid, KSAPExistsMask, foundSAPs );
+    if ( foundSAPs.Count() != 1 )
+        {
+        User::Leave( KErrNotFound );
+        }
+    CleanupStack::PopAndDestroy(); //foundSAPs
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SetUpDefaultsL()
+// Sets up default SAP ids if they do not exist in the repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::SetUpDefaultsL()
+    {
+    TInt uid( 0 );
+    TInt err ( iRepository->Get( KDefaultIMSAPId, uid ) );
+    if ( err == KErrNotFound )
+        {
+        User::LeaveIfError( iRepository->Create( KDefaultIMSAPId,
+                                                 KIMPSSettingsNullUid ) );
+        }
+    else
+        {
+        User::LeaveIfError( err );
+        }
+
+    err = iRepository->Get( KDefaultPECSAPId, uid );
+    if ( err == KErrNotFound )
+        {
+        User::LeaveIfError( iRepository->Create( KDefaultPECSAPId,
+                                                 KIMPSSettingsNullUid ) );
+        }
+    else
+        {
+        User::LeaveIfError( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::FindSAPsFromAccessGroupL()
+// Finds and populates SAP ids to an array from desired access group
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::FindSAPsFromAccessGroupL( TIMPSAccessGroup aGroup,
+                                               RArray<TUint32>& aFoundSAPs )
+    {
+    if ( aGroup == EIMPSAccessFilterAll )
+        {
+        iRepository->FindL( ESAPAddress, KSAPPopulateAllMask, aFoundSAPs );
+        }
+    else if ( aGroup == EIMPSIMAccessGroup )
+        {
+        iRepository->FindL( MaskedId( ESAPAddress, KIMPSSettingsNullUid,
+                                      EIMPSIMAccessGroup ), KSAPPopulateGroupMask, aFoundSAPs );
+        }
+    else if ( aGroup == EIMPSPECAccessGroup )
+        {
+        iRepository->FindL( MaskedId( ESAPAddress, KIMPSSettingsNullUid,
+                                      EIMPSPECAccessGroup ), KSAPPopulateGroupMask, aFoundSAPs );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::StartOwnTransaction()
+// Starts new transaction if there is no ongoing transaction
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CIMPSSAPCenRep::StartOwnTransactionL( TInt aMode )
+    {
+//    TInt transaction( iRepository->TransactionState() );
+
+ 	if( !iInTransaction )
+ 		{
+ 		iInTransaction = ETrue;
+ 		CleanupStack::PushL( TCleanupItem( ReSetTransactionState, this ));
+ 		iRepository->StartTransaction( static_cast<CRepository::TTransactionMode>( aMode ) );
+ 		return ETrue;
+ 		}
+	return EFalse;
+    }
+
+// OBSERVER SUPPORT
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::AddObserverL()
+// Adds SAP observer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMPSSAPCenRep::AddObserverL( MIMPSSAPObserver* aObserver,
+                                   TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::AddObserverL()" );
+    iNotifier->AddObserverL( aObserver, aGroup );
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::RemoveObserverL()
+// Removes SAP observer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMPSSAPCenRep::RemoveObserver( MIMPSSAPObserver* aObserver )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::RemoveObserver()" );
+    iNotifier->RemoveObserver( aObserver );
+    }
+
+// SAP SETTINGS
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::StoreNewSAPL()
+// Stores new SAP in central repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint32 CIMPSSAPCenRep::StoreNewSAPL( CIMPSSAPSettings* aSAPSettings,
+                                      TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::StoreNewSAPL()" );
+
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+    // SAP name must be defined
+    if ( aSAPSettings->SAPName().Length() == 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // no documentation for StartTransaction() return values, leave if any error
+	iInTransaction = ETrue;
+	CleanupStack::PushL(TCleanupItem( ReSetTransactionState, this ));
+    User::LeaveIfError( iRepository->StartTransaction( CRepository::EReadWriteTransaction ) );
+
+    iRepository->CleanupCancelTransactionPushL();
+
+    //Check if SAP with given name already exists
+
+    // KIMPSSettingsNullUid cannot exist so this checks for all duplicates
+    if ( SAPNameExistsL( aSAPSettings->SAPName(), KIMPSSettingsNullUid,
+                         aGroup ) )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    RIMPSReleaseArray tempArray;
+    CleanupClosePushL( tempArray );
+
+    // Assign Uid for the new entry, leave if all Uids are in use
+    TUint32 newUid( NewUidL() );
+
+    //Encrypt passwords before storing has been removed
+    //401-1808 - Ease of Instant Messaging SERVER customization
+    HBufC* tmpPasswd = aSAPSettings->SAPUserPassword().AllocLC();
+    HBufC* tmpHTTPPasswd = aSAPSettings->HTTPProxyUserPassword().AllocLC();
+    TPtr passwdPtr( tmpPasswd->Des() );
+    TPtr httpPasswdPtr( tmpHTTPPasswd->Des() );
+
+    //get the first stored setting ID as the returnable ID for the client
+    TUint32 returnId( MaskedId( ESAPAddress, newUid, aGroup ) );
+
+    // If this is the first SAP to be stored in either access group,
+    // set it to default
+    if ( aGroup == EIMPSIMAccessGroup )
+        {
+        if ( SAPCountL( EIMPSIMAccessGroup ) == 0 )
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultIMSAPId,
+                                                  static_cast< TInt >( returnId ) ) );
+            }
+        }
+    else
+        {
+        if ( SAPCountL( EIMPSPECAccessGroup ) == 0 )
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultPECSAPId,
+                                                  static_cast< TInt >( returnId ) ) );
+            }
+        }
+
+    TIMPSCenRepOperations op( returnId, *iRepository );
+
+    op.CreateL( ESAPAddress, aSAPSettings->SAPAddress() );
+    op.CreateL( ESAPName, aSAPSettings->SAPName() );
+    op.CreateL( ESAPPort, static_cast< TInt >( aSAPSettings->SAPPort() ) );
+    op.CreateL( ESAPUserId, aSAPSettings->SAPUserId() );
+    op.CreateL( ESAPUserPassword, passwdPtr );
+    op.CreateL( EHTTPProxyUserId, aSAPSettings->HTTPProxyUserId() );
+    op.CreateL( EHTTPProxyUserPassword, httpPasswdPtr );
+    op.CreateL( EHTTPProxyAddress, aSAPSettings->HTTPProxyAddress() );
+    op.CreateL( EHTTPProxyPort, static_cast< TInt >( aSAPSettings->HTTPProxyPort() ) );
+
+    HBufC* apName = DoGetAccessPointsNameL(
+                        static_cast< TInt >( aSAPSettings->AccessPoint() ) );
+    CleanupStack::PushL( apName );
+    op.CreateL( EAccessPoint, *apName );
+    CleanupStack::PopAndDestroy( apName );
+
+    op.CreateL( EClientId, aSAPSettings->ClientId() );
+    op.CreateL( EServerAuthenticationName, aSAPSettings->ServerAuthenticationName() );
+    op.CreateL( EServerAuthenticationPassword, aSAPSettings->ServerAuthenticationPassword() );
+    op.CreateL( EServerAcceptedContentType, aSAPSettings->ServerAcceptedContentType() );
+    op.CreateL( EHighLevelServices, static_cast< TInt >( aSAPSettings->HighLevelServices() ) );
+    op.CreateL( EAuthorizationMode, static_cast< TInt >( aSAPSettings->AuthorizationMode() ) );
+    op.CreateL( EProtection, static_cast< TInt >( aSAPSettings->Protection() ) );
+
+    const RPointerArray< CIMPSSAPKeyValuePair >& pairs( aSAPSettings->KeyValuePairs().Pairs() );
+
+    TInt count( pairs.Count() );
+
+    for ( TInt i( 0 );i < count; ++i )
+        {
+        //HBufC ownership transfers here
+        HBufC* valuePairFlat = pairs[i]->KeyValuePairFlatLC();
+        User::LeaveIfError( iRepository->Create( EKeyValuePairBase +
+                                                 returnId + i,
+                                                 *valuePairFlat ) );
+        // CRepository->Create() is not copying the pointed data during transaction
+        // so these must be stored until the transaction has completed
+        tempArray.AppendL( valuePairFlat );
+        CleanupStack::Pop( valuePairFlat );
+        }
+
+    TUint32 err( KErrNone );
+    //passed err will be silently consumed because the value is of no use to client
+    User::LeaveIfError( iRepository->CommitTransaction( err ) );
+	iInTransaction = EFalse;
+	CleanupStack::PopAndDestroy( 5 ); //cleanupitem, Transaction, tempArray, tmpPasswd, tmpHTTPPasswd
+
+    aSAPSettings->Body().DoSetUid( returnId );
+    aSAPSettings->Body().DoSetAccessGroup( aGroup );
+    return returnId;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::GetSAPL()
+// Gets SAP from central repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+
+void CIMPSSAPCenRep::GetSAPL( TUint32 aUid, CIMPSSAPSettings* aSAPSettings )
+    {
+    TRAPD( err, DoGetSAPL( aUid, aSAPSettings ) );
+    if ( err == KErrArgument )
+        {
+        aSAPSettings->Reset();
+        }
+    else if ( err )
+        {
+        User::Leave( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::DoGetSAPL()
+// Does the actual get operation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+
+void CIMPSSAPCenRep::DoGetSAPL( TUint32 aUid, CIMPSSAPSettings* aSAPSettings )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::GetSAPL()" );
+
+	TBool transaction( StartOwnTransactionL( CRepository::EReadTransaction ) );
+    if ( transaction )
+        {
+        iRepository->CleanupCancelTransactionPushL();
+        }
+
+    HBufC* tmpBuffer = HBufC::NewLC( NCentralRepositoryConstants::KMaxUnicodeStringLength );
+    TPtr tmpPtr( tmpBuffer->Des() );
+
+    TInt tmpInteger( 0 );
+
+    SAPExistsL( aUid );
+
+    TIMPSAccessGroup type( SAPTypeL( aUid ) );
+
+    TIMPSCenRepOperations op( aUid, *iRepository );
+
+    op.GetL( ESAPAddress, tmpPtr );
+    aSAPSettings->SetSAPAddressL( tmpPtr );
+
+    op.GetL( ESAPName, tmpPtr );
+    aSAPSettings->SetSAPNameL( tmpPtr );
+
+    op.GetL( ESAPPort, tmpInteger );
+    aSAPSettings->SetSAPPort( tmpInteger );
+
+    op.GetL( ESAPUserId, tmpPtr );
+    aSAPSettings->SetSAPUserIdL( tmpPtr );
+
+    op.GetL( ESAPUserPassword, tmpPtr );
+    //Decrypting of passwrd has been removed
+    //401-1808 - Ease of Instant Messaging SERVER customization
+    aSAPSettings->SetSAPUserPasswordL( tmpPtr );
+
+    op.GetL( EHTTPProxyUserId, tmpPtr );
+    aSAPSettings->SetHTTPProxyUserIdL( tmpPtr );
+
+    //Decrypting of passwrd has been removed
+    //401-1808 - Ease of Instant Messaging SERVER customization
+    op.GetL( EHTTPProxyUserPassword, tmpPtr );
+    aSAPSettings->SetHTTPProxyUserPasswordL( tmpPtr );
+
+    op.GetL( EHTTPProxyAddress, tmpPtr );
+    aSAPSettings->SetHTTPProxyAddressL( tmpPtr );
+
+    op.GetL( EHTTPProxyPort, tmpInteger );
+    aSAPSettings->SetHTTPProxyPort( tmpInteger );
+
+    //op.GetL( EAccessPoint, tmpInteger );
+    op.GetL( EAccessPoint, tmpPtr );
+    tmpInteger = static_cast< TInt >( DoGetAccessPointsL( tmpPtr ) );
+    aSAPSettings->SetAccessPoint( tmpInteger );
+
+    op.GetL( EClientId, tmpPtr );
+    aSAPSettings->SetClientIdL( tmpPtr );
+
+    op.GetL( EServerAuthenticationName, tmpPtr );
+    aSAPSettings->SetServerAuthenticationNameL( tmpPtr );
+
+    op.GetL( EServerAuthenticationPassword, tmpPtr );
+    aSAPSettings->SetServerAuthenticationPasswordL( tmpPtr );
+
+    op.GetL( EServerAcceptedContentType, tmpPtr );
+    aSAPSettings->SetServerAcceptedContentTypeL( tmpPtr );
+
+    op.GetL( EHighLevelServices, tmpInteger );
+    aSAPSettings->SetHighLevelServices( tmpInteger );
+
+    op.GetL( EAuthorizationMode, tmpInteger );
+    aSAPSettings->SetAuthorizationMode( tmpInteger );
+
+    op.GetL( EProtection, tmpInteger );
+    aSAPSettings->ProtectL( static_cast<TIMPSSAPProtection>( tmpInteger ) );
+
+    RPointerArray< CIMPSSAPKeyValuePair >& pairs( aSAPSettings->KeyValuePairs().Pairs() );
+    pairs.ResetAndDestroy();
+
+    RArray<TUint32> foundPairs;
+    CleanupClosePushL( foundPairs );
+    iRepository->FindL( EKeyValuePairBase + aUid, KSAPPairsMask, foundPairs );
+    TInt count( foundPairs.Count() );
+
+    for ( TInt i( 0 );i < count; ++i )
+        {
+        TPtr valuePairFlatPtr( tmpBuffer->Des() );
+
+        User::LeaveIfError(
+            iRepository->Get( foundPairs[ i ],
+                              valuePairFlatPtr ) );
+
+        // parse the key-value pair descriptor
+
+        CIMPSSAPKeyValuePair* pair = CIMPSSAPKeyValuePair::NewLC( valuePairFlatPtr );
+
+        pairs.AppendL( pair );
+
+        CleanupStack::Pop( pair );
+        }
+
+    if ( transaction )
+        {
+        TUint32 err( KErrNone );
+        User::LeaveIfError( iRepository->CommitTransaction( err ) );
+		iInTransaction = EFalse;
+		CleanupStack::PopAndDestroy(2); // cleanupitem, transaction
+        }
+    CleanupStack::PopAndDestroy( 2 ); // foundPairs, tmpBuffer
+    aSAPSettings->Body().DoSetAccessGroup( type );
+    aSAPSettings->Body().DoSetUid( aUid );
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SAPCountL()
+// Counts the number of SAPs
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMPSSAPCenRep::SAPCountL( TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::SAPCountL()" );
+
+    __ASSERT_ALWAYS(    aGroup & EIMPSAccessFilterAll,
+                        Panic( EIMPSInvalidAccessGroup ) );
+
+    RArray<TUint32> foundSAPs;
+    CleanupClosePushL( foundSAPs );
+    FindSAPsFromAccessGroupL( aGroup, foundSAPs );
+    TInt count( foundSAPs.Count() );
+    CleanupStack::PopAndDestroy(); //foundSAPs
+    return count;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::DeleteSAPL()
+// Deletes SAP from central repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMPSSAPCenRep::DeleteSAPL( TUint32 aUid )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::DeleteSAPL()" );
+
+    iInTransaction = ETrue;
+    CleanupStack::PushL( TCleanupItem( ReSetTransactionState, this ));
+    User::LeaveIfError( iRepository->StartTransaction( CRepository::EReadWriteTransaction ) );
+    iRepository->CleanupCancelTransactionPushL();
+
+    SAPExistsL( aUid );
+    TIMPSAccessGroup type( SAPTypeL( aUid ) );
+
+    RArray<TUint32> foundIds;
+    CleanupClosePushL( foundIds );
+    iRepository->FindL( aUid, KSAPUidMask, foundIds );
+    TInt count( foundIds.Count() );
+    for ( TInt i( 0 ); i < count; ++i )
+        {
+        User::LeaveIfError( iRepository->Delete( foundIds[ i ] ) );
+        }
+
+    CleanupStack::PopAndDestroy(); //foundIds
+
+    TInt sapCount( SAPCountL( type ) );
+
+    if ( sapCount > 1 )	// deletion not commited yet, but nowadays the API
+        // seems to give up-to-date counts regardless
+        {
+        TUint32 defaultUid;
+        GetDefaultL( defaultUid, type );
+        // default SAP id is set to KIMPSSettingsNullUid if the
+        // default SAP was deleted
+        if ( type == EIMPSIMAccessGroup )
+            {
+            if ( aUid == defaultUid )
+                {
+                User::LeaveIfError( iRepository->Set( KDefaultIMSAPId,
+                                                      KIMPSSettingsNullUid ) );
+                }
+            }
+        else
+            {
+            if ( aUid == defaultUid )
+                {
+                User::LeaveIfError( iRepository->Set( KDefaultPECSAPId,
+                                                      KIMPSSettingsNullUid ) );
+                }
+            }
+        }
+    // If there is only one SAP left after the deletion, set it to default.
+    if ( sapCount == 1 )
+        {
+        CIMPSSAPSettingsList* list = CIMPSSAPSettingsList::NewLC();
+        PopulateSAPSettingsListL( *list, type );
+        TUint32 newDefault( list->UidForIndex( 0 ) );
+        SetToDefaultL( newDefault, type );
+        CleanupStack::PopAndDestroy( list );
+        }
+    // If there are no SAPs left after the deletion, default SAP id is
+    // set to KIMPSSettingsNullUid
+    if ( sapCount == 0 )
+        {
+        if ( type == EIMPSIMAccessGroup )
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultIMSAPId,
+                                                  KIMPSSettingsNullUid ) );
+            }
+        else
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultPECSAPId,
+                                                  KIMPSSettingsNullUid ) );
+            }
+        }
+    TUint32 err;
+    User::LeaveIfError( iRepository->CommitTransaction( err ) );
+	iInTransaction = EFalse;
+  	CleanupStack::PopAndDestroy(2); //cleanupitem, Transaction
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::UpdateOldSAPL()
+// Updates existing SAP
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMPSSAPCenRep::UpdateOldSAPL( CIMPSSAPSettings* aSAPSettings, TUint32 aUid )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::UpdateOldSAPL()" );
+
+    iInTransaction = ETrue;
+    CleanupStack::PushL( TCleanupItem( ReSetTransactionState, this ));
+    User::LeaveIfError( iRepository->StartTransaction( CRepository::EReadWriteTransaction ) );
+    iRepository->CleanupCancelTransactionPushL();
+
+    SAPExistsL( aUid );
+    TIMPSAccessGroup type( SAPTypeL( aUid ) );
+    TIMPSSAPProtection protection( SAPProtectionL( aUid, type ) );
+
+    if ( protection == ESAPBrandProtection )
+        {
+        CIMPSSAPSettings* settings = CIMPSSAPSettings::NewLC();
+        GetSAPL( aUid, settings );
+        if ( ( settings->SAPName().Compare( aSAPSettings->SAPName() ) != 0 ) )
+            {
+            // User is trying to modify protected values, leave
+            User::Leave( KErrAccessDenied );
+            }
+        CleanupStack::PopAndDestroy( settings );
+        }
+
+    //Check for duplicate SAP names. SAPName in SAP with aUid is permitted to be
+    //same as it is the one we are updating.
+    if ( SAPNameExistsL( aSAPSettings->SAPName(), aUid, type ) )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    RIMPSReleaseArray tempArray;
+    CleanupClosePushL( tempArray );
+
+    //Encrypt password before storing has been removed
+    //401-1808 - Ease of Instant Messaging SERVER customization
+    HBufC* tmpPasswd = aSAPSettings->SAPUserPassword().AllocLC();
+    HBufC* tmpHTTPPasswd = aSAPSettings->HTTPProxyUserPassword().AllocLC();
+    TPtr passwdPtr( tmpPasswd->Des() );
+    TPtr httpPasswdPtr( tmpHTTPPasswd->Des() );
+
+    TIMPSCenRepOperations op( aUid, *iRepository );
+
+    op.SetL( ESAPAddress, aSAPSettings->SAPAddress() );
+    op.SetL( ESAPName, aSAPSettings->SAPName() );
+    op.SetL( ESAPPort, static_cast< TInt >( aSAPSettings->SAPPort() ) );
+    op.SetL( ESAPUserId, aSAPSettings->SAPUserId() );
+    op.SetL( ESAPUserPassword, passwdPtr );
+    op.SetL( EHTTPProxyUserId, aSAPSettings->HTTPProxyUserId() );
+    op.SetL( EHTTPProxyUserPassword, httpPasswdPtr );
+    op.SetL( EHTTPProxyAddress, aSAPSettings->HTTPProxyAddress() );
+    op.SetL( EHTTPProxyPort, static_cast< TInt >( aSAPSettings->HTTPProxyPort() ) );
+
+    HBufC* apName = DoGetAccessPointsNameL(
+                        static_cast< TInt >( aSAPSettings->AccessPoint() ) );
+    CleanupStack::PushL( apName );
+    op.SetL( EAccessPoint, *apName );
+    CleanupStack::PopAndDestroy( apName );
+
+    op.SetL( EClientId, aSAPSettings->ClientId() );
+    op.SetL( EServerAuthenticationName, aSAPSettings->ServerAuthenticationName() );
+    op.SetL( EServerAuthenticationPassword, aSAPSettings->ServerAuthenticationPassword() );
+    op.SetL( EServerAcceptedContentType, aSAPSettings->ServerAcceptedContentType() );
+    op.SetL( EHighLevelServices, static_cast< TInt >( aSAPSettings->HighLevelServices() ) );
+    op.SetL( EAuthorizationMode, static_cast< TInt >( aSAPSettings->AuthorizationMode() ) );
+    op.SetL( EProtection, static_cast< TInt >( aSAPSettings->Protection() ) );
+
+    //First delete old key-value pairs
+    RArray<TUint32> foundPairs;
+    CleanupClosePushL( foundPairs );
+    iRepository->FindL( EKeyValuePairBase + aUid, KSAPPairsMask, foundPairs );
+    TInt oldCount( foundPairs.Count() );
+
+    for ( TInt i( 0 ); i < oldCount; ++i )
+        {
+        User::LeaveIfError( iRepository->Delete( foundPairs[i] ) );
+        }
+
+    //Create new pairs
+    const RPointerArray< CIMPSSAPKeyValuePair >& pairs( aSAPSettings->KeyValuePairs().Pairs() );
+
+    TInt count( pairs.Count() );
+
+    for ( TInt i( 0 );i < count; ++i )
+        {
+        //this creates a new hbufc and transfers ownership here
+        HBufC* valuePairFlat = pairs[i]->KeyValuePairFlatLC();
+        TPtr valuePairFlatPtr( valuePairFlat->Des() );
+
+        User::LeaveIfError( iRepository->Create( EKeyValuePairBase + i + aUid,
+                                                 valuePairFlatPtr ) );
+
+        // CRepository->Set() is not copying the pointed data during transaction
+        // so these must be stored until the transaction has completed
+        tempArray.AppendL( valuePairFlat );
+        CleanupStack::Pop( valuePairFlat );
+        }
+
+    TUint32 err( KErrNone );
+    User::LeaveIfError( iRepository->CommitTransaction( err ) );
+    iInTransaction = EFalse;
+	CleanupStack::PopAndDestroy( 6 ); // cleanupitem, Transaction, tmpPasswd, tmpHTTPPasswd, tempArray, foundPairs
+
+    aSAPSettings->Body().DoSetUid( aUid );
+    aSAPSettings->Body().DoSetAccessGroup( type );
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::PopulateSAPSettingsListL()
+// Populates SAP settings list
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::PopulateSAPSettingsListL( CIMPSSAPSettingsList& aList,
+                                               TIMPSAccessGroup aGroup, TBool aAscending )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::PopulateSAPSettingsListL()" );
+
+    __ASSERT_ALWAYS(    aGroup & EIMPSAccessFilterAll,
+                        Panic( EIMPSInvalidAccessGroup ) );
+
+	TBool transaction( StartOwnTransactionL( CRepository::EReadTransaction ) );
+    if ( transaction )
+        {
+        iRepository->CleanupCancelTransactionPushL();
+        }
+
+    CIMPSSAPSettingsListItem* listItem = NULL;
+    TIMPSSAPSettingsListItemNameKey key( aAscending );
+
+    RArray<TUint32> foundSAPs;
+    CleanupClosePushL( foundSAPs );
+
+    FindSAPsFromAccessGroupL( aGroup, foundSAPs );
+
+    TInt count( foundSAPs.Count() );
+
+    for ( TInt i( 0 ); i < count; ++i )
+        {
+        HBufC16* name = HBufC::NewLC( NCentralRepositoryConstants::KMaxUnicodeStringLength );
+        TPtr namePtr( name->Des() );
+
+        TIMPSAccessGroup type( SAPTypeL( foundSAPs[i] ) );
+
+        TInt err( iRepository->Get( foundSAPs[i] + ESAPName, namePtr ) );
+        if ( err && ( err != KErrArgument ) )
+            {
+            User::Leave( err );
+            }
+
+        TInt protectionInt( ESAPNoProtection );
+        err = iRepository->Get( foundSAPs[i] + EProtection, protectionInt );
+
+        if ( err && ( err != KErrArgument ) )
+            {
+            User::Leave( err );
+            }
+
+        listItem = CIMPSSAPSettingsListItem::NewLC( *name, foundSAPs[ i ], type,
+                                                    static_cast<TIMPSSAPProtection>( protectionInt ) );
+        aList.InsertIsqAllowDuplicatesL( listItem, key ); //takes ownership of listitem
+        CleanupStack::Pop( listItem );
+        CleanupStack::PopAndDestroy( name );
+        }
+    CleanupStack::PopAndDestroy(); // foundSAPs
+    if ( transaction )
+        {
+        TUint32 err( KErrNone );
+        User::LeaveIfError( iRepository->CommitTransaction( err ) );
+		iInTransaction = EFalse;
+		CleanupStack::PopAndDestroy(2); // cleanupitem, transaction
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::GetDefaultL()
+// Gets Uid of default SAP
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::GetDefaultL( TUint32& aUid, TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::GetDefaultL()" );
+
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+	TBool transaction( StartOwnTransactionL( CRepository::EReadTransaction ) );
+    if ( transaction )
+        {
+        iRepository->CleanupCancelTransactionPushL();
+        }
+
+    TInt uid( 0 );
+    if ( aGroup & EIMPSIMAccessGroup )
+        {
+        User::LeaveIfError( iRepository->Get( KDefaultIMSAPId, uid ) );
+        }
+    else
+        {
+        User::LeaveIfError( iRepository->Get( KDefaultPECSAPId, uid ) );
+        }
+    if ( transaction )
+        {
+        TUint32 err( KErrNone );
+        User::LeaveIfError( iRepository->CommitTransaction( err ) );
+		iInTransaction = EFalse;
+		CleanupStack::PopAndDestroy(2); // cleanupitem, transaction
+        }
+    aUid = uid;
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::GetDefaultL()
+// Gets default SAP to settings container
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::GetDefaultL( CIMPSSAPSettings* aSAPSettings,
+                                  TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::GetDefaultL() #2" );
+
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+    TUint32 uid;
+    GetDefaultL( uid, aGroup );
+    GetSAPL( uid, aSAPSettings );
+    }
+
+// -----------------------------------------------------------------------------
+// CIMPSSAPCenRep::SetToDefaultL()
+// Sets given SAP to default SAP
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CIMPSSAPCenRep::SetToDefaultL( TUint32 aUid, TIMPSAccessGroup aGroup )
+    {
+    SSS_DP_TXT( "CIMPSSAPCenRep::SetToDefaultL()" );
+
+    __ASSERT_ALWAYS( ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSIMAccessGroup ) ||
+                     ( ( aGroup & EIMPSAccessFilterAll ) == EIMPSPECAccessGroup ),
+                     Panic( EIMPSInvalidAccessGroup ) );
+
+	TBool transaction( StartOwnTransactionL( CRepository::EReadWriteTransaction ) );
+    if ( transaction )
+        {
+        iRepository->CleanupCancelTransactionPushL();
+        }
+
+    // check that aUid exists
+    SAPExistsL( aUid );
+
+    //and it belongs to the given group
+    if ( SAPTypeL( aUid ) & aGroup )
+        {
+        if ( aGroup & EIMPSIMAccessGroup )
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultIMSAPId,
+                                                  static_cast<TInt>( aUid ) ) );
+            }
+        else
+            {
+            User::LeaveIfError( iRepository->Set( KDefaultPECSAPId,
+                                                  static_cast<TInt>( aUid ) ) );
+            }
+        }
+    else
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    if ( transaction )
+        {
+        TUint32 err( KErrNone );
+        User::LeaveIfError( iRepository->CommitTransaction( err ) );
+		iInTransaction = EFalse;
+		CleanupStack::PopAndDestroy(2); // cleanupitem, transaction
+        }
+    }
+
+//401-1808 - Ease of Instant Messaging SERVER customization
+
+// ---------------------------------------------------------
+// CIMPSSAPCenRep::DoGetAccessPointsL
+// ---------------------------------------------------------
+//
+TUint32 CIMPSSAPCenRep::DoGetAccessPointsL( const TDesC& aAPName )
+    {
+    TUint32 ap = 0;
+    TInt err( KErrNone );
+
+    // Iterate the IAP table from CommsDat
+    CCommsDbTableView* table = NULL;
+
+    table = iCommsDatabase->OpenViewMatchingTextLC( TPtrC( IAP ), TPtrC( COMMDB_NAME ), aAPName );
+
+    err = table->GotoFirstRecord();
+
+    if ( !err )
+        {
+        // Read IAP's ID
+        //
+        table->ReadUintL( TPtrC( COMMDB_ID ), ap );
+        }
+
+    CleanupStack::PopAndDestroy( table );
+
+    return ap;
+    }
+
+
+// ---------------------------------------------------------
+// CIMPSSAPCenRep::DoGetAccessPointsNameL
+// ---------------------------------------------------------
+//
+HBufC* CIMPSSAPCenRep::DoGetAccessPointsNameL( const TUint32 aAP )
+    {
+    TInt err( KErrNone );
+    HBufC* buf1 = NULL;
+
+    // Iterate the IAP table from CommsDat
+    CCommsDbTableView* table = NULL;
+    table = iCommsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aAP );
+    err = table->GotoFirstRecord();
+
+    if ( !err )
+        {
+        TInt    length1( 0 );
+
+        // Read IAP's connection name
+        //
+        table->ReadColumnLengthL( TPtrC( COMMDB_NAME ), length1 );
+        buf1 = HBufC::NewLC( length1 );
+        TPtr ptr1( buf1->Des() );
+        table->ReadTextL( TPtrC( COMMDB_NAME ), ptr1 );
+        }
+    else
+        {
+        buf1 = KNullDesC().AllocLC();
+        }
+
+    CleanupStack::Pop( buf1 );
+    CleanupStack::PopAndDestroy( table );
+
+    return buf1;
+    }
+
+// ---------------------------------------------------------
+// CIMPSSAPCenRep::ReSetTransactionState
+// ---------------------------------------------------------
+//
+void CIMPSSAPCenRep::ReSetTransactionState(TAny* ptr)
+	{
+	reinterpret_cast<CIMPSSAPCenRep*>( ptr )->ReSetTransactionFlag();
+	}
+
+// ---------------------------------------------------------
+// CIMPSSAPCenRep::ReSetTransactionFlag
+// ---------------------------------------------------------
+//
+void CIMPSSAPCenRep::ReSetTransactionFlag()
+	{
+	iInTransaction = EFalse;
+	}
+//End 401-1808 - Ease of Instant Messaging SERVER customization
+
+//  End of File