--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/secureswitools/swisistools/source/dumpsislib/dumpsis.cpp Tue Jan 26 12:06:03 2010 +0200
@@ -0,0 +1,444 @@
+/*
+* Copyright (c) 2008-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:
+*
+*/
+
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4786)
+#endif
+
+#include <iostream>
+#include <sstream> // for strstream, wistringstream
+#include <stdio.h>
+#include <sys/stat.h>
+#include <algorithm>
+#include <functional>
+#include <set>
+
+
+#include "dumpsis.h"
+#include "siscontroller.h"
+#include "exception.h"
+
+CDumpSis::CDumpSis(const std::wstring& aSISFileName, bool aVerbose)
+ : iController(NULL),
+ iSisFileName(aSISFileName),
+ iVerbose(aVerbose),
+ iIsStub(false)
+ {
+ bool isSiSFile = CSISContents::IsSisFile(aSISFileName);
+ if(isSiSFile)
+ {
+ iSisContents.Load (iSisFileName);
+ iController = &iSisContents.Controller();
+ }
+ else
+ {
+ iIsStub = true;
+ iController = new CSISController;
+ SISLogger::Log(L"Dumping Stub SIS Controller\n");
+ iController->Load(iSisFileName);
+ }
+ }
+
+CDumpSis::~CDumpSis()
+ {
+ if(iIsStub)
+ {
+ delete iController;
+ }
+ }
+
+void CDumpSis::CreatePackage(const std::wstring& aPkgFileName)
+ {
+ std::wistringstream inStream (std::ios::in | std::ios::out);
+ std::wostream outStream (inStream.rdbuf ());
+
+ outStream << wchar_t(0xfeff);
+ if(iIsStub)
+ {
+ iController->AddPackageEntry (outStream, iVerbose);
+ }
+ else
+ {
+ iSisContents.AddPackageEntry (outStream, iVerbose);
+ }
+
+ std::wstring str = inStream.str();
+ WriteToFile(aPkgFileName, reinterpret_cast<const TUint8*>(str.c_str()), str.length()*2);
+ }
+
+void CDumpSis::CreatePackage(const CSISController& aSisController, const std::wstring& aPkgFileName)
+ {
+ std::wistringstream inStream (std::ios::in | std::ios::out);
+ std::wostream outStream (inStream.rdbuf ());
+
+ outStream << wchar_t(0xfeff);
+ aSisController.AddPackageEntry (outStream, iVerbose);
+ std::wstring str = inStream.str();
+ WriteToFile(aPkgFileName, reinterpret_cast<const TUint8*>(str.c_str()), str.length()*2);
+ }
+
+void CDumpSis::ExtractFiles(const std::wstring& aTargetDir, TExtractionLevel aLevel)
+ {
+ std::wstring targetDir = aTargetDir;
+ CreateTargetDir(targetDir);
+
+ switch(aLevel)
+ {
+ case EOnlyPackage:
+ {
+ ExtractBasePackageFile(targetDir);
+ break;
+ }
+ case ECertificates:
+ {
+ ExtractCertificates(*iController, targetDir);
+ break;
+ }
+ case EBaseFiles:
+ {
+ ExtractFiles(*iController, targetDir);
+ break;
+ }
+ case EAllDataFiles:
+ {
+ ExtractBasePackageFile(targetDir);
+ ExtractFiles(*iController, targetDir);
+ ExtractNestedSisFile(targetDir, *iController, false, 0, iSisContents.SisData().DataUnitCount());
+ break;
+ }
+ case EAllButCerts:
+ {
+ ExtractBasePackageFile(targetDir);
+ ExtractFiles(*iController, targetDir);
+ ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount());
+ break;
+ }
+ case EEverything:
+ {
+ ExtractBasePackageFile(targetDir);
+ ExtractFiles(*iController, targetDir);
+ ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount());
+ ExtractAllCertificates(targetDir);
+ break;
+ }
+ }
+ }
+
+void CDumpSis::ExtractAllCertificates(const std::wstring& aTargetDir)
+ {
+ ExtractCertificates(*iController, aTargetDir);
+
+ TControllerMap controllerList;
+ iController->InstallBlock().GetEmbeddedControllers(controllerList);
+
+ for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter)
+ {
+ wchar_t pathName[20];
+ swprintf(pathName, 20, L"sis%d", iter->first);
+
+ std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName;
+ CreateTargetDir(extractionPath);
+ ExtractCertificates(*iter->second, extractionPath);
+ }
+ }
+void CDumpSis::ExtractCertificates(const CSISController& aSisController, const std::wstring& aTargetDir)
+ {
+ TUint32 certChainCount = aSisController.SignatureCount();
+ for(TUint32 i = 0; i < certChainCount; ++i)
+ {
+ wchar_t certName[30];
+ swprintf(certName, 30, L"certChain%d%d.der", aSisController.DataIndex(), i+1);
+ std::wstring certFullPath = aTargetDir + KSisDirectorySeparator + certName;
+ const CCertChainData certChain = aSisController.SignatureCertChain(i).CertificateChain();
+ const TUint8* certChainData = certChain.CertificateData().Data();
+ TUint32 certSize = certChain.CertificateData().Size();
+ WriteToFile(certFullPath, certChainData, certSize);
+ }
+ }
+
+
+void CDumpSis::ExtractBasePackageFile(const std::wstring& aTargetDir)
+ {
+ std::wstring pkgFileName = iSisFileName;
+ pkgFileName = FixPathDelimiters(pkgFileName);
+ SisFileNameToPkgFileName(pkgFileName);
+ pkgFileName = aTargetDir + KSisDirectorySeparator + pkgFileName;
+ CreatePackage(pkgFileName);
+ }
+void CDumpSis::ExtractFiles(const CSISController& aSisController, const std::wstring& aTargetDir, int aBaseIndex)
+ {
+ if(iIsStub)
+ {
+ // There is no data associated with stub sis file.
+ return;
+ }
+ TFileDescList fileList;
+ aSisController.InstallBlock().GetFileList(fileList);
+ // Controller's index is relative to base controller's index.
+ TUint32 dataIndex = aBaseIndex + aSisController.DataIndex();
+ if(dataIndex >= iSisContents.SisData().DataUnitCount())
+ {
+ return;
+ }
+ const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(dataIndex);
+
+ const CSISLogo& logo = aSisController.Logo();
+ if(!logo.WasteOfSpace())
+ {
+ const CSISFileDescription& logoFile = logo.FileDesc();
+ const wchar_t* fileName = logoFile.GetFileName();
+ std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName;
+ const CSISFileData& fileData = dataUnit.FileData(logoFile.FileIndex());
+ WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize());
+ delete[] const_cast<wchar_t*>(fileName);
+ }
+
+
+ if(dataUnit.FileCount() <= 0)
+ {
+ return; // No files present to extract.
+ }
+
+ for(int i = 0; i < fileList.size(); ++i)
+ {
+ const CSISFileDescription* fdesc = fileList[i];
+ const wchar_t* fileName = fdesc->GetFileName();
+ std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName;
+ const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex());
+ WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize());
+ delete[] const_cast<wchar_t*>(fileName);
+ }
+ }
+
+void CDumpSis::ExtractNestedSisFile(const std::wstring& aTargetDir,
+ const CSISController& aController,
+ bool aExtractSis,
+ int aStartIndex,
+ int aEndIndex)
+ {
+ TControllerMap controllerList;
+ aController.InstallBlock().GetEmbeddedControllers(controllerList);
+
+ for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter)
+ {
+ TControllerMapConstIter nextIter = iter;
+ int curindex = iter->second->DataIndex();
+ int maxDataUnit = 0;
+ if (++nextIter != controllerList.end())
+ {
+ maxDataUnit = nextIter->first;
+ }
+ else
+ {
+ maxDataUnit = aEndIndex;
+ }
+ wchar_t pathName[20];
+#ifdef _MSC_VER
+ swprintf(pathName, L"sis%d", iter->second->GetControllerID());
+#else
+ swprintf(pathName, 20, L"sis%d", iter->second->GetControllerID());
+#endif //_MSC_VER
+
+ if(aExtractSis)
+ {
+ std::wstring sisPath = aTargetDir + KSisDirectorySeparator + pathName + L".sis";
+ CSISController* ctl = const_cast<CSISController*>(iter->second);
+ CreateEmbeddedSis(sisPath, *ctl, aStartIndex + iter->first, maxDataUnit);
+ }
+
+ std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName;
+ CreateTargetDir(extractionPath);
+ ExtractFiles(*iter->second, extractionPath, aStartIndex);
+ extractionPath = extractionPath + KSisDirectorySeparator + pathName + L".pkg";
+ CreatePackage(*iter->second, extractionPath);
+ ExtractNestedSisFile(aTargetDir, *(iter->second), aExtractSis, aStartIndex + iter->first, maxDataUnit);
+ }
+ }
+
+void CDumpSis::CreateTargetDir(std::wstring& aTargetDir)
+ {
+ aTargetDir = FixPathDelimiters(aTargetDir);
+ if(CreateDir(aTargetDir.c_str()) != 0)
+ {
+ return;
+ }
+
+ int err = GetErrorValue();
+
+ switch (err)
+ {
+ case ERROR_ALREADY_EXISTS:
+ {
+ int attrs;
+
+ if (0xFFFFFFFF != (attrs = FileAttributes(aTargetDir.c_str())))
+ {
+ if (!(attrs & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ throw CSISException::EDirIsFile;
+ }
+ else if (attrs & FILE_ATTRIBUTE_READONLY)
+ {
+ throw CSISException::EPermissionDenied;
+ }
+ }
+ else
+ {
+ throw CSISException::EInvalidDestination;
+ }
+ break;
+ }
+ case ERROR_PATH_NOT_FOUND:
+ CreateDirectoriesRecursively(aTargetDir);
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ throw CSISException::EInvalidDestination;
+ break;
+
+ case ERROR_INVALID_NAME:
+ aTargetDir = L".";
+ break;
+
+ default:
+ throw CSISException::EInvalidDestination;
+ }
+ }
+
+
+void CDumpSis::CreateDirectoriesRecursively(std::wstring aTargetDir)
+ {
+ int pos = aTargetDir.find(L'/');
+
+ if(0 == pos)
+ {
+ // Path starting with "/" can be skipped
+ pos = aTargetDir.find(L'/', 1);
+ }
+
+ while(pos != std::wstring::npos)
+ {
+ std::wstring path = aTargetDir.substr(0, pos);
+
+ if (0 == CreateDir(path.c_str()))
+ {
+ int err = GetErrorValue();
+ switch(err)
+ {
+ case ERROR_ACCESS_DENIED:
+ {
+ // If this is caused by a path like "D:" we can continue
+ bool validPath = ((aTargetDir.size() >= 2) && (isalpha(aTargetDir[0])) && (aTargetDir[1] ==L':'));
+ if (!validPath)
+ {
+ throw CSISException::EInvalidDestination;
+ }
+ break;
+ }
+
+ case ERROR_ALREADY_EXISTS:
+ // NOOP
+ break;
+
+ default:
+ throw CSISException::EInvalidDestination;
+ }
+ }
+ pos = aTargetDir.find(L'/', pos+1);
+ }
+
+ if (0 == CreateDir(aTargetDir.c_str()))
+ {
+ if ( GetErrorValue() != ERROR_ALREADY_EXISTS)
+ {
+ throw CSISException::EInvalidDestination;
+ }
+ }
+ }
+
+void CDumpSis::SisFileNameToPkgFileName(std::wstring& aFileName)
+ {
+ int pos = aFileName.find_last_of(L'/');
+ if(std::wstring::npos != pos)
+ {
+ aFileName = aFileName.substr(pos+1);
+ }
+
+ for(int i = 0; i < aFileName.size(); ++i)
+ {
+ aFileName[i] = tolower(aFileName[i]);
+ }
+
+ pos = aFileName.rfind(L".sis");
+ if(std::wstring::npos == pos)
+ {
+ pos = aFileName.rfind(L".ctl");
+ }
+
+ aFileName = aFileName.substr(0, pos);
+ aFileName.append(L".pkg");
+ }
+
+void CDumpSis::CreateEmbeddedSis(const std::wstring& aFileName, CSISController& aController, int aStart, int aEnd)
+ {
+ const CSISData& parentSisData = iSisContents.SisData();
+ TUint32 dataIndex = aController.DataIndex();
+ aController.SetDataIndex(0);
+ CSISCompressed<CSISController> compressedController(aController);
+ aController.SetDataIndex(dataIndex);
+
+ CSISData sisData;
+ for (int i = aStart; i < aEnd; ++i)
+ {
+ sisData.AddDataUnit(parentSisData.DataUnit(i));
+ }
+
+ CSISContents contents( const_cast<CSISControllerChecksum&>(iSisContents.ControllerChecksum()),
+ const_cast<CSISDataChecksum&>(iSisContents.DataChecksum()),
+ compressedController,
+ sisData
+ );
+
+ contents.Save(aFileName);
+ }
+
+void CDumpSis::GetCapVerifiedFileList(TFileCapTestList& aFileCapList)
+ {
+ TFileDescList fileList;
+ iSisContents.Controller().InstallBlock().GetFileList(fileList);
+ const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(0);
+ int fileCount = fileList.size();
+ for(int i = 0; i < fileCount; ++i)
+ {
+ const CSISFileDescription* fdesc = fileList[i];
+ const wchar_t* fileName = L"symbiantemp.xyz";
+ const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex());
+ WriteToFile(fileName, fileData.Data(), fileData.UncompressedSize());
+ CSISCapabilities capObj;
+ capObj.ExtractCapabilities(fileName);
+ TFileCapTest fileCapTest;
+ fileCapTest.iFileDesc = fdesc;
+ fileCapTest.iActualCap = capObj.Capabilities();
+ fileCapTest.iCapVerified = (fileCapTest.iActualCap == fileList[i]->Capabilities())? true : false;
+ aFileCapList.push_back(fileCapTest);
+ MakeSISDeleteFile(fileName);
+ }
+ }
+
+
+// End Of File