|
1 /* |
|
2 * Copyright (c) 2004-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 /** |
|
20 @file |
|
21 @internalComponent |
|
22 @released |
|
23 */ |
|
24 |
|
25 #include "utility.h" |
|
26 #include "exception.h" |
|
27 #include "utility_interface.h" |
|
28 #include "utils.h" |
|
29 #include <stdio.h> |
|
30 #include <assert.h> |
|
31 #include <stdlib.h> |
|
32 #include <fstream> |
|
33 #include <algorithm> |
|
34 |
|
35 std::wostream* SISLogger::iStream = NULL; |
|
36 |
|
37 void SISLogger::SetStream(std::wostream& aStream) |
|
38 { |
|
39 iStream = &aStream; |
|
40 } |
|
41 |
|
42 void SISLogger::Log(const std::wstring& aString) |
|
43 { |
|
44 if(NULL != iStream) |
|
45 { |
|
46 (*iStream) << aString; |
|
47 } |
|
48 } |
|
49 |
|
50 |
|
51 std::string wstring2string (const std::wstring& aWide) |
|
52 { |
|
53 int max = ConvertWideCharToMultiByte(aWide.c_str(),aWide.length(),0,0); |
|
54 std::string reply; |
|
55 if (max > 0 ) |
|
56 { |
|
57 char* buffer = new char [max]; |
|
58 try |
|
59 { |
|
60 ConvertWideCharToMultiByte(aWide.c_str(),aWide.length(),buffer,max); |
|
61 reply = std::string (buffer, max); |
|
62 } |
|
63 catch (...) |
|
64 { |
|
65 } |
|
66 delete [] buffer; |
|
67 } |
|
68 return reply; |
|
69 } |
|
70 |
|
71 std::wstring string2wstring (const std::string& aNarrow) |
|
72 { |
|
73 int max = ConvertMultiByteToWideChar(aNarrow.c_str(),aNarrow.length(),0,0, CP_OEMCP); |
|
74 std::wstring reply; |
|
75 if (max > 0 ) |
|
76 { |
|
77 wchar_t* buffer = new wchar_t [max]; |
|
78 try |
|
79 { |
|
80 ConvertMultiByteToWideChar(aNarrow.c_str(),aNarrow.length(),buffer,max,CP_OEMCP); |
|
81 reply = std::wstring (buffer, max); |
|
82 } |
|
83 catch (...) |
|
84 { |
|
85 } |
|
86 delete [] buffer; |
|
87 } |
|
88 return reply; |
|
89 } |
|
90 |
|
91 void EnsureExtended (std::wstring& aName, const std::wstring& aDefaultExtension) |
|
92 { |
|
93 assert (! aName.empty ()); |
|
94 assert (! aDefaultExtension.empty ()); |
|
95 std::wstring::size_type posSlash (aName.rfind ('\\')); |
|
96 if (posSlash == std::wstring::npos) |
|
97 { |
|
98 posSlash = 0; |
|
99 } |
|
100 std::wstring::size_type posDot (aName.find (posSlash, '.')); |
|
101 if (posDot == std::wstring::npos) |
|
102 { |
|
103 aName += aDefaultExtension; |
|
104 } |
|
105 } |
|
106 |
|
107 bool ValidateFileName (std::wstring& aName, const bool aMustExist) |
|
108 { |
|
109 assert (! aName.empty ()); |
|
110 if (aName.size () < 3) |
|
111 { |
|
112 return false; |
|
113 } |
|
114 std::wstring filename (aName); |
|
115 bool isUNC ((filename.at (0) == L'/') && (filename.at (1) == L'/')); |
|
116 bool isRelative (! isUNC && ((filename.at (1) != L':'))); |
|
117 |
|
118 if (! isRelative) |
|
119 { |
|
120 if (! isUNC && (filename.at (2) != L'/')) |
|
121 { |
|
122 return false; |
|
123 } |
|
124 } |
|
125 else |
|
126 { |
|
127 const int maxlen = PATHMAX * 8; /* The value of PATHMAX assumes short name FAT environment, |
|
128 not long names and / or NTFS, UNC, URL, etc. etc.. Using a |
|
129 larger value significantly reduces the chances of failure |
|
130 when the application is deep in a subdirectory tree. Windows |
|
131 calls require fixed length buffers. |
|
132 */ |
|
133 wchar_t directorybuffer [maxlen]; |
|
134 std::wstring cwd (_wgetcwd (directorybuffer, maxlen)); |
|
135 if (cwd.empty ()) |
|
136 { |
|
137 return false; |
|
138 } |
|
139 if (cwd.size () > 3) |
|
140 { |
|
141 cwd += KSisDirectorySeparator; // trailing backslash is returned inconsistently according to docs for getcwd |
|
142 } |
|
143 filename = cwd + filename; |
|
144 } |
|
145 |
|
146 if (aMustExist) |
|
147 { |
|
148 DWORD attributes (GetFileAttributesW (filename.c_str ())); |
|
149 if (attributes == RESULT) |
|
150 { |
|
151 return false; |
|
152 } |
|
153 } |
|
154 aName = filename; |
|
155 return true; |
|
156 } |
|
157 |
|
158 |
|
159 bool ValidateDirectory (std::wstring& aName, const bool aMustExist) |
|
160 { |
|
161 if (! ValidateFileName (aName, aMustExist)) |
|
162 { |
|
163 return false; |
|
164 } |
|
165 if (aName.at (aName.size () - 1) != L'/') |
|
166 { |
|
167 aName += L'/'; |
|
168 } |
|
169 return true; |
|
170 } |
|
171 |
|
172 bool ValidateFileName (std::wstring& aName, const bool aMustExist, const std::wstring& aDefaultExtension) |
|
173 { |
|
174 assert (! aName.empty ()); |
|
175 assert (! aDefaultExtension.empty ()); |
|
176 std::wstring filename (aName); |
|
177 EnsureExtended (filename, aDefaultExtension); |
|
178 if (! ValidateFileName (filename, aMustExist)) |
|
179 { |
|
180 return false; |
|
181 } |
|
182 aName = filename; |
|
183 return true; |
|
184 } |
|
185 |
|
186 TUint32 IdentifyUCKeyword (const SKeyword aKeyword [], std::wstring aIdentifier, const std::wstring& aContext) |
|
187 { |
|
188 for (std::wstring::size_type letter = 0; letter < aIdentifier.size (); letter++) |
|
189 { |
|
190 aIdentifier [letter] = toupper (aIdentifier [letter]); |
|
191 } |
|
192 for (const SKeyword* index = &aKeyword [0]; index -> iName != NULL; index++) |
|
193 { |
|
194 if (aIdentifier.compare (index -> iName) == 0) |
|
195 { |
|
196 return index -> iId; |
|
197 } |
|
198 } |
|
199 throw CSISException (CSISException::ESyntax, aContext + aIdentifier); |
|
200 } |
|
201 |
|
202 |
|
203 CSISFieldRoot::TFieldSize Alignment (const CSISFieldRoot::TFieldSize aOriginal) |
|
204 { |
|
205 const CSISFieldRoot::TFieldSize coarseness (4); |
|
206 CSISFieldRoot::TFieldSize modulus (aOriginal % coarseness); |
|
207 return (modulus == 0) ? 0 : (coarseness - modulus); |
|
208 } |
|
209 |
|
210 |
|
211 CSISFieldRoot::TFieldSize AlignedSize (const CSISFieldRoot::TFieldSize aOriginal) |
|
212 { |
|
213 return aOriginal + Alignment (aOriginal); |
|
214 } |
|
215 |
|
216 |
|
217 |
|
218 void ReadFiller (TSISStream& aFile) |
|
219 { |
|
220 CSISFieldRoot::TFieldSize diff (Alignment (aFile.tell ())); |
|
221 assert (diff >= 0); |
|
222 if (diff) |
|
223 { |
|
224 TUint8 junk; |
|
225 for (CSISFieldRoot::TFieldSize index = 0; index < diff; index++) |
|
226 { |
|
227 aFile >> junk; |
|
228 } |
|
229 } |
|
230 } |
|
231 |
|
232 |
|
233 void WriteFiller (TSISStream& aFile) |
|
234 { |
|
235 TSISStream::pos_type pos (aFile.tell ()); |
|
236 if (pos >= 0) |
|
237 { |
|
238 CSISFieldRoot::TFieldSize diff (Alignment (pos)); |
|
239 if (diff) |
|
240 { |
|
241 TUint8 padding = 0; |
|
242 for (CSISFieldRoot::TFieldSize index = 0; index < diff; index++) |
|
243 { |
|
244 aFile << padding; |
|
245 } |
|
246 } |
|
247 } |
|
248 } |
|
249 |
|
250 HANDLE OpenFileAndGetSize (const std::wstring& aName, TUint64* aSize) |
|
251 { |
|
252 HANDLE file = MakeSISOpenFile(aName.c_str(),GENERIC_READ,OPEN_EXISTING); |
|
253 CSISException::ThrowIf ((INVALID_HANDLE_VALUE == file), |
|
254 CSISException::EFileProblem, std::wstring (L"cannot open ") + aName); |
|
255 if (aSize) |
|
256 { |
|
257 DWORD dwHigh = 0; |
|
258 DWORD dwLow = ::GetFileSize(file,&dwHigh); |
|
259 TUint64 size = (dwHigh << 32) | dwLow; |
|
260 *aSize = static_cast <TUint64> (size); |
|
261 } |
|
262 return file; |
|
263 } |
|
264 |
|
265 |
|
266 void ReadAndCloseFile (HANDLE aFile, const TUint64 aSize, TUint8* aBuffer) |
|
267 { |
|
268 size_t got = 0; |
|
269 ::ReadFile(aFile,aBuffer,aSize,(DWORD*)&got,0); |
|
270 ::CloseHandle(aFile); |
|
271 CSISException::ThrowIf (got != static_cast <size_t> (aSize), |
|
272 CSISException::EFileProblem, |
|
273 "cannot read file"); |
|
274 } |
|
275 |
|
276 |
|
277 int SearchSortedUCTable (const SIdentifierTable aTable [], const std::wstring& aIdentifier) |
|
278 { |
|
279 for (int index = 0; aTable [index].iName; index++) |
|
280 { |
|
281 int comparision = aIdentifier.compare (aTable [index].iName); |
|
282 if (comparision == 0) |
|
283 { |
|
284 return index; |
|
285 } |
|
286 if (comparision < 0) |
|
287 { |
|
288 break; |
|
289 } |
|
290 } |
|
291 return -1; |
|
292 } |
|
293 |
|
294 |
|
295 LPSTR MakeMBCSString(LPCWSTR uniStr, UINT codePage, DWORD& length) |
|
296 // Convert a UNICODE string to a multi-byte string |
|
297 { |
|
298 LPSTR mbStr; |
|
299 // get num unicode chars required |
|
300 DWORD len = ConvertWideCharToMultiByte(uniStr, length, NULL, 0); |
|
301 mbStr = new CHAR[len+1]; |
|
302 if (!mbStr) throw ErrNotEnoughMemory; |
|
303 // convert |
|
304 ConvertWideCharToMultiByte(uniStr, length, mbStr, len); |
|
305 mbStr[len]='\0'; |
|
306 length=len; |
|
307 |
|
308 return mbStr; |
|
309 } |
|
310 |
|
311 |
|
312 char* Copy2TmpFile(const wchar_t *fName, TFileType fType) |
|
313 { |
|
314 char *tmpName, *tmpFileName=NULL; |
|
315 int numread = 0; |
|
316 |
|
317 tmpName = GetTempFile(); |
|
318 |
|
319 if(tmpName == NULL) |
|
320 return NULL; |
|
321 |
|
322 tmpFileName = new char[strlen(tmpName)+5]; |
|
323 strcpy(tmpFileName, tmpName); |
|
324 |
|
325 if(fType == CERTFILE) |
|
326 { |
|
327 tmpFileName = strcat(tmpFileName, ".cer"); |
|
328 } |
|
329 else if(fType == KEYFILE) |
|
330 { |
|
331 tmpFileName = strcat(tmpFileName, ".key"); |
|
332 } |
|
333 else |
|
334 { |
|
335 tmpFileName = strcat(tmpFileName, ".dat"); |
|
336 } |
|
337 |
|
338 TransferFileData(fName,tmpFileName); |
|
339 return tmpFileName; |
|
340 |
|
341 if(tmpFileName != NULL) |
|
342 delete tmpFileName; |
|
343 |
|
344 return NULL; |
|
345 } |
|
346 |
|
347 /** |
|
348 * Returns the size of the first occurance of an invalid directory separator. |
|
349 * @param aPath Path to be validated. |
|
350 * @param aIndex index from which the search begin. On function return this |
|
351 * index will point to the illegal directory separator. |
|
352 * @return 0 if path is valid. Else the number of character to be replaced. |
|
353 * e.g. \sys\bin\ should be replaced with /sys/bin/ |
|
354 * and \\sys\\bin\\ should be replaced with /sys/bin/ |
|
355 */ |
|
356 int FirstInvalidDirSeparatorSize(std::wstring& aPath, std::wstring::size_type& aIndex) |
|
357 { |
|
358 // If path semantics is correct (as needed by sisx library) |
|
359 // then the function will return 0 |
|
360 int ret = 0; |
|
361 int pos = 0; |
|
362 if((pos = aPath.find(L"\\\\", aIndex)) != std::wstring::npos) |
|
363 { |
|
364 ret = 2; |
|
365 } |
|
366 else if((pos = aPath.find(L"\\", aIndex)) != std::wstring::npos) |
|
367 { |
|
368 ret = 1; |
|
369 } |
|
370 aIndex = pos; |
|
371 return ret; |
|
372 } |
|
373 |
|
374 |
|
375 std::wstring FixPathDelimiters( const std::wstring& aString ) |
|
376 { |
|
377 std::wstring ret = aString; |
|
378 |
|
379 std::wstring::size_type idx = 0; |
|
380 int len = 0; |
|
381 while(len = FirstInvalidDirSeparatorSize(ret, idx)) |
|
382 { |
|
383 ret.replace( idx, len, KSisDirectorySeparator ); |
|
384 } |
|
385 return ret; |
|
386 } |
|
387 |
|
388 int GetFileType(std::wstring& aFileName) |
|
389 { |
|
390 int len = ConvertWideCharToMultiByte(aFileName.c_str(), -1, NULL, 0); |
|
391 char* fileName = new char[len + 1]; |
|
392 ConvertWideCharToMultiByte(aFileName.c_str(), -1, fileName, len); |
|
393 |
|
394 std::ifstream fs(fileName, std::ios::binary | std::ios::in); |
|
395 fs.seekg(0, std::ios::end); |
|
396 len = fs.tellg(); |
|
397 fs.seekg(0, std::ios::beg); |
|
398 unsigned char* buffer = new unsigned char[len]; |
|
399 fs.read((char*)buffer, len); |
|
400 fs.close(); |
|
401 |
|
402 int type = EFileUnknown; |
|
403 |
|
404 const TUint32* data32 = reinterpret_cast<const TUint32*>(buffer); |
|
405 |
|
406 if (len <= sizeof(TUint32)*0x04) |
|
407 { |
|
408 delete[] buffer; |
|
409 return type; |
|
410 } |
|
411 |
|
412 if(IsExeData(buffer, len)) |
|
413 { |
|
414 type = EFileExe; |
|
415 } |
|
416 else if(IsDllData(buffer, len)) |
|
417 { |
|
418 type = EFileDll; |
|
419 } |
|
420 |
|
421 if(IsEmulatorExecutableData(buffer, len)) |
|
422 { |
|
423 type |= EFileEmulatorExe; |
|
424 } |
|
425 |
|
426 return type; |
|
427 } |
|
428 |
|
429 bool IsExecutableData(const unsigned char* aContent, TUint32 aLength) |
|
430 { |
|
431 if (aLength <= sizeof(TUint32)*0x05) |
|
432 { |
|
433 return false; |
|
434 } |
|
435 const TUint32* data32 = reinterpret_cast<const TUint32*>(aContent); |
|
436 bool isExecutable = false; |
|
437 |
|
438 if ( IsExeData(aContent, aLength) || |
|
439 IsDllData(aContent, aLength) || |
|
440 IsEmulatorExecutableData(aContent, aLength)) |
|
441 { |
|
442 isExecutable = true; |
|
443 } |
|
444 |
|
445 return isExecutable; |
|
446 } |
|
447 |
|
448 bool IsEmulatorExecutableData(const unsigned char* aContent, TUint32 aLength) |
|
449 { |
|
450 bool isEmulatorExe = false; |
|
451 |
|
452 // winscw binary |
|
453 if (aLength > 2 && aContent[0] == 'M' && aContent[1] == 'Z') |
|
454 { |
|
455 isEmulatorExe = true; |
|
456 } |
|
457 |
|
458 return isEmulatorExe; |
|
459 } |
|
460 |
|
461 |
|
462 bool IsExeData(const unsigned char* aContent, TUint32 aLength) |
|
463 { |
|
464 return (GetExecutableType(aContent, aLength) == KExecutableImageUid)? true: false; |
|
465 } |
|
466 |
|
467 bool IsDllData(const unsigned char* aContent, TUint32 aLength) |
|
468 { |
|
469 return (GetExecutableType(aContent, aLength) == KDynamicLibraryUid)? true: false; |
|
470 } |
|
471 |
|
472 |
|
473 TInt32 GetExecutableType(const unsigned char* aContent, TUint32 aLength) |
|
474 { |
|
475 const TUint32* data32 = reinterpret_cast<const TUint32*>(aContent); |
|
476 if(aLength < sizeof(TUint32)*0x05) |
|
477 { |
|
478 return 0; |
|
479 } |
|
480 |
|
481 TInt32 type = 0; |
|
482 |
|
483 if(data32[0x04] == KFileHeaderSignature) |
|
484 { |
|
485 type = data32[0]; |
|
486 } |
|
487 else if (IsEmulatorExecutableData(aContent, aLength)) |
|
488 { |
|
489 const char symbian[] = ".SYMBIAN"; |
|
490 const int len2 = sizeof(symbian)-1; |
|
491 const unsigned char* index = std::search(aContent, aContent+aLength, symbian, symbian+len2); |
|
492 |
|
493 if ( (index + KHeaderUidLength < aContent+aLength) && (index != aContent+aLength) ) |
|
494 { |
|
495 index += KHeaderUidLength; |
|
496 TInt32 offset = *(TInt32*)index; |
|
497 |
|
498 if (offset < aLength) |
|
499 { |
|
500 const TUint32* x = (TUint32*)(aContent+offset); |
|
501 type = x[0]; |
|
502 } |
|
503 } |
|
504 } |
|
505 |
|
506 return type; |
|
507 } |