mirror of
https://github.com/r4sas/ExtraMirror
synced 2025-02-03 18:35:05 +00:00
Update
This commit is contained in:
parent
fc8339d30f
commit
ca70d8925f
@ -1,26 +1,17 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.6
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shel", "MiniBase\MiniBase.vcxproj", "{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ЭкстраМиррор", "MiniBase\MiniBase.vcxproj", "{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|x64.Build.0 = Debug|x64
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|Win32.Build.0 = Release|Win32
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|x64.ActiveCfg = Release|x64
|
||||
{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -170,7 +170,6 @@
|
||||
<ClCompile Include="client.cpp" />
|
||||
<ClCompile Include="enginemsg.cpp" />
|
||||
<ClCompile Include="eventmsg.cpp" />
|
||||
<ClCompile Include="font.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="minIni.c" />
|
||||
<ClCompile Include="offset.cpp" />
|
||||
@ -181,7 +180,6 @@
|
||||
<ClInclude Include="client.h" />
|
||||
<ClInclude Include="enginemsg.h" />
|
||||
<ClInclude Include="eventmsg.h" />
|
||||
<ClInclude Include="font.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="minGlue.h" />
|
||||
<ClInclude Include="minIni.h" />
|
||||
|
@ -26,9 +26,6 @@
|
||||
<ClCompile Include="utils.cpp">
|
||||
<Filter>Файлы исходного кода</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="font.cpp">
|
||||
<Filter>Файлы исходного кода</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ValveSDK\misc\parsemsg.cpp">
|
||||
<Filter>Заголовочные файлы\msg</Filter>
|
||||
</ClCompile>
|
||||
@ -58,9 +55,6 @@
|
||||
<ClInclude Include="struct.h">
|
||||
<Filter>Заголовочные файлы</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="font.h">
|
||||
<Filter>Заголовочные файлы</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ValveSDK\misc\parsemsg.h">
|
||||
<Filter>Заголовочные файлы\msg</Filter>
|
||||
</ClInclude>
|
||||
|
@ -9,12 +9,11 @@
|
||||
#include <vector>
|
||||
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
extern TCHAR g_settingsFileName[MAX_PATH];
|
||||
bool FirstFrame = false;
|
||||
pfnUserMsgHook pMOTD;
|
||||
GameInfo_t BuildInfo;
|
||||
cvar_t *random;
|
||||
cvar_t *steamid_r;
|
||||
map<string, string> g_modelsHashMap;
|
||||
cvar_t *logsfiles;
|
||||
cvar_t *events_block;
|
||||
@ -46,12 +45,15 @@ void models(){
|
||||
for (DWORD i = 0; i < 32; i++){
|
||||
player_info_s* player = g_pStudio->PlayerInfo(i);
|
||||
if (player && (lstrlenA(player->name)>1) && player->model){
|
||||
char buffer[128];
|
||||
sprintf_s(buffer, "NAME -> [ %s ] | MODEL -> [ %s ]\n", player->name, player->model);
|
||||
ConsolePrintColor(255, 255, 15, buffer);
|
||||
ConsolePrintColor(255, 255, 15, "NAME -> [ %s ] | MODEL -> [ %s ]\n", player->name, player->model);
|
||||
}
|
||||
}
|
||||
}
|
||||
string filename;
|
||||
void Set_Ticket() {
|
||||
filename = g_Engine.Cmd_Argv(1);
|
||||
ConsolePrintColor(255, 255, 255, "[ExtraMirror] Ticket set -> \"%s\"\n", filename.c_str());
|
||||
}
|
||||
void Credits(){
|
||||
ConsolePrintColor(255, 255, 255, "-- Thank's to");ConsolePrintColor(0, 255, 0, " [2010] Team\n");ConsolePrintColor(255, 255, 255, "-- Thank's to");
|
||||
ConsolePrintColor(0, 255, 0, " madotsuki-team < *\n");ConsolePrintColor(255, 255, 255, "-- Thank's to ");ConsolePrintColor(0, 255, 0, "or_75\n");
|
||||
@ -71,11 +73,8 @@ int Callback(const char *section, const char *key, const char *value, const void
|
||||
return 1;
|
||||
}
|
||||
void Inject(){LoadLibraryA(g_Engine.Cmd_Argv(1)); }
|
||||
/*int g_blockedCvarCount;
|
||||
char *g_blockedCvars[512];*/
|
||||
|
||||
void DumpCmd()
|
||||
{
|
||||
void DumpCmd(){
|
||||
cmd_s *pCmd = g_Engine.pfnGetCmdList();
|
||||
ConsolePrintColor(255, 255, 255, "Dump Commands: \n");
|
||||
while (pCmd)
|
||||
@ -88,9 +87,12 @@ void DumpCmd()
|
||||
void Reload(){
|
||||
models_list.clear();
|
||||
ini_browse(Callback,NULL,g_settingsFileName);
|
||||
memset(g_blockedCmds,0,sizeof(g_blockedCmds));//memset(g_blockedCvars, 0, sizeof(g_blockedCvars));
|
||||
memset(g_serverCmds, 0, sizeof(g_serverCmds)); memset(g_anticheckfiles2, 0, sizeof(g_anticheckfiles2));
|
||||
g_blockedCmdCount = 0; g_serverCmdCount = 0; g_anticheckfiles = 0;
|
||||
memset(g_blockedCmds,0,sizeof(g_blockedCmds));
|
||||
memset(g_serverCmds, 0, sizeof(g_serverCmds));
|
||||
memset(g_anticheckfiles2, 0, sizeof(g_anticheckfiles2));
|
||||
g_blockedCmdCount = 0;
|
||||
g_serverCmdCount = 0;
|
||||
g_anticheckfiles = 0;
|
||||
static TCHAR sKeyNames[4096*3];
|
||||
|
||||
GetPrivateProfileSection(TEXT("ADetect"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
||||
@ -105,20 +107,14 @@ void Reload(){
|
||||
char *psKeyName3 = sKeyNames;
|
||||
while (psKeyName3[0] != '\0') { g_serverCmds[g_serverCmdCount++] = strdup(psKeyName3); psKeyName3 += strlen(psKeyName3) + 1; }
|
||||
|
||||
/*GetPrivateProfileSection(TEXT("Blocked cvars"),sKeyNames,ARRAYSIZE(sKeyNames),g_settingsFileName);
|
||||
char *psKeyName2=sKeyNames;
|
||||
while (psKeyName2[0]!='\0'){g_blockedCvars[g_blockedCvarCount++]=strdup(psKeyName2);psKeyName2+=strlen(psKeyName2)+1;}*/
|
||||
GetPrivateProfileSection(TEXT("Cvars"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
||||
char *psKeyName2 = sKeyNames;
|
||||
// Clear vector
|
||||
Cvars.clear();
|
||||
while (psKeyName2[0] != '\0'){
|
||||
AddOrModCvar(psKeyName2);
|
||||
psKeyName2 += strlen(psKeyName2) + 1;
|
||||
}
|
||||
while (psKeyName2[0] != '\0'){AddOrModCvar(psKeyName2);psKeyName2 += strlen(psKeyName2) + 1;}
|
||||
TCHAR value[16];char cvarname[32];
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("sid_random"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
sprintf(cvarname, "sid_random %s", value);g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("steamid"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
sprintf(cvarname, "steamid %s", value);g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("cust_hud"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
sprintf(cvarname, "cust_hud %s", value); g_Engine.pfnClientCmd(cvarname);memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("logs"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
@ -176,15 +172,16 @@ void InitHack(){
|
||||
AddOrModCvar(psKeyName2);
|
||||
psKeyName2 += strlen(psKeyName2) + 1;
|
||||
}
|
||||
if (!(g_Engine.Con_IsVisible() != 0))g_Engine.pfnClientCmd("toggleconsole");
|
||||
ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.6\n");
|
||||
g_pEngine->pfnAddCommand("set_ticket", Set_Ticket);
|
||||
if (g_Engine.Con_IsVisible() == 0)g_Engine.pfnClientCmd("toggleconsole");
|
||||
ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.7\n", BuildInfo.Build);
|
||||
ConsolePrintColor(255, 255, 255, "-- Use 'credits' for more information\n");
|
||||
ConsolePrintColor(255, 255, 255, "-- Thank's to Realwar for title\n");
|
||||
ConsolePrintColor(255, 255, 255, "-- Thank's to FightMagister for functions\n");
|
||||
ConsolePrintColor(255, 255, 255, "-- Thank's to Spawner { Kiass }\n");
|
||||
g_pEngine->pfnAddCommand("credits", Credits); g_pEngine->pfnAddCommand("inject", Inject); g_pEngine->pfnAddCommand("modelsn", models); g_pEngine->pfnAddCommand("update", Reload);TCHAR value[16];
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("sid_random"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
random = g_pEngine->pfnRegisterVariable("sid_random", strdup(value), 0);memset(value, 0, sizeof(value));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("steamid"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
steamid_r = g_pEngine->pfnRegisterVariable("steamid", strdup(value), 0);memset(value, 0, sizeof(value));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("cust_hud"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
ex_thud = g_pEngine->pfnRegisterVariable("cust_hud", value, 0);memset(value, 0, sizeof(value));
|
||||
GetPrivateProfileString(TEXT("Settings"), TEXT("logs"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
||||
|
@ -115,12 +115,9 @@ bool CheckExecute(char *text)
|
||||
char *c = text;
|
||||
char *a = isGood ? "[Extra Mirror] execute: \"" : "[Extra Mirror] blocked: \"";
|
||||
if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); }
|
||||
/*else*/if (isSet)a = "[Extra Mirror] update server-side cvar: \"";
|
||||
|
||||
if (isGood)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (isSet)a = "[Extra Mirror] update server-side cvar: \"";
|
||||
if (isSet) { if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } }
|
||||
if (isGood)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -158,46 +155,6 @@ void ExecuteString_Add(const char *str) {
|
||||
hooker.unhook(ExecuteString_Tramp, ExecuteString_Prologue);
|
||||
}
|
||||
|
||||
/*
|
||||
bool BlackList(char *str) {
|
||||
bool changed = false;
|
||||
char *text = str;
|
||||
char command[MAX_CMD_LINE];
|
||||
int i, quotes;
|
||||
int len = strlen(str);
|
||||
while (text[0] != 0) {
|
||||
quotes = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (text[i] == '\"') quotes++;
|
||||
if (text[i] == '\n')break;
|
||||
if (!(quotes & 1) && text[i] == ';')break;
|
||||
if (text[i] == 0x00 || text[i] == ' ' )break;
|
||||
}
|
||||
if (i >= MAX_CMD_LINE)i = MAX_CMD_LINE;
|
||||
strncpy(command, text, i); command[i] = 0;
|
||||
bool isGood = IsCommandGood(command);
|
||||
bool isGood2 = IsCommandGood2(command);
|
||||
bool isSet = CheckAndSetCvar(command);
|
||||
bool isFake = CheckIsFake(command);
|
||||
char *x = command;
|
||||
if (!isGood2) {
|
||||
g_Engine.pfnServerCmd(command);
|
||||
if (logsfiles->value > 0) { ConsolePrintColor(24, 122, 224, "[Extra Mirror] server command sent: \""); ConsolePrintColor(24, 122, 224, ("%s", x)); ConsolePrintColor(24, 122, 224, "\"\n"); }
|
||||
}
|
||||
char *c = command;
|
||||
char *a = isGood ? "[Extra Mirror] execute: \"" : "[Extra Mirror] blocked: \"";
|
||||
if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); }
|
||||
// if (isFake) a = isGood ? "[Extra Mirror] set fake cvar: \"" : "[Extra Mirror] block fake cvar: \"";
|
||||
/*else*//*if (isSet)a = "[Extra Mirror] update server-side cvar: \"";
|
||||
if (isGood)g_Engine.pfnClientCmd(c);
|
||||
if (isSet) { if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } }
|
||||
len -= i;
|
||||
if (!isGood) { strncpy(text, text + i, len); text[len] = 0; text++; changed = true; }
|
||||
else { text += i + 1; }
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
|
||||
void SVC_SendCvarValue() {
|
||||
MSG_SaveReadCount();
|
||||
char* cvar = MSG_ReadString();
|
||||
@ -335,7 +292,7 @@ bool CheckAndSetCvar(string FullCmd) {
|
||||
Cvars[pos].value = Value;
|
||||
return true;
|
||||
}
|
||||
void SVC_StuffText() {
|
||||
void SVC_StuffText() {
|
||||
char* command = MSG_ReadString();
|
||||
ExecuteString_Add(command);
|
||||
}
|
||||
@ -365,28 +322,4 @@ void SVC_VoiceInit() {
|
||||
if (blocked)return;
|
||||
MSG_RestoreReadCount();
|
||||
pSVC_VoiceInit();
|
||||
}
|
||||
/*
|
||||
void SVC_Resourcelist() {
|
||||
MSG_SaveReadCount();
|
||||
int NumResources, Type, Index, DownloadSize, HasExtraInfo, ExtraInfo, HasConsistency, Flags, Flags;
|
||||
MSG_StartBitReading(MSG_Buffer);
|
||||
NumResources = MSG_ReadBits(12);
|
||||
|
||||
for (int i = 1; i <= NumResources; i++) {
|
||||
Type = MSG_ReadBits(4);
|
||||
char* szFileName[64];
|
||||
// szFileName = MSG_ReadBitString();
|
||||
Index = MSG_ReadBits(12);
|
||||
DownloadSize = MSG_ReadBits(24);
|
||||
unsigned char Flags = READ_CHAR();
|
||||
unsigned char rgucMD5_hash[16];
|
||||
for (int i = 0; i < 16; i++)(BYTE)rgucMD5_hash[i] = READ_CHAR();
|
||||
HasExtraInfo = MSG_ReadBits(1);
|
||||
if (HasExtraInfo)ExtraInfo = MSG_ReadBits(256);
|
||||
}
|
||||
HasConsistency = MSG_ReadBits(1);
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
extern cvar_t *random;
|
||||
extern cvar_t *steamid_r;
|
||||
extern cvar_t *logsfiles;
|
||||
TCHAR g_settingsFileName[MAX_PATH];
|
||||
typedef void *HOOKSERVERMSG(const char *pszMsgName, void *pfnCallback);
|
||||
@ -444,27 +444,44 @@ uint32_t RevHash(const char *str) {
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
extern string filename;
|
||||
int Steam_GSInitiateGameConnection_CallHook(void *pData, int maxDataBytes, uint64_t steamID, uint32_t serverIP, uint16_t serverPort, bool isSecure) {
|
||||
int ret = (*g_pfnSteam_GSInitiateGameConnection)(pData, maxDataBytes, steamID, serverIP, serverPort, isSecure);
|
||||
if (random->value == 0) return ret;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
revEmuTicket.hash[i] = g_hashSymbolTable[rand() % 36];
|
||||
}
|
||||
revEmuTicket.hash[7] = '\0';
|
||||
if (steamid_r->value == 0) return ret;
|
||||
else if (steamid_r->value == 1) {
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
revEmuTicket.hash[i] = g_hashSymbolTable[rand() % 36];
|
||||
}
|
||||
revEmuTicket.hash[7] = '\0';
|
||||
|
||||
revEmuTicket.version = 'J';
|
||||
revEmuTicket.highPartAuthID = RevHash((const char *)revEmuTicket.hash) & 0x7FFFFFFF;
|
||||
revEmuTicket.signature = 'rev';
|
||||
revEmuTicket.secondSignature = 0;
|
||||
revEmuTicket.authID = RevHash((const char *)revEmuTicket.hash) << 1;
|
||||
revEmuTicket.thirdSignature = 0x01100001;
|
||||
memcpy(pData, &revEmuTicket, sizeof(revEmuTicket));
|
||||
return sizeof(revEmuTicket);
|
||||
revEmuTicket.version = 'J';
|
||||
revEmuTicket.highPartAuthID = RevHash((const char *)revEmuTicket.hash) & 0x7FFFFFFF;
|
||||
revEmuTicket.signature = 'rev';
|
||||
revEmuTicket.secondSignature = 0;
|
||||
revEmuTicket.authID = RevHash((const char *)revEmuTicket.hash) << 1;
|
||||
revEmuTicket.thirdSignature = 0x01100001;
|
||||
memcpy(pData, &revEmuTicket, sizeof(revEmuTicket));
|
||||
return sizeof(revEmuTicket);
|
||||
}
|
||||
else if (steamid_r->value >= 2) {
|
||||
ifstream file(filename.c_str(), ios::in | ios::binary | ios::ate);
|
||||
ifstream::pos_type size;
|
||||
char * bufferzz;
|
||||
if (file.is_open()){
|
||||
size = file.tellg();
|
||||
bufferzz = new char[size];
|
||||
file.seekg(0, ios::beg);
|
||||
file.read(bufferzz, size);
|
||||
file.close();
|
||||
memcpy(pData, bufferzz, size);
|
||||
delete[] bufferzz;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook(const char *str){
|
||||
// Add your filters there
|
||||
// Add your filters there
|
||||
|
||||
//MessagePrintf("Demo tried to execute: %s", str);
|
||||
}
|
||||
@ -513,7 +530,7 @@ void ModuleLoaded() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
ptr = pModule->FindFirstUseOfString("Tried to read a demo message with no demo file\n");
|
||||
ptr = pModule->SearchDownForFirstCallToFunction(ptr, pfnCbuf_AddText);
|
||||
CallOpcode::SetDestination(ptr, &CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook);
|
||||
|
@ -40,7 +40,6 @@ using namespace std;
|
||||
#include "utils.h"
|
||||
#include "usermsg.h"
|
||||
#include "enginemsg.h"
|
||||
#include "font.h"
|
||||
#include "eventmsg.h"
|
||||
#include "redirect.h"
|
||||
|
||||
|
@ -243,7 +243,7 @@ DWORD cOffset::FindEventMsgBase()
|
||||
{
|
||||
DWORD PatternAddress = FindPattern(OFF_EVENT_MSG_BASE, HwBase, HwEnd, 0);
|
||||
DWORD ReferenAddress;
|
||||
if (equali(BuildInfo.GameVersion,"1.1.2.6")){
|
||||
if (BuildInfo.Build<6027){
|
||||
ReferenAddress = FindReference(HwBase, HwEnd, PatternAddress) - 0x06;
|
||||
}
|
||||
else { ReferenAddress = FindReference(HwBase, HwEnd, PatternAddress) - 0x07; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user