|
|
1.1 root 1: /*
2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved.
3:
4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file
5: License.txt included in TrueCrypt binary and source code distribution archives.
6: */
7:
8: #include "Language.h"
9: #include "Dlgcode.h"
10: #include "Dictionary.h"
11: #include "Tcdefs.h"
12: #include "Xml.h"
13:
14: #include "../Common/Resource.h"
15:
16: #ifdef TCMOUNT
17: #include "../Mount/Resource.h"
18: #endif
19:
20: #ifdef VOLFORMAT
21: #include "../Format/Resource.h"
22: #endif
23:
24: #ifdef SETUP
25: #include "../Setup/Resource.h"
26: #endif
27:
28: BOOL LocalizationActive;
29: int LocalizationSerialNo;
30:
31: wchar_t UnknownString[1024];
32: static char *LanguageFileBuffer;
33: static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE;
34: static char PreferredLangId[6];
35: static char *LanguageResource;
36: static char *HeaderResource[2];
37: static char ActiveLangPackVersion[6];
38:
39: static char *MapFirstLanguageFile ()
40: {
41: if (LanguageFileFindHandle != INVALID_HANDLE_VALUE)
42: {
43: FindClose (LanguageFileFindHandle);
44: LanguageFileFindHandle = INVALID_HANDLE_VALUE;
45: }
46:
47: if (LanguageResource == NULL)
48: LanguageResource = MapResource ("Xml", IDR_LANGUAGE, NULL);
49:
50: return LanguageResource;
51: }
52:
53:
54: static char *MapNextLanguageFile ()
55: {
56: wchar_t f[TC_MAX_PATH*2], *t;
57: WIN32_FIND_DATAW find;
58: HANDLE file;
59: DWORD read;
60:
61: if (LanguageFileFindHandle == INVALID_HANDLE_VALUE)
62: {
63: GetModuleFileNameW (NULL, f, sizeof (f));
64: t = wcsrchr (f, L'\\');
65: if (t == NULL) return NULL;
66:
67: wcscpy (t, L"\\Language*.xml");
68:
69: LanguageFileFindHandle = FindFirstFileW (f, &find);
70: }
71: else if (!FindNextFileW (LanguageFileFindHandle, &find))
72: {
73: FindClose (LanguageFileFindHandle);
74: LanguageFileFindHandle = INVALID_HANDLE_VALUE;
75: return NULL;
76: }
77:
78: if (find.nFileSizeHigh != 0) return NULL;
79:
80: if (LanguageFileBuffer != NULL) free (LanguageFileBuffer);
81: LanguageFileBuffer = malloc(find.nFileSizeLow);
82: if (LanguageFileBuffer == NULL) return NULL;
83:
84: GetModuleFileNameW (NULL, f, sizeof (f));
85: t = wcsrchr (f, L'\\');
86: wcscpy (t + 1, find.cFileName);
87:
88: file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
89: if (file == INVALID_HANDLE_VALUE) return NULL;
90:
91: ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL);
92: CloseHandle (file);
93: if (read != find.nFileSizeLow) return NULL;
94:
95: return LanguageFileBuffer;
96: }
97:
98:
99: BOOL LoadLanguageFile ()
100: {
101: DWORD size;
102: BYTE *res;
103: char *xml, *header;
104: char langId[6] = "en", attr[2048], key[128];
105: BOOL defaultLangParsed = FALSE, langFound = FALSE;
106: WCHAR wattr[2048];
107: int i, intKey, len;
108:
109: char *xmlElements[] = {"control", "string", 0};
110:
111: #ifdef TCMOUNT
112: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 };
113: #endif
114:
115: #ifdef VOLFORMAT
116: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 };
117: #endif
118:
119: #ifdef SETUP
120: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 };
121: #endif
122:
123: LocalizationActive = FALSE;
124: ClearDictionaryPool ();
125:
126: if (PreferredLangId[0] != 0)
127: strcpy (langId, PreferredLangId);
128:
129: // Parse all available language files until preferred language is found
130: for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ())
131: {
132: xml = (char *) res;
133: xml = XmlFindElement (xml, "localization");
1.1.1.2 ! root 134: if (!xml)
! 135: continue;
! 136:
1.1 root 137: // Required TrueCrypt version
138: XmlAttribute (xml, "prog-version", attr, sizeof (attr));
139:
140: // Check version of external language file
141: if (defaultLangParsed && strcmp (attr, VERSION_STRING))
142: {
143: wchar_t m[1024];
144: swprintf (m, L"The installed language pack is incompatible with this version of TrueCrypt\n(this language pack is for TrueCrypt %hs).\n\nA newer version may be available at www.truecrypt.org.\n\nTo prevent this message from being displayed, do any of the following:\n- Update the language pack\n- Remove the language pack file from the TrueCrypt folder", attr);
145: MessageBoxW (NULL, m, L"TrueCrypt", MB_ICONERROR);
146: continue;
147: }
148:
149: // Search language id in language file
150: if (defaultLangParsed)
151: {
152: while (xml = XmlFindElement (xml, "language"))
153: {
154: XmlAttribute (xml++, "langid", attr, sizeof (attr));
155: if (strcmp (attr, langId) == 0)
156: {
157: langFound = TRUE;
158: break;
159: }
160: }
161:
162: if (!langFound) continue;
163: }
164:
165: // Create font dictionary
166: xml = (char *) res;
167: while (xml = XmlFindElement (xml, "font"))
168: {
169: XmlAttribute (xml, "lang", attr, sizeof (attr));
170: if (!defaultLangParsed
171: || strcmp (attr, langId) == 0)
172: {
173: Font font;
1.1.1.2 ! root 174: memset (&font, 0, sizeof (font));
! 175:
1.1 root 176: XmlAttribute (xml, "face", attr, sizeof (attr));
177:
178: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr));
179: font.FaceName = AddPoolData ((void *) wattr, len * 2);
180:
181: XmlAttribute (xml, "size", attr, sizeof (attr));
182: sscanf (attr, "%d", &font.Size);
183:
184: strcpy (attr, "font_");
185: XmlAttribute (xml, "class", attr + 5, sizeof (attr) - 5);
1.1.1.2 ! root 186: AddDictionaryEntry (
! 187: AddPoolData ((void *) attr, strlen (attr) + 1), 0,
1.1 root 188: AddPoolData ((void *) &font, sizeof(font)));
189: }
190:
191: xml++;
192: }
193:
194: // Create string and control dictionaries
195: for (i = 0; xmlElements[i] != 0; i++)
196: {
197: xml = (char *) res;
198: while (xml = XmlFindElement (xml, xmlElements[i]))
199: {
200: void *key;
201: void *text;
202:
203: XmlAttribute (xml, "lang", attr, sizeof (attr));
204: if (!defaultLangParsed
205: || strcmp (attr, langId) == 0)
206: {
207: if (XmlAttribute (xml, "key", attr, sizeof (attr)))
208: {
209: key = AddPoolData (attr, strlen (attr) + 1);
210: if (key == NULL) return FALSE;
211:
212: XmlNodeText (xml, attr, sizeof (attr));
213:
214: // Parse \ escape sequences
215: {
216: char *in = attr, *out = attr;
217: while (*in)
218: {
219: if (*in == '\\')
220: {
221: in++;
222: switch (*in++)
223: {
224: case '\\': *out++ = '\\'; break;
225: case 't': *out++ = '\t'; break;
226: case 'n': *out++ = 13; *out++ = 10; break;
227: default:
228: MessageBox (0, key, "TrueCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR);
229: return FALSE;
230: }
231: }
232: else
233: *out++ = *in++;
234: }
235: *out = 0;
236: }
237:
238: // UTF8 => wide char
239: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr));
240: if (len == 0 || len == ERROR_NO_UNICODE_TRANSLATION)
241: {
242: MessageBox (0, key, "TrueCrypt: Error while decoding UTF-8 string", MB_ICONERROR);
243: return FALSE;
244: }
245:
246: // Add to dictionary
247: text = AddPoolData ((void *) wattr, len * 2);
248: if (text == NULL) return FALSE;
249:
250: AddDictionaryEntry ((char *) key, 0, text);
251: }
252: }
253:
254: xml++;
255: }
256: }
257:
258: if (langFound)
259: break;
260:
261: if (!defaultLangParsed)
262: {
263: defaultLangParsed = TRUE;
264: if (langId[0] == 0 || strcmp (langId, "en") == 0)
265: break;
266: }
267: }
268:
269: LocalizationActive = langFound && strcmp (langId, "en") != 0;
270: LocalizationSerialNo++;
271:
272: // Create control ID dictionary
273:
274: // Default controls
275: AddDictionaryEntry (NULL, 1, GetString ("IDOK"));
276: AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL"));
277: AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE"));
278: AddDictionaryEntry (NULL, 9, GetString ("IDHELP"));
279:
280: for (i = 0; headers[i] != 0; i++)
281: {
282: if (HeaderResource[i] == NULL)
283: HeaderResource[i] = MapResource ("Header", headers[i], &size);
284:
285: header = HeaderResource[i];
286: if (header == NULL) return FALSE;
287:
288: do
289: {
290: if (sscanf (header, "#define %s %d", key, &intKey) == 2)
291: {
292: WCHAR *str = GetString (key);
293:
294: if (str != UnknownString)
295: AddDictionaryEntry (NULL, intKey, str);
296: }
297:
298: } while ((header = strchr (header, '\n') + 1) != (char *) 1);
299: }
300:
301: return TRUE;
302: }
303:
304:
305: // lParam = 1: auto mode
306: BOOL WINAPI LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
307: {
308: WORD lw = LOWORD (wParam);
309: WORD hw = HIWORD (wParam);
310:
311: switch (msg)
312: {
313: case WM_INITDIALOG:
314: {
315: char *xml;
316: char attr[2048], lastLangId[10];
317: WCHAR wattr[2048];
318: int len;
319: int langCount = 0;
320: BOOL defaultLangFound = FALSE;
321:
322: LocalizeDialog (hwndDlg, "IDD_LANGUAGE");
323:
324: SendMessage (GetDlgItem (hwndDlg, IDC_GET_LANG_PACKS), WM_SETFONT, (WPARAM) hUserUnderlineFont, 0);
325:
326: for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ())
327: {
328: while (xml = XmlFindElement (xml, "language"))
329: {
330: XmlAttribute (xml, "name", attr, sizeof (attr));
331: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr));
332:
333: if (len != 0 && len != ERROR_NO_UNICODE_TRANSLATION
334: && (!defaultLangFound || wcscmp (wattr, L"English") != 0))
335: {
336: int i = SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr);
337: if (i >= 0)
338: {
339: int id;
340:
341: // Encode language id in LPARAM
342: XmlAttribute (xml, "langid", attr, sizeof (attr));
343: switch (strlen (attr))
344: {
345: case 2: id = attr[0] | attr[1] << 8; break;
346: case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break;
347: default: continue;
348: }
349:
350: if (!defaultLangFound)
351: defaultLangFound = TRUE;
352:
353: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id);
354:
355: if (strcmp (attr, PreferredLangId) == 0)
356: {
357: char credits [10000];
358: WCHAR wcredits [10000];
359: WCHAR wversion [20];
360: wchar_t szVers [200];
361: int nLen;
362:
363: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0);
364:
365: // Language pack version
366: XmlAttribute (xml, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
367: if (memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0)
368: {
369: swprintf (szVers, GetString("LANG_PACK_VERSION"), L"--");
370: }
371: else
372: {
373: nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (ActiveLangPackVersion));
374: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION)
375: swprintf (szVers, GetString("LANG_PACK_VERSION"), wversion);
376: }
377: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers);
378:
379: // Translator credits
380: XmlAttribute (xml, "translators", credits, sizeof (credits));
381: nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits));
382: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION)
383: {
384: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits);
385: }
386: }
387:
388: strcpy (lastLangId, attr);
389: langCount++;
390: }
391: }
392:
393: xml++;
394: }
395: }
396:
397: if (lParam == 1)
398: {
399: // Auto mode
400: if (langCount < 2)
401: EndDialog (hwndDlg, IDCANCEL);
402:
403: if (langCount == 2)
404: {
405: strcpy (PreferredLangId, lastLangId);
406: EndDialog (hwndDlg, IDOK);
407: }
408: }
409:
410: return 1;
411: }
412:
413:
414: case WM_COMMAND:
415:
416: if (lw == IDOK || hw == LBN_DBLCLK)
417: {
418: int i = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0);
419:
420: if (i >= 0)
421: {
422: int id = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0);
423:
424: if (id != LB_ERR)
425: {
426: char l[6];
427:
428: // Decode language id from LPARAM
429: l[0] = id;
430: l[1] = id >> 8;
431: l[2] = 0;
432:
433: if ((id & 0xffff0000) != 0)
434: {
435: l[2] = '-';
436: l[3] = id >> 16;
437: l[4] = id >> 24;
438: l[5] = 0;
439: }
440:
441: if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1)
442: strcpy (PreferredLangId, l);
443: }
444: }
445:
446: EndDialog (hwndDlg, IDOK);
447: return 1;
448: }
449:
450: if (lw == IDCANCEL)
451: {
452: EndDialog (hwndDlg, lw);
453: return 1;
454: }
455:
456: if (lw == IDC_GET_LANG_PACKS)
457: {
458: char tmpstr [256];
459:
460: ArrowWaitCursor ();
1.1.1.2 ! root 461: if (strlen(ActiveLangPackVersion) > 0 && strlen(GetPreferredLangId()) > 0)
! 462: sprintf (tmpstr, "http://www.truecrypt.org/applink.php?version=%s&dest=localizations&langpackversion=%s&lang=%s", VERSION_STRING, ActiveLangPackVersion, GetPreferredLangId());
1.1 root 463: else
464: sprintf (tmpstr, "http://www.truecrypt.org/applink.php?version=%s&dest=localizations", VERSION_STRING);
465:
466: ShellExecute (NULL, "open", (LPCTSTR) tmpstr, NULL, NULL, SW_SHOWNORMAL);
467: Sleep (200);
468: NormalCursor ();
469: return 1;
470: }
471: return 0;
472: }
473:
474: return 0;
475: }
476:
477:
478: char *GetPreferredLangId ()
479: {
480: return PreferredLangId;
481: }
482:
483:
484: void SetPreferredLangId (char *langId)
485: {
486: strncpy (PreferredLangId, langId, 5);
487: }
488:
489:
490: wchar_t *GetString (char *stringId)
491: {
492: WCHAR *str = (WCHAR *) GetDictionaryValue (stringId);
493: if (str != NULL) return str;
494:
495: wsprintfW (UnknownString, UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId);
496: return UnknownString;
497: }
498:
499:
500: Font *GetFont (char *fontType)
501: {
502: return (Font *) GetDictionaryValue (fontType);
503:
504: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.