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