2015-11-01 04:50:24 +06:00
# include "precompiled.h"
2015-11-11 23:29:54 +06:00
CResourceFile Resource ;
2015-11-11 21:48:48 +03:00
std : : vector < const char * > StringsCache ;
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
void CResourceFile : : CreateResourceList ( )
2015-11-09 00:38:31 +06:00
{
int nConsistency = g_RehldsServerData - > GetConsistencyNum ( ) ;
2015-11-13 05:01:02 +06:00
m_DecalsNum = g_RehldsServerData - > GetDecalNameNum ( ) ;
2015-11-09 00:38:31 +06:00
2015-11-13 05:01:02 +06:00
for ( auto iter = m_resourceList . cbegin ( ) , end = m_resourceList . cend ( ) ; iter ! = end ; + + iter )
2015-11-09 00:38:31 +06:00
{
2015-11-11 23:29:54 +06:00
CResourceBuffer * pRes = ( * iter ) ;
2015-11-09 00:38:31 +06:00
// prevent duplicate of filenames
// check if filename is been marked so do not add the resource again
2015-11-13 05:01:02 +06:00
if ( ! pRes - > IsDuplicate ( ) )
{
// check limit resource
if ( g_RehldsServerData - > GetResourcesNum ( ) > = MAX_RESOURCE_LIST )
{
UTIL_Printf ( __FUNCTION__ " : can't add resource \" %s \" on line %d; exceeded the limit of resources max '%d' \n " , pRes - > GetFileName ( ) , pRes - > GetLine ( ) , MAX_RESOURCE_LIST ) ;
break ;
2015-11-11 23:29:54 +06:00
}
2015-11-13 05:01:02 +06:00
# ifdef _DEBUG
UTIL_Printf ( __FUNCTION__ " :: (%s)(%s)(%x) \n " , pRes - > GetFileName ( ) , pRes - > GetCmdExec ( ) , pRes - > GetFileHash ( ) ) ;
# endif // _DEBUG
SV_AddResource ( t_decal , pRes - > GetFileName ( ) , 0 , RES_CHECKFILE , m_DecalsNum + + ) ;
2015-11-09 00:38:31 +06:00
nConsistency + + ;
}
}
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
m_DecalsNum = g_RehldsServerData - > GetDecalNameNum ( ) ;
2015-11-09 00:38:31 +06:00
g_RehldsServerData - > SetConsistencyNum ( nConsistency ) ;
}
2015-11-11 23:29:54 +06:00
void CResourceFile : : Clear ( )
2015-11-09 00:38:31 +06:00
{
2015-11-11 23:29:54 +06:00
m_PrevHash = 0 ;
2015-11-13 17:01:39 +06:00
m_DecalsNum = 0 ;
2015-11-09 00:38:31 +06:00
// clear resources
2015-11-11 23:29:54 +06:00
m_resourceList . clear ( ) ;
2015-11-11 21:48:48 +03:00
ClearStringsCache ( ) ;
2015-11-09 00:38:31 +06:00
}
2015-11-11 23:29:54 +06:00
void CResourceFile : : Init ( )
2015-11-01 04:50:24 +06:00
{
char * pos ;
char path [ MAX_PATH_LENGTH ] ;
strncpy ( path , GET_PLUGIN_PATH ( PLID ) , sizeof ( path ) - 1 ) ;
path [ sizeof ( path ) - 1 ] = ' \0 ' ;
pos = strrchr ( path , ' / ' ) ;
if ( * pos = = ' \0 ' )
return ;
* ( pos + 1 ) = ' \0 ' ;
// resources.ini
2015-11-11 21:48:48 +03:00
snprintf ( m_PathDir , sizeof ( m_PathDir ) , " %s " FILE_INI_RESOURCES , path ) ;
2015-11-01 04:50:24 +06:00
}
inline uint8 hexbyte ( uint8 * hex )
{
return ( ( hex [ 0 ] > ' 9 ' ? toupper ( hex [ 0 ] ) - ' A ' + 10 : hex [ 0 ] - ' 0 ' ) < < 4 )
| ( hex [ 1 ] > ' 9 ' ? toupper ( hex [ 1 ] ) - ' A ' + 10 : hex [ 1 ] - ' 0 ' ) ;
}
2015-11-09 00:38:31 +06:00
inline bool invalidchar ( const char c )
{
// to check for invalid characters
return ( c = = ' \\ ' | | c = = ' / ' | | c = = ' : '
| | c = = ' * ' | | c = = ' ? '
| | c = = ' " ' | | c = = ' < '
| | c = = ' > ' | | c = = ' | ' ) ! = 0 ;
}
2015-11-13 05:01:02 +06:00
bool IsValidFilename ( char * psrc , char & pchar )
{
2015-11-09 00:38:31 +06:00
char * pch = strrchr ( psrc , ' / ' ) ;
2015-11-13 05:01:02 +06:00
if ( pch = = NULL )
2015-11-09 00:38:31 +06:00
pch = psrc ;
2015-11-13 05:01:02 +06:00
while ( * pch + + )
{
if ( invalidchar ( * pch ) )
{
2015-11-09 00:38:31 +06:00
pchar = * pch ;
return false ;
}
}
return true ;
}
2015-11-13 05:01:02 +06:00
bool IsFileHasExtension ( char * psrc )
{
2015-11-09 00:38:31 +06:00
// find the extension filename
char * pch = strrchr ( psrc , ' . ' ) ;
2015-11-13 05:01:02 +06:00
if ( pch = = NULL )
2015-11-09 00:38:31 +06:00
return false ;
// the size extension
2015-11-13 05:01:02 +06:00
if ( strlen ( & pch [ 1 ] ) < = 0 )
2015-11-09 00:38:31 +06:00
return false ;
return strchr ( pch , ' / ' ) = = NULL ;
}
2015-11-13 05:01:02 +06:00
void CResourceFile : : LoadResources ( )
2015-11-01 04:50:24 +06:00
{
char * pos ;
2015-11-13 05:01:02 +06:00
char line [ 4096 ] ;
2015-11-01 04:50:24 +06:00
uint8 hash [ 16 ] ;
FILE * fp ;
int argc ;
2015-11-09 00:38:31 +06:00
int len ;
2015-11-13 05:01:02 +06:00
flag_type_resources flag ;
2015-11-01 04:50:24 +06:00
char filename [ MAX_PATH_LENGTH ] ;
2015-11-09 00:38:31 +06:00
char cmdBufExec [ MAX_PATH_LENGTH ] ;
int cline = 0 ;
2015-11-01 04:50:24 +06:00
2015-11-11 23:29:54 +06:00
fp = fopen ( m_PathDir , " r " ) ;
2015-11-01 04:50:24 +06:00
if ( fp = = NULL )
{
2015-11-11 21:48:48 +03:00
m_ConfigFailed = true ;
2015-11-09 00:38:31 +06:00
UTIL_Printf ( __FUNCTION__ " : can't find path to " FILE_INI_RESOURCES " \n " ) ;
2015-11-01 04:50:24 +06:00
return ;
}
2015-11-13 05:01:02 +06:00
while ( ! feof ( fp ) & & fgets ( line , sizeof ( line ) , fp ) )
2015-11-01 04:50:24 +06:00
{
2015-11-13 05:01:02 +06:00
pos = line ;
2015-11-01 04:50:24 +06:00
2015-11-09 00:38:31 +06:00
cline + + ;
2015-11-13 05:01:02 +06:00
2015-11-01 04:50:24 +06:00
if ( * pos = = ' \0 ' | | * pos = = ' ; ' | | * pos = = ' \\ ' | | * pos = = ' / ' | | * pos = = ' # ' )
continue ;
const char * pToken = GetNextToken ( & pos ) ;
argc = 0 ;
2015-11-13 05:01:02 +06:00
flag = FLAG_TYPE_NONE ;
2015-11-11 23:29:54 +06:00
memset ( hash , 0 , sizeof ( hash ) ) ;
2015-11-01 04:50:24 +06:00
while ( pToken ! = NULL & & argc < = MAX_PARSE_ARGUMENT )
{
2015-11-09 00:38:31 +06:00
len = strlen ( pToken ) ;
2015-11-01 04:50:24 +06:00
switch ( argc )
{
case ARG_TYPE_FILE_NAME :
{
2015-11-13 05:01:02 +06:00
strncpy ( filename , pToken , len ) ;
filename [ len ] = ' \0 ' ;
2015-11-01 04:50:24 +06:00
break ;
}
case ARG_TYPE_FILE_HASH :
{
uint8 pbuf [ 33 ] ;
2015-11-09 00:38:31 +06:00
strncpy ( ( char * ) pbuf , pToken , len ) ;
pbuf [ len ] = ' \0 ' ;
2015-11-13 05:01:02 +06:00
if ( _stricmp ( ( const char * ) pbuf , " UNKNOWN " ) = = 0 )
{
flag = FLAG_TYPE_HASH_ANY ;
2015-11-09 00:38:31 +06:00
}
else
{
for ( int i = 0 ; i < sizeof ( pbuf ) / 2 ; i + + )
hash [ i ] = hexbyte ( & pbuf [ i * 2 ] ) ;
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
flag = ( * ( uint32 * ) & hash [ 0 ] ! = 0x00000000 ) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSING ;
2015-11-09 00:38:31 +06:00
}
2015-11-01 04:50:24 +06:00
break ;
}
2015-11-09 00:38:31 +06:00
case ARG_TYPE_CMD_EXEC :
2015-11-01 04:50:24 +06:00
{
2015-11-13 05:01:02 +06:00
strncpy ( cmdBufExec , pToken , len ) ;
cmdBufExec [ len ] = ' \0 ' ;
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
if ( _stricmp ( cmdBufExec , " IGNORE " ) = = 0 )
{
flag = FLAG_TYPE_IGNORE ;
2015-11-11 23:29:54 +06:00
cmdBufExec [ 0 ] = ' \0 ' ;
}
2015-11-13 05:01:02 +06:00
else if ( _stricmp ( cmdBufExec , " BREAK " ) = = 0 )
{
flag = FLAG_TYPE_BREAK ;
2015-11-11 23:29:54 +06:00
cmdBufExec [ 0 ] = ' \0 ' ;
}
2015-11-13 05:01:02 +06:00
else
{
2015-11-11 23:29:54 +06:00
// replface \' to "
StringReplace ( cmdBufExec , " ' " , " \" " ) ;
}
2015-11-13 05:01:02 +06:00
break ;
2015-11-11 23:29:54 +06:00
}
case ARG_TYPE_FLAG :
{
2015-11-13 05:01:02 +06:00
if ( _stricmp ( pToken , " IGNORE " ) = = 0 )
{
flag = FLAG_TYPE_IGNORE ;
2015-11-11 23:29:54 +06:00
}
2015-11-13 05:01:02 +06:00
else if ( _stricmp ( pToken , " BREAK " ) = = 0 )
{
flag = FLAG_TYPE_BREAK ;
2015-11-11 23:29:54 +06:00
}
2015-11-01 04:50:24 +06:00
break ;
}
default :
break ;
}
argc + + ;
pToken = GetNextToken ( & pos ) ;
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
if ( pToken = = NULL & & argc = = ARG_TYPE_FLAG )
{
2015-11-11 23:29:54 +06:00
// go to next argument
argc + + ;
}
2015-11-01 04:50:24 +06:00
}
2015-11-13 05:01:02 +06:00
if ( argc > = MAX_PARSE_ARGUMENT )
{
2015-11-09 00:38:31 +06:00
char pchar ;
2015-11-13 05:01:02 +06:00
if ( strlen ( filename ) < = 0 )
{
2015-11-09 00:38:31 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; path to filename is empty on line %d \n " , cline ) ;
continue ;
}
2015-11-13 05:01:02 +06:00
else if ( ! IsFileHasExtension ( filename ) )
{
2015-11-09 00:38:31 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; filename has no extension on line %d \n " , cline ) ;
continue ;
}
2015-11-13 05:01:02 +06:00
else if ( ! IsValidFilename ( filename , pchar ) )
{
2015-11-09 00:38:31 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; filename has invalid character '%c' on line %d \n " , pchar , cline ) ;
continue ;
}
2015-11-13 05:01:02 +06:00
else if ( flag = = FLAG_TYPE_NONE )
{
2015-11-09 00:38:31 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; parsing hash failed on line %d \n " , cline ) ;
continue ;
}
2015-11-11 23:29:54 +06:00
// TODO: is there a need to flag FLAG_TYPE_BREAK without cmdexec?
2015-11-13 05:01:02 +06:00
else if ( strlen ( cmdBufExec ) < = 0 & & ( flag ! = FLAG_TYPE_IGNORE & & flag ! = FLAG_TYPE_BREAK ) )
{
2015-11-11 23:29:54 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; parsing command line is empty on line %d \n " , cline ) ;
2015-11-09 00:38:31 +06:00
continue ;
}
2015-11-13 05:01:02 +06:00
AddElement ( filename , cmdBufExec , flag , * ( uint32 * ) & hash [ 0 ] , cline ) ;
2015-11-11 23:29:54 +06:00
}
2015-11-13 05:01:02 +06:00
else if ( pToken ! = NULL | | argc > ARG_TYPE_FILE_NAME )
{
2015-11-11 23:29:54 +06:00
UTIL_Printf ( __FUNCTION__ " : Failed to load \" " FILE_INI_RESOURCES " \" ; parsing not enough arguments on line %d (got '%d', expected '%d') \n " , cline , argc , MAX_PARSE_ARGUMENT ) ;
2015-11-01 04:50:24 +06:00
}
}
fclose ( fp ) ;
2015-11-11 21:48:48 +03:00
m_ConfigFailed = false ;
2015-11-01 04:50:24 +06:00
}
2015-11-11 23:29:54 +06:00
const char * CResourceFile : : GetNextToken ( char * * pbuf )
2015-11-01 04:50:24 +06:00
{
char * rpos = * pbuf ;
if ( * rpos = = ' \0 ' )
return NULL ;
2015-11-09 00:38:31 +06:00
// skip spaces at the beginning
2015-11-01 04:50:24 +06:00
while ( * rpos ! = 0 & & isspace ( * rpos ) )
rpos + + ;
2015-11-13 05:01:02 +06:00
if ( * rpos = = ' \0 ' )
{
2015-11-01 04:50:24 +06:00
* pbuf = rpos ;
return NULL ;
}
const char * res = rpos ;
char * wpos = rpos ;
char inQuote = ' \0 ' ;
while ( * rpos ! = ' \0 ' )
{
char cc = * rpos ;
if ( inQuote )
{
if ( inQuote = = cc )
{
inQuote = ' \0 ' ;
rpos + + ;
}
else
{
if ( rpos ! = wpos )
* wpos = cc ;
rpos + + ;
wpos + + ;
}
}
else if ( isspace ( cc ) )
{
break ;
}
else if ( cc = = ' \' ' | | cc = = ' " ' )
{
inQuote = cc ;
rpos + + ;
}
else
{
if ( rpos ! = wpos )
* wpos = cc ;
rpos + + ; wpos + + ;
}
}
if ( * rpos ! = ' \0 ' )
rpos + + ;
* pbuf = rpos ;
* wpos = ' \0 ' ;
return res ;
}
2015-11-13 05:01:02 +06:00
void CResourceFile : : AddElement ( char * filename , char * cmdExec , flag_type_resources flag , uint32 hash , int line )
2015-11-01 04:50:24 +06:00
{
2015-11-13 05:01:02 +06:00
auto nRes = new CResourceBuffer ( filename , cmdExec , flag , hash , line ) ;
2015-11-01 04:50:24 +06:00
2015-11-09 00:38:31 +06:00
// to mark files which are not required to add to the resource again
2015-11-13 05:01:02 +06:00
for ( auto iter = m_resourceList . cbegin ( ) , end = m_resourceList . cend ( ) ; iter ! = end ; + + iter )
2015-11-09 00:38:31 +06:00
{
2015-11-11 23:29:54 +06:00
CResourceBuffer * pRes = ( * iter ) ;
2015-11-13 05:01:02 +06:00
if ( _stricmp ( pRes - > GetFileName ( ) , filename ) = = 0 )
{
2015-11-11 21:48:48 +03:00
// resource name already registered
nRes - > SetDuplicate ( ) ;
break ;
2015-11-09 00:38:31 +06:00
}
}
2015-11-11 21:48:48 +03:00
m_resourceList . push_back ( nRes ) ;
2015-11-01 04:50:24 +06:00
}
2015-11-11 23:29:54 +06:00
bool CResourceFile : : FileConsistencyResponce ( IGameClient * pSenderClient , resource_t * resource , uint32 hash )
2015-11-01 04:50:24 +06:00
{
2015-11-13 05:01:02 +06:00
if ( resource - > type ! = t_decal
| | resource - > nIndex < m_DecalsNum ) // if by some miracle the decals will have the flag RES_CHECKFILE
// to be sure not bypass the decals
{
m_PrevHash = hash ;
return true ;
}
// strange thing
// if this happened when missing all the files from client
if ( ! m_PrevHash )
{
return true ;
}
2015-11-11 21:48:48 +03:00
bool bHandled = false ;
2015-11-13 05:01:02 +06:00
flag_type_resources typeFind ;
2015-11-11 23:29:54 +06:00
std : : vector < CResourceBuffer * > tempResourceList ;
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
for ( auto iter = m_resourceList . cbegin ( ) , end = m_resourceList . cend ( ) ; iter ! = end ; + + iter )
2015-11-01 04:50:24 +06:00
{
2015-11-11 23:29:54 +06:00
CResourceBuffer * pRes = ( * iter ) ;
2015-11-09 00:38:31 +06:00
if ( strcmp ( resource - > szFileName , pRes - > GetFileName ( ) ) ! = 0 )
continue ;
2015-11-13 05:01:02 +06:00
typeFind = pRes - > GetFileFlag ( ) ;
2015-11-09 00:38:31 +06:00
2015-11-13 05:01:02 +06:00
if ( m_PrevHash = = hash & & typeFind ! = FLAG_TYPE_MISSING )
typeFind = FLAG_TYPE_NONE ;
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
switch ( typeFind )
2015-11-11 23:29:54 +06:00
{
2015-11-13 05:01:02 +06:00
case FLAG_TYPE_BREAK :
/* empty */
break ;
case FLAG_TYPE_IGNORE :
tempResourceList . push_back ( pRes ) ;
break ;
case FLAG_TYPE_EXISTS :
if ( pRes - > GetFileHash ( ) = = hash )
{
typeFind = FLAG_TYPE_EXISTS ;
2015-11-09 00:38:31 +06:00
}
2015-11-13 05:01:02 +06:00
break ;
case FLAG_TYPE_HASH_ANY :
for ( auto it = tempResourceList . cbegin ( ) ; it ! = tempResourceList . cend ( ) ; + + it )
2015-11-11 23:29:54 +06:00
{
2015-11-13 05:01:02 +06:00
CResourceBuffer * pTemp = ( * it ) ;
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
if ( _stricmp ( pTemp - > GetFileName ( ) , pRes - > GetFileName ( ) ) ! = 0 )
continue ;
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
if ( pTemp - > GetFileHash ( ) = = hash )
{
typeFind = FLAG_TYPE_NONE ;
break ;
2015-11-11 23:29:54 +06:00
}
2015-11-09 00:38:31 +06:00
}
2015-11-13 05:01:02 +06:00
break ;
case FLAG_TYPE_MISSING :
if ( m_PrevHash ! = hash )
{
typeFind = FLAG_TYPE_NONE ;
}
break ;
default :
typeFind = FLAG_TYPE_NONE ;
break ;
2015-11-09 00:38:31 +06:00
}
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
if ( typeFind ! = FLAG_TYPE_NONE )
{
2015-11-09 00:38:31 +06:00
// push exec cmd
2015-11-11 23:29:54 +06:00
Exec . AddElement ( pSenderClient , pRes , hash ) ;
2015-11-13 05:01:02 +06:00
# ifdef _DEBUG
UTIL_Printf ( " -> filename: (%s), cmdexec: (%s), hash: (%x), typeFind: (%d) \n " , pRes - > GetFileName ( ) , pRes - > GetCmdExec ( ) , pRes - > GetFileHash ( ) , typeFind ) ;
# endif // _DEBUG
2015-11-09 00:38:31 +06:00
}
2015-11-13 05:01:02 +06:00
bHandled = true ;
2015-11-01 04:50:24 +06:00
}
2015-11-09 00:38:31 +06:00
2015-11-11 23:29:54 +06:00
m_PrevHash = hash ;
2015-11-11 21:48:48 +03:00
return ! bHandled ;
2015-11-01 04:50:24 +06:00
}
2015-11-13 05:01:02 +06:00
const char * DuplicateString ( const char * str )
2015-11-01 04:50:24 +06:00
{
2015-11-13 05:01:02 +06:00
for ( auto iter = StringsCache . cbegin ( ) , end = StringsCache . cend ( ) ; iter ! = end ; + + iter )
2015-11-11 21:48:48 +03:00
{
2015-11-13 05:01:02 +06:00
if ( ! strcmp ( * iter , str ) )
return * iter ;
2015-11-11 21:48:48 +03:00
}
2015-11-11 23:29:54 +06:00
2015-11-13 05:01:02 +06:00
const char * s = strcpy ( new char [ strlen ( str ) + 1 ] , str ) ;
2015-11-11 21:48:48 +03:00
StringsCache . push_back ( s ) ;
return s ;
}
2015-11-11 23:29:54 +06:00
2015-11-11 21:48:48 +03:00
void ClearStringsCache ( )
{
2015-11-13 05:01:02 +06:00
for ( auto iter = StringsCache . begin ( ) , end = StringsCache . end ( ) ; iter ! = end ; + + iter )
delete [ ] * iter ;
StringsCache . clear ( ) ;
2015-11-11 21:48:48 +03:00
}
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
CResourceBuffer : : CResourceBuffer ( char * filename , char * cmdExec , flag_type_resources flag , uint32 hash , int line )
2015-11-11 21:48:48 +03:00
{
m_FileName = DuplicateString ( filename ) ;
2015-11-13 05:01:02 +06:00
m_CmdExec = ( cmdExec [ 0 ] ! = ' \0 ' ) ? DuplicateString ( cmdExec ) : NULL ;
2015-11-01 04:50:24 +06:00
2015-11-11 21:48:48 +03:00
m_Duplicate = false ;
2015-11-01 04:50:24 +06:00
2015-11-13 05:01:02 +06:00
m_Flag = flag ;
2015-11-11 21:48:48 +03:00
m_FileHash = hash ;
2015-11-13 05:01:02 +06:00
m_Line = line ;
2015-11-01 04:50:24 +06:00
}