terminalsecurity/SCP/SCPHistoryPlugin/src/SCPSpecificStringsPlugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 16:04:06 +0300
branchRCL_3
changeset 25 b183ec05bd8c
parent 0 b497e44ab2fc
child 26 19bba8228ff0
permissions -rw-r--r--
Revision: 201033 Kit: 201035

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


// INCLUDE FILES
#include <e32base.h>
#include <e32std.h>
#include <ecom/implementationproxy.h>
#include <SCPParamObject.h>

#include "SCPSpecificStringsPlugin.h"
#include <scphistorypluginlang.rsg>
#include "SCP_IDs.h"
#include <featmgr.h>
#include <SCPServerInterface.h>
// ============================= LOCAL FUNCTIONS  =============================

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

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::NewL
// Two-phased contructor
// (static, may leave)
// Status : Approved
// ----------------------------------------------------------------------------
//
CSCPSpecificStringsPlugin* CSCPSpecificStringsPlugin::NewL()
    {
	CSCPSpecificStringsPlugin* self = new ( ELeave ) CSCPSpecificStringsPlugin();
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	
    Dprint ( ( _L( "( 0x%x ) CSCPSpecificStringsPlugin::NewL()" ), self ) );

    return self;
    }

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::CSCPSpecificStringsPlugin
// Constructor
// Status : Approved
// ----------------------------------------------------------------------------
//
CSCPSpecificStringsPlugin::CSCPSpecificStringsPlugin()
   
    {
    Dprint ( ( _L( "CSCPSpecificStringsPlugin::CSCPSpecificStringsPlugin()" ) ) );
    return;
    }

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::ConstructL
// 2nd phase construction
// (may leave)
// Status : Approved
// ----------------------------------------------------------------------------
//
void CSCPSpecificStringsPlugin::ConstructL()
    {
    
    FeatureManager::InitializeLibL();
	if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements))
	{
    	FeatureManager::UnInitializeLib();
   		User::Leave( KErrNotSupported );
  	}
   	FeatureManager::UnInitializeLib();
    return;
    }
    
// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::HandleEvent
// 
// 
// Status : Approved
// ----------------------------------------------------------------------------
//    
void CSCPSpecificStringsPlugin :: HandleEventL( TInt aID, CSCPParamObject& aParam,CSCPParamObject& aOutParam )
	{	
		
	if ( iFs == NULL )
	    {
	    User::Leave(KErrGeneral);
	    }

	// check for Case
	switch ( aID )
	    {
		case ( KSCPEventValidate ) :
    		{   		
			TBool specificstringscheck;
			
			// Get params
			CSCPParamObject& config = iEventHandler->GetParameters();
			
			// Check if validation is required.
			if ( config.Get( ( RTerminalControl3rdPartySession::EPasscodeCheckSpecificStrings), 
				  specificstringscheck ) !=  KErrNone )
				   specificstringscheck = EFalse;

			 if ( specificstringscheck )
			    {
			 	// Check for specific strings			 	
			 	
				// Get the configFile's path.
				// If this fails, there is something badly wrong(Private folder is not there)
				TInt errSCF = SetConfigFile ();
				if (errSCF != KErrNone)
				    {
					break; // Break out from Case!
				    }
			 	
			 	// Get the password from the paramObject
	     		TBuf<KSCPPasscodeMaxLength> securitycode;
	            if ( aParam.Get( KSCPParamPassword, securitycode ) != KErrNone )
                    {
                	// Nothing to do anymore
                   	Dprint( (_L("CSCPSpecificStringsPlugin::HandleEvent()\
                   	ERROR: KSCPEventPasswordChanged/KSCPParamPassword is  != KErrNone") ));
					break; // Break out from the Case!;
                    }			 	
			 	
			 	TBool forbiddensecuritycode = EFalse;
			 	
			 	TInt errCSS = CheckSpecificStrings ( securitycode, forbiddensecuritycode );
			 	if (errCSS != KErrNone)
				    {
					break; // Break out from Case!
    				}
			 	
			 	if ( forbiddensecuritycode )
			    	{
			    	    aOutParam.Set( KSCPParamStatus, KErrSCPInvalidCode );
			    	    Dprint ( ( _L( "EDeviceLockDisallowSpecificStrings Failed" ) ) );
			    	    aOutParam.AddtoFailedPolices(EDeviceLockDisallowSpecificStrings);
			 	    }			 	    		
					
			    } // end of specificstringscheck

			break;
		    } // End of KSCPEventValidate

	    case ( KSCPEventRetrieveConfiguration ):
	        {
	        // This event is sent when a client wishes to retrieve the value for the given parameter.
	        // None of the parameters, which handle the string-buffer cannot be retrieved by anyone,
	        // so we'll return KErrNotSupported. Note that EPasscodeCheckSpecificStrings is OK to get.
	        
	        // Get the ID from the paramObject   
	        TInt paramID = -1;    
			if ( aParam.Get( KSCPParamID, paramID ) != KErrNone )
			    {
				// Nothing to do anymore
				break;
    			}   
			    
			if ( ( paramID ==  RTerminalControl3rdPartySession::EPasscodeDisallowSpecific )
				||  ( paramID ==  RTerminalControl3rdPartySession::EPasscodeAllowSpecific)
				||  ( paramID ==  RTerminalControl3rdPartySession::EPasscodeClearSpecificStrings) )
			    {
	                Dprint ( ( _L( "CSCPSpecificStringsPlugin::HandleEvent():\
	                    Get not supported for %d" ), paramID ) );
	                aOutParam.Set( KSCPParamStatus, KErrNotSupported );
	            }
	        break;
	        }

		// same for All plugins
		case ( KSCPEventConfigurationQuery ):
    		{   		
			TInt paramID = -1; 

			// Get the ID from the paramObject      
			if ( aParam.Get( KSCPParamID, paramID ) != KErrNone )
			    {
				// Nothing to do anymore
				break;
			    }            

			if ( paramID == (RTerminalControl3rdPartySession::EPasscodeCheckSpecificStrings)
				||  paramID ==  (RTerminalControl3rdPartySession::EPasscodeDisallowSpecific)
				||  paramID ==  (RTerminalControl3rdPartySession::EPasscodeAllowSpecific)
				||  paramID ==  (RTerminalControl3rdPartySession::EPasscodeClearSpecificStrings) )
			    {
				TInt retStatus = KErrNone;
				
			    if ( paramID != RTerminalControl3rdPartySession::EPasscodeCheckSpecificStrings )
			        {
        		    // Set the storage attribute, so the server won't save the value,
        		    // we'll do it ourselves.
        			aOutParam.Set( KSCPParamStorage, KSCPStoragePrivate );			        
			        }

				switch ( paramID )
				    {
					case ( RTerminalControl3rdPartySession::EPasscodeCheckSpecificStrings ):
					    {
						// 1015				
						TInt paramValue;
						if ( (aParam.Get( KSCPParamValue, paramValue ) != KErrNone) ||
							 ( paramValue < 0 ) || 	( paramValue > 1 ) ) 
						       retStatus = KErrArgument;
						
					    break;
					    }
					
					// 1016
					// Handle param change for strings to block
					case ( RTerminalControl3rdPartySession::EPasscodeDisallowSpecific ):
					    {
						// Get the params value's length
						// If param length is not correct, there's something very wrong. out
						TInt paramlength = aParam.GetParamLength( KSCPParamValue );
						if ( paramlength <= 0)
						    {
							retStatus = KErrArgument;
							break; // from case!
						    }

						HBufC* paramvaluebuf = NULL;
						TRAPD( err, paramvaluebuf = HBufC::NewL( paramlength ) );
						if ( err != KErrNone )
						    {
						    retStatus = err;
						    break;
						    }
						    
						TPtr paramptr = paramvaluebuf->Des();
						aParam.Get( KSCPParamValue, paramptr );

						// Check for basic test
						if ( IsNotValidWord ( paramptr ) )
						    {
							retStatus = KErrArgument;
							delete paramvaluebuf;
							break;
    						}
    						
						// Send them to parser and store them
						TInt errgPS = KErrNone;
						TRAPD( err2, errgPS = ParseAndStoreL( paramptr ) );
						if ( err2 != KErrNone )
						    {
						    errgPS = err2;
						    }
						
						delete paramvaluebuf;
						
						if (errgPS != KErrNone)
						    {
							if (errgPS == KErrArgument)
							    {
								retStatus = KErrArgument;
								break; // from case!
							    }	
							break; // Break out.
						    } 
					    break;
					    }
					

					// 1017
					// Handle param change for strings exclude from the list
					case ( RTerminalControl3rdPartySession::EPasscodeAllowSpecific ):
					    {
	
						// Get the params value's length
						// If param length is not correct, there's something very wrong. out
						TInt paramlength = aParam.GetParamLength( KSCPParamValue );
						if ( paramlength <= 0)
						    {
							retStatus = KErrArgument;
							break; // from case!
						    }
																		
						HBufC* paramvaluebuf = NULL;
						TRAPD( err, paramvaluebuf = HBufC::NewL( paramlength ) );
						if ( err != KErrNone )
						    {
						    retStatus = err;
						    break;
						    }
						    
						TPtr paramptr = paramvaluebuf->Des();
						aParam.Get( KSCPParamValue, paramptr );

						// Check for basic test
						if ( IsNotValidWord ( paramptr ) )
						    {
							retStatus = KErrArgument;
							delete paramvaluebuf;
							break;
						    }
						    
						// Send the word to remover and gets them off the list
						TInt errgPR = KErrNone;
						TRAPD( err2, errgPR = ParseAndRemoveL( paramptr ) );
						if ( err2 != KErrNone )
						    {
						    errgPR = err2;
						    }
						
						delete paramvaluebuf;
						
						if (errgPR != KErrNone)
						    {
							if (errgPR == KErrArgument)
							    {
							    retStatus = KErrArgument;
								break; // from case!
							    }
	
							break; // Break out.
						    } 												
						
					    break;
					    }												
					
					case ( RTerminalControl3rdPartySession::EPasscodeClearSpecificStrings ):
					    {					
						// 1018, Flush the config file

					    TRAP_IGNORE( FlushConfigFileL() );
						break;
					    }							
    				} // End of switch                          

				aOutParam.Set( KSCPParamStatus, retStatus );
			    }
			break;
		    } //End of KSCPEventConfigurationQuery Case

        case ( KSCPEventReset ):
              {
              // Reset the configuration for this plugin.
              TRAP_IGNORE( FlushConfigFileL() );
              
              break;
              }

	} // End of  switch ( aID )
	}

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::SetEventHandler
// SetEventHandler
// 
// Status : Approved
// ----------------------------------------------------------------------------
//    
void CSCPSpecificStringsPlugin::SetEventHandler( MSCPPluginEventHandler* aHandler )
	{
	iEventHandler = aHandler;
	
	iFs = &(iEventHandler->GetFsSession());
	}	

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::~CSCPSpecificStringsPlugin
// Destructor
// Status : Approved
// ----------------------------------------------------------------------------
//
CSCPSpecificStringsPlugin::~CSCPSpecificStringsPlugin()
    {
	Dprint( (_L("CSCPSpecificStringsPlugin::~CSCPSpecificStringsPlugin()") ));
    
	iRf.Close();   
        	
	return;
    }

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::SetConfigFile
// SetConfigFile
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::SetConfigFile()
    {	
	Dprint( (_L("CSCPSpecificStringsPlugin::SetConfigFile()") ));
	TRAPD( err, iEventHandler->GetStoragePathL( iCfgFilenamepath ) );
	if ( err != KErrNone )
        {
		Dprint( (_L("CSCPSpecificStringsPlugin::SetConfigFile:\
		ERROR: Failed to get storage path: %d"), err ));             
		return err;
	    }
	iCfgFilenamepath.Append( KConfigFileSpecific );
	return err;
    }

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::CheckSpecificStrings
// CheckSpecificStrings
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::CheckSpecificStrings( TDes& aSecuritycode, 
													  TBool& aForbiddenSecurityCode )
    {
	Dprint( (_L("CSCPSpecificStringsPlugin::CheckSpecificStrings()") ));
	// Default is not blocklistedword
	aForbiddenSecurityCode = EFalse;
	
	// get GetSpecificStringsArray
	CDesCArrayFlat*  array = new CDesCArrayFlat(1);
	TInt err = KErrNone;
	
	if ( array == NULL )
	    {
	    err = KErrNoMemory;
	    }
	else
	    {
	    TRAPD( err2, err = GetSpecificStringsArrayL( *array ) );
	    if ( err2 != KErrNone )
	        {
	        err = err2;
	        }
	    }
	
	if (err != KErrNone)
	    {
		// Kill local array
		if ( array != NULL )
		    {
		    array->Reset();    
		    delete array;
		    }
		    		
		return err;
	    }

	// check for match
	TBuf<KSCPPasscodeMaxLength> arrayItem;
	// We use the uppercase version of the given string while checking
	TBuf<KSCPPasscodeMaxLength> secCodeBuf;
	secCodeBuf = aSecuritycode;
	secCodeBuf.UpperCase();

	// Set the historyobject
	for (TInt i=0; i < array->Count(); i++)
    	{
		arrayItem.Zero();
		arrayItem = array->MdcaPoint(i);
		arrayItem.UpperCase();
		// Check if this string causes the password to be invalid
		// the strings are matched by a case-insensitive substring match.
		if ( secCodeBuf.Find( arrayItem ) != KErrNotFound )
		    {
			aForbiddenSecurityCode = ETrue;
			break; // Out from for
		    }
    	}
    	
	// Kill local array
	array->Reset();
	delete array;
	return err; 
    }

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::ParseAndStoreL
// ParseAndStore ForbiddenSecurityCodes
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::ParseAndStoreL( TDes& aForbiddenSecurityCodes )
    {
	Dprint( (_L("CSCPSpecificStringsPlugin::ParseAndStore()") ));
	// Set The file environment
	TInt errSC = SetConfigFile ();
	if (errSC != KErrNone) return errSC;
	

	// Make array for data
	CDesCArrayFlat*  array = new (ELeave) CDesCArrayFlat(1);
	CleanupStack::PushL( array );

	// Read the previous wordlist.
	// Reading might fall for NotFound, don't care
	TInt errGS = GetSpecificStringsArrayL( *array );
	
	if (errGS != KErrNone && errGS != KErrNotFound  )
	    {
		// Kill local array
		array->Reset();
		CleanupStack::PopAndDestroy( array );
		return errGS;
	    }
		
	// Parse the ; separated values into array
	TLex16 lex (aForbiddenSecurityCodes);
	lex.Mark();
	while(!lex.Eos())
	    {
		while(lex.Peek() != ';' && !lex.Eos() ) lex.Inc();

		array->AppendL(lex.MarkedToken());
		lex.Inc();
		lex.Mark();
		}
		
		
	// Check for duplicates!
	RemoveDuplicateWords( *array );

	// Store Array
	// Make the ParamObject
	CSCPParamObject* forbiddensecuritycodeobject = CSCPParamObject::NewL();
	CleanupStack::PushL( forbiddensecuritycodeobject );
	TBuf<KSCPPasscodeMaxLength> arrayItem;

	// Append the Data 
	for (TInt i=0 ; i < array->Count(); i++)
		{
		arrayItem =  array->MdcaPoint(i);
		forbiddensecuritycodeobject->Set( KSpecificStringsParamBase+i,arrayItem);
		arrayItem.Zero();
		}

	// Set the Counter param
	forbiddensecuritycodeobject->Set( KSpecificStringsCounterParamID,array->Count());
			
	//Write
	TRAPD( err, forbiddensecuritycodeobject->WriteToFileL( iCfgFilenamepath, iFs ) );
	if (  err != KErrNone  )
	    {
		Dprint( (_L("CSCPSpecificStringsPlugin::ParseAndStore(): WARNING:\
		failed to write plugin configuration: %d"), err )); 
    	}

    CleanupStack::PopAndDestroy( forbiddensecuritycodeobject );
    
    // Kill the array
	array->Reset();
	CleanupStack::PopAndDestroy( array );
    
	return err;
}


// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::FlushConfigFileL
// FlushConfigFile
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::FlushConfigFileL()
    {
	Dprint( (_L("CSCPSpecificStringsPlugin::FlushConfigFile()") ));

	SetConfigFile();

	CFileMan* fileMan = CFileMan::NewL( *iFs );
	CleanupStack::PushL( fileMan );

	TInt ret= fileMan->Delete( iCfgFilenamepath, 0 );

	CleanupStack::PopAndDestroy( fileMan ); // fileMan
	return ret;
    }


// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::GetSpecificStringsArrayL
// Reads the historyconfig file and retrieves the forbidden data
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::GetSpecificStringsArrayL( CDesCArrayFlat& array )
{   

	Dprint( (_L("CSCPSpecificStringsPlugin::GetSpecificStringsArray()") ));
	
	 TBuf<KSCPPasscodeMaxLength> arrayItem;
	 TInt counter;
	 TInt err = KErrNone;
	 
	// Make the ParamObject
	CSCPParamObject* forbiddensecuritycodeobject = CSCPParamObject::NewL();
	CleanupStack::PushL( forbiddensecuritycodeobject );

	TRAP( err, forbiddensecuritycodeobject->ReadFromFileL( iCfgFilenamepath, iFs ) );
	if ( err != KErrNone ) 
	{
			// Reading from history fails. 
			Dprint( (_L("CSCPHistoryPlugin::GetHistoryArray():\
			failed to read plugin configuration: %d"), err )); 
			CleanupStack::PopAndDestroy( forbiddensecuritycodeobject );
			return err;
	}

	// Get the historyCount
	forbiddensecuritycodeobject->Get(KSpecificStringsCounterParamID,counter);

	// Loop them into array
	for (TInt i = 0 ; i < counter ; i ++)
	{
		forbiddensecuritycodeobject->Get(KSpecificStringsParamBase+i,arrayItem);
		array.AppendL(arrayItem);
		arrayItem.Zero();
	}

    CleanupStack::PopAndDestroy( forbiddensecuritycodeobject );
	return err;
	
}

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::IsNotValidWord
// Checks wheater the given buf contains any illegal chars like ., <space>
// ; char is granted due to a delimiter role. ETrue means buf is no good!
// Status : Approved
// ----------------------------------------------------------------------------
//
TBool CSCPSpecificStringsPlugin::IsNotValidWord ( TDes& aForbiddenSecurityCodes )
{
	
	Dprint( (_L("CSCPSpecificStringsPlugin::IsNotValidWord()") ));
	// If so, there is a problem ETrue!!
	TBool ret;
	TChar now,previous;		// at hand & prevous char
	ret = EFalse;
	now = 0;
	previous = 0;
	
	// Go through the word
	for (TInt i=0; i < aForbiddenSecurityCodes.Length(); i++)
	{
		
		// Get the current Char to examine
		now =  static_cast<TChar>( aForbiddenSecurityCodes[i] );
		// And the previous
		if ( i >= 1 ) 
		    {
		    previous = static_cast<TChar>( aForbiddenSecurityCodes[i-1] );
		    }
	
		// Check for Sapce!
		if ( now.IsSpace() || now < 1 || now > 126 )
		{
			// Space or Invalid character found, bad, out!
			ret = ETrue;
			break;
			
		}
		
		
		/*if (! now.IsAlphaDigit() )
		{
				// Was not alphadigit. Anyhow ; must come through
				if ( now != ';'  )
				{
					// bad, out!
					ret = ETrue;
					break;
				}
				
				if ( now == ';' && previous == ';'  )
				{
					// bad, out!
					ret = ETrue;
					break;
				}
		
		}*/

	} // EOFor
	return ret;
}

// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::RemoveDuplicateWords
// Checks wheater there are duplicate words in the array, removes them!
// Status : Approved
// ----------------------------------------------------------------------------
//
void CSCPSpecificStringsPlugin::RemoveDuplicateWords( CDesCArrayFlat& array )
{
	Dprint( (_L("CSCPSpecificStringsPlugin::RemoveDuplicateWords()") ));
	// check for match
	TBuf<KSCPPasscodeMaxLength> arrayItemAt;
	TBuf<KSCPPasscodeMaxLength> arrayItemNext;
	TInt arraycounter =0;
	while (arraycounter < array.Count())
	{
		// Get the item from array.
		arrayItemAt =  array.MdcaPoint(arraycounter);	
		
		// search the rest for match
		for (TInt n = 1 + arraycounter ; n < array.Count() ; n++)
		{		
			arrayItemNext = array.MdcaPoint(n);
			if (arrayItemAt.Compare(arrayItemNext) == KErrNone)
			{
				// Delete 
				array.Delete(n);
				n--; 
				
			}
		}
		arraycounter++;
	
	}

}


// ----------------------------------------------------------------------------
// CSCPSpecificStringsPlugin::ParseAndRemoveL
// Parses And Removes ForbiddenSecurityCodes from ini file
// Status : Approved
// ----------------------------------------------------------------------------
//
TInt CSCPSpecificStringsPlugin::ParseAndRemoveL( TDes& aForbiddenSecurityCodes )
    {
	Dprint( (_L("CSCPSpecificStringsPlugin::ParseAndRemoveL()") ));
	// Set The file environment
	TInt errSC = SetConfigFile ();
	if (errSC != KErrNone) return errSC;


	// Make array for data
	CDesCArrayFlat*  arraycurrent = new (ELeave) CDesCArrayFlat(1);
	CleanupStack::PushL( arraycurrent );
	
	// Read the previous wordlist.
	// Reading might fall for NotFound, get out, nothing to do.
	if ( GetSpecificStringsArrayL( *arraycurrent ) == KErrNotFound  )
	    {
	    arraycurrent->Reset();
	    CleanupStack::PopAndDestroy( arraycurrent );
	    return KErrNone;
	    }

	// Make array for data for wordlist to be removed
	CDesCArrayFlat*  arrayremoved = new (ELeave) CDesCArrayFlat(1);
	CleanupStack::PushL( arrayremoved );
	
	// Parse the ; separated values into array from given wordlist
	TLex16 lex (aForbiddenSecurityCodes);
	lex.Mark();
	while(!lex.Eos())
	{
		while(lex.Peek() != ';' && !lex.Eos() ) lex.Inc();

			arrayremoved->AppendL(lex.MarkedToken());
			lex.Inc();
			lex.Mark();
		}
		
	// Remove possible duplicates in wordlist
	RemoveDuplicateWords( *arrayremoved );
	
	// Make the ParamObject
	CSCPParamObject* forbiddensecuritycodeobject = CSCPParamObject::NewL();
	CleanupStack::PushL( forbiddensecuritycodeobject );
	
	TBuf<KSCPPasscodeMaxLength> arrayItemcurrent;
	TBuf<KSCPPasscodeMaxLength> arrayItemremove;
	TInt addedcounter,removedcounter,currentItemCounter,err;
	TBool itemremovedexlude,itemremovecurrent;
	itemremovedexlude = EFalse;
	itemremovecurrent = EFalse;
	addedcounter = 0;
	removedcounter = 0;
	err = 0;
	
	// Remember the current situation before exluding.
	currentItemCounter = arraycurrent->Count();
	
	// Loop the main array
	while (addedcounter < arraycurrent->Count())
	{
		// Get the item from current spesific wordarray.
		arrayItemcurrent =  arraycurrent->MdcaPoint(addedcounter);	
		while (removedcounter < arrayremoved->Count())
		{
			
			arrayItemremove =  arrayremoved->MdcaPoint(removedcounter);
			if(arrayItemcurrent.CompareC(arrayItemremove) == KErrNone)
			{
				arrayremoved->Delete(removedcounter);
				arraycurrent->Delete(addedcounter);
				itemremovedexlude = ETrue;
				itemremovecurrent = ETrue;
			}
			if (itemremovedexlude) itemremovedexlude = EFalse;
			else removedcounter++;
	
		}
	
		if (itemremovecurrent) itemremovecurrent = EFalse;
		else addedcounter++;
		removedcounter = 0;
	}
	
	// Check wheather there has been eny changes in the current array (removes)
	if (currentItemCounter != arraycurrent->Count() )
	    {
		// All of items were removed, flush the file
		if ( arraycurrent->Count() == 0 )
		    {
		    TRAP_IGNORE( FlushConfigFileL() );
		    }
		else
		    {
			// Reuse
			arrayItemcurrent.Zero();
			// Set the object with fixed array
			for (TInt n = 0; n < arraycurrent->Count() ; n++)
			{
				// Get the item from current spesific wordarray.
				arrayItemcurrent =  arraycurrent->MdcaPoint(n);	
				forbiddensecuritycodeobject->Set( KSpecificStringsParamBase+n,arrayItemcurrent);
			}
		
			// Set the Counter param
			forbiddensecuritycodeobject->Set( KSpecificStringsCounterParamID,arraycurrent->Count());

			//Write
			TRAP( err, forbiddensecuritycodeobject->WriteToFileL( iCfgFilenamepath, iFs ) );
			if (  err != KErrNone  )
			    {
				Dprint( (_L("CSCPSpecificStringsPlugin::ParseAndRemoveL(): WARNING:\
				failed to write plugin configuration: %d"), err )); 
			    }			
		    }		
	    }
	
	
	CleanupStack::PopAndDestroy( forbiddensecuritycodeobject );
	
	// Kill arrays
	arrayremoved->Reset();
	CleanupStack::PopAndDestroy( arrayremoved );
	
	arraycurrent->Reset();
	CleanupStack::PopAndDestroy( arraycurrent );			    
 
	return err;
    }
    
// End of File