secureswitools/swisistools/source/dumpsislib/dumpsis.cpp
changeset 0 ba25891c3a9e
child 24 5cc91383ab1e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2008-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 
       
    19 #ifdef _MSC_VER
       
    20 #pragma warning (disable: 4786)
       
    21 #endif 
       
    22 
       
    23 #include <iostream>
       
    24 #include <sstream>    // for strstream, wistringstream
       
    25 #include <stdio.h>
       
    26 #include <sys/stat.h>
       
    27 #include <algorithm>
       
    28 #include <functional>
       
    29 #include <set>
       
    30 
       
    31 
       
    32 #include "dumpsis.h"
       
    33 #include "siscontroller.h"
       
    34 #include "exception.h"
       
    35 
       
    36 CDumpSis::CDumpSis(const std::wstring& aSISFileName, bool aVerbose)
       
    37 		: 	iController(NULL),
       
    38 			iSisFileName(aSISFileName),
       
    39 			iVerbose(aVerbose),
       
    40 			iIsStub(false)
       
    41 	{
       
    42 	bool isSiSFile = CSISContents::IsSisFile(aSISFileName);
       
    43 	if(isSiSFile)
       
    44 		{
       
    45 		iSisContents.Load (iSisFileName);
       
    46 		iController = &iSisContents.Controller();
       
    47 		}
       
    48 	else
       
    49 		{
       
    50 		iIsStub = true;
       
    51 		iController = new CSISController;
       
    52 		SISLogger::Log(L"Dumping Stub SIS Controller\n");
       
    53 		iController->Load(iSisFileName);
       
    54 		}
       
    55 	}
       
    56 
       
    57 CDumpSis::~CDumpSis()
       
    58 	{
       
    59 	if(iIsStub)
       
    60 		{
       
    61 		delete iController;
       
    62 		}
       
    63 	}
       
    64 
       
    65 void CDumpSis::CreatePackage(const std::wstring& aPkgFileName)
       
    66 	{
       
    67 	std::wistringstream inStream (std::ios::in | std::ios::out);
       
    68 	std::wostream outStream (inStream.rdbuf ());
       
    69 
       
    70 	outStream << wchar_t(0xfeff);
       
    71 	if(iIsStub)
       
    72 		{
       
    73 		iController->AddPackageEntry (outStream, iVerbose);
       
    74 		}
       
    75 	else
       
    76 		{
       
    77 		iSisContents.AddPackageEntry (outStream, iVerbose);
       
    78 		}
       
    79 	
       
    80 	std::wstring str = inStream.str();
       
    81 	WriteToFile(aPkgFileName, reinterpret_cast<const TUint8*>(str.c_str()), str.length()*2);
       
    82 	}
       
    83 
       
    84 void CDumpSis::CreatePackage(const CSISController& aSisController, const std::wstring& aPkgFileName)
       
    85 	{
       
    86 	std::wistringstream inStream (std::ios::in | std::ios::out);
       
    87 	std::wostream outStream (inStream.rdbuf ());
       
    88 
       
    89 	outStream << wchar_t(0xfeff);
       
    90 	aSisController.AddPackageEntry (outStream, iVerbose);
       
    91 	std::wstring str = inStream.str();
       
    92 	WriteToFile(aPkgFileName, reinterpret_cast<const TUint8*>(str.c_str()), str.length()*2);
       
    93 	}
       
    94 
       
    95 void CDumpSis::ExtractFiles(const std::wstring& aTargetDir, TExtractionLevel aLevel)
       
    96 	{
       
    97 	std::wstring targetDir = aTargetDir;
       
    98 	CreateTargetDir(targetDir);
       
    99 	
       
   100 	switch(aLevel)
       
   101 		{
       
   102 		case EOnlyPackage:
       
   103 			{
       
   104 			ExtractBasePackageFile(targetDir);
       
   105 			break;
       
   106 			}
       
   107 		case ECertificates:
       
   108 			{
       
   109 			ExtractCertificates(*iController, targetDir);
       
   110 			break;
       
   111 			}
       
   112 		case EBaseFiles:
       
   113 			{
       
   114 			ExtractFiles(*iController, targetDir);
       
   115 			break;
       
   116 			}
       
   117 		case EAllDataFiles:
       
   118 			{
       
   119 			ExtractBasePackageFile(targetDir);	
       
   120 			ExtractFiles(*iController, targetDir);
       
   121 			ExtractNestedSisFile(targetDir, *iController, false, 0, iSisContents.SisData().DataUnitCount());
       
   122 			break;
       
   123 			}
       
   124 		case EAllButCerts:
       
   125 			{
       
   126 			ExtractBasePackageFile(targetDir);	
       
   127 			ExtractFiles(*iController, targetDir);
       
   128 			ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount());
       
   129 			break;
       
   130 			}
       
   131 		case EEverything:
       
   132 			{
       
   133 			ExtractBasePackageFile(targetDir);	
       
   134 			ExtractFiles(*iController, targetDir);
       
   135 			ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount());
       
   136 			ExtractAllCertificates(targetDir);
       
   137 			break;
       
   138 			}
       
   139 		}
       
   140 	}
       
   141 
       
   142 void CDumpSis::ExtractAllCertificates(const std::wstring& aTargetDir)
       
   143 	{
       
   144 	ExtractCertificates(*iController, aTargetDir);
       
   145 	
       
   146 	TControllerMap controllerList;
       
   147 	iController->InstallBlock().GetEmbeddedControllers(controllerList);
       
   148 	
       
   149 	for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter)
       
   150 		{
       
   151 		wchar_t pathName[20];
       
   152 		swprintf(pathName, 20, L"sis%d", iter->first);
       
   153 
       
   154 		std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName;
       
   155 		CreateTargetDir(extractionPath);
       
   156 		ExtractCertificates(*iter->second, extractionPath);
       
   157 		}	
       
   158 	}
       
   159 void CDumpSis::ExtractCertificates(const CSISController& aSisController, const std::wstring& aTargetDir)
       
   160 	{
       
   161 	TUint32 certChainCount = aSisController.SignatureCount();
       
   162 	for(TUint32 i = 0; i < certChainCount; ++i)
       
   163 		{
       
   164 		wchar_t certName[30];
       
   165 		swprintf(certName, 30, L"certChain%d%d.der", aSisController.DataIndex(), i+1);
       
   166 		std::wstring certFullPath = aTargetDir + KSisDirectorySeparator + certName;
       
   167 		const CCertChainData certChain = aSisController.SignatureCertChain(i).CertificateChain();
       
   168 		const TUint8* certChainData = certChain.CertificateData().Data();
       
   169 		TUint32 certSize =  certChain.CertificateData().Size();
       
   170 		WriteToFile(certFullPath, certChainData, certSize);
       
   171 		}
       
   172 	}
       
   173 
       
   174 
       
   175 void CDumpSis::ExtractBasePackageFile(const std::wstring& aTargetDir)
       
   176 	{
       
   177 	std::wstring pkgFileName = iSisFileName;
       
   178 	pkgFileName = FixPathDelimiters(pkgFileName);
       
   179 	SisFileNameToPkgFileName(pkgFileName);
       
   180 	pkgFileName = aTargetDir + KSisDirectorySeparator + pkgFileName;
       
   181 	CreatePackage(pkgFileName);
       
   182 	}
       
   183 void CDumpSis::ExtractFiles(const CSISController& aSisController, const std::wstring& aTargetDir, int aBaseIndex)
       
   184 	{
       
   185 	if(iIsStub)
       
   186 		{
       
   187 		// There is no data associated with stub sis file.
       
   188 		return;
       
   189 		}
       
   190 	TFileDescList fileList;
       
   191 	aSisController.InstallBlock().GetFileList(fileList);
       
   192 	// Controller's index is relative to base controller's index.
       
   193 	TUint32 dataIndex = aBaseIndex + aSisController.DataIndex();
       
   194 	if(dataIndex >= iSisContents.SisData().DataUnitCount())
       
   195 		{
       
   196 		return;
       
   197 		}
       
   198 	const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(dataIndex);
       
   199 	
       
   200 	const CSISLogo& logo = aSisController.Logo();
       
   201 	if(!logo.WasteOfSpace())
       
   202 		{
       
   203 		const CSISFileDescription& logoFile = logo.FileDesc();
       
   204 		const wchar_t* fileName = logoFile.GetFileName();
       
   205 		std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName;
       
   206 		const CSISFileData& fileData = dataUnit.FileData(logoFile.FileIndex());
       
   207 		WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize());
       
   208 		delete[] const_cast<wchar_t*>(fileName);
       
   209 		}
       
   210 	
       
   211 	
       
   212 	if(dataUnit.FileCount() <= 0)
       
   213 		{
       
   214 		return; // No files present to extract.
       
   215 		}
       
   216 
       
   217 	for(int i = 0; i < fileList.size(); ++i)
       
   218 		{
       
   219 		const CSISFileDescription* fdesc = fileList[i];
       
   220 		const wchar_t* fileName = fdesc->GetFileName();
       
   221 		std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName;
       
   222 		const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex());
       
   223 		WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize());
       
   224 		delete[] const_cast<wchar_t*>(fileName);
       
   225 		}
       
   226 	}
       
   227 
       
   228 void CDumpSis::ExtractNestedSisFile(const std::wstring& aTargetDir, 
       
   229 									const CSISController& aController,
       
   230 									bool aExtractSis,
       
   231 									int aStartIndex, 
       
   232 									int aEndIndex)
       
   233 	{
       
   234 	TControllerMap controllerList;
       
   235 	aController.InstallBlock().GetEmbeddedControllers(controllerList);
       
   236 	
       
   237 	for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter)
       
   238 		{
       
   239 		TControllerMapConstIter nextIter = iter;
       
   240 		int curindex = iter->second->DataIndex();
       
   241 		int maxDataUnit = 0;
       
   242 		if (++nextIter != controllerList.end())
       
   243 			{
       
   244 			maxDataUnit = nextIter->first;
       
   245 			}
       
   246 		else
       
   247 			{
       
   248 			maxDataUnit = aEndIndex;
       
   249 			}
       
   250 		wchar_t pathName[20];
       
   251 #ifdef _MSC_VER
       
   252 		swprintf(pathName, L"sis%d", iter->second->GetControllerID());
       
   253 #else
       
   254 		swprintf(pathName, 20, L"sis%d", iter->second->GetControllerID());
       
   255 #endif //_MSC_VER
       
   256 		
       
   257 		if(aExtractSis)
       
   258 			{
       
   259 			std::wstring sisPath = aTargetDir + KSisDirectorySeparator + pathName + L".sis";
       
   260 			CSISController* ctl = const_cast<CSISController*>(iter->second);
       
   261 			CreateEmbeddedSis(sisPath, *ctl, aStartIndex + iter->first, maxDataUnit);
       
   262 			}
       
   263 
       
   264 		std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName;
       
   265 		CreateTargetDir(extractionPath);
       
   266 		ExtractFiles(*iter->second, extractionPath, aStartIndex);
       
   267 		extractionPath = extractionPath + KSisDirectorySeparator + pathName + L".pkg";
       
   268 		CreatePackage(*iter->second, extractionPath);
       
   269 		ExtractNestedSisFile(aTargetDir, *(iter->second), aExtractSis, aStartIndex + iter->first, maxDataUnit);
       
   270 		}
       
   271 	}
       
   272 
       
   273 void CDumpSis::CreateTargetDir(std::wstring& aTargetDir)
       
   274 	{
       
   275 	aTargetDir = FixPathDelimiters(aTargetDir);
       
   276 	if(CreateDir(aTargetDir.c_str()) != 0)
       
   277 		{
       
   278 		return;
       
   279 		}
       
   280 
       
   281 	int err = GetErrorValue();
       
   282 	
       
   283 	switch (err)
       
   284 		{
       
   285 		case ERROR_ALREADY_EXISTS:
       
   286 			{
       
   287 			int attrs;
       
   288 
       
   289 			if (0xFFFFFFFF != (attrs = FileAttributes(aTargetDir.c_str())))
       
   290 				{
       
   291 				if (!(attrs & FILE_ATTRIBUTE_DIRECTORY))
       
   292 					{
       
   293 					throw CSISException::EDirIsFile;
       
   294 					}
       
   295 				else if (attrs & FILE_ATTRIBUTE_READONLY)
       
   296 					{
       
   297 					throw CSISException::EPermissionDenied;
       
   298 					}
       
   299 				}
       
   300 			else
       
   301 				{
       
   302 				throw CSISException::EInvalidDestination;
       
   303 				}
       
   304 			break;
       
   305 			}
       
   306 		case ERROR_PATH_NOT_FOUND:
       
   307 			CreateDirectoriesRecursively(aTargetDir);
       
   308 			break;
       
   309 
       
   310 		case ERROR_ACCESS_DENIED:
       
   311 			throw CSISException::EInvalidDestination;
       
   312 			break;
       
   313 
       
   314 		case ERROR_INVALID_NAME:
       
   315 			aTargetDir = L".";
       
   316 			break;
       
   317 
       
   318 		default:
       
   319 			throw CSISException::EInvalidDestination;
       
   320 		}
       
   321 	}
       
   322 
       
   323 
       
   324 void CDumpSis::CreateDirectoriesRecursively(std::wstring aTargetDir)
       
   325 	{
       
   326 	int pos = aTargetDir.find(L'/');
       
   327 	
       
   328 	if(0 == pos)
       
   329 		{
       
   330 		// Path starting with "/" can be skipped
       
   331 		pos = aTargetDir.find(L'/', 1);
       
   332 		}
       
   333 	
       
   334 	while(pos != std::wstring::npos)
       
   335 		{
       
   336 		std::wstring path = aTargetDir.substr(0, pos);
       
   337 		
       
   338 		if (0 == CreateDir(path.c_str()))
       
   339 			{
       
   340 			int err = GetErrorValue();
       
   341 			switch(err)
       
   342 				{
       
   343 				case ERROR_ACCESS_DENIED:
       
   344 					{
       
   345 					// If this is caused by a path like "D:" we can continue
       
   346 					bool validPath = ((aTargetDir.size() >= 2) && (isalpha(aTargetDir[0])) && (aTargetDir[1] ==L':'));
       
   347 					if (!validPath)
       
   348 						{
       
   349 						throw CSISException::EInvalidDestination;
       
   350 						}
       
   351 					break;
       
   352 					}
       
   353 	
       
   354 				case ERROR_ALREADY_EXISTS:
       
   355 					// NOOP
       
   356 					break;
       
   357 	
       
   358 				default:
       
   359 					throw CSISException::EInvalidDestination;
       
   360 				}
       
   361 			}
       
   362 		pos = aTargetDir.find(L'/', pos+1);
       
   363 		}
       
   364 
       
   365 	if (0 == CreateDir(aTargetDir.c_str()))
       
   366 		{
       
   367 		if ( GetErrorValue() != ERROR_ALREADY_EXISTS)
       
   368 			{
       
   369 			throw CSISException::EInvalidDestination;
       
   370 			}
       
   371 		}
       
   372 	}
       
   373 
       
   374 void CDumpSis::SisFileNameToPkgFileName(std::wstring& aFileName)
       
   375 	{
       
   376 	int pos = aFileName.find_last_of(L'/');
       
   377 	if(std::wstring::npos != pos)
       
   378 		{
       
   379 		aFileName = aFileName.substr(pos+1);
       
   380 		}
       
   381 
       
   382 	for(int i = 0; i < aFileName.size(); ++i)
       
   383 		{
       
   384 		aFileName[i] = tolower(aFileName[i]);
       
   385 		}
       
   386 	
       
   387 	pos = aFileName.rfind(L".sis");
       
   388 	if(std::wstring::npos == pos)
       
   389 		{
       
   390 		pos = aFileName.rfind(L".ctl");
       
   391 		}
       
   392 
       
   393 	aFileName = aFileName.substr(0, pos);
       
   394 	aFileName.append(L".pkg");
       
   395 	}
       
   396 
       
   397 void CDumpSis::CreateEmbeddedSis(const std::wstring& aFileName, CSISController& aController, int aStart, int aEnd)
       
   398 	{
       
   399 	const CSISData& parentSisData = iSisContents.SisData();
       
   400 	TUint32 dataIndex = aController.DataIndex();
       
   401 	aController.SetDataIndex(0);
       
   402 	CSISCompressed<CSISController> compressedController(aController);
       
   403 	aController.SetDataIndex(dataIndex);
       
   404 
       
   405 	CSISData sisData;
       
   406 	for (int i = aStart; i < aEnd; ++i)
       
   407 		{
       
   408 		sisData.AddDataUnit(parentSisData.DataUnit(i));
       
   409 		}
       
   410 	
       
   411 	CSISContents contents(	const_cast<CSISControllerChecksum&>(iSisContents.ControllerChecksum()),
       
   412 							const_cast<CSISDataChecksum&>(iSisContents.DataChecksum()),
       
   413 							compressedController,
       
   414 							sisData
       
   415 						 	);
       
   416 	
       
   417 	contents.Save(aFileName);
       
   418 	}
       
   419 
       
   420 void CDumpSis::GetCapVerifiedFileList(TFileCapTestList& aFileCapList)
       
   421 	{
       
   422 	TFileDescList fileList;
       
   423 	iSisContents.Controller().InstallBlock().GetFileList(fileList);
       
   424 	const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(0);
       
   425 	int fileCount = fileList.size();
       
   426 	for(int i = 0; i < fileCount; ++i)
       
   427 		{
       
   428 		const CSISFileDescription* fdesc = fileList[i];
       
   429 		const wchar_t* fileName = L"symbiantemp.xyz";
       
   430 		const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex());
       
   431 		WriteToFile(fileName, fileData.Data(), fileData.UncompressedSize());
       
   432 		CSISCapabilities capObj;
       
   433 		capObj.ExtractCapabilities(fileName);
       
   434 		TFileCapTest fileCapTest;
       
   435 		fileCapTest.iFileDesc = fdesc;
       
   436 		fileCapTest.iActualCap = capObj.Capabilities();
       
   437 		fileCapTest.iCapVerified = (fileCapTest.iActualCap == fileList[i]->Capabilities())? true : false;
       
   438 		aFileCapList.push_back(fileCapTest);
       
   439 		MakeSISDeleteFile(fileName);
       
   440 		}
       
   441 	}
       
   442 
       
   443 
       
   444 // End Of File