2017-10-19 05:48:23 +03:00
// SoftEther VPN Source Code - Developer Edition Master Branch
2014-01-04 17:00:08 +04:00
// Mayaqua Kernel
// Table.c
// Read and management routines for string table
2021-04-05 05:48:25 +03:00
# include "Table.h"
# include "Cfg.h"
2021-04-18 02:46:59 +03:00
# include "DNS.h"
2021-04-05 05:48:25 +03:00
# include "FileIO.h"
# include "Internat.h"
# include "Mayaqua.h"
# include "Memory.h"
# include "Microsoft.h"
# include "Network.h"
# include "Str.h"
# include "Tick64.h"
2014-01-04 17:00:08 +04:00
# include <stdlib.h>
// List of TABLE
static LIST * TableList = NULL ;
static wchar_t old_table_name [ MAX_SIZE ] = { 0 } ; // Old table name
static LANGLIST current_lang = { 0 } ;
static LANGLIST current_os_lang = { 0 } ;
// Initialization of string table routine
void InitTable ( )
{
LIST * o ;
char tmp [ MAX_SIZE ] ;
LANGLIST * e = NULL ;
LANGLIST * os_lang = NULL ;
char table_name [ MAX_SIZE ] ;
if ( MayaquaIsMinimalMode ( ) )
{
// Not to load in case of minimum mode
return ;
}
o = LoadLangList ( ) ;
if ( o = = NULL )
{
LABEL_FATAL_ERROR :
Alert ( " Fatal Error: The file \" hamcore.se2 \" is missing or broken. \r \n Please check hamcore.se2. \r \n \r \n (First, reboot the computer. If this problem occurs again, please reinstall VPN software files.) " , NULL ) ;
exit ( - 1 ) ;
return ;
}
// Read the lang.config
if ( LoadLangConfigCurrentDir ( tmp , sizeof ( tmp ) ) )
{
e = GetBestLangByName ( o , tmp ) ;
}
os_lang = GetBestLangForCurrentEnvironment ( o ) ;
if ( e = = NULL )
{
e = os_lang ;
}
if ( e = = NULL )
{
goto LABEL_FATAL_ERROR ;
}
SaveLangConfigCurrentDir ( e - > Name ) ;
Copy ( & current_lang , e , sizeof ( LANGLIST ) ) ;
Copy ( & current_os_lang , os_lang , sizeof ( LANGLIST ) ) ;
current_lang . LangList = current_lang . LcidList = NULL ;
current_os_lang . LangList = current_os_lang . LcidList = NULL ;
// Read the corresponding string table
Format ( table_name , sizeof ( table_name ) , " |strtable_%s.stb " , current_lang . Name ) ;
if ( LoadTable ( table_name ) = = false )
{
goto LABEL_FATAL_ERROR ;
}
FreeLangList ( o ) ;
}
// Get the language of the current OS
void GetCurrentOsLang ( LANGLIST * e )
{
// Validate arguments
if ( e = = NULL )
{
return ;
}
Copy ( e , & current_os_lang , sizeof ( LANGLIST ) ) ;
}
// Get the language ID of the current OS
UINT GetCurrentOsLangId ( )
{
LANGLIST e ;
Zero ( & e , sizeof ( e ) ) ;
GetCurrentOsLang ( & e ) ;
return e . Id ;
}
// Get the current language
void GetCurrentLang ( LANGLIST * e )
{
// Validate arguments
if ( e = = NULL )
{
return ;
}
Copy ( e , & current_lang , sizeof ( LANGLIST ) ) ;
}
// Get the current language ID
UINT GetCurrentLangId ( )
{
LANGLIST e ;
Zero ( & e , sizeof ( e ) ) ;
GetCurrentLang ( & e ) ;
return e . Id ;
}
// Write to the lang.config file in the current directory
bool SaveLangConfigCurrentDir ( char * str )
{
// Validate arguments
if ( str = = NULL )
{
return false ;
}
return SaveLangConfig ( LANG_CONFIG_FILENAME , str ) ;
}
// Write to the lang.config file
bool SaveLangConfig ( wchar_t * filename , char * str )
{
BUF * b ;
LIST * o ;
UINT i ;
bool ret ;
// Validate arguments
if ( filename = = NULL )
{
return false ;
}
// Read the template
b = ReadDump ( LANG_CONFIG_TEMPLETE ) ;
if ( b = = NULL )
{
return false ;
}
SeekBuf ( b , b - > Size , 0 ) ;
o = LoadLangList ( ) ;
if ( o ! = NULL )
{
wchar_t tmp [ MAX_SIZE ] ;
AppendBufStr ( b , " # Available Language IDs are: \r \n " ) ;
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
UniFormat ( tmp , sizeof ( tmp ) , L " # %S: %s (%s) \r \n " ,
e - > Name , e - > TitleEnglish , e - > TitleLocal ) ;
AppendBufUtf8 ( b , tmp ) ;
}
AppendBufStr ( b , " \r \n \r \n # Specify a Language ID here. \r \n " ) ;
AppendBufStr ( b , str ) ;
AppendBufStr ( b , " \r \n \r \n " ) ;
FreeLangList ( o ) ;
}
2015-07-26 13:39:40 +03:00
ret = DumpBufWIfNecessary ( b , filename ) ;
2014-01-04 17:00:08 +04:00
FreeBuf ( b ) ;
return ret ;
}
// Read the lang.config file in the current directory
bool LoadLangConfigCurrentDir ( char * str , UINT str_size )
{
// Validate arguments
if ( str = = NULL )
{
return false ;
}
return LoadLangConfig ( LANG_CONFIG_FILENAME , str , str_size ) ;
}
// Read the lang.config file
bool LoadLangConfig ( wchar_t * filename , char * str , UINT str_size )
{
BUF * b ;
bool ret = false ;
// Validate arguments
if ( filename = = NULL | | str = = NULL )
{
return false ;
}
b = ReadDumpW ( filename ) ;
if ( b = = NULL )
{
return false ;
}
while ( true )
{
char * line = CfgReadNextLine ( b ) ;
if ( line = = NULL )
{
break ;
}
Trim ( line ) ;
if ( IsEmptyStr ( line ) = = false )
{
if ( StartWith ( line , " # " ) = = false & & StartWith ( line , " // " ) = = false & & StartWith ( line , " ; " ) = = false & &
InStr ( line , " # " ) = = false )
{
StrCpy ( str , str_size , line ) ;
ret = true ;
}
}
Free ( line ) ;
}
FreeBuf ( b ) ;
return ret ;
}
// Choose the language from the ID
LANGLIST * GetLangById ( LIST * o , UINT id )
{
UINT i ;
// Validate arguments
if ( o = = NULL )
{
return NULL ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
if ( e - > Id = = id )
{
return e ;
}
}
return NULL ;
}
// Choice the best language for the current environment
LANGLIST * GetBestLangForCurrentEnvironment ( LIST * o )
{
LANGLIST * ret = NULL ;
// Validate arguments
if ( o = = NULL )
{
return NULL ;
}
# ifdef OS_WIN32
ret = GetBestLangByLcid ( o , MsGetUserLocaleId ( ) ) ;
# else // OS_WIN32
if ( true )
{
char lang [ MAX_SIZE ] ;
if ( GetEnv ( " LANG " , lang , sizeof ( lang ) ) )
{
ret = GetBestLangByLangStr ( o , lang ) ;
}
else
{
ret = GetBestLangByLangStr ( o , " C " ) ;
}
}
# endif // OS_WIN32
return ret ;
}
// Search for the best language from LANG string of UNIX
LANGLIST * GetBestLangByLangStr ( LIST * o , char * str )
{
UINT i ;
LANGLIST * ret ;
// Validate arguments
if ( o = = NULL )
{
return NULL ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
UINT j ;
for ( j = 0 ; j < LIST_NUM ( e - > LangList ) ; j + + )
{
char * v = LIST_DATA ( e - > LangList , j ) ;
if ( StrCmpi ( v , str ) = = 0 )
{
return e ;
}
}
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
UINT j ;
for ( j = 0 ; j < LIST_NUM ( e - > LangList ) ; j + + )
{
char * v = LIST_DATA ( e - > LangList , j ) ;
if ( StartWith ( str , v ) | | StartWith ( v , str ) )
{
return e ;
}
}
}
ret = GetBestLangByName ( o , " en " ) ;
return ret ;
}
// Search for the best language from LCID
LANGLIST * GetBestLangByLcid ( LIST * o , UINT lcid )
{
LANGLIST * ret ;
UINT i ;
// Validate arguments
if ( o = = NULL )
{
return NULL ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
if ( IsIntInList ( e - > LcidList , lcid ) )
{
return e ;
}
}
ret = GetBestLangByName ( o , " en " ) ;
return ret ;
}
// Search for the best language from the name
LANGLIST * GetBestLangByName ( LIST * o , char * name )
{
UINT i ;
LANGLIST * ret = NULL ;
// Validate arguments
if ( o = = NULL )
{
return NULL ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
if ( StrCmpi ( e - > Name , name ) = = 0 )
{
ret = e ;
break ;
}
}
if ( ret ! = NULL )
{
return ret ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
if ( StartWith ( e - > Name , name ) | | StartWith ( name , e - > Name ) )
{
ret = e ;
break ;
}
}
if ( ret ! = NULL )
{
return ret ;
}
return ret ;
}
// Release the language list
void FreeLangList ( LIST * o )
{
UINT i ;
// Validate arguments
if ( o = = NULL )
{
return ;
}
for ( i = 0 ; i < LIST_NUM ( o ) ; i + + )
{
LANGLIST * e = LIST_DATA ( o , i ) ;
FreeStrList ( e - > LangList ) ;
ReleaseIntList ( e - > LcidList ) ;
Free ( e ) ;
}
ReleaseList ( o ) ;
}
// Read the language list
LIST * LoadLangList ( )
{
LIST * o = NewListFast ( NULL ) ;
char * filename = LANGLIST_FILENAME ;
BUF * b ;
2016-04-24 17:49:31 +03:00
# ifdef OS_WIN32
if ( MsIsWine ( ) )
{
filename = LANGLIST_FILENAME_WINE ;
}
# endif // OS_WIN32
2014-01-04 17:00:08 +04:00
b = ReadDump ( filename ) ;
if ( b = = NULL )
{
return NULL ;
}
while ( true )
{
char * line = CfgReadNextLine ( b ) ;
if ( line = = NULL )
{
break ;
}
Trim ( line ) ;
if ( IsEmptyStr ( line ) = = false & & StartWith ( line , " # " ) = = false )
{
TOKEN_LIST * t = ParseToken ( line , " \t " ) ;
if ( t ! = NULL )
{
if ( t - > NumTokens = = 6 )
{
LANGLIST * e = ZeroMalloc ( sizeof ( LANGLIST ) ) ;
TOKEN_LIST * t2 ;
e - > Id = ToInt ( t - > Token [ 0 ] ) ;
StrCpy ( e - > Name , sizeof ( e - > Name ) , t - > Token [ 1 ] ) ;
Utf8ToUni ( e - > TitleEnglish , sizeof ( e - > TitleEnglish ) , t - > Token [ 2 ] , StrLen ( t - > Token [ 2 ] ) ) ;
Utf8ToUni ( e - > TitleLocal , sizeof ( e - > TitleLocal ) , t - > Token [ 3 ] , StrLen ( t - > Token [ 3 ] ) ) ;
UniReplaceStrEx ( e - > TitleEnglish , sizeof ( e - > TitleEnglish ) , e - > TitleEnglish ,
L " _ " , L " " , true ) ;
UniReplaceStrEx ( e - > TitleLocal , sizeof ( e - > TitleLocal ) , e - > TitleLocal ,
L " _ " , L " " , true ) ;
e - > LcidList = NewIntList ( false ) ;
t2 = ParseToken ( t - > Token [ 4 ] , " , " ) ;
if ( t2 ! = NULL )
{
UINT i ;
for ( i = 0 ; i < t2 - > NumTokens ; i + + )
{
UINT id = ToInt ( t2 - > Token [ i ] ) ;
AddIntDistinct ( e - > LcidList , id ) ;
}
FreeToken ( t2 ) ;
}
e - > LangList = NewListFast ( NULL ) ;
t2 = ParseToken ( t - > Token [ 5 ] , " , " ) ;
if ( t2 ! = NULL )
{
UINT i ;
for ( i = 0 ; i < t2 - > NumTokens ; i + + )
{
Add ( e - > LangList , CopyStr ( t2 - > Token [ i ] ) ) ;
}
FreeToken ( t2 ) ;
}
Add ( o , e ) ;
}
FreeToken ( t ) ;
}
}
Free ( line ) ;
}
FreeBuf ( b ) ;
return o ;
}
// Get an error string in Unicode
wchar_t * GetUniErrorStr ( UINT err )
{
wchar_t * ret ;
char name [ MAX_SIZE ] ;
Format ( name , sizeof ( name ) , " ERR_%u " , err ) ;
ret = GetTableUniStr ( name ) ;
if ( UniStrLen ( ret ) ! = 0 )
{
return ret ;
}
else
{
return _UU ( " ERR_UNKNOWN " ) ;
}
}
// Get an error string
char * GetErrorStr ( UINT err )
{
char * ret ;
char name [ MAX_SIZE ] ;
Format ( name , sizeof ( name ) , " ERR_%u " , err ) ;
ret = GetTableStr ( name ) ;
if ( StrLen ( ret ) ! = 0 )
{
return ret ;
}
else
{
return _SS ( " ERR_UNKNOWN " ) ;
}
}
// Load the integer value from the table
UINT GetTableInt ( char * name )
{
char * str ;
// Validate arguments
if ( name = = NULL )
{
return 0 ;
}
str = GetTableStr ( name ) ;
return ToInt ( str ) ;
}
// Load a Unicode string from the table
wchar_t * GetTableUniStr ( char * name )
{
TABLE * t ;
// Validate arguments
if ( name = = NULL )
{
// Debug("%s: ************\n", name);
return L " " ;
}
// Search
t = FindTable ( name ) ;
if ( t = = NULL )
{
//Debug("%s: UNICODE STRING NOT FOUND\n", name);
return L " " ;
}
return t - > unistr ;
}
// Load the string from the table
char * GetTableStr ( char * name )
{
TABLE * t ;
// Validate arguments
if ( name = = NULL )
{
return " " ;
}
// Search
t = FindTable ( name ) ;
if ( t = = NULL )
{
//Debug("%s: ANSI STRING NOT FOUND\n", name);
return " " ;
}
return t - > str ;
}
// Get the string name that begins with the specified name
TOKEN_LIST * GetTableNameStartWith ( char * str )
{
UINT i ;
UINT len ;
LIST * o ;
TOKEN_LIST * t ;
char tmp [ MAX_SIZE ] ;
// Validate arguments
if ( str = = NULL )
{
return NullToken ( ) ;
}
StrCpy ( tmp , sizeof ( tmp ) , str ) ;
StrUpper ( tmp ) ;
len = StrLen ( tmp ) ;
o = NewListFast ( NULL ) ;
for ( i = 0 ; i < LIST_NUM ( TableList ) ; i + + )
{
TABLE * t = LIST_DATA ( TableList , i ) ;
UINT len2 = StrLen ( t - > name ) ;
if ( len2 > = len )
{
if ( Cmp ( t - > name , tmp , len ) = = 0 )
{
Insert ( o , CopyStr ( t - > name ) ) ;
}
}
}
t = ZeroMalloc ( sizeof ( TOKEN_LIST ) ) ;
t - > NumTokens = LIST_NUM ( o ) ;
t - > Token = ZeroMalloc ( sizeof ( char * ) * t - > NumTokens ) ;
for ( i = 0 ; i < t - > NumTokens ; i + + )
{
t - > Token [ i ] = LIST_DATA ( o , i ) ;
}
ReleaseList ( o ) ;
return t ;
}
// Search the table
TABLE * FindTable ( char * name )
{
TABLE * t , tt ;
// Validate arguments
if ( name = = NULL | | TableList = = NULL )
{
return NULL ;
}
tt . name = CopyStr ( name ) ;
t = Search ( TableList , & tt ) ;
Free ( tt . name ) ;
return t ;
}
// A function that compares the table name
int CmpTableName ( void * p1 , void * p2 )
{
TABLE * t1 , * t2 ;
if ( p1 = = NULL | | p2 = = NULL )
{
return 0 ;
}
t1 = * ( TABLE * * ) p1 ;
t2 = * ( TABLE * * ) p2 ;
if ( t1 = = NULL | | t2 = = NULL )
{
return 0 ;
}
return StrCmpi ( t1 - > name , t2 - > name ) ;
}
// Interpret a line
TABLE * ParseTableLine ( char * line , char * prefix , UINT prefix_size , LIST * replace_list )
{
UINT i , len ;
UINT len_name ;
UINT string_start ;
char * name ;
char * name2 ;
UINT name2_size ;
wchar_t * unistr ;
char * str ;
UINT unistr_size , str_size ;
TABLE * t ;
// Validate arguments
if ( line = = NULL | | prefix = = NULL )
{
return NULL ;
}
TrimLeft ( line ) ;
// No line
len = StrLen ( line ) ;
if ( len = = 0 )
{
return NULL ;
}
// Comment
if ( line [ 0 ] = = ' # ' | | ( line [ 0 ] = = ' / ' & & line [ 1 ] = = ' / ' ) )
{
return NULL ;
}
// Search to the end position of the name
len_name = 0 ;
for ( i = 0 ; ; i + + )
{
if ( line [ i ] = = 0 )
{
// There is only one token
return NULL ;
}
if ( line [ i ] = = ' ' | | line [ i ] = = ' \t ' )
{
break ;
}
len_name + + ;
}
name = Malloc ( len_name + 1 ) ;
StrCpy ( name , len_name + 1 , line ) ;
string_start = len_name ;
for ( i = len_name ; i < len ; i + + )
{
if ( line [ i ] ! = ' ' & & line [ i ] ! = ' \t ' )
{
break ;
}
string_start + + ;
}
if ( i = = len )
{
Free ( name ) ;
return NULL ;
}
// Unescape
UnescapeStr ( & line [ string_start ] ) ;
// Convert to Unicode
unistr_size = CalcUtf8ToUni ( & line [ string_start ] , StrLen ( & line [ string_start ] ) ) ;
if ( unistr_size = = 0 )
{
Free ( name ) ;
return NULL ;
}
unistr = Malloc ( unistr_size ) ;
Utf8ToUni ( unistr , unistr_size , & line [ string_start ] , StrLen ( & line [ string_start ] ) ) ;
if ( UniInChar ( unistr , L ' $ ' ) )
{
// Replace the replacement string
wchar_t * tmp ;
UINT tmp_size = ( UniStrSize ( unistr ) + 1024 ) * 2 ;
UINT i ;
tmp = Malloc ( tmp_size ) ;
UniStrCpy ( tmp , tmp_size , unistr ) ;
for ( i = 0 ; i < LIST_NUM ( replace_list ) ; i + + )
{
TABLE * r = LIST_DATA ( replace_list , i ) ;
UniReplaceStrEx ( tmp , tmp_size , tmp , ( wchar_t * ) r - > name , r - > unistr , false ) ;
}
2018-10-29 08:48:15 +03:00
Free ( unistr ) ;
2014-01-04 17:00:08 +04:00
unistr = CopyUniStr ( tmp ) ;
Free ( tmp ) ;
}
// Convert to ANSI
str_size = CalcUniToStr ( unistr ) ;
if ( str_size = = 0 )
{
str_size = 1 ;
str = Malloc ( 1 ) ;
str [ 0 ] = 0 ;
}
else
{
str = Malloc ( str_size ) ;
UniToStr ( str , str_size , unistr ) ;
}
if ( StrCmpi ( name , " PREFIX " ) = = 0 )
{
// Prefix is specified
StrCpy ( prefix , prefix_size , str ) ;
Trim ( prefix ) ;
if ( StrCmpi ( prefix , " $ " ) = = 0 | | StrCmpi ( prefix , " NULL " ) = = 0 )
{
prefix [ 0 ] = 0 ;
}
Free ( name ) ;
Free ( str ) ;
Free ( unistr ) ;
return NULL ;
}
name2_size = StrLen ( name ) + StrLen ( prefix ) + 2 ;
name2 = ZeroMalloc ( name2_size ) ;
if ( prefix [ 0 ] ! = 0 )
{
StrCat ( name2 , name2_size , prefix ) ;
StrCat ( name2 , name2_size , " @ " ) ;
}
StrCat ( name2 , name2_size , name ) ;
Free ( name ) ;
// Create a TABLE
t = Malloc ( sizeof ( TABLE ) ) ;
StrUpper ( name2 ) ;
t - > name = name2 ;
t - > str = str ;
t - > unistr = unistr ;
return t ;
}
// Unescape the string
void UnescapeStr ( char * src )
{
UINT i , len , wp ;
char * tmp ;
// Validate arguments
if ( src = = NULL )
{
return ;
}
len = StrLen ( src ) ;
tmp = Malloc ( len + 1 ) ;
wp = 0 ;
for ( i = 0 ; i < len ; i + + )
{
if ( src [ i ] = = ' \\ ' )
{
i + + ;
switch ( src [ i ] )
{
case 0 :
goto FINISH ;
case ' \\ ' :
tmp [ wp + + ] = ' \\ ' ;
break ;
case ' ' :
tmp [ wp + + ] = ' ' ;
break ;
case ' n ' :
case ' N ' :
tmp [ wp + + ] = ' \n ' ;
break ;
case ' r ' :
case ' R ' :
tmp [ wp + + ] = ' \r ' ;
break ;
case ' t ' :
case ' T ' :
tmp [ wp + + ] = ' \t ' ;
break ;
}
}
else
{
tmp [ wp + + ] = src [ i ] ;
}
}
FINISH :
tmp [ wp + + ] = 0 ;
StrCpy ( src , 0 , tmp ) ;
Free ( tmp ) ;
}
// Release the table
void FreeTable ( )
{
UINT i , num ;
TABLE * * tables ;
if ( TableList = = NULL )
{
return ;
}
num = LIST_NUM ( TableList ) ;
tables = ToArray ( TableList ) ;
for ( i = 0 ; i < num ; i + + )
{
TABLE * t = tables [ i ] ;
Free ( t - > name ) ;
Free ( t - > str ) ;
Free ( t - > unistr ) ;
Free ( t ) ;
}
ReleaseList ( TableList ) ;
TableList = NULL ;
Free ( tables ) ;
Zero ( old_table_name , sizeof ( old_table_name ) ) ;
}
// Read a string table from the buffer
bool LoadTableFromBuf ( BUF * b )
{
char * tmp ;
char prefix [ MAX_SIZE ] ;
LIST * replace_list = NULL ;
UINT i ;
// Validate arguments
if ( b = = NULL )
{
return false ;
}
// If the table already exists, delete it
FreeTable ( ) ;
// Create a list
TableList = NewList ( CmpTableName ) ;
Zero ( prefix , sizeof ( prefix ) ) ;
replace_list = NewListFast ( NULL ) ;
// Read the contents of the buffer line by line
while ( true )
{
TABLE * t ;
bool ok = true ;
tmp = CfgReadNextLine ( b ) ;
if ( tmp = = NULL )
{
break ;
}
if ( tmp [ 0 ] = = ' $ ' )
{
char key [ 128 ] ;
char value [ MAX_SIZE ] ;
if ( GetKeyAndValue ( tmp , key , sizeof ( key ) , value , sizeof ( value ) , " \t " ) )
{
if ( StartWith ( key , " $ " ) & & EndWith ( key , " $ " ) & & StrLen ( key ) > = 3 )
{
TABLE * t ;
wchar_t univalue [ MAX_SIZE ] ;
wchar_t uniname [ MAX_SIZE ] ;
t = ZeroMalloc ( sizeof ( TABLE ) ) ;
Zero ( univalue , sizeof ( univalue ) ) ;
Utf8ToUni ( univalue , sizeof ( univalue ) , value , StrLen ( value ) ) ;
StrToUni ( uniname , sizeof ( uniname ) , key ) ;
t - > name = ( char * ) CopyUniStr ( uniname ) ;
t - > unistr = CopyUniStr ( univalue ) ;
Add ( replace_list , t ) ;
// Found a replacement definition
ok = false ;
}
}
}
if ( ok )
{
t = ParseTableLine ( tmp , prefix , sizeof ( prefix ) , replace_list ) ;
if ( t ! = NULL )
{
// Register
Insert ( TableList , t ) ;
}
}
Free ( tmp ) ;
}
for ( i = 0 ; i < LIST_NUM ( replace_list ) ; i + + )
{
TABLE * t = LIST_DATA ( replace_list , i ) ;
Free ( t - > name ) ;
Free ( t - > str ) ;
Free ( t - > unistr ) ;
Free ( t ) ;
}
ReleaseList ( replace_list ) ;
return true ;
}
// Generate the Unicode string cache file name
void GenerateUnicodeCacheFileName ( wchar_t * name , UINT size , wchar_t * strfilename , UINT strfilesize , UCHAR * filehash )
{
wchar_t tmp [ MAX_SIZE ] ;
wchar_t hashstr [ 64 ] ;
wchar_t hashtemp [ MAX_SIZE ] ;
wchar_t exe [ MAX_SIZE ] ;
UCHAR hash [ SHA1_SIZE ] ;
// Validate arguments
if ( name = = NULL | | strfilename = = NULL | | filehash = = NULL )
{
return ;
}
GetExeDirW ( exe , sizeof ( exe ) ) ;
UniStrCpy ( hashtemp , sizeof ( hashtemp ) , strfilename ) ;
BinToStrW ( tmp , sizeof ( tmp ) , filehash , MD5_SIZE ) ;
UniStrCat ( hashtemp , sizeof ( hashtemp ) , tmp ) ;
UniStrCat ( hashtemp , sizeof ( hashtemp ) , exe ) ;
UniStrLower ( hashtemp ) ;
2018-09-22 07:35:30 +03:00
Sha0 ( hash , hashtemp , UniStrLen ( hashtemp ) * sizeof ( wchar_t ) ) ;
2014-01-04 17:00:08 +04:00
BinToStrW ( hashstr , sizeof ( hashstr ) , hash , 4 ) ;
UniFormat ( tmp , sizeof ( tmp ) , UNICODE_CACHE_FILE , hashstr ) ;
UniStrLower ( tmp ) ;
# ifndef OS_WIN32
UniStrCpy ( exe , sizeof ( exe ) , L " /tmp " ) ;
# else // OS_WIN32
StrToUni ( exe , sizeof ( exe ) , MsGetTempDir ( ) ) ;
# endif // OS_WIN32
UniFormat ( name , size , L " %s/%s " , exe , tmp ) ;
NormalizePathW ( name , size , name ) ;
}
// Save the Unicode cache
void SaveUnicodeCache ( wchar_t * strfilename , UINT strfilesize , UCHAR * hash )
{
UNICODE_CACHE c ;
BUF * b ;
UINT i ;
IO * io ;
wchar_t name [ MAX_PATH ] ;
UCHAR binhash [ MD5_SIZE ] ;
// Validate arguments
if ( strfilename = = NULL | | hash = = NULL )
{
return ;
}
Zero ( & c , sizeof ( c ) ) ;
UniToStr ( c . StrFileName , sizeof ( c . StrFileName ) , strfilename ) ;
c . StrFileSize = strfilesize ;
GetMachineName ( c . MachineName , sizeof ( c . MachineName ) ) ;
c . OsType = GetOsInfo ( ) - > OsType ;
Copy ( c . hash , hash , MD5_SIZE ) ;
# ifdef OS_UNIX
GetCurrentCharSet ( c . CharSet , sizeof ( c . CharSet ) ) ;
# else // OS_UNIX
{
UINT id = MsGetThreadLocale ( ) ;
Copy ( c . CharSet , & id , sizeof ( id ) ) ;
}
# endif // OS_UNIX
b = NewBuf ( ) ;
WriteBuf ( b , & c , sizeof ( c ) ) ;
WriteBufInt ( b , LIST_NUM ( TableList ) ) ;
for ( i = 0 ; i < LIST_NUM ( TableList ) ; i + + )
{
TABLE * t = LIST_DATA ( TableList , i ) ;
WriteBufInt ( b , StrLen ( t - > name ) ) ;
WriteBuf ( b , t - > name , StrLen ( t - > name ) ) ;
WriteBufInt ( b , StrLen ( t - > str ) ) ;
WriteBuf ( b , t - > str , StrLen ( t - > str ) ) ;
WriteBufInt ( b , UniStrLen ( t - > unistr ) ) ;
WriteBuf ( b , t - > unistr , UniStrLen ( t - > unistr ) * sizeof ( wchar_t ) ) ;
}
2018-09-22 07:35:30 +03:00
Md5 ( binhash , b - > Buf , b - > Size ) ;
2014-01-04 17:00:08 +04:00
WriteBuf ( b , binhash , MD5_SIZE ) ;
GenerateUnicodeCacheFileName ( name , sizeof ( name ) , strfilename , strfilesize , hash ) ;
io = FileCreateW ( name ) ;
if ( io ! = NULL )
{
SeekBuf ( b , 0 , 0 ) ;
BufToFile ( io , b ) ;
FileClose ( io ) ;
}
FreeBuf ( b ) ;
}
// Reading the Unicode cache
bool LoadUnicodeCache ( wchar_t * strfilename , UINT strfilesize , UCHAR * hash )
{
UNICODE_CACHE c , t ;
BUF * b ;
UINT i , num ;
IO * io ;
wchar_t name [ MAX_PATH ] ;
UCHAR binhash [ MD5_SIZE ] ;
UCHAR binhash_2 [ MD5_SIZE ] ;
// Validate arguments
if ( strfilename = = NULL | | hash = = NULL )
{
return false ;
}
GenerateUnicodeCacheFileName ( name , sizeof ( name ) , strfilename , strfilesize , hash ) ;
io = FileOpenW ( name , false ) ;
if ( io = = NULL )
{
return false ;
}
b = FileToBuf ( io ) ;
if ( b = = NULL )
{
FileClose ( io ) ;
return false ;
}
SeekBuf ( b , 0 , 0 ) ;
FileClose ( io ) ;
2018-09-22 07:35:30 +03:00
Md5 ( binhash , b - > Buf , b - > Size > = MD5_SIZE ? ( b - > Size - MD5_SIZE ) : 0 ) ;
2014-01-04 17:00:08 +04:00
Copy ( binhash_2 , ( ( UCHAR * ) b - > Buf ) + ( b - > Size > = MD5_SIZE ? ( b - > Size - MD5_SIZE ) : 0 ) , MD5_SIZE ) ;
if ( Cmp ( binhash , binhash_2 , MD5_SIZE ) ! = 0 )
{
FreeBuf ( b ) ;
return false ;
}
Zero ( & c , sizeof ( c ) ) ;
UniToStr ( c . StrFileName , sizeof ( c . StrFileName ) , strfilename ) ;
c . StrFileSize = strfilesize ;
2021-04-18 02:46:59 +03:00
DnsCacheToggle ( false ) ;
2014-01-04 17:00:08 +04:00
GetMachineName ( c . MachineName , sizeof ( c . MachineName ) ) ;
2021-04-18 02:46:59 +03:00
DnsCacheToggle ( true ) ;
2014-01-04 17:00:08 +04:00
c . OsType = GetOsInfo ( ) - > OsType ;
Copy ( c . hash , hash , MD5_SIZE ) ;
# ifdef OS_UNIX
GetCurrentCharSet ( c . CharSet , sizeof ( c . CharSet ) ) ;
# else // OS_UNIX
{
UINT id = MsGetThreadLocale ( ) ;
Copy ( c . CharSet , & id , sizeof ( id ) ) ;
}
# endif // OS_UNIX
Zero ( & t , sizeof ( t ) ) ;
ReadBuf ( b , & t , sizeof ( t ) ) ;
if ( Cmp ( & c , & t , sizeof ( UNICODE_CACHE ) ) ! = 0 )
{
FreeBuf ( b ) ;
return false ;
}
num = ReadBufInt ( b ) ;
FreeTable ( ) ;
TableList = NewList ( CmpTableName ) ;
for ( i = 0 ; i < num ; i + + )
{
UINT len ;
TABLE * t = ZeroMalloc ( sizeof ( TABLE ) ) ;
len = ReadBufInt ( b ) ;
t - > name = ZeroMalloc ( len + 1 ) ;
ReadBuf ( b , t - > name , len ) ;
len = ReadBufInt ( b ) ;
t - > str = ZeroMalloc ( len + 1 ) ;
ReadBuf ( b , t - > str , len ) ;
len = ReadBufInt ( b ) ;
t - > unistr = ZeroMalloc ( ( len + 1 ) * sizeof ( wchar_t ) ) ;
ReadBuf ( b , t - > unistr , len * sizeof ( wchar_t ) ) ;
Add ( TableList , t ) ;
}
FreeBuf ( b ) ;
Sort ( TableList ) ;
return true ;
}
// Read the string table
bool LoadTableMain ( wchar_t * filename )
{
BUF * b ;
UINT64 t1 , t2 ;
UCHAR hash [ MD5_SIZE ] ;
// Validate arguments
if ( filename = = NULL )
{
return false ;
}
if ( MayaquaIsMinimalMode ( ) )
{
return true ;
}
if ( UniStrCmpi ( old_table_name , filename ) = = 0 )
{
// Already loaded
return true ;
}
t1 = Tick64 ( ) ;
// Open the file
b = ReadDumpW ( filename ) ;
if ( b = = NULL )
{
char tmp [ MAX_SIZE ] ;
StrCpy ( tmp , sizeof ( tmp ) , " Error: Can't read string tables (file not found). \r \n Please check hamcore.se2. \r \n \r \n (First, reboot the computer. If this problem occurs again, please reinstall VPN software files.) " ) ;
Alert ( tmp , NULL ) ;
exit ( - 1 ) ;
return false ;
}
2018-09-22 07:35:30 +03:00
Md5 ( hash , b - > Buf , b - > Size ) ;
2014-01-04 17:00:08 +04:00
if ( LoadUnicodeCache ( filename , b - > Size , hash ) = = false )
{
if ( LoadTableFromBuf ( b ) = = false )
{
FreeBuf ( b ) ;
return false ;
}
SaveUnicodeCache ( filename , b - > Size , hash ) ;
2014-06-06 01:53:20 +04:00
//Debug("Unicode Source: strtable.stb\n");
2014-01-04 17:00:08 +04:00
}
else
{
2014-06-06 01:53:20 +04:00
//Debug("Unicode Source: unicode_cache\n");
2014-01-04 17:00:08 +04:00
}
FreeBuf ( b ) ;
2018-05-17 00:47:10 +03:00
SetLocale ( _UU ( " DEFAULT_LOCALE " ) ) ;
2014-01-04 17:00:08 +04:00
UniStrCpy ( old_table_name , sizeof ( old_table_name ) , filename ) ;
t2 = Tick64 ( ) ;
if ( StrCmpi ( _SS ( " STRTABLE_ID " ) , STRTABLE_ID ) ! = 0 )
{
char tmp [ MAX_SIZE ] ;
Format ( tmp , sizeof ( tmp ) , " Error: Can't read string tables (invalid version: '%s'!='%s'). \r \n Please check hamcore.se2. \r \n \r \n (First, reboot the computer. If this problem occurs again, please reinstall VPN software files.) " ,
_SS ( " STRTABLE_ID " ) , STRTABLE_ID ) ;
Alert ( tmp , NULL ) ;
exit ( - 1 ) ;
return false ;
}
2014-06-06 01:53:20 +04:00
//Debug("Unicode File Read Cost: %u (%u Lines)\n", (UINT)(t2 - t1), LIST_NUM(TableList));
2014-01-04 17:00:08 +04:00
return true ;
}
bool LoadTable ( char * filename )
{
wchar_t * filename_a = CopyStrToUni ( filename ) ;
bool ret = LoadTableW ( filename_a ) ;
Free ( filename_a ) ;
return ret ;
}
bool LoadTableW ( wchar_t * filename )
{
bool ret ;
BUF * b ;
wchar_t replace_name [ MAX_PATH ] ;
Zero ( replace_name , sizeof ( replace_name ) ) ;
b = ReadDump ( " @table_name.txt " ) ;
if ( b ! = NULL )
{
char * s = CfgReadNextLine ( b ) ;
if ( s ! = NULL )
{
if ( IsEmptyStr ( s ) = = false )
{
StrToUni ( replace_name , sizeof ( replace_name ) , s ) ;
filename = replace_name ;
}
Free ( s ) ;
}
FreeBuf ( b ) ;
}
ret = LoadTableMain ( filename ) ;
return ret ;
}