|
|
1.1.1.5 ! root 1: /* ! 2: Copyright (c) TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.5 ! root 4: Covered by the TrueCrypt License 2.2 the full text of which is contained ! 5: in the file License.txt included in TrueCrypt binary and source code ! 6: distribution 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: { 68: GetModuleFileNameW (NULL, f, sizeof (f)); 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: 89: GetModuleFileNameW (NULL, f, sizeof (f)); 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; 109: char langId[6] = "en", attr[2048], key[128]; 110: BOOL defaultLangParsed = FALSE, langFound = FALSE; 111: WCHAR wattr[2048]; 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; 129: ClearDictionaryPool (); 130: 131: if (PreferredLangId[0] != 0) 132: strcpy (langId, PreferredLangId); 133: 134: // Parse all available language files until preferred language is found 135: for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ()) 136: { 137: xml = (char *) res; 138: xml = XmlFindElement (xml, "localization"); 1.1.1.2 root 139: if (!xml) 140: continue; 141: 1.1 root 142: // Required TrueCrypt version 1.1.1.5 ! root 143: XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr)); 1.1 root 144: 145: // Check version of external language file 146: if (defaultLangParsed && strcmp (attr, VERSION_STRING)) 147: { 1.1.1.5 ! root 148: wchar_t m[2048]; ! 149: 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 150: MessageBoxW (NULL, m, L"TrueCrypt", MB_ICONERROR); 151: continue; 152: } 153: 154: // Search language id in language file 155: if (defaultLangParsed) 156: { 157: while (xml = XmlFindElement (xml, "language")) 158: { 1.1.1.5 ! root 159: XmlGetAttributeText (xml++, "langid", attr, sizeof (attr)); 1.1 root 160: if (strcmp (attr, langId) == 0) 161: { 162: langFound = TRUE; 163: break; 164: } 165: } 166: 167: if (!langFound) continue; 168: } 169: 170: // Create font dictionary 171: xml = (char *) res; 172: while (xml = XmlFindElement (xml, "font")) 173: { 1.1.1.5 ! root 174: XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); 1.1 root 175: if (!defaultLangParsed 176: || strcmp (attr, langId) == 0) 177: { 178: Font font; 1.1.1.2 root 179: memset (&font, 0, sizeof (font)); 180: 1.1.1.5 ! root 181: XmlGetAttributeText (xml, "face", attr, sizeof (attr)); 1.1 root 182: 183: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); 184: font.FaceName = AddPoolData ((void *) wattr, len * 2); 185: 1.1.1.5 ! root 186: XmlGetAttributeText (xml, "size", attr, sizeof (attr)); 1.1 root 187: sscanf (attr, "%d", &font.Size); 188: 189: strcpy (attr, "font_"); 1.1.1.5 ! root 190: XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5); 1.1.1.2 root 191: AddDictionaryEntry ( 192: AddPoolData ((void *) attr, strlen (attr) + 1), 0, 1.1 root 193: AddPoolData ((void *) &font, sizeof(font))); 194: } 195: 196: xml++; 197: } 198: 199: // Create string and control dictionaries 200: for (i = 0; xmlElements[i] != 0; i++) 201: { 202: xml = (char *) res; 203: while (xml = XmlFindElement (xml, xmlElements[i])) 204: { 205: void *key; 206: void *text; 207: 1.1.1.5 ! root 208: XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); 1.1 root 209: if (!defaultLangParsed 210: || strcmp (attr, langId) == 0) 211: { 1.1.1.5 ! root 212: if (XmlGetAttributeText (xml, "key", attr, sizeof (attr))) 1.1 root 213: { 214: key = AddPoolData (attr, strlen (attr) + 1); 215: if (key == NULL) return FALSE; 216: 1.1.1.5 ! root 217: XmlGetNodeText (xml, attr, sizeof (attr)); 1.1 root 218: 219: // Parse \ escape sequences 220: { 221: char *in = attr, *out = attr; 222: while (*in) 223: { 224: if (*in == '\\') 225: { 226: in++; 227: switch (*in++) 228: { 229: case '\\': *out++ = '\\'; break; 230: case 't': *out++ = '\t'; break; 231: case 'n': *out++ = 13; *out++ = 10; break; 232: default: 233: MessageBox (0, key, "TrueCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); 234: return FALSE; 235: } 236: } 237: else 238: *out++ = *in++; 239: } 240: *out = 0; 241: } 242: 243: // UTF8 => wide char 244: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); 245: if (len == 0 || len == ERROR_NO_UNICODE_TRANSLATION) 246: { 247: MessageBox (0, key, "TrueCrypt: Error while decoding UTF-8 string", MB_ICONERROR); 248: return FALSE; 249: } 250: 251: // Add to dictionary 252: text = AddPoolData ((void *) wattr, len * 2); 253: if (text == NULL) return FALSE; 254: 255: AddDictionaryEntry ((char *) key, 0, text); 256: } 257: } 258: 259: xml++; 260: } 261: } 262: 263: if (langFound) 264: break; 265: 266: if (!defaultLangParsed) 267: { 268: defaultLangParsed = TRUE; 269: if (langId[0] == 0 || strcmp (langId, "en") == 0) 270: break; 271: } 272: } 273: 274: LocalizationActive = langFound && strcmp (langId, "en") != 0; 275: LocalizationSerialNo++; 276: 277: // Create control ID dictionary 278: 279: // Default controls 280: AddDictionaryEntry (NULL, 1, GetString ("IDOK")); 281: AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL")); 282: AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE")); 283: AddDictionaryEntry (NULL, 9, GetString ("IDHELP")); 284: 285: for (i = 0; headers[i] != 0; i++) 286: { 287: if (HeaderResource[i] == NULL) 1.1.1.5 ! root 288: { 1.1 root 289: HeaderResource[i] = MapResource ("Header", headers[i], &size); 1.1.1.5 ! root 290: *(HeaderResource[i] + size - 1) = 0; ! 291: } 1.1 root 292: 293: header = HeaderResource[i]; 294: if (header == NULL) return FALSE; 295: 296: do 297: { 298: if (sscanf (header, "#define %s %d", key, &intKey) == 2) 299: { 300: WCHAR *str = GetString (key); 301: 302: if (str != UnknownString) 303: AddDictionaryEntry (NULL, intKey, str); 304: } 305: 306: } while ((header = strchr (header, '\n') + 1) != (char *) 1); 307: } 308: 309: return TRUE; 310: } 311: 312: 313: // lParam = 1: auto mode 314: BOOL WINAPI LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 315: { 316: WORD lw = LOWORD (wParam); 317: WORD hw = HIWORD (wParam); 318: 319: switch (msg) 320: { 321: case WM_INITDIALOG: 322: { 323: char *xml; 324: char attr[2048], lastLangId[10]; 325: WCHAR wattr[2048]; 326: int len; 327: int langCount = 0; 328: BOOL defaultLangFound = FALSE; 329: 330: LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); 1.1.1.5 ! root 331: ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); 1.1 root 332: 333: for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ()) 334: { 335: while (xml = XmlFindElement (xml, "language")) 336: { 1.1.1.5 ! root 337: XmlGetAttributeText (xml, "name", attr, sizeof (attr)); 1.1 root 338: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); 339: 340: if (len != 0 && len != ERROR_NO_UNICODE_TRANSLATION 341: && (!defaultLangFound || wcscmp (wattr, L"English") != 0)) 342: { 343: int i = SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr); 344: if (i >= 0) 345: { 346: int id; 347: 348: // Encode language id in LPARAM 1.1.1.5 ! root 349: XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); 1.1 root 350: switch (strlen (attr)) 351: { 352: case 2: id = attr[0] | attr[1] << 8; break; 353: case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break; 354: default: continue; 355: } 356: 357: if (!defaultLangFound) 358: defaultLangFound = TRUE; 359: 360: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id); 361: 362: if (strcmp (attr, PreferredLangId) == 0) 363: { 364: char credits [10000]; 365: WCHAR wcredits [10000]; 366: WCHAR wversion [20]; 367: wchar_t szVers [200]; 368: int nLen; 369: 370: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0); 371: 372: // Language pack version 1.1.1.5 ! root 373: XmlGetAttributeText (xml, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); 1.1 root 374: if (memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0) 375: { 376: swprintf (szVers, GetString("LANG_PACK_VERSION"), L"--"); 377: } 378: else 379: { 380: nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (ActiveLangPackVersion)); 381: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) 382: swprintf (szVers, GetString("LANG_PACK_VERSION"), wversion); 383: } 384: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers); 385: 386: // Translator credits 1.1.1.5 ! root 387: XmlGetAttributeText (xml, "translators", credits, sizeof (credits)); 1.1 root 388: nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits)); 389: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) 390: { 391: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits); 392: } 393: } 394: 395: strcpy (lastLangId, attr); 396: langCount++; 397: } 398: } 399: 400: xml++; 401: } 402: } 403: 404: if (lParam == 1) 405: { 406: // Auto mode 407: if (langCount < 2) 408: EndDialog (hwndDlg, IDCANCEL); 409: 410: if (langCount == 2) 411: strcpy (PreferredLangId, lastLangId); 1.1.1.5 ! root 412: ! 413: EndDialog (hwndDlg, IDOK); 1.1 root 414: } 415: 416: return 1; 417: } 418: 419: case WM_COMMAND: 420: 421: if (lw == IDOK || hw == LBN_DBLCLK) 422: { 423: int i = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0); 424: 425: if (i >= 0) 426: { 427: int id = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0); 428: 429: if (id != LB_ERR) 430: { 431: char l[6]; 432: 433: // Decode language id from LPARAM 434: l[0] = id; 435: l[1] = id >> 8; 436: l[2] = 0; 437: 438: if ((id & 0xffff0000) != 0) 439: { 440: l[2] = '-'; 441: l[3] = id >> 16; 442: l[4] = id >> 24; 443: l[5] = 0; 444: } 445: 446: if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1) 447: strcpy (PreferredLangId, l); 448: } 449: } 450: 451: EndDialog (hwndDlg, IDOK); 452: return 1; 453: } 454: 455: if (lw == IDCANCEL) 456: { 457: EndDialog (hwndDlg, lw); 458: return 1; 459: } 460: 461: if (lw == IDC_GET_LANG_PACKS) 462: { 463: char tmpstr [256]; 464: 1.1.1.5 ! root 465: if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0) ! 466: sprintf (tmpstr, "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId()); 1.1 root 467: else 1.1.1.5 ! root 468: tmpstr[0] = 0; ! 469: ! 470: Applink ("localizations", TRUE, tmpstr); 1.1 root 471: 472: return 1; 473: } 474: return 0; 475: } 476: 477: return 0; 478: } 479: 480: 481: char *GetPreferredLangId () 482: { 483: return PreferredLangId; 484: } 485: 486: 487: void SetPreferredLangId (char *langId) 488: { 489: strncpy (PreferredLangId, langId, 5); 490: } 491: 492: 493: wchar_t *GetString (char *stringId) 494: { 495: WCHAR *str = (WCHAR *) GetDictionaryValue (stringId); 496: if (str != NULL) return str; 497: 498: wsprintfW (UnknownString, UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); 499: return UnknownString; 500: } 501: 502: 503: Font *GetFont (char *fontType) 504: { 505: return (Font *) GetDictionaryValue (fontType); 506: 507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.