|
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 |