|
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 #include "sisutils.h" |
|
20 #include "sis2iby.h" |
|
21 |
|
22 /** |
|
23 Constructor: Sis2Iby class |
|
24 Initilize the parameters to data members. |
|
25 |
|
26 @internalComponent |
|
27 @released |
|
28 |
|
29 @param aFile - SIS file name |
|
30 */ |
|
31 Sis2Iby::Sis2Iby(char* aFile) : SisUtils(aFile) |
|
32 { |
|
33 } |
|
34 |
|
35 /** |
|
36 Destructor: Sis2Iby class |
|
37 Deallocates the memory for data members |
|
38 |
|
39 @internalComponent |
|
40 @released |
|
41 */ |
|
42 Sis2Iby::~Sis2Iby() |
|
43 { |
|
44 PKGFILE_MAP::iterator begin = iPkgFileMap.begin(); |
|
45 PKGFILE_MAP::iterator end = iPkgFileMap.end(); |
|
46 while(begin != end) |
|
47 { |
|
48 PPKGPARSER ptemp = 0; |
|
49 ptemp = (*begin).second; |
|
50 |
|
51 if(ptemp) |
|
52 delete ptemp; |
|
53 ++begin; |
|
54 } |
|
55 iPkgFileMap.clear(); |
|
56 } |
|
57 |
|
58 /** |
|
59 ProcessSisFile: Processes the input sis file |
|
60 Invoke the DUMPSIS tool to extract the sis file contents |
|
61 Creates package parser object for each of the package file |
|
62 |
|
63 @internalComponent |
|
64 @released |
|
65 */ |
|
66 void Sis2Iby::ProcessSisFile() |
|
67 { |
|
68 TUint32 retStatus = STAT_SUCCESS; |
|
69 String sisFile = SisFileName(); |
|
70 |
|
71 if(IsVerboseMode()) |
|
72 { |
|
73 std::cout << "Processing " << (char*)sisFile.data() << std::endl; |
|
74 } |
|
75 |
|
76 if(IsFileExist(sisFile)) |
|
77 { |
|
78 retStatus = InvokeExtractTool(sisFile); |
|
79 |
|
80 switch(retStatus) |
|
81 { |
|
82 case STAT_SUCCESS: |
|
83 { |
|
84 UpdatePkgFileMap(iExtractPath, sisFile); |
|
85 } |
|
86 break; |
|
87 case STAT_FAILURE: |
|
88 { |
|
89 throw SisUtilsException((char*)sisFile.data(), "Failed to extract SIS file"); |
|
90 } |
|
91 } |
|
92 } |
|
93 else |
|
94 throw SisUtilsException((char*)sisFile.data(), "File not found"); |
|
95 } |
|
96 |
|
97 /** |
|
98 GenerateOutput: Generates IBY for each of the package file |
|
99 |
|
100 @internalComponent |
|
101 @released |
|
102 */ |
|
103 void Sis2Iby::GenerateOutput() |
|
104 { |
|
105 PKGFILE_MAP::iterator begin = iPkgFileMap.begin(); |
|
106 PKGFILE_MAP::iterator end = iPkgFileMap.end(); |
|
107 while(begin != end) |
|
108 { |
|
109 GenerateIby((*begin).first, (*begin).second); |
|
110 ++begin; |
|
111 } |
|
112 } |
|
113 |
|
114 /** |
|
115 GenerateOutput: Generates IBY file for the given package file |
|
116 |
|
117 @internalComponent |
|
118 @released |
|
119 |
|
120 @param aPkgFile - package file name |
|
121 @param aParser - corresponding package file reader object |
|
122 */ |
|
123 void Sis2Iby::GenerateIby(String aPkgFile, PPKGPARSER aParser) |
|
124 { |
|
125 String ibyFile = iOutputPath; |
|
126 |
|
127 AppendFileName(ibyFile, aPkgFile); |
|
128 ibyFile.append(".iby"); |
|
129 |
|
130 if( !MakeDirectory(iOutputPath) ) |
|
131 throw SisUtilsException((char*)iOutputPath.data(), "Failed to create path"); |
|
132 |
|
133 if(IsVerboseMode()) |
|
134 { |
|
135 std::cout << "Generating IBY file " << (char*)ibyFile.data() << std::endl; |
|
136 } |
|
137 |
|
138 ibyHandle.open((char*)ibyFile.data(),(std::ios::out)); |
|
139 |
|
140 if(!ibyHandle.good()) |
|
141 { |
|
142 throw SisUtilsException((char*)ibyFile.data(), "Failed to create IBY file"); |
|
143 } |
|
144 |
|
145 // Generating Header |
|
146 MakeFullPath(aPkgFile); |
|
147 ibyHandle << "\n// Generated IBY file for the package file: "; |
|
148 ibyHandle << aPkgFile; |
|
149 |
|
150 // Language Supported |
|
151 WriteLanguages(aParser); |
|
152 |
|
153 // Package Header |
|
154 WritePackageHeader(aParser); |
|
155 |
|
156 // Install options list |
|
157 WriteInstallOptions(aParser); |
|
158 |
|
159 // Package Body |
|
160 WritePackageBody(aParser); |
|
161 |
|
162 ibyHandle.close(); |
|
163 } |
|
164 |
|
165 /** |
|
166 InvokeExtractTool: Invokes the SIS file extraction tool and returns the status |
|
167 |
|
168 @internalComponent |
|
169 @released |
|
170 |
|
171 @param sisFile - SIS file name |
|
172 */ |
|
173 TUint32 Sis2Iby::InvokeExtractTool(String sisFile) |
|
174 { |
|
175 String cmdLine; |
|
176 |
|
177 cmdLine.append(SISEXTRACT_TOOL_NAME SISEXTRACT_TOOL_DEFOPT); |
|
178 |
|
179 AppendFileName(iExtractPath, sisFile); |
|
180 |
|
181 cmdLine.append(SISEXTRACT_TOOL_EXTOPT); |
|
182 cmdLine.append("\"" + iExtractPath + "\" "); |
|
183 cmdLine.append(sisFile); |
|
184 |
|
185 if(IsVerboseMode()) |
|
186 { |
|
187 std::cout << "Executing " << (char*)cmdLine.data() << std::endl; |
|
188 } |
|
189 |
|
190 return RunCommand(cmdLine); |
|
191 } |
|
192 |
|
193 /** |
|
194 UpdatePkgFileMap: Update the package file map by getting the embedded sis file list from the parser object |
|
195 |
|
196 @internalComponent |
|
197 @released |
|
198 |
|
199 @param aPath - Extract path |
|
200 @param aFile - SIS file name |
|
201 */ |
|
202 void Sis2Iby::UpdatePkgFileMap(String aPath, String aFile) |
|
203 { |
|
204 String pkgFileName; |
|
205 std::list<String> sisList; |
|
206 |
|
207 // main pkg file |
|
208 pkgFileName = aPath; |
|
209 AppendFileName(pkgFileName, aFile); |
|
210 pkgFileName.append(".pkg"); |
|
211 |
|
212 // create an instance for the pkg file parser |
|
213 // get the embedded sis file list |
|
214 // add each as pkg file into the list |
|
215 pkgParser = 0; |
|
216 if( IsFileExist(pkgFileName) ) |
|
217 { |
|
218 pkgParser = new PkgParser(pkgFileName); |
|
219 |
|
220 if(pkgParser) |
|
221 { |
|
222 pkgParser->ParsePkgFile(); |
|
223 |
|
224 iPkgFileMap[pkgFileName] = pkgParser; |
|
225 |
|
226 pkgParser->GetEmbeddedSisList(sisList); |
|
227 SISFILE_LIST::iterator begin = sisList.begin(); |
|
228 SISFILE_LIST::iterator end = sisList.end(); |
|
229 |
|
230 while(begin != end) |
|
231 { |
|
232 String currPath = aPath; |
|
233 |
|
234 currPath.append(PATHSEPARATOR); |
|
235 GetFileName((*begin), currPath); |
|
236 UpdatePkgFileMap(currPath, (*begin)); |
|
237 |
|
238 ++begin; |
|
239 } |
|
240 } |
|
241 else |
|
242 throw SisUtilsException((char*)pkgFileName.data(), "Could not create parser object"); |
|
243 } |
|
244 else |
|
245 throw SisUtilsException((char*)pkgFileName.data(), "File not found"); |
|
246 } |
|
247 |
|
248 /** |
|
249 WriteLanguages: Writes language section in the IBY file |
|
250 |
|
251 @internalComponent |
|
252 @released |
|
253 |
|
254 @param aParser - Package file parser object |
|
255 */ |
|
256 void Sis2Iby::WriteLanguages(PPKGPARSER aParser) |
|
257 { |
|
258 LANGUAGE_LIST lanMap; |
|
259 PLANG_LIST langCode; |
|
260 |
|
261 aParser->GetLanguageList(lanMap); |
|
262 ibyHandle << "\n// Languages: "; |
|
263 |
|
264 LANGUAGE_LIST::iterator begin = lanMap.begin(); |
|
265 LANGUAGE_LIST::iterator end = lanMap.end(); |
|
266 |
|
267 while(begin != end) |
|
268 { |
|
269 langCode = (*begin); |
|
270 |
|
271 ibyHandle << " " << langCode->langName; |
|
272 ibyHandle << "(" << langCode->langCode; |
|
273 |
|
274 if(langCode->dialectCode) |
|
275 { |
|
276 ibyHandle << "-" << langCode->dialectCode; |
|
277 } |
|
278 ibyHandle << ")"; |
|
279 |
|
280 ++begin; |
|
281 } |
|
282 } |
|
283 |
|
284 /** |
|
285 WritePackageHeader: Writes package header section in the IBY file |
|
286 |
|
287 @internalComponent |
|
288 @released |
|
289 |
|
290 @param aParser - Package file parser object |
|
291 */ |
|
292 void Sis2Iby::WritePackageHeader(PPKGPARSER aParser) |
|
293 { |
|
294 PKG_HEADER pkgHeader; |
|
295 std::list<String> pkgList; |
|
296 std::ostringstream str; |
|
297 |
|
298 aParser->GetHeader(pkgHeader); |
|
299 |
|
300 ibyHandle << "\n// Header: "; |
|
301 |
|
302 pkgList = pkgHeader.pkgNameList; |
|
303 while(pkgList.size()) |
|
304 { |
|
305 ibyHandle << "\"" << pkgList.front() << "\" "; |
|
306 pkgList.pop_front(); |
|
307 } |
|
308 |
|
309 str << "(0x" << std::setbase(16) << pkgHeader.pkgUid << ")"; |
|
310 |
|
311 ibyHandle << str.str(); |
|
312 } |
|
313 |
|
314 /** |
|
315 WriteInstallOptions: Writes install option section in the IBY file |
|
316 |
|
317 @internalComponent |
|
318 @released |
|
319 |
|
320 @param aParser - Package file parser object |
|
321 */ |
|
322 void Sis2Iby::WriteInstallOptions(PPKGPARSER aParser) |
|
323 { |
|
324 std::list<String> optList; |
|
325 String ibyName; |
|
326 |
|
327 aParser->GetInstallOptions(optList); |
|
328 SISFILE_LIST::iterator begin = optList.begin(); |
|
329 SISFILE_LIST::iterator end = optList.end(); |
|
330 |
|
331 if(begin != end) |
|
332 { |
|
333 ibyHandle << "\n// Install Options: "; |
|
334 } |
|
335 |
|
336 while(begin != end) |
|
337 { |
|
338 ibyHandle << " \"" << (*begin) << "\""; |
|
339 ++begin; |
|
340 } |
|
341 } |
|
342 |
|
343 /** |
|
344 InsertTabs: Inserts spaces for indentation in the output IBY file |
|
345 |
|
346 @internalComponent |
|
347 @released |
|
348 |
|
349 @param num - num of spaces to be inserted |
|
350 */ |
|
351 void Sis2Iby::InsertTabs(int num) |
|
352 { |
|
353 ibyHandle << "\n"; |
|
354 while(num--) |
|
355 { |
|
356 ibyHandle << " "; |
|
357 } |
|
358 } |
|
359 |
|
360 /** |
|
361 WritePackageBody: Writes package body details in the IBY file |
|
362 |
|
363 @internalComponent |
|
364 @released |
|
365 |
|
366 @param aParser - Package file parser object |
|
367 */ |
|
368 void Sis2Iby::WritePackageBody(PPKGPARSER aParser) |
|
369 { |
|
370 CMDBLOCK_LIST cmdList; |
|
371 PCMD_BLOCK cmd; |
|
372 int pad = 0; |
|
373 |
|
374 ibyHandle << "\n\n"; |
|
375 aParser->GetCommandList(cmdList); |
|
376 |
|
377 CMDBLOCK_LIST::iterator begin = cmdList.begin(); |
|
378 CMDBLOCK_LIST::iterator end = cmdList.end(); |
|
379 |
|
380 while(begin != end) |
|
381 { |
|
382 cmd = (*begin); |
|
383 |
|
384 switch(cmd->cmdType) |
|
385 { |
|
386 case IF: |
|
387 { |
|
388 InsertTabs(pad); |
|
389 ibyHandle << "#if " << cmd->cmdExpression; |
|
390 pad++; |
|
391 } |
|
392 break; |
|
393 case ELSEIF: |
|
394 { |
|
395 InsertTabs(pad-1); |
|
396 ibyHandle << "#elif " << cmd->cmdExpression; |
|
397 } |
|
398 break; |
|
399 case ELSE: |
|
400 { |
|
401 InsertTabs(pad-1); |
|
402 ibyHandle << "#else"; |
|
403 } |
|
404 break; |
|
405 case ENDIF: |
|
406 { |
|
407 --pad; |
|
408 InsertTabs(pad); |
|
409 ibyHandle << "#endif"; |
|
410 } |
|
411 break; |
|
412 case INSTALLFILE: |
|
413 { |
|
414 WriteInstallFileList(cmd->iInstallFileList, aParser, pad); |
|
415 } |
|
416 break; |
|
417 case PACKAGE: |
|
418 { |
|
419 InsertTabs(pad); |
|
420 ibyHandle << "#include " << "\"" << cmd->cmdExpression << "\""; |
|
421 } |
|
422 break; |
|
423 } |
|
424 |
|
425 ++begin; |
|
426 } |
|
427 } |
|
428 |
|
429 /** |
|
430 WriteFileInclusion: Writes installable file details in the IBY file |
|
431 |
|
432 @internalComponent |
|
433 @released |
|
434 |
|
435 @param aSrcFile - Name of the source file |
|
436 @param aDestFile - Name of the destination file |
|
437 @param aPkgName - Name of the package file |
|
438 */ |
|
439 void Sis2Iby::WriteFileInclusion(String aSrcFile, String aDestFile, String aPkgName, int pad) |
|
440 { |
|
441 NormaliseSourceFile(aSrcFile, aPkgName); |
|
442 |
|
443 InsertTabs(pad); |
|
444 if(IsValidE32Image(aSrcFile)) |
|
445 { |
|
446 ibyHandle << "file = "; |
|
447 } |
|
448 else |
|
449 { |
|
450 ibyHandle << "data = "; |
|
451 } |
|
452 |
|
453 ibyHandle << aSrcFile << " "; |
|
454 NormaliseDestFile(aDestFile); |
|
455 ibyHandle << aDestFile; |
|
456 } |
|
457 |
|
458 /** |
|
459 WriteInstallFileList: Writes installable file details in the IBY file |
|
460 |
|
461 @internalComponent |
|
462 @released |
|
463 |
|
464 @param aFileList - Installable file list structure |
|
465 @param aParser - Package file parser object |
|
466 @param pad - Number of spaces for indentation purpose |
|
467 */ |
|
468 void Sis2Iby::WriteInstallFileList(PINSTALLFILE_LIST aFileList, PPKGPARSER aParser, int pad) |
|
469 { |
|
470 WriteFileInclusion(aFileList->srcFiles.front(), aFileList->destFile, aParser->GetPkgFileName(), pad); |
|
471 } |
|
472 |
|
473 /** |
|
474 AppendFileName: Appends file name to the given path |
|
475 |
|
476 @internalComponent |
|
477 @released |
|
478 |
|
479 @param aPath - Source path |
|
480 @param aFile - File name |
|
481 */ |
|
482 void Sis2Iby::AppendFileName(String& aPath, String aFile) |
|
483 { |
|
484 TUint pos = 0; |
|
485 |
|
486 TrimQuotes(aPath); |
|
487 TrimQuotes(aFile); |
|
488 |
|
489 pos = aPath.rfind(PATHSEPARATOR); |
|
490 if(pos == String::npos) |
|
491 { |
|
492 aPath.append(PATHSEPARATOR); |
|
493 } |
|
494 |
|
495 if(pos < (aPath.length()-1)) |
|
496 { |
|
497 aPath.append(PATHSEPARATOR); |
|
498 } |
|
499 |
|
500 GetFileName(aFile, aPath); |
|
501 return; |
|
502 } |
|
503 |
|
504 /** |
|
505 GetFileName: Returns the base file name |
|
506 |
|
507 @internalComponent |
|
508 @released |
|
509 |
|
510 @param aName - Input file name |
|
511 @param aFile - Output parameter to hold the return value |
|
512 */ |
|
513 void Sis2Iby::GetFileName(String aName, String& aFile) |
|
514 { |
|
515 TUint spos = 0, epos = 0; |
|
516 |
|
517 spos = aName.rfind(PATHSEPARATOR); |
|
518 if(spos != String::npos) |
|
519 { |
|
520 spos += 1; |
|
521 } |
|
522 else |
|
523 { |
|
524 spos = 0; |
|
525 } |
|
526 |
|
527 epos = aName.rfind("."); |
|
528 if(epos == String::npos) |
|
529 { |
|
530 epos = aName.size(); |
|
531 } |
|
532 |
|
533 aFile.append(aName.substr(spos, (epos-spos))); |
|
534 } |
|
535 |
|
536 /** |
|
537 MakeFullPath: Returns the absolute path of the given file |
|
538 |
|
539 @internalComponent |
|
540 @released |
|
541 |
|
542 @param aFile - Input file name |
|
543 */ |
|
544 void Sis2Iby::MakeFullPath(String& aFile) |
|
545 { |
|
546 #ifdef WIN32 |
|
547 char fPath[_MAX_PATH]; |
|
548 |
|
549 if( _fullpath(fPath, (char*)aFile.data(), _MAX_PATH) != NULL ) |
|
550 { |
|
551 aFile.assign(fPath); |
|
552 } |
|
553 #else |
|
554 #error "TODO: Implement this function under other OS than Windows" |
|
555 #endif |
|
556 return; |
|
557 } |
|
558 |
|
559 /** |
|
560 NormaliseSourceFile: Normalise the source file with its absolute path |
|
561 |
|
562 @internalComponent |
|
563 @released |
|
564 |
|
565 @param aFile - Input file name |
|
566 @param aPkgFile - Package file path |
|
567 */ |
|
568 void Sis2Iby::NormaliseSourceFile(String& aFile, String aPkgFile) |
|
569 { |
|
570 String result; |
|
571 TUint pos = 0; |
|
572 |
|
573 pos = aPkgFile.rfind(PATHSEPARATOR); |
|
574 if(pos != String::npos) |
|
575 { |
|
576 result = aPkgFile.substr(0,pos); |
|
577 } |
|
578 else |
|
579 { |
|
580 result = "."; |
|
581 } |
|
582 |
|
583 result.append(PATHSEPARATOR); |
|
584 result.append(aFile); |
|
585 |
|
586 MakeFullPath(result); |
|
587 |
|
588 aFile = "\"" + result + "\""; |
|
589 } |
|
590 |
|
591 /** |
|
592 NormaliseDestFile: Normalise the destination file |
|
593 |
|
594 @internalComponent |
|
595 @released |
|
596 |
|
597 @param aFile - Input file name |
|
598 */ |
|
599 void Sis2Iby::NormaliseDestFile(String& aFile) |
|
600 { |
|
601 TUint pos = 0; |
|
602 |
|
603 /** Comment by KunXu to fix DEF122540 on 18 Jun 2008 |
|
604 pos = aFile.find("$:"); |
|
605 if(pos != String::npos) |
|
606 { |
|
607 aFile.replace(pos, 2, ""); |
|
608 } |
|
609 |
|
610 pos = aFile.find("!:"); |
|
611 if(pos != String::npos) |
|
612 { |
|
613 aFile.replace(pos, 2, ""); |
|
614 } |
|
615 **/ |
|
616 |
|
617 /** Add by KunXu to fix DEF122540 on 18 Jun 2008 **/ |
|
618 /** Ignore any drive indication in the filename to generate an iby file **/ |
|
619 /** Begin **/ |
|
620 pos = aFile.find(":"); |
|
621 if (1 == pos) |
|
622 { |
|
623 char chFirst = aFile[0]; |
|
624 if ('$' == chFirst || '!' == chFirst || (chFirst >='a' && chFirst <='z') || (chFirst >='A' && chFirst <='Z')) |
|
625 { |
|
626 aFile.replace(0, 2, ""); |
|
627 } |
|
628 } |
|
629 /** End **/ |
|
630 |
|
631 aFile = "\"" + aFile + "\""; |
|
632 } |
|
633 |
|
634 /** |
|
635 IsValidE32Image: Checks whether the given file is E32 image |
|
636 |
|
637 @internalComponent |
|
638 @released |
|
639 |
|
640 @param aFile - Input file name |
|
641 */ |
|
642 TBool Sis2Iby::IsValidE32Image(String aFile) |
|
643 { |
|
644 std::ifstream aIfs; |
|
645 TInt8 aSig[5]; |
|
646 TUint32 e32SigOffset = 0x10, fileSize = 0; |
|
647 TBool validE32 = EFalse; |
|
648 |
|
649 TrimQuotes(aFile); |
|
650 |
|
651 aIfs.open(aFile.c_str(), std::ios::in | std::ios::binary); |
|
652 |
|
653 if( !aIfs.is_open() ) |
|
654 { |
|
655 throw SisUtilsException((char*)aFile.data(), "Cannot open file"); |
|
656 } |
|
657 |
|
658 aIfs.seekg(0,std::ios::end); |
|
659 fileSize = aIfs.tellg(); |
|
660 if(fileSize > 20) |
|
661 { |
|
662 aIfs.seekg(e32SigOffset,std::ios::beg); |
|
663 aIfs.read((char*)aSig, 4); |
|
664 aSig[4] = '\0'; |
|
665 |
|
666 if(!strcmp((char*)aSig, "EPOC")) |
|
667 { |
|
668 validE32 = ETrue; |
|
669 } |
|
670 } |
|
671 |
|
672 aIfs.close(); |
|
673 |
|
674 return validE32; |
|
675 } |