Annotation of truecrypt/common/language.c, revision 1.1.1.14

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.