secureswitools/swisistools/source/interpretsislib/expressionevaluator.cpp
changeset 0 ba25891c3a9e
child 34 741e5bba2bd1
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <iostream>
       
    19 #include <sstream>
       
    20 
       
    21 // User includes
       
    22 #include "sisexpression.h"
       
    23 #include "expressionevaluator.h"
       
    24 #include "sisstring.h"
       
    25 #include "is_utils.h"
       
    26 #include "errors.h"
       
    27 #include "symbiantypes.h"
       
    28 #include "stringutils.h"
       
    29 #include "rommanager.h"
       
    30 #include "configmanager.h"
       
    31 #include "sisfile.h"
       
    32 #include "sisregistryobject.h"
       
    33 #include "logger.h"
       
    34 #include "version.h"
       
    35 #include "is_utils.h"
       
    36 
       
    37 // ExpressionResult
       
    38 using namespace Utils;
       
    39 ExpressionResult::ExpressionResult(const std::wstring& aString)
       
    40 :   iType(EString), iString(&aString)
       
    41     {
       
    42     }
       
    43 
       
    44 
       
    45 ExpressionResult::ExpressionResult(TUint32 aInt)
       
    46 :   iType(EInt), iInt(aInt)
       
    47     {
       
    48     }
       
    49 
       
    50 
       
    51 TUint32 ExpressionResult::IntegerValue() const
       
    52     {
       
    53 	if (iType!=EInt)
       
    54 	    {
       
    55 		std::string error = "corrupt SIS file: expression corrupt in condition statement";
       
    56 		throw InvalidSis("",error,INVALID_SIS);
       
    57     	}
       
    58 
       
    59     return iInt;
       
    60     }
       
    61 
       
    62 
       
    63 bool ExpressionResult::BoolValue() const
       
    64     {
       
    65 	return bool(IntegerValue());
       
    66     }
       
    67 
       
    68 
       
    69 const std::wstring& ExpressionResult::StringValue() const
       
    70     {
       
    71 	if (iType!=EString)
       
    72 	    {
       
    73 		std::string error = "corrupt SIS file: expression corrupt in condition statement";
       
    74 		throw InvalidSis("",error,INVALID_SIS);
       
    75 	    }
       
    76 
       
    77     return *iString;
       
    78     }
       
    79 
       
    80 
       
    81 // ExpressionEvaluator
       
    82 
       
    83 ExpressionEvaluator::ExpressionEvaluator(ExpressionEnvironment& aEnvironment)
       
    84 :   iExpEnv(aEnvironment), iTempResult(false), iExpressionDepth(0)
       
    85     {
       
    86     }
       
    87 
       
    88 
       
    89 void ExpressionEvaluator::Require(const void *aPointer) const
       
    90     {
       
    91 	if (!aPointer)
       
    92 	    {
       
    93 		throw std::runtime_error("null pointer");
       
    94     	}
       
    95     }
       
    96 
       
    97 
       
    98 ExpressionResult ExpressionEvaluator::Evaluate(const CSISExpression* aExpression)
       
    99     {
       
   100 	Require(aExpression);
       
   101 	return Evaluate(*aExpression);
       
   102     }
       
   103 
       
   104 
       
   105 ExpressionResult ExpressionEvaluator::Evaluate(const CSISExpression& aExpression)
       
   106     {
       
   107 	if (++iExpressionDepth > KMaxExpressionDepth)
       
   108 	    {
       
   109 		iExpressionDepth=0;
       
   110 		std::string error = "SIS File expression too complex\n";
       
   111 		std::string x;
       
   112         //
       
   113 		throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED);
       
   114 	    }
       
   115 
       
   116 	switch (aExpression.Operator())
       
   117 	    {
       
   118 	case CSISExpression::EBinOpEqual:
       
   119 	case CSISExpression::EBinOpNotEqual:
       
   120 	case CSISExpression::EBinOpGreaterThan:
       
   121 	case CSISExpression::EBinOpLessThan:
       
   122 	case CSISExpression::EBinOpGreaterThanOrEqual:
       
   123 	case CSISExpression::EBinOpLessThanOrEqual:
       
   124         {
       
   125 		const ExpressionResult resultLeft = Evaluate( aExpression.LHS() );
       
   126 		const ExpressionResult resultRight = Evaluate( aExpression.RHS() );
       
   127         //
       
   128 	    switch (aExpression.Operator())
       
   129 	        {
       
   130 	    case CSISExpression::EBinOpEqual:
       
   131             iTempResult = ( resultLeft == resultRight );
       
   132             break;
       
   133 	    case CSISExpression::EBinOpNotEqual:
       
   134             iTempResult = ( resultLeft != resultRight );
       
   135             break;
       
   136 	    case CSISExpression::EBinOpGreaterThan:
       
   137             iTempResult = ( resultLeft > resultRight );
       
   138             break;
       
   139 	    case CSISExpression::EBinOpLessThan:
       
   140             iTempResult = ( resultLeft < resultRight );
       
   141             break;
       
   142 	    case CSISExpression::EBinOpGreaterThanOrEqual:
       
   143             iTempResult = ( resultLeft >= resultRight );
       
   144             break;
       
   145 	    case CSISExpression::EBinOpLessThanOrEqual:
       
   146             iTempResult = ( resultLeft <= resultRight );
       
   147             break;
       
   148             }
       
   149         //
       
   150 		break;
       
   151         }
       
   152     
       
   153     case CSISExpression::ELogOpAnd:
       
   154 		{
       
   155 		ExpressionResult tmp1 = Evaluate(aExpression.LHS());
       
   156 		ExpressionResult tmp2 = Evaluate(aExpression.RHS());
       
   157 		iTempResult = ExpressionResult(tmp1.BoolValue() && tmp2.BoolValue());
       
   158 		break;
       
   159 		}
       
   160 
       
   161 	case CSISExpression::ELogOpOr:
       
   162 		{
       
   163 		ExpressionResult tmp1 = Evaluate(aExpression.LHS());
       
   164 		if (tmp1.BoolValue())
       
   165     		{
       
   166 			iTempResult = ExpressionResult(true);
       
   167 	    	}
       
   168 		else
       
   169 		    {
       
   170 			iTempResult = ExpressionResult(Evaluate(aExpression.RHS())).BoolValue();
       
   171 		    }
       
   172 		break;
       
   173 		}
       
   174 
       
   175 	case CSISExpression::EUnaryOpNot:
       
   176 		iTempResult=!Evaluate(aExpression.RHS());
       
   177 		break;
       
   178 
       
   179 	case CSISExpression::EFuncAppProperties:
       
   180         {
       
   181         const TUint32 resultLeft = Evaluate( aExpression.LHS() ).IntegerValue();
       
   182         const TUint32 resultRight = Evaluate( aExpression.RHS() ).IntegerValue();
       
   183         //
       
   184 		iTempResult = iExpEnv.ApplicationProperty( resultLeft, resultRight );
       
   185 		break;
       
   186         }
       
   187 
       
   188 	case CSISExpression::EFuncDevProperties:
       
   189 		iTempResult = ExpressionResult(iExpEnv.Package(Evaluate(aExpression.RHS()).IntegerValue()));
       
   190 		break;
       
   191 
       
   192 	case CSISExpression::EFuncExists:
       
   193 		{
       
   194 		const CSISString& pS = aExpression.String();
       
   195 		if(pS.WasteOfSpace())
       
   196 			{
       
   197 			throw std::runtime_error("null pointer");
       
   198 			}
       
   199 
       
   200 		/**
       
   201 		 * CR1125 - Add Package Versions to SIS File Conditionals
       
   202 		 * 
       
   203 		 * If the CSISExpression CSISString has been prefixed with the argument string identifier stored within
       
   204 		 * KVersionFuncPrefix, the condition is considered to be a VERSION function call. The argument string
       
   205 		 * is then passed to PackageVersion() to query the SIS Registry and determine whether the version of
       
   206 		 * an installed package satisfies the presented condition. 
       
   207 		 */
       
   208 		if(pS.GetString().substr(0,KFuncVersionPrefix.length()) == KFuncVersionPrefix)
       
   209 			{
       
   210 			iTempResult = ExpressionResult(iExpEnv.PackageVersion(pS.GetString().substr(KFuncVersionPrefix.length())));
       
   211 			}
       
   212 		/**
       
   213 		 * Support for exact and equivalent device supported languages
       
   214 		 */
       
   215 		else if (pS.GetString().substr(0,KFuncSupportedLanguagePrefix.length()) == KFuncSupportedLanguagePrefix)
       
   216 			{
       
   217 			iTempResult = ExpressionResult(iExpEnv.DeviceLanguage(pS.GetString().substr(KFuncSupportedLanguagePrefix.length())));
       
   218 			}
       
   219 		else
       
   220 			{
       
   221 			iTempResult = ExpressionResult(iExpEnv.FindFile(pS.GetString()));
       
   222 			}
       
   223 		}
       
   224 		break;
       
   225 
       
   226 	case CSISExpression::EPrimTypeString:
       
   227 		{
       
   228 		const CSISString& pS = aExpression.String();
       
   229 		if(pS.WasteOfSpace())
       
   230 			{
       
   231 			throw std::runtime_error("null pointer");
       
   232 			}
       
   233 		
       
   234 		iTempResult = ExpressionResult(pS.GetString());
       
   235 		}
       
   236 		break;
       
   237 
       
   238 	case CSISExpression::EPrimTypeVariable:
       
   239 		{
       
   240         const int variableId = aExpression.IntValue();
       
   241         const int variableValue = iExpEnv.Variable( variableId );
       
   242         //
       
   243 		iTempResult = ExpressionResult( variableValue );
       
   244 		break;
       
   245 		}
       
   246 
       
   247 	case CSISExpression::EPrimTypeOption:
       
   248 		{
       
   249 		iExpressionDepth=0;
       
   250 		std::string error = "SIS File contains user options\n";
       
   251 		std::string x;
       
   252         //
       
   253 		throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED);
       
   254 		}
       
   255 
       
   256 	case CSISExpression::EPrimTypeNumber:
       
   257 		iTempResult = ExpressionResult(aExpression.IntValue());
       
   258 		break;
       
   259 
       
   260 	default:
       
   261 		{
       
   262 		iExpressionDepth=0;
       
   263 		std::string error = "SIS File contains unknown expression\n";
       
   264 		std::string x;
       
   265         //
       
   266 		throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED);
       
   267 		}
       
   268     	}
       
   269 
       
   270 	--iExpressionDepth;
       
   271 	return iTempResult;
       
   272     }
       
   273 
       
   274 
       
   275 // ExpressionEnvironment
       
   276 
       
   277 ExpressionEnvironment::ExpressionEnvironment( const SisFile& aSisFile,
       
   278                                               const SisRegistry& aSisRegistry,
       
   279                                               RomManager& aRomManager,
       
   280                                               ConfigManager& aConfigManager,
       
   281                                               const std::wstring& aCDrive ) 
       
   282 :   iSisFile(aSisFile), iSisRegistry(aSisRegistry), 
       
   283     iRomManager( aRomManager ), iConfigManager( aConfigManager ),
       
   284     iCDrive(aCDrive)
       
   285     {
       
   286     }
       
   287 
       
   288 
       
   289 const std::wstring ExpressionEnvironment::GetPackageName()
       
   290     {
       
   291 	return iSisFile.GetPackageName();
       
   292     }
       
   293 
       
   294 
       
   295 bool ExpressionEnvironment::FindFile( const std::wstring& aFileName )
       
   296     {
       
   297     bool fileExists = false;
       
   298 
       
   299     // Fixed up file name
       
   300     std::wstring fileName( aFileName );
       
   301    
       
   302     // If the file is in ROM then we really need to check with the ROM
       
   303     // manager. If its on C:, then we'll have to resort to using
       
   304     // the specified 'C' drive and hope that it helps.
       
   305     //
       
   306     // Filename length must be at least 3 characters, i.e. drive + semicolon + backslash + filename
       
   307     //
       
   308     if ( fileName.length() >= 1 && fileName[ 0 ] == L'\\' )
       
   309         {
       
   310         // Bad file name?
       
   311   		LWARN(L"\tAssuming file path \'" << aFileName << L"\' refers to Z:" );
       
   312         fileName = L"Z:" + fileName;
       
   313         }
       
   314 
       
   315     // Require for invalid file exception (also helps with debugging)
       
   316     std::string narrowFileName;
       
   317     narrowFileName = Ucs2ToUtf8( fileName, narrowFileName );
       
   318 
       
   319     // Now continue with file, assuming we've fixed up the path or then
       
   320     // have enough characters to process
       
   321     bool startsWithDrive = StringUtils::StartsWithDrive( fileName );
       
   322     if  ( startsWithDrive )
       
   323         {
       
   324         const wchar_t drive = fileName[ 0 ];
       
   325         //
       
   326         switch( drive )
       
   327             {
       
   328         case L'z':
       
   329         case L'Z':
       
   330             {
       
   331             // File is in 'ROM' so use ROM manager
       
   332             fileExists = iRomManager.RomFileExists( fileName );
       
   333             break;
       
   334             }
       
   335         case L'c':
       
   336         case L'C':
       
   337         case L'!':
       
   338         default:
       
   339             {
       
   340             // File is on 'C:' so merge with C-drive specification and
       
   341             // use native FileExists() check
       
   342             ConvertToLocalPath( fileName, iCDrive );
       
   343 
       
   344             // For debugging
       
   345             narrowFileName = Ucs2ToUtf8( fileName, narrowFileName );
       
   346 
       
   347             fileExists = FileExists( fileName );
       
   348             break;
       
   349             }
       
   350             }
       
   351         }
       
   352     else
       
   353         {
       
   354 		std::string error = "corrupt SIS file: bad \'EXISTS' filename: \'" + narrowFileName + "\'";
       
   355 		throw InvalidSis( "", error, INVALID_SIS );
       
   356         }
       
   357     //
       
   358     std::ostringstream stream;
       
   359     stream << "\tIF EXISTS(\'" << narrowFileName << "\') => " << fileExists;
       
   360     std::string msg = stream.str();
       
   361     std::wstring finalMessage = Utf8ToUcs2( msg );
       
   362     LINFO( finalMessage );
       
   363     //
       
   364     return fileExists;
       
   365     }
       
   366 
       
   367 
       
   368 TUint32 ExpressionEnvironment::ApplicationProperty(TUint32 aPackageUid, TUint32 aKey)
       
   369     {
       
   370 	// First of all, check in this package
       
   371 	if (aPackageUid == iSisFile.GetPackageUid())
       
   372 	    {
       
   373 		const CSISProperties::SISPropertyArray& props = iSisFile.GetProperties()->Properties(); 
       
   374 		for(int i = 0; i < props.size(); ++i)
       
   375 			{
       
   376 			if (props[i].Key() == aKey)
       
   377 				{
       
   378 				return props[i].Value();
       
   379 				}
       
   380 			}
       
   381 	    }
       
   382 
       
   383 	// Then check the registry
       
   384 	const SisRegistryObject& aObj = iSisRegistry.GetRegistryObject(aPackageUid);
       
   385 	const std::vector<SisRegistryProperty*>& props = aObj.GetProperties();
       
   386 	for (std::vector<SisRegistryProperty*>::const_iterator curr1 = props.begin(); curr1 != props.end(); ++curr1)
       
   387 		{
       
   388 		if ((*curr1)->GetKey() == aKey)
       
   389 			{
       
   390 			return (*curr1)->GetValue();
       
   391 			}
       
   392 		}
       
   393 
       
   394 	// No property
       
   395 	return 0;
       
   396     }
       
   397 
       
   398 
       
   399 int ExpressionEnvironment::Variable( int aVariableId )
       
   400     {
       
   401     int result = 0;
       
   402 
       
   403     // For debugging
       
   404     std::string attributeName = ConfigManager::AttributeNameById( aVariableId );
       
   405 
       
   406     // See if the config manager has an over-ride for this property.
       
   407     // If so, we'll use that value in preference to any other.
       
   408     const bool attributeMappingExists = iConfigManager.ValueExists( (TUint32) aVariableId );
       
   409     if ( attributeMappingExists )
       
   410         {
       
   411         result = iConfigManager.ValueById( (TUint32) aVariableId );
       
   412         
       
   413 		// verify whether the language input code is within the supported list in SIS
       
   414 		// if not select first langauge in SIS file
       
   415 		if (aVariableId == KVariableLanguage)
       
   416 			{
       
   417 			if (!iSisFile.IsSupportedLanguage((TUint32)result))
       
   418 				{
       
   419 				int firstLanguage = iSisFile.GetLanguage(); // get the first language
       
   420 				std::ostringstream stream;
       
   421 				stream << "Input language " << result << " is not supported by SIS file. Using first language " <<firstLanguage;
       
   422 				std::string msg = stream.str();
       
   423 				std::wstring finalMessage = Utf8ToUcs2( msg );
       
   424 				LWARN( finalMessage );	
       
   425 				result = firstLanguage;
       
   426 				}
       
   427 			}
       
   428         std::ostringstream stream;
       
   429         stream << "\tIF " << attributeName << " ... where [" << attributeName << " = " << result << "]";
       
   430         std::string msg = stream.str();
       
   431         std::wstring finalMessage = Utf8ToUcs2( msg );
       
   432         LINFO( finalMessage );
       
   433         }
       
   434 	else if ( aVariableId == KVariableLanguage )
       
   435     	{
       
   436 		LWARN(L"Disregarding language selection. Using ELangEnglish");
       
   437 		result = 1;
       
   438     	}
       
   439     else
       
   440         {
       
   441         std::string packageName;
       
   442         packageName = Ucs2ToUtf8( GetPackageName(), packageName );
       
   443         //
       
   444 		std::string error = "SIS File contains HAL attributes\n";
       
   445 		throw InvalidSis( packageName, error, SIS_NOT_SUPPORTED );
       
   446         }
       
   447     //
       
   448     return result;
       
   449     }
       
   450 
       
   451 
       
   452 bool ExpressionEnvironment::Package(TUint32 aKey)
       
   453     {
       
   454 	return iSisRegistry.IsInstalled(aKey);
       
   455     }
       
   456 
       
   457 
       
   458 bool ExpressionEnvironment::PackageVersion(const std::wstring& aArgsString)
       
   459 	{
       
   460 	// Create a copy of the argument string to be used when parsing
       
   461 	std::wstring parseString(aArgsString);
       
   462 
       
   463 	// *** Parse 'Package UID' argument ***
       
   464 	std::wstring packageUidStr;
       
   465 	if(!CSISExpression::ExtractNextToken(parseString,packageUidStr))
       
   466 		{
       
   467 		return false;
       
   468 		}
       
   469 	
       
   470 	// Package UID format checking
       
   471 	packageUidStr[1] = tolower(packageUidStr[1]);
       
   472 	if(packageUidStr.find(L"0x") != 0 || packageUidStr.length() != 10)
       
   473 		{
       
   474 		return false;
       
   475 		}
       
   476 	
       
   477 	// Check and convert the wstring to a TUint32
       
   478 	TUint32 packageUid;
       
   479 	if(!CSISExpression::IsHexadecimal(packageUidStr.substr(2),packageUid))
       
   480 		{
       
   481 		return false;
       
   482 		}
       
   483 
       
   484 
       
   485 	// *** Parse 'Relational Operator' argument ***
       
   486 	std::wstring relationOpStr;
       
   487 	if(!CSISExpression::ExtractNextToken(parseString,relationOpStr))
       
   488 		{
       
   489 		return false;
       
   490 		}
       
   491 
       
   492 
       
   493 	// *** Parse 'Major Version Component' argument ***
       
   494 	std::wstring vMajorStr;
       
   495 	if(!CSISExpression::ExtractNextToken(parseString,vMajorStr))
       
   496 		{
       
   497 		return false;
       
   498 		}
       
   499 
       
   500 	// Check and convert the wstring to an TInt
       
   501 	TInt vMajor;
       
   502 	if(!CSISExpression::IsDecimal(vMajorStr, vMajor))
       
   503 		{
       
   504 		return false;
       
   505 		}
       
   506 
       
   507 
       
   508 	// *** Parse 'Minor Version Component' argument ***
       
   509 	std::wstring vMinorStr;
       
   510 	if(!CSISExpression::ExtractNextToken(parseString,vMinorStr))
       
   511 		{
       
   512 		return false;
       
   513 		}
       
   514 
       
   515 	// Check and convert the wstring to an TInt
       
   516 	TInt vMinor;
       
   517 	if(!CSISExpression::IsDecimal(vMinorStr, vMinor))
       
   518 		{
       
   519 		return false;
       
   520 		}
       
   521 
       
   522 
       
   523 	// *** Parse 'Build Version Component' argument ***
       
   524 	std::wstring vBuildStr = parseString;
       
   525 
       
   526 	// Check and convert the wstring to an TInt
       
   527 	TInt vBuild;
       
   528 	if(!CSISExpression::IsDecimal(vBuildStr, vBuild))
       
   529 		{
       
   530 		return false;
       
   531 		}
       
   532 	
       
   533 	Version argsVersion(vMajor,vMinor,vBuild);
       
   534 
       
   535 	// Check that the version component values lie within the valid range
       
   536 	if(!argsVersion.IsValid())
       
   537 		{
       
   538 		return false;
       
   539 		}
       
   540 
       
   541 	// Then check the registry
       
   542 	if(iSisRegistry.IsInstalled(packageUid))
       
   543 		{
       
   544 		const SisRegistryObject& pkgRegEntry = iSisRegistry.GetRegistryObject(packageUid);
       
   545 		Version registryVersion = pkgRegEntry.GetVersion();
       
   546 
       
   547 		// Compare the package version retrieved from the SIS Registry against the version
       
   548 		// specified in the PKG condition
       
   549 		if(relationOpStr == L"ET") 
       
   550 			{// Equal To 
       
   551 			return registryVersion == argsVersion;
       
   552 			}
       
   553 		else if(relationOpStr == L"LT")
       
   554 			{// Less Than
       
   555 			return registryVersion < argsVersion;
       
   556 			}
       
   557 		else if(relationOpStr == L"LE") 
       
   558 			{// Less Than Or Equal To
       
   559 			return registryVersion <= argsVersion;
       
   560 			}
       
   561 		else if(relationOpStr == L"GT")
       
   562 			{// Greater Than
       
   563 			return registryVersion > argsVersion;
       
   564 			}
       
   565 		else if(relationOpStr == L"GE") 
       
   566 			{// Greater Than Or Equal To
       
   567 			return registryVersion >= argsVersion;
       
   568 			}
       
   569 		else if(relationOpStr == L"NE")
       
   570 			{// Not Equal
       
   571 			return registryVersion != argsVersion;
       
   572 			}
       
   573 		else 
       
   574 			{
       
   575 			// If the operator is not recognised, return false
       
   576 			return false;
       
   577 			}
       
   578 		}
       
   579 	else
       
   580 		{
       
   581 		// Package UID has not been found within the SIS Registry
       
   582 		return false;
       
   583 		}
       
   584 	}
       
   585 
       
   586 bool ExpressionEnvironment::DeviceLanguage(const std::wstring& aArgsString)
       
   587 	{
       
   588 	TInt langID = 0;
       
   589 	if(!CSISExpression::IsDecimal(aArgsString, langID))
       
   590 		{
       
   591 		return false;
       
   592 		}
       
   593 	std::vector<TInt>  devSuppLang = iConfigManager.GetDeviceSupportedLanguages();		
       
   594  	std::vector<int>::const_iterator end = devSuppLang.end();
       
   595 	for (std::vector<int>::const_iterator curr = devSuppLang.begin(); curr != end; ++curr)
       
   596 		{
       
   597 			 if ( *curr == langID )
       
   598 				 {
       
   599 				 iConfigManager.AddMatchingSupportedLanguages(langID);
       
   600 				 return true;
       
   601 				 }
       
   602 			 else
       
   603 				 {
       
   604 				  TLanguagePath equivalentLang;
       
   605 				  Utils::GetEquivalentLanguageList((CSISLanguage::TLanguage)(*curr),equivalentLang);
       
   606 				  for ( TInt i=0; i < KMaxDowngradeLanguages; i++)
       
   607 					  {
       
   608 					  if ( equivalentLang[i] != CSISLanguage::ELangNone )
       
   609 						  {
       
   610 						  if (equivalentLang[i] == langID )
       
   611 							 {
       
   612 							 iConfigManager.AddMatchingSupportedLanguages(langID);
       
   613 							 return true;
       
   614 							 }
       
   615 						  }
       
   616 					  else
       
   617 						  {
       
   618 						  break;
       
   619 						  }
       
   620 					  }
       
   621 				 }
       
   622 		}
       
   623 	return false;
       
   624 	}
       
   625