/*
* 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 <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <fstream>
#include <algorithm>
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 <TUint64> (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 <size_t> (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<const TUint32*>(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<const TUint32*>(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<const TUint32*>(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;
}