diff -r 000000000000 -r ba25891c3a9e secureswitools/swisistools/source/sisxlibrary/utility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/secureswitools/swisistools/source/sisxlibrary/utility.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,507 @@ +/* +* Copyright (c) 2004-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: +* +*/ + + +/** + @file + @internalComponent + @released +*/ + +#include "utility.h" +#include "exception.h" +#include "utility_interface.h" +#include "utils.h" +#include +#include +#include +#include +#include + +std::wostream* SISLogger::iStream = NULL; + +void SISLogger::SetStream(std::wostream& aStream) + { + iStream = &aStream; + } + +void SISLogger::Log(const std::wstring& aString) + { + if(NULL != iStream) + { + (*iStream) << aString; + } + } + + +std::string wstring2string (const std::wstring& aWide) + { + int max = ConvertWideCharToMultiByte(aWide.c_str(),aWide.length(),0,0); + std::string reply; + if (max > 0 ) + { + char* buffer = new char [max]; + try + { + ConvertWideCharToMultiByte(aWide.c_str(),aWide.length(),buffer,max); + reply = std::string (buffer, max); + } + catch (...) + { + } + delete [] buffer; + } + return reply; + } + +std::wstring string2wstring (const std::string& aNarrow) + { + int max = ConvertMultiByteToWideChar(aNarrow.c_str(),aNarrow.length(),0,0, CP_OEMCP); + std::wstring reply; + if (max > 0 ) + { + wchar_t* buffer = new wchar_t [max]; + try + { + ConvertMultiByteToWideChar(aNarrow.c_str(),aNarrow.length(),buffer,max,CP_OEMCP); + reply = std::wstring (buffer, max); + } + catch (...) + { + } + delete [] buffer; + } + return reply; + } + +void EnsureExtended (std::wstring& aName, const std::wstring& aDefaultExtension) + { + assert (! aName.empty ()); + assert (! aDefaultExtension.empty ()); + std::wstring::size_type posSlash (aName.rfind ('\\')); + if (posSlash == std::wstring::npos) + { + posSlash = 0; + } + std::wstring::size_type posDot (aName.find (posSlash, '.')); + if (posDot == std::wstring::npos) + { + aName += aDefaultExtension; + } + } + +bool ValidateFileName (std::wstring& aName, const bool aMustExist) + { + assert (! aName.empty ()); + if (aName.size () < 3) + { + return false; + } + std::wstring filename (aName); + bool isUNC ((filename.at (0) == L'/') && (filename.at (1) == L'/')); + bool isRelative (! isUNC && ((filename.at (1) != L':'))); + + if (! isRelative) + { + if (! isUNC && (filename.at (2) != L'/')) + { + return false; + } + } + else + { + const int maxlen = PATHMAX * 8; /* The value of PATHMAX assumes short name FAT environment, + not long names and / or NTFS, UNC, URL, etc. etc.. Using a + larger value significantly reduces the chances of failure + when the application is deep in a subdirectory tree. Windows + calls require fixed length buffers. + */ + wchar_t directorybuffer [maxlen]; + std::wstring cwd (_wgetcwd (directorybuffer, maxlen)); + if (cwd.empty ()) + { + return false; + } + if (cwd.size () > 3) + { + cwd += KSisDirectorySeparator; // trailing backslash is returned inconsistently according to docs for getcwd + } + filename = cwd + filename; + } + + if (aMustExist) + { + DWORD attributes (GetFileAttributesW (filename.c_str ())); + if (attributes == RESULT) + { + return false; + } + } + aName = filename; + return true; + } + + +bool ValidateDirectory (std::wstring& aName, const bool aMustExist) + { + if (! ValidateFileName (aName, aMustExist)) + { + return false; + } + if (aName.at (aName.size () - 1) != L'/') + { + aName += L'/'; + } + return true; + } + +bool ValidateFileName (std::wstring& aName, const bool aMustExist, const std::wstring& aDefaultExtension) + { + assert (! aName.empty ()); + assert (! aDefaultExtension.empty ()); + std::wstring filename (aName); + EnsureExtended (filename, aDefaultExtension); + if (! ValidateFileName (filename, aMustExist)) + { + return false; + } + aName = filename; + return true; + } + +TUint32 IdentifyUCKeyword (const SKeyword aKeyword [], std::wstring aIdentifier, const std::wstring& aContext) + { + for (std::wstring::size_type letter = 0; letter < aIdentifier.size (); letter++) + { + aIdentifier [letter] = toupper (aIdentifier [letter]); + } + for (const SKeyword* index = &aKeyword [0]; index -> iName != NULL; index++) + { + if (aIdentifier.compare (index -> iName) == 0) + { + return index -> iId; + } + } + throw CSISException (CSISException::ESyntax, aContext + aIdentifier); + } + + +CSISFieldRoot::TFieldSize Alignment (const CSISFieldRoot::TFieldSize aOriginal) + { + const CSISFieldRoot::TFieldSize coarseness (4); + CSISFieldRoot::TFieldSize modulus (aOriginal % coarseness); + return (modulus == 0) ? 0 : (coarseness - modulus); + } + + +CSISFieldRoot::TFieldSize AlignedSize (const CSISFieldRoot::TFieldSize aOriginal) + { + return aOriginal + Alignment (aOriginal); + } + + + +void ReadFiller (TSISStream& aFile) + { + CSISFieldRoot::TFieldSize diff (Alignment (aFile.tell ())); + assert (diff >= 0); + if (diff) + { + TUint8 junk; + for (CSISFieldRoot::TFieldSize index = 0; index < diff; index++) + { + aFile >> junk; + } + } + } + + +void WriteFiller (TSISStream& aFile) + { + TSISStream::pos_type pos (aFile.tell ()); + if (pos >= 0) + { + CSISFieldRoot::TFieldSize diff (Alignment (pos)); + if (diff) + { + TUint8 padding = 0; + for (CSISFieldRoot::TFieldSize index = 0; index < diff; index++) + { + aFile << padding; + } + } + } + } + +HANDLE OpenFileAndGetSize (const std::wstring& aName, TUint64* aSize) + { + HANDLE file = MakeSISOpenFile(aName.c_str(),GENERIC_READ,OPEN_EXISTING); + CSISException::ThrowIf ((INVALID_HANDLE_VALUE == file), + CSISException::EFileProblem, std::wstring (L"cannot open ") + aName); + if (aSize) + { + DWORD dwHigh = 0; + DWORD dwLow = ::GetFileSize(file,&dwHigh); + TUint64 size = (dwHigh << 32) | dwLow; + *aSize = static_cast (size); + } + return file; + } + + +void ReadAndCloseFile (HANDLE aFile, const TUint64 aSize, TUint8* aBuffer) + { + size_t got = 0; + ::ReadFile(aFile,aBuffer,aSize,(DWORD*)&got,0); + ::CloseHandle(aFile); + CSISException::ThrowIf (got != static_cast (aSize), + CSISException::EFileProblem, + "cannot read file"); + } + + +int SearchSortedUCTable (const SIdentifierTable aTable [], const std::wstring& aIdentifier) + { + for (int index = 0; aTable [index].iName; index++) + { + int comparision = aIdentifier.compare (aTable [index].iName); + if (comparision == 0) + { + return index; + } + if (comparision < 0) + { + break; + } + } + return -1; + } + + +LPSTR MakeMBCSString(LPCWSTR uniStr, UINT codePage, DWORD& length) +// Convert a UNICODE string to a multi-byte string + { + LPSTR mbStr; + // get num unicode chars required + DWORD len = ConvertWideCharToMultiByte(uniStr, length, NULL, 0); + mbStr = new CHAR[len+1]; + if (!mbStr) throw ErrNotEnoughMemory; + // convert + ConvertWideCharToMultiByte(uniStr, length, mbStr, len); + mbStr[len]='\0'; + length=len; + + return mbStr; + } + + +char* Copy2TmpFile(const wchar_t *fName, TFileType fType) +{ + char *tmpName, *tmpFileName=NULL; + int numread = 0; + + tmpName = GetTempFile(); + + if(tmpName == NULL) + return NULL; + + tmpFileName = new char[strlen(tmpName)+5]; + strcpy(tmpFileName, tmpName); + + if(fType == CERTFILE) + { + tmpFileName = strcat(tmpFileName, ".cer"); + } + else if(fType == KEYFILE) + { + tmpFileName = strcat(tmpFileName, ".key"); + } + else + { + tmpFileName = strcat(tmpFileName, ".dat"); + } + + TransferFileData(fName,tmpFileName); + return tmpFileName; + + if(tmpFileName != NULL) + delete tmpFileName; + + return NULL; +} + +/** + * Returns the size of the first occurance of an invalid directory separator. + * @param aPath Path to be validated. + * @param aIndex index from which the search begin. On function return this + * index will point to the illegal directory separator. + * @return 0 if path is valid. Else the number of character to be replaced. + * e.g. \sys\bin\ should be replaced with /sys/bin/ + * and \\sys\\bin\\ should be replaced with /sys/bin/ + */ +int FirstInvalidDirSeparatorSize(std::wstring& aPath, std::wstring::size_type& aIndex) + { + // If path semantics is correct (as needed by sisx library) + // then the function will return 0 + int ret = 0; + int pos = 0; + if((pos = aPath.find(L"\\\\", aIndex)) != std::wstring::npos) + { + ret = 2; + } + else if((pos = aPath.find(L"\\", aIndex)) != std::wstring::npos) + { + ret = 1; + } + aIndex = pos; + return ret; + } + + +std::wstring FixPathDelimiters( const std::wstring& aString ) + { + std::wstring ret = aString; + + std::wstring::size_type idx = 0; + int len = 0; + while(len = FirstInvalidDirSeparatorSize(ret, idx)) + { + ret.replace( idx, len, KSisDirectorySeparator ); + } + return ret; + } + +int GetFileType(std::wstring& aFileName) + { + int len = ConvertWideCharToMultiByte(aFileName.c_str(), -1, NULL, 0); + char* fileName = new char[len + 1]; + ConvertWideCharToMultiByte(aFileName.c_str(), -1, fileName, len); + + std::ifstream fs(fileName, std::ios::binary | std::ios::in); + fs.seekg(0, std::ios::end); + len = fs.tellg(); + fs.seekg(0, std::ios::beg); + unsigned char* buffer = new unsigned char[len]; + fs.read((char*)buffer, len); + fs.close(); + + int type = EFileUnknown; + + const TUint32* data32 = reinterpret_cast(buffer); + + if (len <= sizeof(TUint32)*0x04) + { + delete[] buffer; + return type; + } + + if(IsExeData(buffer, len)) + { + type = EFileExe; + } + else if(IsDllData(buffer, len)) + { + type = EFileDll; + } + + if(IsEmulatorExecutableData(buffer, len)) + { + type |= EFileEmulatorExe; + } + + return type; + } + +bool IsExecutableData(const unsigned char* aContent, TUint32 aLength) + { + if (aLength <= sizeof(TUint32)*0x05) + { + return false; + } + const TUint32* data32 = reinterpret_cast(aContent); + bool isExecutable = false; + + if ( IsExeData(aContent, aLength) || + IsDllData(aContent, aLength) || + IsEmulatorExecutableData(aContent, aLength)) + { + isExecutable = true; + } + + return isExecutable; + } + +bool IsEmulatorExecutableData(const unsigned char* aContent, TUint32 aLength) + { + bool isEmulatorExe = false; + + // winscw binary + if (aLength > 2 && aContent[0] == 'M' && aContent[1] == 'Z') + { + isEmulatorExe = true; + } + + return isEmulatorExe; + } + + +bool IsExeData(const unsigned char* aContent, TUint32 aLength) + { + return (GetExecutableType(aContent, aLength) == KExecutableImageUid)? true: false; + } + +bool IsDllData(const unsigned char* aContent, TUint32 aLength) + { + return (GetExecutableType(aContent, aLength) == KDynamicLibraryUid)? true: false; + } + + +TInt32 GetExecutableType(const unsigned char* aContent, TUint32 aLength) + { + const TUint32* data32 = reinterpret_cast(aContent); + if(aLength < sizeof(TUint32)*0x05) + { + return 0; + } + + TInt32 type = 0; + + if(data32[0x04] == KFileHeaderSignature) + { + type = data32[0]; + } + else if (IsEmulatorExecutableData(aContent, aLength)) + { + const char symbian[] = ".SYMBIAN"; + const int len2 = sizeof(symbian)-1; + const unsigned char* index = std::search(aContent, aContent+aLength, symbian, symbian+len2); + + if ( (index + KHeaderUidLength < aContent+aLength) && (index != aContent+aLength) ) + { + index += KHeaderUidLength; + TInt32 offset = *(TInt32*)index; + + if (offset < aLength) + { + const TUint32* x = (TUint32*)(aContent+offset); + type = x[0]; + } + } + } + + return type; + }