From 6e4dbe9da7e2a539b9d1bbcfaf88afec50eadffb Mon Sep 17 00:00:00 2001 From: s1lentq Date: Mon, 9 Nov 2015 00:38:31 +0600 Subject: [PATCH] Start working. Implemented CBufExec. --- engine/rehlds_api.h | 10 +- engine/rehlds_interfaces.h | 14 +- msvc/rechecker.vcxproj | 2 + msvc/rechecker.vcxproj.filters | 2 + src/cmdexec.cpp | 110 +++++++++++++ src/cmdexec.h | 35 ++++ src/config.cpp | 284 ++++++++++++++++++++++++--------- src/config.h | 72 ++++++--- src/dllapi.cpp | 97 ++++++++++- src/engine_rehlds.cpp | 10 +- src/engine_rehlds.h | 6 +- src/main.cpp | 134 +++++++--------- src/main.h | 2 + src/meta_api.cpp | 8 +- src/precompiled.h | 7 + src/sdk_util.cpp | 17 +- 16 files changed, 602 insertions(+), 208 deletions(-) create mode 100644 src/cmdexec.cpp create mode 100644 src/cmdexec.h diff --git a/engine/rehlds_api.h b/engine/rehlds_api.h index a6d04bc..bb25873 100644 --- a/engine/rehlds_api.h +++ b/engine/rehlds_api.h @@ -141,9 +141,9 @@ typedef IVoidHookChainRegistry IRehldsHook_SV_WriteFullClientUpdate; typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_WriteFullClientUpdate; -//SV_GenericFileConsistencyResponce hook -typedef IVoidHookChain IRehldsHook_GenericFileConsistencyResponce; -typedef IVoidHookChainRegistry IRehldsHookRegistry_GenericFileConsistencyResponce; +//SV_CheckConsistencyResponce hook +typedef IHookChain IRehldsHook_SV_CheckConsistencyResponce; +typedef IHookChainRegistry IRehldsHookRegistry_SV_CheckConsistencyResponce; class IRehldsHookchains { public: @@ -175,7 +175,7 @@ public: virtual IRehldsHookRegistry_PF_Remove_I* PF_Remove_I() = 0; virtual IRehldsHookRegistry_PF_BuildSoundMsg_I* PF_BuildSoundMsg_I() = 0; virtual IRehldsHookRegistry_SV_WriteFullClientUpdate* SV_WriteFullClientUpdate() = 0; - virtual IRehldsHookRegistry_GenericFileConsistencyResponce* GenericFileConsistencyResponce() = 0; + virtual IRehldsHookRegistry_SV_CheckConsistencyResponce* SV_CheckConsistencyResponce() = 0; }; struct RehldsFuncs_t { @@ -211,6 +211,7 @@ struct RehldsFuncs_t { void*(*SZ_GetSpace)(sizebuf_t *buf, int length); cvar_t*(*GetCvarVars)(); int (*SV_GetChallenge)(const netadr_t& adr); + void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index); }; class IRehldsApi { @@ -222,7 +223,6 @@ public: virtual const RehldsFuncs_t* GetFuncs() = 0; virtual IRehldsHookchains* GetHookchains() = 0; virtual IRehldsServerStatic* GetServerStatic() = 0; - virtual IRehldsServer* GetServer() = 0; virtual IRehldsServerData* GetServerData() = 0; virtual IRehldsFlightRecorder* GetFlightRecorder() = 0; }; diff --git a/engine/rehlds_interfaces.h b/engine/rehlds_interfaces.h index 6aa29eb..9d31442 100644 --- a/engine/rehlds_interfaces.h +++ b/engine/rehlds_interfaces.h @@ -90,18 +90,6 @@ public: struct client_t; #endif -class IRehldsServer { -public: - virtual ~IRehldsServer() { } - - virtual int GetNumResources() = 0; - virtual int GetNumConsistency() = 0; - virtual void SetNumConsistency(int iValue) = 0; - virtual void SetNumResources(int iValue) = 0; - virtual resource_t *GetResourceList() = 0; - virtual struct consistency_s *GetConsistencyList() = 0; -}; - class IRehldsServerStatic { public: virtual ~IRehldsServerStatic() { } @@ -125,4 +113,6 @@ public: virtual sizebuf_t* GetReliableDatagram() = 0; virtual void SetModelName(const char* modelname) = 0; + virtual void SetConsistencyNum(int num) = 0; + virtual int GetConsistencyNum() = 0; }; diff --git a/msvc/rechecker.vcxproj b/msvc/rechecker.vcxproj index c4fd99f..81e17be 100644 --- a/msvc/rechecker.vcxproj +++ b/msvc/rechecker.vcxproj @@ -163,6 +163,7 @@ + @@ -173,6 +174,7 @@ true + diff --git a/msvc/rechecker.vcxproj.filters b/msvc/rechecker.vcxproj.filters index 27f6458..5514b97 100644 --- a/msvc/rechecker.vcxproj.filters +++ b/msvc/rechecker.vcxproj.filters @@ -461,6 +461,7 @@ + @@ -478,6 +479,7 @@ + diff --git a/src/cmdexec.cpp b/src/cmdexec.cpp new file mode 100644 index 0000000..cc05f2e --- /dev/null +++ b/src/cmdexec.cpp @@ -0,0 +1,110 @@ +#include "precompiled.h" + +CBufExec CmdExec; + +CBufExecNew::CBufExecNew(IGameClient *pClient, CResourceCheckerNew *pResource) +{ + m_pClient = pClient; + m_pResource = pResource; +} + +CBufExecNew::~CBufExecNew() +{ + ; +} + +void CBufExec::AddElement(IGameClient *pClient, CResourceCheckerNew *pResource) +{ + m_vector.push_back(new CBufExecNew(pClient, pResource)); +} + +void StringReplace(char *src, const char *strold, const char *strnew) +{ + if (strnew == NULL) { + return; + } + + char *p = src; + int oldLen = strlen(strold), newLen = strlen(strnew); + + while ((p = strstr(p, strold)) != NULL) + { + if (oldLen != newLen) + memmove(p + newLen, p + oldLen, strlen(p) - oldLen + 1); + + memcpy(p, strnew, newLen); + p += newLen; + } +} + +char *GetExecCmdPrepare(IGameClient *pClient, CResourceCheckerNew *pResource) +{ + int len; + const netadr_t *net; + static char string[256]; + + strncpy(string, pResource->GetCmdExec(), sizeof(string) - 1); + string[sizeof(string) - 1] = '\0'; + + net = pClient->GetNetChan()->GetRemoteAdr(); + + // replace of templates for identification + StringReplace(string, "[name]", pClient->GetName()); + StringReplace(string, "[userid]", UTIL_VarArgs("#%u", g_engfuncs.pfnGetPlayerUserId(pClient->GetEdict()))); + StringReplace(string, "[steamid]", UTIL_VarArgs("%s", g_engfuncs.pfnGetPlayerAuthId(pClient->GetEdict()))); + StringReplace(string, "[ip]", UTIL_VarArgs("%i.%i.%i.%i", net->ip[0], net->ip[1], net->ip[2], net->ip[3])); + + // replace key values + StringReplace(string, "[file_name]", pResource->GetFileName()); + StringReplace(string, "[file_hash]", UTIL_VarArgs("%x", pResource->GetHashFile())); + + len = strlen(string); + + if (len < sizeof(string) - 2) { + strcat(string, "\n"); + } + else + string[len - 1] = '\n'; + + return string; +} + +void CBufExec::Exec(IGameClient *pClient) +{ + CBufExecVectorIt it = m_vector.begin(); + + while (it != m_vector.end()) + { + CBufExecNew *exc = (*it); + + if (exc->GetGameClient() != pClient) { + it++; + continue; + } + + // exit the loop if the client is out of the game + // TODO: Check me! + + if (!pClient->IsConnected()) { + break; + } + + char *cmdExec = GetExecCmdPrepare(pClient, exc->GetResource()); + + if (cmdExec != NULL && cmdExec[0] != '\0') { + // execute cmd + SERVER_COMMAND(cmdExec); + + // erase cmd exec + delete exc; + it = m_vector.erase(it); + } + else + it++; + } +} + +void CBufExec::Clear() +{ + m_vector.clear(); +} diff --git a/src/cmdexec.h b/src/cmdexec.h new file mode 100644 index 0000000..3475cc2 --- /dev/null +++ b/src/cmdexec.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +class CBufExecNew +{ +public: + CBufExecNew(IGameClient *pClient, CResourceCheckerNew *pResource); + ~CBufExecNew(); + + IGameClient *GetGameClient() { return m_pClient; }; + CResourceCheckerNew *GetResource() { return m_pResource; }; + +private: + IGameClient *m_pClient; + CResourceCheckerNew *m_pResource; +}; + +typedef std::vector CBufExecVector; +typedef CBufExecVector::iterator CBufExecVectorIt; + +class CBufExec +{ +public: + void AddElement(IGameClient *pClient, CResourceCheckerNew *pResource); + + void Exec(IGameClient *pClient); + void Clear(); + +private: + CBufExecVector m_vector; +}; + +extern CBufExec CmdExec; +extern void StringReplace(char *src, const char *strold, const char *strnew); diff --git a/src/config.cpp b/src/config.cpp index c359af9..0328f5c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -2,6 +2,38 @@ CConfig Config; +void CConfig::AddResource() +{ + ResourceCheckerVectorIt it = m_vector.begin(); + int nConsistency = g_RehldsServerData->GetConsistencyNum(); + + while (it != m_vector.end()) + { + CResourceCheckerNew *pRes = (*it); + + // prevent duplicate of filenames + // check if filename is been marked so do not add the resource again + if (pRes->GetMark() != true) { +#ifdef _DEBUG + printf(__FUNCTION__ " :: (%s)(%s)\n", pRes->GetFileName(), pRes->GetCmdExec()); +#endif // _DEBUG + SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, 4095); + nConsistency++; + } + + it++; + } + g_RehldsServerData->SetConsistencyNum(nConsistency); +} + +void CConfig::ClearResources() +{ + m_PreHash = 0; + + // clear resources + m_vector.clear(); +} + void CConfig::Init() { char *pos; @@ -22,8 +54,11 @@ void CConfig::Init() // resources.ini snprintf(m_szPathResourcesDir, sizeof(m_szPathResourcesDir) - 1, "%s" FILE_INI_RESOURCES, path); +} - ParseConfig(); +void CConfig::Load() +{ + //ParseConfig(); ParseResources(); } @@ -33,7 +68,8 @@ void CConfig::ParseConfig() if (fp == NULL) { - UTIL_LogPrintf(__FUNCTION__ ": can't find path to " FILE_INI_CONFIG); + UTIL_Printf(__FUNCTION__ ": can't find path to " FILE_INI_CONFIG "\n"); + return; } // soon coming.. @@ -47,6 +83,50 @@ inline uint8 hexbyte(uint8 *hex) | (hex[1] > '9' ? toupper(hex[1]) - 'A' + 10 : hex[1] - '0'); } +inline bool invalidchar(const char c) +{ + // to check for invalid characters + return (c == '\\' || c == '/' || c == ':' + || c == '*' || c == '?' + || c == '"' || c == '<' + || c == '>' || c == '|') != 0; +} + +bool FileIsValidChar(char *psrc, char &pchar) { + + char *pch = strrchr(psrc, '/'); + + if (pch == NULL) { + pch = psrc; + } + + while (*pch++) { + if (invalidchar(*pch)) { + pchar = *pch; + return false; + } + } + + return true; +} + +bool FileIsExtension(char *psrc) { + + // find the extension filename + char *pch = strrchr(psrc, '.'); + + if (pch == NULL) { + return false; + } + + // the size extension + if (strlen(&pch[1]) <= 0) { + return false; + } + + return strchr(pch, '/') == NULL; +} + void CConfig::ParseResources() { char *pos; @@ -54,23 +134,26 @@ void CConfig::ParseResources() uint8 hash[16]; FILE *fp; int argc; - flag_type_resources flags = FLAG_TYPE_NONE; + int len; + flag_type_resources flag = FLAG_TYPE_NONE; char filename[MAX_PATH_LENGTH]; - char cmdPunish[MAX_PATH_LENGTH]; + char cmdBufExec[MAX_PATH_LENGTH]; + int cline = 0; fp = fopen(m_szPathResourcesDir, "r"); if (fp == NULL) { - UTIL_LogPrintf(__FUNCTION__ ": can't find path to " FILE_INI_RESOURCES); + m_ConfigFailed = false; + UTIL_Printf(__FUNCTION__ ": can't find path to " FILE_INI_RESOURCES "\n"); return; } while (!feof(fp) && fgets(buffer, sizeof(buffer) - 1, fp)) { - pos = &buffer[0]; + pos = buffer; - // TrimSpace(pos); + cline++; if (*pos == '\0' || *pos == ';' || *pos == '\\' || *pos == '/' || *pos == '#') continue; @@ -78,44 +161,48 @@ void CConfig::ParseResources() const char *pToken = GetNextToken(&pos); argc = 0; - memset(hash, 0, sizeof(hash)); - + hash[0] = '\0'; + flag = FLAG_TYPE_NONE; + while (pToken != NULL && argc <= MAX_PARSE_ARGUMENT) { - int iLen = strlen(pToken); + len = strlen(pToken); switch (argc) { case ARG_TYPE_FILE_NAME: { - strncpy(filename, pToken, iLen + 1); - filename[iLen + 1] = '\0'; + strncpy(filename, pToken, len + 1); + filename[len + 1] = '\0'; break; } case ARG_TYPE_FILE_HASH: { uint8 pbuf[33]; - strncpy((char *)pbuf, pToken, iLen); - pbuf[iLen] = '\0'; + strncpy((char *)pbuf, pToken, len); + pbuf[len] = '\0'; - for (int i = 0; i < sizeof(pbuf) / 2; i++) - hash[i] = hexbyte(&pbuf[i * 2]); + if (_stricmp((const char *)pbuf, "UNKNOWN") == 0) { + flag = FLAG_TYPE_HASH_ANY; + } + else + { + for (int i = 0; i < sizeof(pbuf) / 2; i++) + hash[i] = hexbyte(&pbuf[i * 2]); + + flag = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSGIN; + } break; } - case ARG_TYPE_CMD_PUNISH: + case ARG_TYPE_CMD_EXEC: { - strncpy(cmdPunish, pToken, iLen + 1); - cmdPunish[iLen + 1] = '\0'; + strncpy(cmdBufExec, pToken, len + 1); + cmdBufExec[len + 1] = '\0'; // replface \' to " - StringReplace(cmdPunish, "'", "\""); - break; - } - case ARG_TYPE_FILE_FLAGS: - { - // TODO: Implement me flags + StringReplace(cmdBufExec, "'", "\""); break; } default: @@ -127,7 +214,34 @@ void CConfig::ParseResources() } if (argc >= MAX_PARSE_ARGUMENT) { - AddElement(filename, cmdPunish, flags, *(uint32 *)&hash[0]); + + char pchar; + if (strlen(filename) <= 0) { + UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; path to filename is empty on line %d\n", cline); + continue; + } + + else if (!FileIsExtension(filename)) { + UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has no extension on line %d\n", cline); + continue; + } + + else if (!FileIsValidChar(filename, pchar)) { + UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has invalid character '%c' on line %d\n", pchar, cline); + continue; + } + + else if (flag == FLAG_TYPE_NONE) { + UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline); + continue; + } + + else if (strlen(cmdBufExec) <= 0) { + UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; command line is empty on line %d\n", cline); + continue; + } + + AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0]); } } @@ -140,7 +254,7 @@ const char *CConfig::GetNextToken(char **pbuf) if (*rpos == '\0') return NULL; - //skip spaces at the beginning + // skip spaces at the beginning while (*rpos != 0 && isspace(*rpos)) rpos++; @@ -197,7 +311,7 @@ const char *CConfig::GetNextToken(char **pbuf) return res; } -void CConfig::TrimSpace(char *pbuf) +void TrimSpace(char *pbuf) { char *pend = pbuf; char *pstart = pbuf; @@ -226,65 +340,91 @@ void CConfig::TrimSpace(char *pbuf) *pend = '\0'; } -void CConfig::AddElement(char *filename, char *cmdPunish, flag_type_resources flags, uint32 hash) +void CConfig::AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash) { - m_vector.push_back(new CResourceCheckerNew(filename, cmdPunish, flags, hash)); -} + m_vector.push_back(new CResourceCheckerNew(filename, cmdExec, flag, hash)); -char *CConfig::CommandPunishment(IGameClient *pClient, const char *src) -{ - char szIp[16]; - edict_t *pEdict; - const netadr_t *net; - static char string[256]; - - strncpy(string, src, sizeof(string) - 1); - string[sizeof(string) - 1] = '\0'; - - pEdict = pClient->GetEdict(); - net = pClient->GetNetChan()->GetRemoteAdr(); - snprintf(szIp, sizeof(szIp), "%i.%i.%i.%i", net->ip[0], net->ip[1], net->ip[2], net->ip[3]); - - // replace of templates punishment - StringReplace(string, "[name]", STRING(pEdict->v.netname)); - StringReplace(string, "[userid]", UTIL_VarArgs("%u", g_engfuncs.pfnGetPlayerUserId(pEdict))); - StringReplace(string, "[steamid]", UTIL_VarArgs("%s", g_engfuncs.pfnGetPlayerAuthId(pEdict))); - StringReplace(string, "[ip]", szIp); - - //SERVER_COMMAND(UTIL_VarArgs("%s\n", string)); - return string; -} - -void CConfig::StringReplace(char *src, const char *strold, const char *strnew) -{ - char *p = src; - int oldLen = strlen(strold), newLen = strlen(strnew); - - while ((p = strstr(p, strold)) != NULL) + // to mark files which are not required to add to the resource again + for (ResourceCheckerVectorIt it = m_vector.begin(); it != m_vector.end(); ++it) { - if (oldLen != newLen) - memmove(p + newLen, p + oldLen, strlen(p) - oldLen + 1); + CResourceCheckerNew *pRes = (*it); - memcpy(p, strnew, newLen); - p += newLen; + // do not check the last element + if (pRes == m_vector.back()) + continue; + + if (_stricmp(pRes->GetFileName(), filename) == 0) { + // set be marked + pRes->SetMark(); + } } } -CResourceCheckerNew::CResourceCheckerNew(char *filename, char *cmdPunish, flag_type_resources flags, uint32 hash) +bool CConfig::FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash) +{ + bool bCheckeFiles = false; + find_type_e typeFind = FIND_TYPE_NONE; + + for (ResourceCheckerVectorIt it = m_vector.begin(); it != m_vector.end(); ++it) + { + CResourceCheckerNew *pRes = (*it); + + if (strcmp(resource->szFileName, pRes->GetFileName()) != 0) + continue; + + bCheckeFiles = true; + + switch (pRes->GetFlagFile()) + { + case FLAG_TYPE_EXISTS: + if (m_PreHash != hash && pRes->GetHashFile() == hash) { + typeFind = FIND_TYPE_ON_HASH; + } + break; + case FLAG_TYPE_MISSGIN: + if (m_PreHash == hash) { + typeFind = FIND_TYPE_MISSING; + } + break; + case FLAG_TYPE_HASH_ANY: + if (m_PreHash != hash) { + typeFind = FIND_TYPE_ANY_HASH; + } + break; + default: + typeFind = FIND_TYPE_NONE; + break; + } + + if (typeFind != FIND_TYPE_NONE) { + // push exec cmd + CmdExec.AddElement(pSenderClient, pRes); +#ifdef _DEBUG + printf("* (%s)(%s)(%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetHashFile()); +#endif // _DEBUG + } + } + + m_PreHash = hash; + return !bCheckeFiles; +} + +CResourceCheckerNew::CResourceCheckerNew(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash) { int iLenFile = strlen(filename); - int iLenPunish = strlen(cmdPunish); + int iLenExec = strlen(cmdExec); m_FileName = new char[iLenFile + 1]; - m_Punishment = new char[iLenPunish + 1]; + m_CmdExec = new char[iLenExec + 1]; strncpy(m_FileName, filename, iLenFile); - strncpy(m_Punishment, cmdPunish, iLenPunish); + strncpy(m_CmdExec, cmdExec, iLenExec); m_FileName[iLenFile] = '\0'; - m_Punishment[iLenPunish] = '\0'; + m_CmdExec[iLenExec] = '\0'; + m_Mark = false; - m_Flags = flags; + m_Flag = flag; m_HashFile = hash; } @@ -292,5 +432,5 @@ CResourceCheckerNew::~CResourceCheckerNew() { // free me delete[] m_FileName, - m_Punishment; + m_CmdExec; } diff --git a/src/config.h b/src/config.h index 6b1eeb0..f1b3bdf 100644 --- a/src/config.h +++ b/src/config.h @@ -5,44 +5,60 @@ #define FILE_INI_CONFIG "config.ini" #define FILE_INI_RESOURCES "resources.ini" -#define MAX_PARSE_ARGUMENT 3 - //#ifdef MAX_PATH //#define MAX_PATH 260 //#endif // MAX_PATH +#define MAX_CLIENTS 32 #define MAX_CMD_LENGTH 128 #define MAX_PATH_LENGTH 260 -enum +enum find_type_e +{ + FIND_TYPE_NONE = 0, + FIND_TYPE_ON_HASH, + FIND_TYPE_ANY_HASH, + FIND_TYPE_MISSING +}; + +enum arg_type_e { ARG_TYPE_FILE_NAME = 0, ARG_TYPE_FILE_HASH, - ARG_TYPE_CMD_PUNISH, - ARG_TYPE_FILE_FLAGS, + ARG_TYPE_CMD_EXEC, + + MAX_PARSE_ARGUMENT, }; -typedef enum +enum flag_type_resources { - FLAG_TYPE_NONE = 0, - FLAG_TYPE_EXISTS = (1<<0), - FLAG_TYPE_MISSGIN = (1<<1), - FLAG_TYPE_HASH_ANY = (1<<2), - -} flag_type_resources; + FLAG_TYPE_NONE = 0, + FLAG_TYPE_EXISTS, + FLAG_TYPE_MISSGIN, + FLAG_TYPE_HASH_ANY, +}; class CResourceCheckerNew { public: - //CResourceCheckerNew(void); - CResourceCheckerNew(char *filename, char *cmdPunish, flag_type_resources flags, uint32 hash); + CResourceCheckerNew(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash); ~CResourceCheckerNew(); - uint32 m_HashFile; - flag_type_resources m_Flags; + uint32 GetHashFile() { return m_HashFile; }; + flag_type_resources GetFlagFile() { return m_Flag; }; - char *m_FileName;//[MAX_PATH_LENGTH]; - char *m_Punishment;//[MAX_CMD_LENGTH]; + char *GetFileName() { return m_FileName; }; + char *GetCmdExec() { return m_CmdExec; }; + bool GetMark() { return m_Mark; }; + void SetMark() { m_Mark = true; }; + +private: + uint32 m_HashFile; + flag_type_resources m_Flag; + + char *m_FileName; + char *m_CmdExec; + bool m_Mark; }; typedef std::vector ResourceCheckerVector; @@ -52,24 +68,30 @@ class CConfig { public: void Init(); - char *CommandPunishment(IGameClient *pClient, const char *src); - ResourceCheckerVector *GetVector() { return &m_vector; }; + void Load(); + + void AddResource(); + void ClearResources(); + + bool FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash); + bool IsConfigLoaded() { return !m_ConfigFailed; }; private: void ParseConfig(); void ParseResources(); - void AddElement(char *filename, char *cmdPunish, flag_type_resources flags, uint32 hash); - + void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash); + // parse const char *GetNextToken(char **pbuf); - void TrimSpace(char *pbuf); - void StringReplace(char *src, const char *strold, const char *strnew); private: ResourceCheckerVector m_vector; - + + uint32 m_PreHash; + bool m_ConfigFailed; char m_szPathConfirDir[MAX_PATH_LENGTH]; char m_szPathResourcesDir[MAX_PATH_LENGTH]; }; extern CConfig Config; +extern void UTIL_Printf(char *fmt, ...); diff --git a/src/dllapi.cpp b/src/dllapi.cpp index 6cbe68c..955dcda 100644 --- a/src/dllapi.cpp +++ b/src/dllapi.cpp @@ -2,10 +2,12 @@ DLL_FUNCTIONS *g_pFunctionTable; -extern qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ]); +extern qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]); +extern void ServerDeactivate_Post(); extern void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax); +extern void ClientPutInServer_Post(edict_t *pEntity); -static DLL_FUNCTIONS gFunctionTable_Post = +static DLL_FUNCTIONS gFunctionTable = { NULL, // pfnGameInit NULL, // pfnSpawn @@ -25,13 +27,13 @@ static DLL_FUNCTIONS gFunctionTable_Post = NULL, // pfnRestoreGlobalState NULL, // pfnResetGlobalState - &ClientConnect_Post, // pfnClientConnect + NULL, // pfnClientConnect NULL, // pfnClientDisconnect NULL, // pfnClientKill NULL, // pfnClientPutInServer NULL, // pfnClientCommand NULL, // pfnClientUserInfoChanged - ServerActivate_Post, // pfnServerActivate + NULL, // pfnServerActivate NULL, // pfnServerDeactivate NULL, // pfnPlayerPreThink @@ -69,6 +71,92 @@ static DLL_FUNCTIONS gFunctionTable_Post = NULL, // pfnAllowLagCompensation }; +static DLL_FUNCTIONS gFunctionTable_Post = +{ + NULL, // pfnGameInit + NULL, // pfnSpawn + NULL, // pfnThink + NULL, // pfnUse + NULL, // pfnTouch + NULL, // pfnBlocked + NULL, // pfnKeyValue + NULL, // pfnSave + NULL, // pfnRestore + NULL, // pfnSetAbsBox + + NULL, // pfnSaveWriteFields + NULL, // pfnSaveReadFields + + NULL, // pfnSaveGlobalState + NULL, // pfnRestoreGlobalState + NULL, // pfnResetGlobalState + + &ClientConnect_Post, // pfnClientConnect + NULL, // pfnClientDisconnect + NULL, // pfnClientKill + &ClientPutInServer_Post, // pfnClientPutInServer + NULL, // pfnClientCommand + NULL, // pfnClientUserInfoChanged + &ServerActivate_Post, // pfnServerActivate + &ServerDeactivate_Post, // pfnServerDeactivate + + NULL, // pfnPlayerPreThink + NULL, // pfnPlayerPostThink + + NULL, // pfnStartFrame + NULL, // pfnParmsNewLevel + NULL, // pfnParmsChangeLevel + + NULL, // pfnGetGameDescription + NULL, // pfnPlayerCustomization + + NULL, // pfnSpectatorConnect + NULL, // pfnSpectatorDisconnect + NULL, // pfnSpectatorThink + + NULL, // pfnSys_Error + + NULL, // pfnPM_Move + NULL, // pfnPM_Init + NULL, // pfnPM_FindTextureType + + NULL, // pfnSetupVisibility + NULL, // pfnUpdateClientData + NULL, // pfnAddToFullPack + NULL, // pfnCreateBaseline + NULL, // pfnRegisterEncoders + NULL, // pfnGetWeaponData + NULL, // pfnCmdStart + NULL, // pfnCmdEnd + NULL, // pfnConnectionlessPacket + NULL, // pfnGetHullBounds + NULL, // pfnCreateInstancedBaselines + NULL, // pfnInconsistentFile + NULL, // pfnAllowLagCompensation +}; + +C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) +{ + if (!pFunctionTable) + { + ALERT(at_logged, __FUNCTION__ " called with null pFunctionTable"); + return FALSE; + } + else if (*interfaceVersion != INTERFACE_VERSION) + { + ALERT(at_logged, __FUNCTION__ " version mismatch; requested=%d ours=%d", *interfaceVersion, INTERFACE_VERSION); + + //! Tell metamod what version we had, so it can figure out who is out of date. + *interfaceVersion = INTERFACE_VERSION; + return FALSE; + } + + memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); + g_pFunctionTable = pFunctionTable; + + return TRUE; +} + C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { if (!pFunctionTable) @@ -90,4 +178,3 @@ C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interface return TRUE; } - diff --git a/src/engine_rehlds.cpp b/src/engine_rehlds.cpp index 3f2221d..ebb8782 100644 --- a/src/engine_rehlds.cpp +++ b/src/engine_rehlds.cpp @@ -3,8 +3,8 @@ IRehldsApi *g_RehldsApi; const RehldsFuncs_t *g_RehldsFuncs; IRehldsHookchains *g_RehldsHookchains; -IRehldsServer *g_RehldsSv; IRehldsServerStatic *g_RehldsSvs; +IRehldsServerData *g_RehldsServerData; rehlds_ret RehldsApi_Init() { @@ -26,7 +26,7 @@ rehlds_ret RehldsApi_Init() if (!g_RehldsApi) { - UTIL_LogPrintf(__FUNCTION__ " : REHLDS can't find Interface API"); + UTIL_LogPrintf(__FUNCTION__ " : REHLDS can't find Interface API\n"); return RETURN_NOT_FOUND; } @@ -35,20 +35,20 @@ rehlds_ret RehldsApi_Init() if (majorVersion != REHLDS_API_VERSION_MAJOR) { - UTIL_LogPrintf(__FUNCTION__ " : REHLDS Api major version mismatch; expected %d, real %d", REHLDS_API_VERSION_MAJOR, majorVersion); + UTIL_LogPrintf(__FUNCTION__ " : REHLDS Api major version mismatch; expected %d, real %d\n", REHLDS_API_VERSION_MAJOR, majorVersion); return RETURN_MAJOR_MISMATCH; } if (minorVersion < REHLDS_API_VERSION_MINOR) { - UTIL_LogPrintf(__FUNCTION__ " : REHLDS Api minor version mismatch; expected at least %d, real %d", REHLDS_API_VERSION_MINOR, minorVersion); + UTIL_LogPrintf(__FUNCTION__ " : REHLDS Api minor version mismatch; expected at least %d, real %d\n", REHLDS_API_VERSION_MINOR, minorVersion); return RETURN_MINOR_MISMATCH; } g_RehldsFuncs = g_RehldsApi->GetFuncs(); g_RehldsHookchains = g_RehldsApi->GetHookchains(); g_RehldsSvs = g_RehldsApi->GetServerStatic(); - g_RehldsSv = g_RehldsApi->GetServer(); + g_RehldsServerData = g_RehldsApi->GetServerData(); return RETURN_LOAD; } diff --git a/src/engine_rehlds.h b/src/engine_rehlds.h index bbd509e..74de7e5 100644 --- a/src/engine_rehlds.h +++ b/src/engine_rehlds.h @@ -1,16 +1,16 @@ #pragma once -typedef enum +enum rehlds_ret { RETURN_LOAD, RETURN_MINOR_MISMATCH, RETURN_MAJOR_MISMATCH, RETURN_NOT_FOUND, -} rehlds_ret; +}; extern IRehldsApi *g_RehldsApi; -extern IRehldsServer *g_RehldsSv; extern IRehldsServerStatic *g_RehldsSvs; +extern IRehldsServerData *g_RehldsServerData; extern rehlds_ret RehldsApi_Init(); diff --git a/src/main.cpp b/src/main.cpp index e8ad88c..082ca74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,106 +1,88 @@ #include "precompiled.h" -cvar_t *mp_consistency = NULL; bool g_bInitialized = false; +bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash); +void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index); -void SV_GenericFileConsistencyResponce(IRehldsHook_GenericFileConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash); +bool OnMetaAttach(void) +{ + if (RehldsApi_Init() != RETURN_LOAD) { + return false; + } + + // register function from ReHLDS API + g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->registerHook(&SV_CheckConsistencyResponce); + SV_AddResource = reinterpret_cast(g_RehldsApi->GetFuncs()->SV_AddResource); + + // initialize config + Config.Init(); + + // if is OK go to attach + return Config.IsConfigLoaded(); +} void OnMetaDetach(void) { - g_RehldsApi->GetHookchains()->GenericFileConsistencyResponce()->unregisterHook(&SV_GenericFileConsistencyResponce); + g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->unregisterHook(&SV_CheckConsistencyResponce); + + // clear + CmdExec.Clear(); + Config.ClearResources(); +} + +void ServerDeactivate_Post() +{ + if (g_bInitialized) { + // clear + CmdExec.Clear(); + Config.ClearResources(); + g_bInitialized = false; + } + + SET_META_RESULT(MRES_IGNORED); } void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax) { - g_bInitialized = false; + Config.Load(); SET_META_RESULT(MRES_IGNORED); } -qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ]) +void ClientPutInServer_Post(edict_t *pEntity) { - if (g_bInitialized) - { - SET_META_RESULT(MRES_IGNORED); - return META_RESULT_ORIG_RET(qboolean); + int nIndex = ENTINDEX(pEntity) - 1; + + if (nIndex < 0 || nIndex >= gpGlobals->maxClients) { + RETURN_META(MRES_IGNORED); } - g_bInitialized = true; - resource_t *resource = g_RehldsSv->GetResourceList(); + IGameClient *pClient = g_RehldsApi->GetServerStatic()->GetClient(nIndex); - int iNumResources = g_RehldsSv->GetNumResources(); - int iNumConsistency = g_RehldsSv->GetNumConsistency(); + if (pClient != NULL) { + // client is connected to putinserver, go execute cmd out buffer + CmdExec.Exec(pClient); + } - if (iNumResources < 1280) - { - ResourceCheckerVectorIt it = Config.GetVector()->begin(); - while (it != Config.GetVector()->end()) - { - strncpy(resource[iNumResources].szFileName, (*it)->m_FileName, 63); - resource[iNumResources].szFileName[63] = '\0'; + SET_META_RESULT(MRES_IGNORED); +} - resource[iNumResources].type = t_decal; - resource[iNumResources].nDownloadSize = 0; - resource[iNumResources].nIndex = 4095; - resource[iNumResources].ucFlags = RES_CHECKFILE; - - iNumResources++; - iNumConsistency++; - - g_RehldsSv->SetNumResources(iNumResources); - g_RehldsSv->SetNumConsistency(iNumConsistency); - - ++it; - } +qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) +{ + if (!g_bInitialized) { + Config.AddResource(); + g_bInitialized = true; } SET_META_RESULT(MRES_IGNORED); return META_RESULT_ORIG_RET(qboolean); } -void SV_GenericFileConsistencyResponce(IRehldsHook_GenericFileConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash) +bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash) { - if (resource->type != t_decal) - { - chain->callNext(pSenderClient, resource, hash); - return; + if (resource->type == t_decal) { + if (!Config.FileConsistencyResponce(pSenderClient, resource, hash)) + return false; } - *(uint32 *)&resource->rgucMD5_hash[0] = hash; - - int i = 0; - for (ResourceCheckerVectorIt it = Config.GetVector()->begin(); it != Config.GetVector()->end(); ++it, i++) - { - CResourceCheckerNew *pnew = (*it); - - if (strcmp(resource->szFileName, pnew->m_FileName) == 0)// && pnew->m_HashFile == hash) - { -#ifdef _DEBUG - printf("filename: %s (%s) | hash: %x | response hash: %x\n", resource->szFileName, pnew->m_FileName, pnew->m_HashFile, hash); -#endif // _DEBUG - break; - } - } -} - -bool OnMetaAttach(void) -{ - if (RehldsApi_Init() != RETURN_LOAD) - return false; - - cvar_t *oldCvar = g_engfuncs.pfnCVarGetPointer("mp_consistency"); - cvar_t newCvar = { "mp_consistency", oldCvar->string, oldCvar->flags, oldCvar->value, NULL }; - - oldCvar->name = "_mp_consistency"; - - g_engfuncs.pfnCVarRegister(&newCvar); - g_engfuncs.pfnCvar_DirectSet(oldCvar, "1"); - mp_consistency = g_engfuncs.pfnCVarGetPointer("mp_consistency"); - - // register function from ReHLDS API - g_RehldsApi->GetHookchains()->GenericFileConsistencyResponce()->registerHook(&SV_GenericFileConsistencyResponce); - - // initialize config - Config.Init(); - - return true; + return chain->callNext(pSenderClient, resource, hash);; } diff --git a/src/main.h b/src/main.h index 6f70f09..4595c1f 100644 --- a/src/main.h +++ b/src/main.h @@ -1 +1,3 @@ #pragma once + +extern void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index); diff --git a/src/meta_api.cpp b/src/meta_api.cpp index c2ee1f2..9e83b10 100644 --- a/src/meta_api.cpp +++ b/src/meta_api.cpp @@ -9,8 +9,8 @@ plugin_info_t Plugin_info = "s1lent", "http://www.dedicated-server.ru/", "ReChecker", - PT_ANYTIME, - PT_ANYTIME, + PT_STARTUP, + PT_NEVER, }; meta_globals_t *gpMetaGlobals; @@ -42,8 +42,10 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now,META_FUNCTIONS *pFunctionTable,met { return 0; } - + + gMetaFunctionTable.pfnGetEntityAPI2 = GetEntityAPI2; gMetaFunctionTable.pfnGetEntityAPI2_Post = GetEntityAPI2_Post; + memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); return 1; diff --git a/src/precompiled.h b/src/precompiled.h index 96c90b4..4cf4b7d 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -1,5 +1,11 @@ #pragma once +#ifdef _WIN32 // WINDOWS + #pragma warning(disable : 4005) +#endif // _WIN32 + +#include // strrchr + #include #include // ALERT() @@ -11,6 +17,7 @@ #include "main.h" #include "config.h" +#include "cmdexec.h" #include "sdk_util.h" // UTIL_LogPrintf, etc /* <7508> ../engine/consistency.h:9 */ diff --git a/src/sdk_util.cpp b/src/sdk_util.cpp index ca20481..d6a1e95 100644 --- a/src/sdk_util.cpp +++ b/src/sdk_util.cpp @@ -1,5 +1,18 @@ #include "precompiled.h" +void UTIL_Printf(char *fmt, ...) +{ + va_list argptr; + static char string[1024]; + + va_start(argptr, fmt); + vsnprintf(string, sizeof(string), fmt, argptr); + va_end(argptr); + + // Print to server console + SERVER_PRINT(string); +} + void UTIL_LogPrintf(char *fmt, ...) { va_list argptr; @@ -9,7 +22,7 @@ void UTIL_LogPrintf(char *fmt, ...) vsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); - // Print to server console + // Print to log ALERT(at_logged, "%s", string); } @@ -19,7 +32,7 @@ char *UTIL_VarArgs(char *format, ...) static char string[1024]; va_start(argptr, format); - vsprintf(string, format, argptr); + vsnprintf(string, sizeof(string), format, argptr); va_end(argptr); return string;