diff -r 000000000000 -r ba25891c3a9e secureswitools/swisistools/source/interpretsislib/expressionevaluator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/secureswitools/swisistools/source/interpretsislib/expressionevaluator.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,625 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include +#include + +// User includes +#include "sisexpression.h" +#include "expressionevaluator.h" +#include "sisstring.h" +#include "is_utils.h" +#include "errors.h" +#include "symbiantypes.h" +#include "stringutils.h" +#include "rommanager.h" +#include "configmanager.h" +#include "sisfile.h" +#include "sisregistryobject.h" +#include "logger.h" +#include "version.h" +#include "is_utils.h" + +// ExpressionResult +using namespace Utils; +ExpressionResult::ExpressionResult(const std::wstring& aString) +: iType(EString), iString(&aString) + { + } + + +ExpressionResult::ExpressionResult(TUint32 aInt) +: iType(EInt), iInt(aInt) + { + } + + +TUint32 ExpressionResult::IntegerValue() const + { + if (iType!=EInt) + { + std::string error = "corrupt SIS file: expression corrupt in condition statement"; + throw InvalidSis("",error,INVALID_SIS); + } + + return iInt; + } + + +bool ExpressionResult::BoolValue() const + { + return bool(IntegerValue()); + } + + +const std::wstring& ExpressionResult::StringValue() const + { + if (iType!=EString) + { + std::string error = "corrupt SIS file: expression corrupt in condition statement"; + throw InvalidSis("",error,INVALID_SIS); + } + + return *iString; + } + + +// ExpressionEvaluator + +ExpressionEvaluator::ExpressionEvaluator(ExpressionEnvironment& aEnvironment) +: iExpEnv(aEnvironment), iTempResult(false), iExpressionDepth(0) + { + } + + +void ExpressionEvaluator::Require(const void *aPointer) const + { + if (!aPointer) + { + throw std::runtime_error("null pointer"); + } + } + + +ExpressionResult ExpressionEvaluator::Evaluate(const CSISExpression* aExpression) + { + Require(aExpression); + return Evaluate(*aExpression); + } + + +ExpressionResult ExpressionEvaluator::Evaluate(const CSISExpression& aExpression) + { + if (++iExpressionDepth > KMaxExpressionDepth) + { + iExpressionDepth=0; + std::string error = "SIS File expression too complex\n"; + std::string x; + // + throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED); + } + + switch (aExpression.Operator()) + { + case CSISExpression::EBinOpEqual: + case CSISExpression::EBinOpNotEqual: + case CSISExpression::EBinOpGreaterThan: + case CSISExpression::EBinOpLessThan: + case CSISExpression::EBinOpGreaterThanOrEqual: + case CSISExpression::EBinOpLessThanOrEqual: + { + const ExpressionResult resultLeft = Evaluate( aExpression.LHS() ); + const ExpressionResult resultRight = Evaluate( aExpression.RHS() ); + // + switch (aExpression.Operator()) + { + case CSISExpression::EBinOpEqual: + iTempResult = ( resultLeft == resultRight ); + break; + case CSISExpression::EBinOpNotEqual: + iTempResult = ( resultLeft != resultRight ); + break; + case CSISExpression::EBinOpGreaterThan: + iTempResult = ( resultLeft > resultRight ); + break; + case CSISExpression::EBinOpLessThan: + iTempResult = ( resultLeft < resultRight ); + break; + case CSISExpression::EBinOpGreaterThanOrEqual: + iTempResult = ( resultLeft >= resultRight ); + break; + case CSISExpression::EBinOpLessThanOrEqual: + iTempResult = ( resultLeft <= resultRight ); + break; + } + // + break; + } + + case CSISExpression::ELogOpAnd: + { + ExpressionResult tmp1 = Evaluate(aExpression.LHS()); + ExpressionResult tmp2 = Evaluate(aExpression.RHS()); + iTempResult = ExpressionResult(tmp1.BoolValue() && tmp2.BoolValue()); + break; + } + + case CSISExpression::ELogOpOr: + { + ExpressionResult tmp1 = Evaluate(aExpression.LHS()); + if (tmp1.BoolValue()) + { + iTempResult = ExpressionResult(true); + } + else + { + iTempResult = ExpressionResult(Evaluate(aExpression.RHS())).BoolValue(); + } + break; + } + + case CSISExpression::EUnaryOpNot: + iTempResult=!Evaluate(aExpression.RHS()); + break; + + case CSISExpression::EFuncAppProperties: + { + const TUint32 resultLeft = Evaluate( aExpression.LHS() ).IntegerValue(); + const TUint32 resultRight = Evaluate( aExpression.RHS() ).IntegerValue(); + // + iTempResult = iExpEnv.ApplicationProperty( resultLeft, resultRight ); + break; + } + + case CSISExpression::EFuncDevProperties: + iTempResult = ExpressionResult(iExpEnv.Package(Evaluate(aExpression.RHS()).IntegerValue())); + break; + + case CSISExpression::EFuncExists: + { + const CSISString& pS = aExpression.String(); + if(pS.WasteOfSpace()) + { + throw std::runtime_error("null pointer"); + } + + /** + * CR1125 - Add Package Versions to SIS File Conditionals + * + * If the CSISExpression CSISString has been prefixed with the argument string identifier stored within + * KVersionFuncPrefix, the condition is considered to be a VERSION function call. The argument string + * is then passed to PackageVersion() to query the SIS Registry and determine whether the version of + * an installed package satisfies the presented condition. + */ + if(pS.GetString().substr(0,KFuncVersionPrefix.length()) == KFuncVersionPrefix) + { + iTempResult = ExpressionResult(iExpEnv.PackageVersion(pS.GetString().substr(KFuncVersionPrefix.length()))); + } + /** + * Support for exact and equivalent device supported languages + */ + else if (pS.GetString().substr(0,KFuncSupportedLanguagePrefix.length()) == KFuncSupportedLanguagePrefix) + { + iTempResult = ExpressionResult(iExpEnv.DeviceLanguage(pS.GetString().substr(KFuncSupportedLanguagePrefix.length()))); + } + else + { + iTempResult = ExpressionResult(iExpEnv.FindFile(pS.GetString())); + } + } + break; + + case CSISExpression::EPrimTypeString: + { + const CSISString& pS = aExpression.String(); + if(pS.WasteOfSpace()) + { + throw std::runtime_error("null pointer"); + } + + iTempResult = ExpressionResult(pS.GetString()); + } + break; + + case CSISExpression::EPrimTypeVariable: + { + const int variableId = aExpression.IntValue(); + const int variableValue = iExpEnv.Variable( variableId ); + // + iTempResult = ExpressionResult( variableValue ); + break; + } + + case CSISExpression::EPrimTypeOption: + { + iExpressionDepth=0; + std::string error = "SIS File contains user options\n"; + std::string x; + // + throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED); + } + + case CSISExpression::EPrimTypeNumber: + iTempResult = ExpressionResult(aExpression.IntValue()); + break; + + default: + { + iExpressionDepth=0; + std::string error = "SIS File contains unknown expression\n"; + std::string x; + // + throw InvalidSis(Ucs2ToUtf8(iExpEnv.GetPackageName(),x), error, SIS_NOT_SUPPORTED); + } + } + + --iExpressionDepth; + return iTempResult; + } + + +// ExpressionEnvironment + +ExpressionEnvironment::ExpressionEnvironment( const SisFile& aSisFile, + const SisRegistry& aSisRegistry, + RomManager& aRomManager, + ConfigManager& aConfigManager, + const std::wstring& aCDrive ) +: iSisFile(aSisFile), iSisRegistry(aSisRegistry), + iRomManager( aRomManager ), iConfigManager( aConfigManager ), + iCDrive(aCDrive) + { + } + + +const std::wstring ExpressionEnvironment::GetPackageName() + { + return iSisFile.GetPackageName(); + } + + +bool ExpressionEnvironment::FindFile( const std::wstring& aFileName ) + { + bool fileExists = false; + + // Fixed up file name + std::wstring fileName( aFileName ); + + // If the file is in ROM then we really need to check with the ROM + // manager. If its on C:, then we'll have to resort to using + // the specified 'C' drive and hope that it helps. + // + // Filename length must be at least 3 characters, i.e. drive + semicolon + backslash + filename + // + if ( fileName.length() >= 1 && fileName[ 0 ] == L'\\' ) + { + // Bad file name? + LWARN(L"\tAssuming file path \'" << aFileName << L"\' refers to Z:" ); + fileName = L"Z:" + fileName; + } + + // Require for invalid file exception (also helps with debugging) + std::string narrowFileName; + narrowFileName = Ucs2ToUtf8( fileName, narrowFileName ); + + // Now continue with file, assuming we've fixed up the path or then + // have enough characters to process + bool startsWithDrive = StringUtils::StartsWithDrive( fileName ); + if ( startsWithDrive ) + { + const wchar_t drive = fileName[ 0 ]; + // + switch( drive ) + { + case L'z': + case L'Z': + { + // File is in 'ROM' so use ROM manager + fileExists = iRomManager.RomFileExists( fileName ); + break; + } + case L'c': + case L'C': + case L'!': + default: + { + // File is on 'C:' so merge with C-drive specification and + // use native FileExists() check + ConvertToLocalPath( fileName, iCDrive ); + + // For debugging + narrowFileName = Ucs2ToUtf8( fileName, narrowFileName ); + + fileExists = FileExists( fileName ); + break; + } + } + } + else + { + std::string error = "corrupt SIS file: bad \'EXISTS' filename: \'" + narrowFileName + "\'"; + throw InvalidSis( "", error, INVALID_SIS ); + } + // + std::ostringstream stream; + stream << "\tIF EXISTS(\'" << narrowFileName << "\') => " << fileExists; + std::string msg = stream.str(); + std::wstring finalMessage = Utf8ToUcs2( msg ); + LINFO( finalMessage ); + // + return fileExists; + } + + +TUint32 ExpressionEnvironment::ApplicationProperty(TUint32 aPackageUid, TUint32 aKey) + { + // First of all, check in this package + if (aPackageUid == iSisFile.GetPackageUid()) + { + const CSISProperties::SISPropertyArray& props = iSisFile.GetProperties()->Properties(); + for(int i = 0; i < props.size(); ++i) + { + if (props[i].Key() == aKey) + { + return props[i].Value(); + } + } + } + + // Then check the registry + const SisRegistryObject& aObj = iSisRegistry.GetRegistryObject(aPackageUid); + const std::vector& props = aObj.GetProperties(); + for (std::vector::const_iterator curr1 = props.begin(); curr1 != props.end(); ++curr1) + { + if ((*curr1)->GetKey() == aKey) + { + return (*curr1)->GetValue(); + } + } + + // No property + return 0; + } + + +int ExpressionEnvironment::Variable( int aVariableId ) + { + int result = 0; + + // For debugging + std::string attributeName = ConfigManager::AttributeNameById( aVariableId ); + + // See if the config manager has an over-ride for this property. + // If so, we'll use that value in preference to any other. + const bool attributeMappingExists = iConfigManager.ValueExists( (TUint32) aVariableId ); + if ( attributeMappingExists ) + { + result = iConfigManager.ValueById( (TUint32) aVariableId ); + + // verify whether the language input code is within the supported list in SIS + // if not select first langauge in SIS file + if (aVariableId == KVariableLanguage) + { + if (!iSisFile.IsSupportedLanguage((TUint32)result)) + { + int firstLanguage = iSisFile.GetLanguage(); // get the first language + std::ostringstream stream; + stream << "Input language " << result << " is not supported by SIS file. Using first language " < argsVersion; + } + else if(relationOpStr == L"GE") + {// Greater Than Or Equal To + return registryVersion >= argsVersion; + } + else if(relationOpStr == L"NE") + {// Not Equal + return registryVersion != argsVersion; + } + else + { + // If the operator is not recognised, return false + return false; + } + } + else + { + // Package UID has not been found within the SIS Registry + return false; + } + } + +bool ExpressionEnvironment::DeviceLanguage(const std::wstring& aArgsString) + { + TInt langID = 0; + if(!CSISExpression::IsDecimal(aArgsString, langID)) + { + return false; + } + std::vector devSuppLang = iConfigManager.GetDeviceSupportedLanguages(); + std::vector::const_iterator end = devSuppLang.end(); + for (std::vector::const_iterator curr = devSuppLang.begin(); curr != end; ++curr) + { + if ( *curr == langID ) + { + iConfigManager.AddMatchingSupportedLanguages(langID); + return true; + } + else + { + TLanguagePath equivalentLang; + Utils::GetEquivalentLanguageList((CSISLanguage::TLanguage)(*curr),equivalentLang); + for ( TInt i=0; i < KMaxDowngradeLanguages; i++) + { + if ( equivalentLang[i] != CSISLanguage::ELangNone ) + { + if (equivalentLang[i] == langID ) + { + iConfigManager.AddMatchingSupportedLanguages(langID); + return true; + } + } + else + { + break; + } + } + } + } + return false; + } +