diff -r 000000000000 -r 307788aac0a8 sipplugins/sippsipsettingsui/src/gssipmodel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sipplugins/sippsipsettingsui/src/gssipmodel.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1229 @@ +/* +* Copyright (c) 2003 - 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: Application's document class +* +*/ + + +// INCLUDE FILES + +#include +#include +#include +#include +#include //GUI Resource +#include +#include "gssipmodel.h" +#include "gssipappshutter.h" +#include "gssipprofileutil.h" +#include "gssippluginlogger.h" + +// CONSTANTS +_LIT( KOpenParenthesis, "(" ); +_LIT( KClosedParenthesis, ")" ); +const TInt KMaxDuplicatePostfixLength = 10; +const TInt KSIPGranularity = 5; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CGSSIPModel +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CGSSIPModel::CGSSIPModel() + { + __GSLOGSTRING("CGSSIPModel::CGSSIPModel" ) + iQuitAfterSave = EFalse; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ConstructL() + { + __GSLOGSTRING("CGSSIPModel::ConstructL" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CGSSIPModel* CGSSIPModel::NewL() + { + __GSLOGSTRING("CGSSIPModel::NewL" ) + CGSSIPModel* self = new( ELeave ) CGSSIPModel(); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +CGSSIPModel::~CGSSIPModel() + { + __GSLOGSTRING("CGSSIPModel::~CGSSIPModel" ) + if ( iProfiles ) + { + iProfiles->ResetAndDestroy(); + delete iProfiles; + } + + delete iAppShutter; + delete iEngine; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CreateEngineL +// Creates the application engine +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CreateEngineL( CGSPluginInterface* aAppUi ) + { + __GSLOGSTRING("CGSSIPModel::CreateEngineL Start" ) + iAppUi = aAppUi; + + // Create AppShutter instance. + iAppShutter = CGSSIPAppShutter::NewL( iAppUi ); + + iEngine = CSIPManagedProfileRegistry::NewL( *this ); + ReadArrayFromEngineL(); + __GSLOGSTRING("CGSSIPModel::CreateEngineL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::EditProfileL +// Copies profile's data to iProfileData +// ----------------------------------------------------------------------------- +// +TBool CGSSIPModel::EditProfileL( TInt aIndex ) + { + __GSLOGSTRING("CGSSIPModel::EditProfileL " ) + __GSLOGSTRING1("CGSSIPModel::EditProfileL aIndex: %d", aIndex) + TBool moveToNextView = ETrue; + + CSIPManagedProfile* profile = + static_cast( iProfiles->At( aIndex ) ); + + if ( iEngine->IsInUseL( *profile ) ) + { + HBufC* errorTxt = StringLoader::LoadLC( R_QTN_SIP_ERROR_PROFILE_USED ); + CAknErrorNote* note = new ( ELeave ) CAknErrorNote( ETrue ); + note->ExecuteLD( errorTxt->Des() ); + CleanupStack::PopAndDestroy( errorTxt ); + + moveToNextView = EFalse; + } + else + { + CopyToProfileDataStructL( aIndex ); + } + + return moveToNextView; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CreateAndEditProfileL +// Starts editing a new profile that is based on an existing one +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CreateAndEditProfileL( TInt aCopiedIndex ) + { + __GSLOGSTRING("CGSSIPModel::CreateAndEditProfileL Start" ) + __GSLOGSTRING1("CGSSIPModel::CreateAndEditProfileL aCopiedIndex: %d", aCopiedIndex) + if ( aCopiedIndex == KUnknownProfileIndex ) + { + // Create new profile with default values + FillDataStructWithDefaultValsL(); + } + else + { + CopyToProfileDataStructL( aCopiedIndex ); + iProfileData.iID = KUnknownProfileIndex; + } + + CheckDuplicateNameL( iProfileData.iID, + iProfileData.iProviderName , ETrue); + __GSLOGSTRING("CGSSIPModel::CreateAndEditProfileL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileData +// Returns pointer to profile data structure for modifying it directly +// ----------------------------------------------------------------------------- +// +TSIPSettingsData* CGSSIPModel::ProfileData() + { + __GSLOGSTRING("CGSSIPModel::ProfileData" ) + return &iProfileData; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileData +// Returns pointer to the profile array +// ----------------------------------------------------------------------------- +// +CArrayPtr* CGSSIPModel::ProfileArray() + { + __GSLOGSTRING("CGSSIPModel::ProfileArray" ) + return iProfiles; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::SaveProfileL +// Saves profile to persistent storage +// ----------------------------------------------------------------------------- +// +TBool CGSSIPModel::SaveProfileL() + { + __GSLOGSTRING("CGSSIPModel::SaveProfileL" ) + TBool modifications = ETrue; + TInt err( KErrNone ); + + CheckDuplicateNameL( iProfileData.iID, iProfileData.iProviderName ); + + if ( iProfileData.iID == KUnknownProfileIndex ) + { + // Need to create a new profile + CSIPManagedProfile* profile = + iEngine->CreateL( iProfileData.iServiceProfile ); + + CleanupStack::PushL( profile ); + + // Copy attributes to the new profile + iNewProfile = profile; + profile = CopyDataToProfileL(); + + // Save the profile to persistent storage + TRAP( err, iEngine->SaveL( *profile ) ); + + if ( err ) + { + // When exit is called and we get error code because of same realm + // with different username, we sohuld exit without saving. + // Otherwise this method leaves. + if ( iQuitAfterSave ) + { + CleanupStack::PopAndDestroy( profile ); + modifications = EFalse; + } + else + { + User::Leave( err ); + } + } + else + { + CleanupStack::Pop( profile ); + } + } + else + { + // check at first if a profile is locked + TBool locked( EFalse ); + err = Profile( iProfileData.iID )->GetParameter( KSIPProfileLocked, + locked ); + if ( locked ) + { + return EFalse; + } + + // We can save the modified changes if any + if ( CheckForModificationsL() ) + { + // Check that the profile is not in use + CSIPManagedProfile* profile = Profile( iProfileData.iID ); + CSIPManagedProfile* clonedProfile = profile->CloneL(); + CleanupStack::PushL( clonedProfile ); + + profile = CopyDataToProfileL(); + + TRAP( err, iEngine->SaveL( *profile ) ); + + if ( err ) + { + // Copy old profile data back to temporary variable + // If this leaves, then nope can do; there hasn't been enough + // memory on the first place to do the operations, so there isn't + // much we can do execpt prevent further memory loss + ReplaceProfileL( iProfileData.iID, clonedProfile ); + + // When exit is called and we get error code because of same realm + // with different username, we sohuld exit without saving. + // Otherwise this method leaves. + if ( iQuitAfterSave ) + { + modifications = EFalse; + } + else + { + User::Leave( err ); + } + } + + CleanupStack::PopAndDestroy( clonedProfile ); + } + else + { + // No modifications, not saving for nothing + modifications = EFalse; + } + } + + return modifications; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::SetDefaultProfileL +// Sets new default profile +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::SetDefaultProfileL( TInt aIndex ) + { + __GSLOGSTRING("CGSSIPModel::SetDefaultProfileL Start" ) + __GSLOGSTRING1("CGSSIPModel::SetDefaultProfileL aIndex: %d", aIndex) + TBool bDefault = EFalse ; + TInt err = + iProfiles->At( aIndex )->GetParameter( KSIPDefaultProfile, bDefault ); + User::LeaveIfError( err ); + if ( !bDefault ) + { + CSIPManagedProfile* profile = + static_cast( iProfiles->At( aIndex ) ); + + if ( iEngine->IsInUseL( *profile ) ) + { + // Can't change the profile, it is in use + User::Leave( KErrInUse ); + } + + // Set the profile to be default and save sum' settings + err= profile->SetParameter( KSIPDefaultProfile, ETrue ); + User::LeaveIfError( err ); + + TRAP( err, iEngine->SaveL( *profile ) ); + + // If SaveL() leaves profile and the old default profile might be + // set as defaults; need to read the whole array again.. + if ( err ) + { + ReadProfileListFromEngineSafeL(); + User::Leave( err ); + } + } + __GSLOGSTRING("CGSSIPModel::SetDefaultProfileL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::DefaultProfileIndex +// Returns index to the default profile +// ----------------------------------------------------------------------------- +// +TInt CGSSIPModel::DefaultProfileIndex() + { + __GSLOGSTRING("CGSSIPModel::DefaultProfileIndex " ) + TInt i( 0 ); + TInt index( KUnknownProfileIndex ); + // "Default values" are not values from default profile; instead they + // are the values that are defined on UI specification + + // Scans through the array and returns the index of the profile + for ( i = 0; i < iProfiles->Count() && index == KUnknownProfileIndex; i++ ) + { + TBool defProfile = EFalse; + TInt err = + iProfiles->At( i )->GetParameter( KSIPDefaultProfile, defProfile ); + if ( err ) + { + // No luck if leaves + defProfile = EFalse; + } + + if ( defProfile ) + { + index = i; + } + } + __GSLOGSTRING1("CGSSIPModel::DefaultProfileIndex: %d", index) + return index; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::TypeListL +// Returns an array consisting of the typenames +// ----------------------------------------------------------------------------- +// +RArray* CGSSIPModel::TypeListL() + { + __GSLOGSTRING("CGSSIPModel::TypeListL" ) + RArray* typeArray = + new (ELeave) RArray; + + TCleanupItem clItem( CloseAndDestroy, &typeArray ); + CleanupStack::PushL( clItem ); + + // Get the supported profile types + iEngine->SupportedProfileTypesL( *typeArray ); + + CleanupStack::Pop(); //clItem + + return typeArray; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::DeleteProfileL +// Deletes a profile from permanent storage +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::DeleteProfileL( TInt aIndex ) + { + __GSLOGSTRING("CGSSIPModel::DeleteProfileL Start" ) + __GSLOGSTRING1("CGSSIPModel::DeleteProfileL aIndex: %d", aIndex) + CSIPManagedProfile* profile = iProfiles->At( aIndex ); + + if ( iEngine->IsInUseL( *profile ) ) + { + User::Leave( KErrInUse ); + } + + iEngine->DestroyL( *profile ); + __GSLOGSTRING("CGSSIPModel::DeleteProfileL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::QuitAfterSave +// Set "Quit after save" flag +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::QuitAfterSave() + { + __GSLOGSTRING("CGSSIPModel::QuitAfterSave" ) + iQuitAfterSave = ETrue; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ErrorInRegistration +// Checks if there has been error in registration +// ----------------------------------------------------------------------------- +// +TBool CGSSIPModel::ErrorInRegistration( TInt aIndex ) + { + __GSLOGSTRING("CGSSIPModel::ErrorInRegistration" ) + __GSLOGSTRING1("CGSSIPModel::ErrorInRegistration aIndex: %d", aIndex) + return ( iEngine->LastRegistrationError( + *( iProfiles->At( aIndex ) ) ) != KErrNone ); + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileRegistryEventOccurred +// SIP profile event +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileRegistryEventOccurred( + TUint32 aSIPProfileId, TEvent aEvent ) + { + __GSLOGSTRING("CGSSIPModel::ProfileRegistryEventOccurred Start" ) + __GSLOGSTRING1("CGSSIPModel::ProfileRegistryEventOccurred aSIPProfileId: %d", aSIPProfileId) + __GSLOGSTRING1("CGSSIPModel::ProfileRegistryEventOccurred aEvent: %d", aEvent) + switch( aEvent ) + { + case EProfileCreated: + TRAP_IGNORE( ProfileCreatedL( aSIPProfileId ) ) + break; + case EProfileUpdated: + TRAP_IGNORE( ProfileUpdatedL( aSIPProfileId ) ) + break; + case EProfileRegistered: + case EProfileDeregistered: + ProfileRegistrationStatusChanged( aSIPProfileId ); + break; + case EProfileDestroyed: + ProfileDestroyed( aSIPProfileId ); + break; + default: + // Do nothing. + break; + } + __GSLOGSTRING("CGSSIPModel::ProfileRegistryEventOccurred End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileCreatedL +// SIP profile creation event +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileCreatedL( TUint32 aSIPProfileId ) + { + __GSLOGSTRING("CGSSIPModel::ProfileCreatedL Start" ) + __GSLOGSTRING1("CGSSIPModel::ProfileCreatedL aSIPProfileId: %d", aSIPProfileId) + CSIPManagedProfile* profile = NULL; + TBool byThisApp = ETrue; + TUint32 profileId = 0; + if( iNewProfile ) + { + TInt err = iNewProfile->GetParameter( KSIPProfileId, profileId ); + if( err ) + { + return; + } + } + if ( iNewProfile && aSIPProfileId == profileId ) + { + profile = iNewProfile; + iNewProfile = NULL; + } + else + { + // Some other application has created a new profile + byThisApp = EFalse; + TRAPD( err, profile = static_cast( + iEngine->ProfileL( aSIPProfileId ) ) ); + if ( err ) + { + // Can't fetch the new profile - nothing to do + return; + } + } + + // Inserts the profile to the correct place + TInt count = iProfiles->Count(); + TInt i( 0 ); + TBool profileAdded( EFalse ); + TInt err( KErrNone ); + const TDesC8* providerName = NULL; + + err = profile->GetParameter( KSIPProviderName, providerName ); + if( !err ) + { + const TDesC8* oldProvider = NULL; + for ( i = 0; i < count; i++ ) + { + err = iProfiles->At( i )->GetParameter( + KSIPProviderName, oldProvider ); + //if there is an error it should continue for next . + if ( !err && !profileAdded + && providerName->CompareC( *oldProvider ) < 0 ) + { + TRAP( err, iProfiles->InsertL( i, profile ) ); + profileAdded = ETrue; + iAddedProfileIndex = i; + i = count; + } + } + } + + // Profile's name was the 'biggest' - append it + if ( !profileAdded ) + { + TRAP( err, iProfiles->AppendL( profile ) ); + iAddedProfileIndex = iProfiles->Count() - 1; + } + + if ( iQuitAfterSave && byThisApp ) + { + // This application has created a new profile, now + // quit the app + iAppShutter->RequestAppShutdown(); + } + else + { + // Update the view if not exiting the application + UpdateListCmd(); + } + __GSLOGSTRING("CGSSIPModel::ProfileCreatedL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileUpdatedL +// SIP profile information update event +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileUpdatedL( + TUint32 aSIPProfileId ) + { + __GSLOGSTRING("CGSSIPModel::ProfileUpdatedL Start" ) + __GSLOGSTRING1("CGSSIPModel::ProfileUpdatedL aSIPProfileId: %d", aSIPProfileId) + if ( iQuitAfterSave && aSIPProfileId == TUint( iProfileData.iID ) ) + { + // Updated the profile that should be updated - now quit + iAppShutter->RequestAppShutdown(); + } + else + { + // Updated profile name is not probably the same. + // Remove from list and add it again, so it will be in right place + // in the list in alphabetical order + TInt err( KErrNone ); + TInt i( 0 ); + TUint32 profileId = 0; + TInt count = iProfiles->Count(); + TInt index( -1 ); + CSIPManagedProfile* profile = NULL; + + TRAP( err, profile = static_cast( + iEngine->ProfileL( aSIPProfileId ) ) ); + + if ( err ) + { + // Can't fetch the new profile - nothing to do + return; + } + + for ( i = 0; i < count; i++ ) + { + err = iProfiles->At( i )->GetParameter(KSIPProfileId, profileId); + if (profileId == aSIPProfileId && !err ) + { + index = i; + i = count; + } + } + + if ( index >= 0 ) + { + // first delete profile from list then add it in right place + // CSIPProfile* profile = iProfiles->At( index ); + CSIPProfile* profileRemoved = iProfiles->At( index ); + iProfiles->Delete( index ); + delete profileRemoved; + count--; + + // now add it again + const TDesC8* providerName = NULL; + TBool profileAdded( EFalse ); + err = profile->GetParameter( KSIPProviderName, providerName ); + if( !err ) + { + const TDesC8* oldProvider = NULL; + for ( i = 0; i < count; i++ ) + { + err = iProfiles->At( i )->GetParameter( + KSIPProviderName, oldProvider ); + + if ( !err && !profileAdded + && providerName->CompareC( *oldProvider ) < 0 ) + { + TRAP( err, iProfiles->InsertL( i, profile ) ); + profileAdded = ETrue; + iAddedProfileIndex = i; + i = count; + } + } + // Profile's name was the 'biggest' - append it + if ( !profileAdded ) + { + TRAP( err, iProfiles->AppendL( profile ) ); + iAddedProfileIndex = iProfiles->Count() - 1; + } + } + } + + UpdateListCmd(); + } + __GSLOGSTRING("CGSSIPModel::ProfileUpdatedL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileRegistrationStatusChanged +// SIP profile registration status changed event +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileRegistrationStatusChanged( + TUint32 /*aSIPProfileId*/ ) + { + __GSLOGSTRING("CGSSIPModel::ProfileRegistrationStatusChanged" ) + UpdateListCmd(); + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileDestroyed +// SIP profile destruction event. +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileDestroyed( + TUint32 aSIPProfileId ) + { + __GSLOGSTRING("CGSSIPModel::ProfileDestroyed Start" ) + __GSLOGSTRING1("CGSSIPModel::ProfileDestroyed aSIPProfileId: %d", aSIPProfileId) + TInt i( 0 ); + TUint32 profileId = 0; + TInt count = iProfiles->Count(); + for ( i = 0; i < count; i++ ) + { + TInt err= iProfiles->At( i )->GetParameter(KSIPProfileId,profileId); + if (profileId == aSIPProfileId && !err ) + { + CSIPProfile* profile = iProfiles->At( i ); + iProfiles->Delete( i ); + delete profile; + i = count; + } + } + + UpdateListCmd( EGSCmdProfileDeleted ); + __GSLOGSTRING("CGSSIPModel::ProfileDestroyed End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::AddedProfileIndex +// Added profile index in the profiles list. +// ----------------------------------------------------------------------------- +// +TInt CGSSIPModel::AddedProfileIndex() + { + __GSLOGSTRING("CGSSIPModel::AddedProfileIndex" ) + return iAddedProfileIndex; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ProfileRegistryErrorOccured +// An asynchronous error has occurred related to SIP profile +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ProfileRegistryErrorOccurred( + TUint32 /*aSIPProfileId*/, + TInt /*aError*/ ) + { + __GSLOGSTRING("CGSSIPModel::ProfileRegistryErrorOccurred" ) + // Updates list to show that error has happened in registration + UpdateListCmd(); + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ReadArrayFromEngineL +// Reads the profile array from SIP Profile Client +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ReadArrayFromEngineL() + { + __GSLOGSTRING("CGSSIPModel::ReadArrayFromEngineL Start" ) + RArray array; + CleanupClosePushL( array ); + + // Get the supported profile types + iEngine->SupportedProfileTypesL( array ); + + // check iProfiles, if exists delete + if ( iProfiles ) + { + iProfiles->ResetAndDestroy(); + delete iProfiles; + } + + // Create the profile pointer array + iProfiles = + new ( ELeave ) CArrayPtrFlat( KSIPGranularity ); + + TInt i( 0 ); + RPointerArray profilePointerArray; + TCleanupItem clItem( ResetAndDestroy, &profilePointerArray ); + CleanupStack::PushL( clItem ); + + // Get all profiles based on profile types + for ( i = 0; i < array.Count(); i++ ) + { + iEngine->ProfilesL( array[i], profilePointerArray ); + TInt j( 0 ); + while ( profilePointerArray.Count() > 0 ) + { + CSIPManagedProfile* profile = + static_cast( profilePointerArray[j] ); + iProfiles->AppendL( profile ); + profilePointerArray.Remove( j ); + } + profilePointerArray.Reset(); + } + + // Sort the profiles according to their ID + // Bubble sort is slow, but because we have only few items it doesn't + // matter + TInt j( 0 ); + TInt err(KErrNone); + const TDesC8* providerName1 = NULL; + const TDesC8* providerName2 = NULL; + for ( i = 0; i < iProfiles->Count() - 1; i++ ) + { + for ( j = 0; j < iProfiles->Count() - 1 - i; j++ ) + { + err= iProfiles->At( j + 1 )->GetParameter( + KSIPProviderName, providerName1 ); + User::LeaveIfError( err ); + err= iProfiles->At( j )->GetParameter( + KSIPProviderName, providerName2 ); + User::LeaveIfError( err ); + if ( providerName1->CompareC( *providerName2 ) < 0 ) + { + CSIPManagedProfile* tmp = iProfiles->At( j ); + CSIPManagedProfile* tmp2 = iProfiles->At( j + 1 ); + iProfiles->Delete( j ); + iProfiles->Delete( j ); + iProfiles->InsertL( j, tmp ); + iProfiles->InsertL( j, tmp2 ); + } + } + } + + CleanupStack::PopAndDestroy(); // clItem + CleanupStack::PopAndDestroy( &array ); + __GSLOGSTRING("CGSSIPModel::ReadArrayFromEngineL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CopyToProfileDataStructL +// Copies profile's attributes to the internal data structure +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CopyToProfileDataStructL( TInt aIndex ) + { + __GSLOGSTRING("CGSSIPModel::CopyToProfileDataStructL Start" ) + __GSLOGSTRING1("CGSSIPModel::CopyToProfileDataStructL aIndex: %d", aIndex) + FillDataStructWithDefaultValsL(); + + CSIPManagedProfile* profile = iProfiles->At( aIndex ); + + GSSIPProfileUtil::CopyToTempStructL( profile, iProfileData ); + GSSIPProfileUtil::CopyServerSettingsToTempStructL( + profile, KSIPOutboundProxy, iProfileData.iProxy ); + GSSIPProfileUtil::CopyServerSettingsToTempStructL( + profile, KSIPRegistrar, iProfileData.iRegistrar ); + __GSLOGSTRING("CGSSIPModel::CopyToProfileDataStructL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::FillDataStructWithDefaultValsL +// Fills the data structures fields with default values +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::FillDataStructWithDefaultValsL() + { + __GSLOGSTRING("CGSSIPModel::FillDataStructWithDefaultValsL Start" ) + HBufC* providerName = StringLoader::LoadLC( R_QTN_DEF_PROFILE_NAME ); + iProfileData.iProviderName = providerName->Des(); + CleanupStack::PopAndDestroy( providerName ); + + iProfileData.iID = KUnknownProfileIndex; + iProfileData.iAPIndex = KDefaultIAP; + iProfileData.iSNAPIndex = KDefaultSNAP; + iProfileData.iUsername = KNullDesC; + iProfileData.iCompression = KDefaultCompression; + iProfileData.iRegistrationMode = KDefaultRegistration; + iProfileData.iSecurity = KDefaultSecurity; + + // Get the supported profile types + RArray typeArray; + CleanupClosePushL( typeArray ); + iEngine->SupportedProfileTypesL( typeArray ); + TInt count = typeArray.Count(); + // Leave if no supported profiles found. + if ( count == KErrNone ) + { + User::Leave( KErrNotFound ); + } + // Find default profile type. + iProfileData.iServiceProfile = typeArray[0]; + for ( TInt i = 0; i < count; i++ ) + { + if ( typeArray[i].iSIPProfileClass == TSIPProfileTypeInfo::EInternet ) + { + iProfileData.iServiceProfile = typeArray[i]; + i = count; + } + } + + CleanupStack::PopAndDestroy( &typeArray ); + + iProfileData.iProxy.iAddress = KNullDesC; + iProfileData.iProxy.iRealm = KNullDesC; + iProfileData.iProxy.iUsername = KNullDesC; + + iProfileData.iProxy.iLooseRouting = KDefaultLooseRouting; + iProfileData.iProxy.iPassword = KNullDesC; + iProfileData.iProxy.iPortNumber = KDefaultPortNumber; + iProfileData.iProxy.iTransportProtocol = KDefaultTranspProtocol; + + // Initial registrar server settings are the same than with proxy + iProfileData.iRegistrar = iProfileData.iProxy; + iProfileData.iRegistrar.iLooseRouting = EGSLooseRoutingOff; + + // Private user identity + iProfileData.iProxy.iPrivateIdentity = KNullDesC; + iProfileData.iRegistrar.iPrivateIdentity = KNullDesC; + __GSLOGSTRING("CGSSIPModel::FillDataStructWithDefaultValsL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::Profile +// Returns profile based on the ID +// ----------------------------------------------------------------------------- +// +CSIPManagedProfile* CGSSIPModel::Profile( TUint aId ) + { + __GSLOGSTRING("CGSSIPModel::Profile" ) + __GSLOGSTRING1("CGSSIPModel::Profile aId: %d", aId) + TInt i( 0 ); + CSIPManagedProfile* profile = NULL; + + TInt count = iProfiles->Count(); + TUint32 profileId( 0 ); + TInt err( KErrNone ); + for ( i = 0; i < count; i++ ) + { + err = iProfiles->At( i )->GetParameter( KSIPProfileId,profileId ); + if ( profileId == aId && !err ) + { + profile = iProfiles->At( i ); + i = count; + } + } + + return profile; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CheckForModificationsL +// Checks for the modifications on the active profile +// ----------------------------------------------------------------------------- +// +TBool CGSSIPModel::CheckForModificationsL() + { + __GSLOGSTRING("CGSSIPModel::CheckForModificationsL " ) + CSIPManagedProfile* profile = Profile( iProfileData.iID ); + + TBool modifs = + GSSIPProfileUtil::ProfileModificationsL( profile, iProfileData ); + modifs |= GSSIPProfileUtil::ServerModificationsL( + profile, KSIPOutboundProxy, iProfileData.iProxy ); + modifs |= GSSIPProfileUtil::ServerModificationsL( + profile, KSIPRegistrar, iProfileData.iRegistrar ); + + return modifs; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CopyDataToProfileL +// Copies data from temporary settings structure to profile +// ----------------------------------------------------------------------------- +// +CSIPManagedProfile* CGSSIPModel::CopyDataToProfileL() + { + __GSLOGSTRING("CGSSIPModel::CopyDataToProfileL " ) + CSIPManagedProfile* profile = NULL; + + // Get profile based on ID + if ( iProfileData.iID == KUnknownProfileIndex ) + { + profile = iNewProfile; + } + else + { + profile = Profile( iProfileData.iID ); + } + + GSSIPProfileUtil::CopyProfileAttributesL( profile, iProfileData ); + GSSIPProfileUtil::CopyServerAttributesL( + profile, KSIPOutboundProxy, iProfileData.iProxy ); + GSSIPProfileUtil::CopyServerAttributesL( + profile, KSIPRegistrar, iProfileData.iRegistrar ); + + return profile; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ReplaceProfileL +// Replaces one profile with another on the array; only cloned profiles +// should be replaced +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ReplaceProfileL( + TInt aId, + CSIPManagedProfile* aProfile ) + { + __GSLOGSTRING("CGSSIPModel::ReplaceProfileL Start " ) + __GSLOGSTRING1("CGSSIPModel::ReplaceProfileL aId: %d", aId) + TInt i( 0 ); + CSIPManagedProfile* origProfile = NULL; + TUint32 profileId( 0 ); + TInt err( KErrNone ); + for ( i = 0; i < iProfiles->Count(); i++ ) + { + err = iProfiles->At( i )->GetParameter( KSIPProfileId, profileId ); + if ( TUint( aId ) == profileId && !err ) + { + origProfile = iProfiles->At( i ); + } + } + + User::LeaveIfNull( origProfile ); + GSSIPProfileUtil::CopyProfileL( aProfile, origProfile ); + __GSLOGSTRING("CGSSIPModel::ReplaceProfileL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ReadProfileListFromEngineSafeL +// Reads profile list from the engine; if reading fails, keeps the old list +// safe and returns it +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ReadProfileListFromEngineSafeL() + { + __GSLOGSTRING("CGSSIPModel::ReadProfileListFromEngineSafeL Start" ) + // To prevent complete disaster it we'll save the pointer of the old array + CArrayPtrFlat* profiles = iProfiles; + iProfiles = 0; + TRAPD( err, ReadArrayFromEngineL() ); + + if ( err ) + { + // Yes, problems with re-reading profiles; use existing + // array + if ( iProfiles ) + { + iProfiles->ResetAndDestroy(); + delete iProfiles; + } + iProfiles = profiles; + User::Leave( err ); + } + else + { + // No problems; delete backup array + profiles->ResetAndDestroy(); + delete profiles; + } + __GSLOGSTRING("CGSSIPModel::ReadProfileListFromEngineSafeL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::UpdateListCmd +// Calls app ui to udpate the lists; might also trigger exit +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::UpdateListCmd( + TInt aCmd ) + { + __GSLOGSTRING("CGSSIPModel::UpdateListCmd" ) + TRAP_IGNORE( iAppUi->HandleCommandL( aCmd ) ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::ResetAndDestroy +// For deleting RPointerArray in case of leave +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::ResetAndDestroy( + TAny* aPointerArray ) + { + __GSLOGSTRING("CGSSIPModel::ResetAndDestroy" ) + RPointerArray* array = + static_cast*>( aPointerArray ); + array->ResetAndDestroy(); + array->Close(); + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CloseAndDestroy +// For deleting RArray in case of leave +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CloseAndDestroy( + TAny* aArray ) + { + __GSLOGSTRING("CGSSIPModel::CloseAndDestroy" ) + RArray* array = + static_cast*>( aArray ); + array->Close(); + delete array; + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CheckDuplicateNameL +// Checks if duplicate named sip profiles. Renames if same. +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CheckDuplicateNameL( TInt32 aProfileId, TDes& aName, + TBool aCreatedFromExistingProfile) + { + __GSLOGSTRING("CGSSIPModel::CheckDuplicateNameL Start" ) + HBufC8* oldName = EscapeUtils::ConvertFromUnicodeToUtf8L( aName ); + CleanupStack::PushL( oldName ); + + HBufC8* newName = + HBufC8::NewLC( oldName->Length() + KMaxDuplicatePostfixLength ); + newName->Des().Copy( oldName->Des() ); + + // Create 16-bit TBuf for comparison and convert its digit type + TBuf + oldNameBuf; + oldNameBuf.Copy(aName); + AknTextUtils::ConvertDigitsTo(oldNameBuf, EDigitTypeWestern); + + TInt count( iProfiles->Count() ); + for( TInt n = 0; n < count; n++ ) + { + TUint32 id( KErrNone ); + iProfiles->At( n )->GetParameter( KSIPProfileId, id ); + + const TDesC8* existingName; + iProfiles->At( n )->GetParameter( KSIPProviderName, existingName ); + + // Create 16-bit TBuf for comparison and convert its digit type + HBufC* tempExistingName16 = + EscapeUtils::ConvertToUnicodeFromUtf8L( *existingName ); + CleanupStack::PushL( tempExistingName16 ); + TBuf + existingNameBuf; + existingNameBuf.Copy(tempExistingName16->Des()); + CleanupStack::PopAndDestroy( tempExistingName16 ); + AknTextUtils::ConvertDigitsTo(existingNameBuf, EDigitTypeWestern); + + if ( id != aProfileId && !existingNameBuf.Compare( oldNameBuf ) ) + { + TBool isUnique( EFalse ); + + for( TInt i = 1; !isUnique; i++ ) + { + TBool found( EFalse ); + + TBuf postFix; + postFix.Append( KOpenParenthesis() ); + postFix.AppendNum( ( TInt64 )i ); + postFix.Append( KClosedParenthesis() ); + + newName->Des().Copy( *oldName ); + newName->Des().Append( postFix ); + + // Convert back to 16-bit descriptor + // because of possible Chinese/Japanese variant. + HBufC* newName16 = + EscapeUtils::ConvertToUnicodeFromUtf8L( newName->Des() ); + CleanupStack::PushL( newName16 ); + + TInt length = newName16->Length(); + if ( length > KMaxSIPProviderNameLength ) + { + TInt deleteLength = length - KMaxSIPProviderNameLength; + TInt pos = length - postFix.Length() - deleteLength; + newName16->Des().Delete( pos, deleteLength ); + + HBufC8* newName8 = EscapeUtils::ConvertFromUnicodeToUtf8L( + newName16->Des() ); + newName->Des().Copy( newName8->Des() ); + delete newName8; + } + + // Create 16-bit TBuf for comparison and convert its digit type + TBuf + newName16Buf; + newName16Buf.Copy(newName16->Des()); + AknTextUtils::ConvertDigitsTo(newName16Buf, EDigitTypeWestern); + CleanupStack::PopAndDestroy( newName16 ); + + for( TInt m = 0; m < count && !found; m++ ) + { + TUint32 mid( KErrNone ); + iProfiles->At( m )->GetParameter( KSIPProfileId, mid ); + + iProfiles->At( m )->GetParameter( + KSIPProviderName, existingName ); + + // Convert the digit type again in existingNameBuf + HBufC* temporaryExistingName16 = + EscapeUtils::ConvertToUnicodeFromUtf8L( *existingName ); + CleanupStack::PushL( temporaryExistingName16 ); + existingNameBuf.Copy(temporaryExistingName16->Des()); + CleanupStack::PopAndDestroy( temporaryExistingName16 ); + AknTextUtils::ConvertDigitsTo(existingNameBuf, EDigitTypeWestern); + + if( mid != aProfileId && + !existingNameBuf.Compare( newName16Buf ) ) + { + found = ETrue; + } + } + + if( !found ) + { + isUnique = ETrue; + } + } + } + } + + HBufC* tempName = + EscapeUtils::ConvertToUnicodeFromUtf8L( newName->Des() ); + CleanupStack::PushL( tempName ); + + if (aCreatedFromExistingProfile) + { + // Convert numbers to language specific numbers. + TPtr ptr = tempName->Des(); + AknTextUtils::LanguageSpecificNumberConversion( ptr ); + } + + aName.Copy( tempName->Des() ); + CleanupStack::PopAndDestroy( tempName ); + + CleanupStack::PopAndDestroy( newName ); + CleanupStack::PopAndDestroy( oldName ); + __GSLOGSTRING("CGSSIPModel::CheckDuplicateNameL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CheckProfileForDeleteL +// Checks if profile can be deleted. +// ----------------------------------------------------------------------------- +// +void CGSSIPModel::CheckProfileForDeleteL( + TInt aIndex, TBool& aIsUse, TBool& aDefault, TBool& aLocked ) + { + __GSLOGSTRING("CGSSIPModel::CheckProfileForDeleteL Start" ) + CSIPManagedProfile* profile = iProfiles->At( aIndex ); + + if ( profile ) + { + profile->GetParameter( KSIPProfileRegistered, aIsUse ); + profile->GetParameter( KSIPDefaultProfile, aDefault ); + profile->GetParameter( KSIPProfileLocked, aLocked ); + } + __GSLOGSTRING("CGSSIPModel::CheckProfileForDeleteL End" ) + } + +// ----------------------------------------------------------------------------- +// CGSSIPModel::CheckIsProfileInUseL +// Checks if profile is used. +// ----------------------------------------------------------------------------- +// +TBool CGSSIPModel::CheckIsProfileInUseL( TUint32 aProfileId ) + { + __GSLOGSTRING("CGSSIPModel::CheckIsProfileInUseL" ) + TBool inUse( EFalse ); + CSIPManagedProfile* profile = Profile( aProfileId ); + + if ( profile ) + { + profile->GetParameter( KSIPProfileRegistered, inUse ); + } + + return inUse; + } + +// End of File +