/*
* PtokaX - hub server for Direct Connect peer to peer network.
* Copyright (C) 2002-2005 Ptaczek, Ptaczek at PtokaX dot org
* Copyright (C) 2004-2017 Petr Kozelka, PPK at PtokaX dot org
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
#include "stdinc.h"
//---------------------------------------------------------------------------
#include "User.h"
//---------------------------------------------------------------------------
#include "colUsers.h"
#include "DcCommands.h"
#include "GlobalDataQueue.h"
#include "hashUsrManager.h"
#include "LanguageManager.h"
#include "LuaScriptManager.h"
#include "ProfileManager.h"
#include "ServerManager.h"
#include "SettingManager.h"
#include "utility.h"
#include "UdpDebug.h"
#include "ZlibUtility.h"
//---------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
#ifdef _WITH_SQLITE
#include "DB-SQLite.h"
#elif _WITH_POSTGRES
#include "DB-PostgreSQL.h"
#elif _WITH_MYSQL
#include "DB-MySQL.h"
#endif
#include "DeFlood.h"
//---------------------------------------------------------------------------
#ifdef _BUILD_GUI
#include "../gui.win/GuiUtil.h"
#include "../gui.win/MainWindowPageUsersChat.h"
#endif
//---------------------------------------------------------------------------
static const size_t ZMINDATALEN = 128;
static const char * sBadTag = "BAD TAG!"; // 8
static const char * sOtherNoTag = "OTHER (NO TAG)"; // 14
static const char * sUnknownTag = "UNKNOWN TAG"; // 11
static const char * sDefaultNick = "<unknown>"; // 9
//---------------------------------------------------------------------------
DcCommand ActualDcCommand = { NULL, NULL, 0 };
//---------------------------------------------------------------------------
static bool UserProcessLines(User * pUser, const uint32_t ui32NewDataStart) {
char c = 0;
char * pBuffer = pUser->m_pRecvBuf;
for(uint32_t ui32i = ui32NewDataStart; ui32i < pUser->m_ui32RecvBufDataLen; ++ui32i) {
// look for pipes in the data - process lines one by one
if(pUser->m_pRecvBuf[ui32i] == '|') {
c = pUser->m_pRecvBuf[ui32i+1];
pUser->m_pRecvBuf[ui32i+1] = '\0';
uint32_t ui32CommandLen = (uint32_t)(((pUser->m_pRecvBuf+ui32i)-pBuffer)+1);
if(pBuffer[0] == '|') {
//UdpDebug->BroadcastFormat("[SYS] heartbeat from %s (%s).", pUser->Nick, pUser->sIP);
//send(Sck, "|", 1, 0);
} else if(ui32CommandLen <= (pUser->m_ui8State < User::STATE_ADDME ? 1024U : 65536U)) {
ActualDcCommand.m_pUser = pUser;
ActualDcCommand.m_sCommand = pBuffer;
ActualDcCommand.m_ui32CommandLen = ui32CommandLen;
DcCommands::m_Ptr->PreProcessData(&ActualDcCommand);
} else {
pUser->SendFormat("UserProcessLines1", false, "<%s> %s!|", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC], LanguageManager::m_Ptr->m_sTexts[LAN_CMD_TOO_LONG]);
pUser->Close();
UdpDebug::m_Ptr->BroadcastFormat("[SYS] %s (%s): Received command too long. User disconnected.", pUser->m_sNick, pUser->m_sIP);
return false;
}
pUser->m_pRecvBuf[ui32i+1] = c;
pBuffer += ui32CommandLen;
if(pUser->m_ui8State >= User::STATE_CLOSING) {
return true;
}
} else if(pUser->m_pRecvBuf[ui32i] == '\0') {
// look for NULL character and replace with zero
pUser->m_pRecvBuf[ui32i] = '0';
continue;
}
}
pUser->m_ui32RecvBufDataLen -= (uint32_t)(pBuffer-pUser->m_pRecvBuf);
if(pUser->m_ui32RecvBufDataLen == 0) {
DcCommands::m_Ptr->ProcessCmds(pUser);
pUser->m_pRecvBuf[0] = '\0';
return false;
} else if(pUser->m_ui32RecvBufDataLen == 1) {
DcCommands::m_Ptr->ProcessCmds(pUser);
pUser->m_pRecvBuf[0] = pBuffer[0];
pUser->m_pRecvBuf[1] = '\0';
return true;
} else {
if(pUser->m_ui32RecvBufDataLen > (pUser->m_ui8State < User::STATE_ADDME ? 1024U : 65536U)) {
// PPK ... we don't want commands longer than 64 kB, drop this user !
pUser->SendFormat("UserProcessLines2", false, "<%s> %s!|", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC], LanguageManager::m_Ptr->m_sTexts[LAN_CMD_TOO_LONG]);
pUser->Close();
UdpDebug::m_Ptr->BroadcastFormat("[SYS] %s (%s): RecvBuffer overflow. User disconnected.", pUser->m_sNick, pUser->m_sIP);
return false;
}
DcCommands::m_Ptr->ProcessCmds(pUser);
memmove(pUser->m_pRecvBuf, pBuffer, pUser->m_ui32RecvBufDataLen);
pUser->m_pRecvBuf[pUser->m_ui32RecvBufDataLen] = '\0';
return true;
}
}
//------------------------------------------------------------------------------
static void UserSetBadTag(User * pUser, char * sDesc, const uint8_t ui8DescLen) {
// PPK ... clear all tag related things
pUser->m_sTagVersion = NULL;
pUser->m_ui8TagVersionLen = 0;
pUser->m_sModes[0] = '\0';
pUser->m_ui32Hubs = pUser->m_ui32Slots = pUser->m_ui32OLimit = pUser->m_ui32LLimit = pUser->m_ui32DLimit = pUser->m_ui32NormalHubs = pUser->m_ui32RegHubs = pUser->m_ui32OpHubs = 0;
pUser->m_ui32BoolBits |= User::BIT_OLDHUBSTAG;
pUser->m_ui32BoolBits |= User::BIT_HAVE_BADTAG;
pUser->m_sDescription = sDesc;
pUser->m_ui8DescriptionLen = ui8DescLen;
// PPK ... clear (fake) tag
pUser->m_sTag = NULL;
pUser->m_ui8TagLen = 0;
// PPK ... set bad tag
pUser->m_sClient = (char *)sBadTag;
pUser->m_ui8ClientLen = 8;
// PPK ... send report to udp debug
UdpDebug::m_Ptr->BroadcastFormat("[SYS] User %s (%s) have bad TAG (%s) ?!?", pUser->m_sNick, pUser->m_sIP, pUser->m_sMyInfoOriginal);
}
//---------------------------------------------------------------------------
static void UserParseMyInfo(User * pUser) {
memcpy(ServerManager::m_pGlobalBuffer, pUser->m_sMyInfoOriginal, pUser->m_ui16MyInfoOriginalLen);
char *sMyINFOParts[] = { NULL, NULL, NULL, NULL, NULL };
uint16_t iMyINFOPartsLen[] = { 0, 0, 0, 0, 0 };
unsigned char cPart = 0;
sMyINFOParts[cPart] = ServerManager::m_pGlobalBuffer+14+pUser->m_ui8NickLen; // desription start
for(uint32_t ui32i = 14+pUser->m_ui8NickLen; ui32i < pUser->m_ui16MyInfoOriginalLen-1u; ui32i++) {
if(ServerManager::m_pGlobalBuffer[ui32i] == '$') {
ServerManager::m_pGlobalBuffer[ui32i] = '\0';
iMyINFOPartsLen[cPart] = (uint16_t)((ServerManager::m_pGlobalBuffer+ui32i)-sMyINFOParts[cPart]);
// are we on end of myinfo ???
if(cPart == 4)
break;
cPart++;
sMyINFOParts[cPart] = ServerManager::m_pGlobalBuffer+ui32i+1;
}
}
// check if we have all myinfo parts, connection and sharesize must have length more than 0 !
if(sMyINFOParts[0] == NULL || sMyINFOParts[1] == NULL || iMyINFOPartsLen[1] != 1 || sMyINFOParts[2] == NULL || iMyINFOPartsLen[2] == 0 || sMyINFOParts[3] == NULL || sMyINFOParts[4] == NULL || iMyINFOPartsLen[4] == 0) {
pUser->SendFormat("UserParseMyInfo1", false, "<%s> %s!|", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC], LanguageManager::m_Ptr->m_sTexts[LAN_YOU_MyINFO_IS_CORRUPTED]);
UdpDebug::m_Ptr->BroadcastFormat("[SYS] User %s (%s) with bad MyINFO (%s) disconnected.", pUser->m_sNick, pUser->m_sIP, pUser->m_sMyInfoOriginal);
pUser->Close();
return;
}
// connection
pUser->m_ui8MagicByte = sMyINFOParts[2][iMyINFOPartsLen[2]-1];
pUser->m_sConnection = pUser->m_sMyInfoOriginal+(sMyINFOParts[2]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8ConnectionLen = (uint8_t)(iMyINFOPartsLen[2]-1);
// email
if(iMyINFOPartsLen[3] != 0) {
pUser->m_sEmail = pUser->m_sMyInfoOriginal+(sMyINFOParts[3]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8EmailLen = (uint8_t)iMyINFOPartsLen[3];
}
// share
// PPK ... check for valid numeric share, kill fakers !
if(HaveOnlyNumbers(sMyINFOParts[4], iMyINFOPartsLen[4]) == false) {
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User %s (%s) with non-numeric sharesize disconnected.", pUser->Nick, pUser->IP);
pUser->Close();
return;
}
if(((pUser->m_ui32BoolBits & User::BIT_HAVE_SHARECOUNTED) == User::BIT_HAVE_SHARECOUNTED) == true) {
ServerManager::m_ui64TotalShare -= pUser->m_ui64SharedSize;
#ifdef _WIN32
pUser->m_ui64SharedSize = _strtoui64(sMyINFOParts[4], NULL, 10);
#else
pUser->m_ui64SharedSize = strtoull(sMyINFOParts[4], NULL, 10);
#endif
ServerManager::m_ui64TotalShare += pUser->m_ui64SharedSize;
} else {
#ifdef _WIN32
pUser->m_ui64SharedSize = _strtoui64(sMyINFOParts[4], NULL, 10);
#else
pUser->m_ui64SharedSize = strtoull(sMyINFOParts[4], NULL, 10);
#endif
}
// Reset all tag infos...
pUser->m_sModes[0] = '\0';
pUser->m_ui32Hubs = 0;
pUser->m_ui32NormalHubs = 0;
pUser->m_ui32RegHubs = 0;
pUser->m_ui32OpHubs =0;
pUser->m_ui32Slots = 0;
pUser->m_ui32OLimit = 0;
pUser->m_ui32LLimit = 0;
pUser->m_ui32DLimit = 0;
// description
if(iMyINFOPartsLen[0] != 0) {
if(sMyINFOParts[0][iMyINFOPartsLen[0]-1] == '>') {
char *DCTag = strrchr(sMyINFOParts[0], '<');
if(DCTag == NULL) {
pUser->m_sDescription = pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8DescriptionLen = (uint8_t)iMyINFOPartsLen[0];
pUser->m_sClient = (char*)sOtherNoTag;
pUser->m_ui8ClientLen = 14;
return;
}
pUser->m_sTag = pUser->m_sMyInfoOriginal+(DCTag-ServerManager::m_pGlobalBuffer);
pUser->m_ui8TagLen = (uint8_t)(iMyINFOPartsLen[0]-(DCTag-sMyINFOParts[0]));
static const uint16_t ui16plusplus = *((uint16_t *)"++");
if(DCTag[3] == ' ' && *((uint16_t *)(DCTag+1)) == ui16plusplus) {
pUser->m_ui32SupportBits |= User::SUPPORTBIT_NOHELLO;
}
static const uint16_t ui16V = *((uint16_t *)"V:");
char * sTemp = strchr(DCTag, ' ');
if(sTemp != NULL && *((uint16_t *)(sTemp+1)) == ui16V) {
sTemp[0] = '\0';
pUser->m_sClient = pUser->m_sMyInfoOriginal+((DCTag+1)-ServerManager::m_pGlobalBuffer);
pUser->m_ui8ClientLen = (uint8_t)((sTemp-DCTag)-1);
} else {
pUser->m_sClient = (char *)sUnknownTag;
pUser->m_ui8ClientLen = 11;
pUser->m_sTag = NULL;
pUser->m_ui8TagLen = 0;
sMyINFOParts[0][iMyINFOPartsLen[0]-1] = '>'; // not valid DC Tag, add back > tag ending
pUser->m_sDescription = pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8DescriptionLen = (uint8_t)iMyINFOPartsLen[0];
return;
}
size_t szTagPattLen = ((sTemp-DCTag)+1);
sMyINFOParts[0][iMyINFOPartsLen[0]-1] = ','; // terminate tag end with ',' for easy tag parsing
uint32_t reqVals = 0;
char * sTagPart = DCTag+szTagPattLen;
for(size_t szi = szTagPattLen; szi < (size_t)(iMyINFOPartsLen[0]-(DCTag-sMyINFOParts[0])); szi++) {
if(DCTag[szi] == ',') {
DCTag[szi] = '\0';
if(sTagPart[1] != ':') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
switch(sTagPart[0]) {
case 'V':
// PPK ... fix for potencial memory leak with fake tag
if(sTagPart[2] == '\0' || pUser->m_sTagVersion) {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_sTagVersion = pUser->m_sMyInfoOriginal+((sTagPart+2)-ServerManager::m_pGlobalBuffer);
pUser->m_ui8TagVersionLen = (uint8_t)((DCTag+szi)-(sTagPart+2));
reqVals++;
break;
case 'M':
if((pUser->m_ui32BoolBits & User::BIT_IPV6) == User::BIT_IPV6 && (pUser->m_ui32SupportBits & User::SUPPORTBIT_IP64) == User::SUPPORTBIT_IP64) {
if(sTagPart[2] == '\0' || sTagPart[3] == '\0' || sTagPart[4] != '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_sModes[0] = sTagPart[2];
pUser->m_sModes[1] = sTagPart[3];
pUser->m_sModes[2] = '\0';
if(toupper(sTagPart[3]) == 'A') {
pUser->m_ui32BoolBits |= User::BIT_IPV6_ACTIVE;
} else {
pUser->m_ui32BoolBits &= ~User::BIT_IPV6_ACTIVE;
}
} else {
if(sTagPart[2] == '\0' || sTagPart[3] != '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_sModes[0] = sTagPart[2];
pUser->m_sModes[1] = '\0';
}
if(toupper(sTagPart[2]) == 'A') {
pUser->m_ui32BoolBits |= User::BIT_IPV4_ACTIVE;
} else {
pUser->m_ui32BoolBits &= ~User::BIT_IPV4_ACTIVE;
}
reqVals++;
break;
case 'H': {
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
DCTag[szi] = '/';
char *sHubsParts[] = { NULL, NULL, NULL };
uint16_t iHubsPartsLen[] = { 0, 0, 0 };
uint8_t ui8Part = 0;
sHubsParts[ui8Part] = sTagPart+2;
for(uint32_t ui32j = 3; ui32j < (uint32_t)((DCTag+szi+1)-sTagPart); ui32j++) {
if(sTagPart[ui32j] == '/') {
sTagPart[ui32j] = '\0';
iHubsPartsLen[ui8Part] = (uint16_t)((sTagPart+ui32j)-sHubsParts[ui8Part]);
// are we on end of hubs tag part ???
if(ui8Part == 2)
break;
ui8Part++;
sHubsParts[ui8Part] = sTagPart+ui32j+1;
}
}
if(sHubsParts[0] != NULL && sHubsParts[1] != NULL && sHubsParts[2] != NULL) {
if(iHubsPartsLen[0] != 0 && iHubsPartsLen[1] != 0 && iHubsPartsLen[2] != 0) {
if(HaveOnlyNumbers(sHubsParts[0], iHubsPartsLen[0]) == false ||
HaveOnlyNumbers(sHubsParts[1], iHubsPartsLen[1]) == false ||
HaveOnlyNumbers(sHubsParts[2], iHubsPartsLen[2]) == false) {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32NormalHubs = atoi(sHubsParts[0]);
pUser->m_ui32RegHubs = atoi(sHubsParts[1]);
pUser->m_ui32OpHubs = atoi(sHubsParts[2]);
pUser->m_ui32Hubs = pUser->m_ui32NormalHubs+pUser->m_ui32RegHubs+pUser->m_ui32OpHubs;
// PPK ... kill LAM3R with fake hubs
if(pUser->m_ui32Hubs != 0) {
pUser->m_ui32BoolBits &= ~User::BIT_OLDHUBSTAG;
reqVals++;
break;
}
}
} else if(sHubsParts[1] == DCTag+szi+1 && sHubsParts[2] == NULL) {
DCTag[szi] = '\0';
pUser->m_ui32Hubs = atoi(sHubsParts[0]);
reqVals++;
pUser->m_ui32BoolBits |= User::BIT_OLDHUBSTAG;
break;
}
pUser->SendFormat("UserParseMyInfo2", false, "<%s> %s!|", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC], LanguageManager::m_Ptr->m_sTexts[LAN_FAKE_TAG]);
pUser->m_sTag[pUser->m_ui8TagLen] = '\0';
UdpDebug::m_Ptr->BroadcastFormat("[SYS] User %s (%s) with fake Tag disconnected: %s", pUser->m_sNick, pUser->m_sIP, pUser->m_sTag);
pUser->Close();
return;
}
case 'S':
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
if(HaveOnlyNumbers(sTagPart+2, (uint16_t)strlen(sTagPart+2)) == false) {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32Slots = atoi(sTagPart+2);
reqVals++;
break;
case 'O':
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32OLimit = atoi(sTagPart+2);
break;
case 'B':
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32LLimit = atoi(sTagPart+2);
break;
case 'L':
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32LLimit = atoi(sTagPart+2);
break;
case 'D':
if(sTagPart[2] == '\0') {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
}
pUser->m_ui32DLimit = atoi(sTagPart+2);
break;
default:
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] %s (%s): Extra info in DC tag: %s", pUser->Nick, pUser->sIP, sTag);
break;
}
sTagPart = DCTag+szi+1;
}
}
if(reqVals < 4) {
UserSetBadTag(pUser, pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer), (uint8_t)iMyINFOPartsLen[0]);
return;
} else {
pUser->m_sDescription = pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8DescriptionLen = (uint8_t)(DCTag-sMyINFOParts[0]);
return;
}
} else {
pUser->m_sDescription = pUser->m_sMyInfoOriginal+(sMyINFOParts[0]-ServerManager::m_pGlobalBuffer);
pUser->m_ui8DescriptionLen = (uint8_t)iMyINFOPartsLen[0];
}
}
pUser->m_sClient = (char *)sOtherNoTag;
pUser->m_ui8ClientLen = 14;
pUser->m_sTag = NULL;
pUser->m_ui8TagLen = 0;
pUser->m_sTagVersion = NULL;
pUser->m_ui8TagVersionLen = 0;
pUser->m_sModes[0] = '\0';
pUser->m_ui32Hubs = 0;
pUser->m_ui32NormalHubs = 0;
pUser->m_ui32RegHubs = 0;
pUser->m_ui32OpHubs =0;
pUser->m_ui32Slots = 0;
pUser->m_ui32OLimit = 0;
pUser->m_ui32LLimit = 0;
pUser->m_ui32DLimit = 0;
}
//---------------------------------------------------------------------------
UserBan::UserBan() : m_sMessage(NULL), m_ui32Len(0), m_ui32NickHash(0) {
// ...
}
//---------------------------------------------------------------------------
UserBan::~UserBan() {
#ifdef _WIN32
if(m_sMessage != NULL && HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sMessage) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sMessage in UserBan::~UserBan\n");
}
#else
free(m_sMessage);
#endif
}
//---------------------------------------------------------------------------
UserBan * UserBan::CreateUserBan(char * sMess, const uint32_t ui32MessLen, const uint32_t ui32Hash) {
UserBan * pUserBan = new (std::nothrow) UserBan();
if(pUserBan == NULL) {
AppendDebugLog("%s - [MEM] Cannot allocate new pUserBan in UserBan::CreateUserBan\n");
return NULL;
}
#ifdef _WIN32
pUserBan->m_sMessage = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, ui32MessLen+1);
#else
pUserBan->m_sMessage = (char *)malloc(ui32MessLen+1);
#endif
if(pUserBan->m_sMessage == NULL) {
AppendDebugLogFormat("[MEM] UserBan::CreateUserBan cannot allocate %u bytes for sMessage\n", ui32MessLen+1);
delete pUserBan;
return NULL;
}
memcpy(pUserBan->m_sMessage, sMess, ui32MessLen);
pUserBan->m_sMessage[ui32MessLen] = '\0';
pUserBan->m_ui32Len = ui32MessLen;
pUserBan->m_ui32NickHash = ui32Hash;
return pUserBan;
}
//---------------------------------------------------------------------------
LoginLogout::LoginLogout() : m_ui64LogonTick(0), m_ui64IPv4CheckTick(0), m_pBan(NULL), m_pBuffer(NULL), m_ui32ToCloseLoops(0), m_ui32UserConnectedLen(0) {
// ...
}
//---------------------------------------------------------------------------
LoginLogout::~LoginLogout() {
delete m_pBan;
#ifdef _WIN32
if(m_pBuffer != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_pBuffer) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_pBuffer in LoginLogout::~LoginLogout\n");
}
}
#else
free(m_pBuffer);
#endif
}
//---------------------------------------------------------------------------
User::User() : m_ui64SharedSize(0), m_ui64ChangedSharedSizeShort(0), m_ui64ChangedSharedSizeLong(0), m_ui64GetNickListsTick(0), m_ui64MyINFOsTick(0), m_ui64SearchsTick(0),
m_ui64ChatMsgsTick(0), m_ui64PMsTick(0), m_ui64SameSearchsTick(0), m_ui64SamePMsTick(0), m_ui64SameChatsTick(0), m_ui64LastMyINFOSendTick(0), m_ui64LastNicklist(0), m_ui64ReceivedPmTick(0),
m_ui64ChatMsgsTick2(0), m_ui64PMsTick2(0), m_ui64SearchsTick2(0), m_ui64MyINFOsTick2(0), m_ui64CTMsTick(0), m_ui64CTMsTick2(0), m_ui64RCTMsTick(0), m_ui64RCTMsTick2(0),
m_ui64SRsTick(0), m_ui64SRsTick2(0), m_ui64RecvsTick(0), m_ui64RecvsTick2(0), m_ui64ChatIntMsgsTick(0), m_ui64PMsIntTick(0), m_ui64SearchsIntTick(0),
m_tLoginTime(0),
m_pLogInOut(NULL),
m_pCmdToUserStrt(NULL), m_pCmdToUserEnd(NULL), m_pCmdStrt(NULL), m_pCmdEnd(NULL), m_pCmdActive4Search(NULL), m_pCmdActive6Search(NULL), m_pCmdPassiveSearch(NULL),
m_pPrev(NULL), m_pNext(NULL), m_pHashTablePrev(NULL), m_pHashTableNext(NULL), m_pHashIpTablePrev(NULL), m_pHashIpTableNext(NULL),
m_sNick((char *)sDefaultNick), m_sVersion(NULL), m_sMyInfoOriginal(NULL), m_sMyInfoShort(NULL), m_sMyInfoLong(NULL),
m_sDescription(NULL), m_sTag(NULL), m_sConnection(NULL), m_sEmail(NULL), m_sClient((char *)sOtherNoTag), m_sTagVersion(NULL),
m_sLastChat(NULL), m_sLastPM(NULL), m_sLastSearch(NULL), m_pSendBuf(NULL), m_pRecvBuf(NULL), m_pSendBufHead(NULL),
m_sChangedDescriptionShort(NULL), m_sChangedDescriptionLong(NULL), m_sChangedTagShort(NULL), m_sChangedTagLong(NULL),
m_sChangedConnectionShort(NULL), m_sChangedConnectionLong(NULL), m_sChangedEmailShort(NULL), m_sChangedEmailLong(NULL),
m_ui32Recvs(0), m_ui32Recvs2(0),
m_ui32Hubs(0), m_ui32Slots(0), m_ui32OLimit(0), m_ui32LLimit(0), m_ui32DLimit(0), m_ui32NormalHubs(0), m_ui32RegHubs(0), m_ui32OpHubs(0),
m_ui32SendCalled(0), m_ui32RecvCalled(0), m_ui32ReceivedPmCount(0), m_ui32SR(0), m_ui32DefloodWarnings(0),
m_ui32BoolBits(0), m_ui32InfoBits(0), m_ui32SupportBits(0),
m_ui32SendBufLen(0), m_ui32RecvBufLen(0), m_ui32SendBufDataLen(0), m_ui32RecvBufDataLen(0),
m_ui32NickHash(0), m_i32Profile(-1),
#ifdef _WIN32
m_Socket(INVALID_SOCKET),
#else
m_Socket(-1),
#endif
m_ui16MyInfoOriginalLen(0), m_ui16MyInfoShortLen(0), m_ui16MyInfoLongLen(0), m_ui16GetNickLists(0), m_ui16MyINFOs(0), m_ui16Searchs(0),
m_ui16ChatMsgs(0), m_ui16PMs(0), m_ui16SameSearchs(0), m_ui16LastSearchLen(0), m_ui16SamePMs(0), m_ui16LastPMLen(0), m_ui16SameChatMsgs(0),
m_ui16LastChatLen(0), m_ui16LastPmLines(0), m_ui16SameMultiPms(0), m_ui16LastChatLines(0), m_ui16SameMultiChats(0), m_ui16ChatMsgs2(0), m_ui16PMs2(0),
m_ui16Searchs2(0), m_ui16MyINFOs2(0), m_ui16CTMs(0), m_ui16CTMs2(0), m_ui16RCTMs(0), m_ui16RCTMs2(0), m_ui16SRs(0), m_ui16SRs2(0), m_ui16ChatIntMsgs(0),
m_ui16PMsInt(0), m_ui16SearchsInt(0), m_ui16IpTableIdx(0),
m_ui8MagicByte(0),
m_ui8NickLen(9), m_ui8IpLen(0), m_ui8ConnectionLen(0), m_ui8DescriptionLen(0), m_ui8EmailLen(0), m_ui8TagLen(0), m_ui8ClientLen(14), m_ui8TagVersionLen(0),
m_ui8Country(246), m_ui8State(User::STATE_SOCKET_ACCEPTED), m_ui8IPv4Len(0),
m_ui8ChangedDescriptionShortLen(0), m_ui8ChangedDescriptionLongLen(0), m_ui8ChangedTagShortLen(0), m_ui8ChangedTagLongLen(0),
m_ui8ChangedConnectionShortLen(0), m_ui8ChangedConnectionLongLen(0), m_ui8ChangedEmailShortLen(0), m_ui8ChangedEmailLongLen(0) {
m_ui32BoolBits |= User::BIT_IPV4_ACTIVE;
m_ui32BoolBits |= User::BIT_OLDHUBSTAG;
time(&m_tLoginTime);
memset(&m_ui128IpHash, 0, 16);
m_sIP[0] = '\0';
m_sIPv4[0] = '\0';
m_sModes[0] = '\0';
}
//---------------------------------------------------------------------------
User::~User() {
#ifdef _WIN32
if(m_pRecvBuf != NULL) {
if(HeapFree(ServerManager::m_hRecvHeap, HEAP_NO_SERIALIZE, (void *)m_pRecvBuf) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_pRecvBuf in User::~User\n");
}
}
#else
free(m_pRecvBuf);
#endif
#ifdef _WIN32
if(m_pSendBuf != NULL) {
if(HeapFree(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, (void *)m_pSendBuf) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_pSendBuf in User::~User\n");
}
}
#else
free(m_pSendBuf);
#endif
#ifdef _WIN32
if(m_sLastChat != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastChat) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastChat in User::~User\n");
}
}
#else
free(m_sLastChat);
#endif
#ifdef _WIN32
if(m_sLastPM != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastPM) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastPM in User::~User\n");
}
}
#else
free(m_sLastPM);
#endif
#ifdef _WIN32
if(m_sLastSearch != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastSearch) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastSearch in User::~User\n");
}
}
#else
free(m_sLastSearch);
#endif
#ifdef _WIN32
if(m_sMyInfoShort != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sMyInfoShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sMyInfoShort in User::~User\n");
}
}
#else
free(m_sMyInfoShort);
#endif
#ifdef _WIN32
if(m_sMyInfoLong != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sMyInfoLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sMyInfoLong in User::~User\n");
}
}
#else
free(m_sMyInfoLong);
#endif
#ifdef _WIN32
if(m_sMyInfoOriginal != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sMyInfoOriginal) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sMyInfoOriginal in User::~User\n");
}
}
#else
free(m_sMyInfoOriginal);
#endif
#ifdef _WIN32
if(m_sVersion != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sVersion) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sVersion in User::~User\n");
}
}
#else
free(m_sVersion);
#endif
#ifdef _WIN32
if(m_sChangedDescriptionShort != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedDescriptionShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedDescriptionShort in User::~User\n");
}
}
#else
free(m_sChangedDescriptionShort);
#endif
#ifdef _WIN32
if(m_sChangedDescriptionLong != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedDescriptionLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedDescriptionLong in User::~User\n");
}
}
#else
free(m_sChangedDescriptionLong);
#endif
#ifdef _WIN32
if(m_sChangedTagShort != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedTagShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedTagShort in User::~User\n");
}
}
#else
free(m_sChangedTagShort);
#endif
#ifdef _WIN32
if(m_sChangedTagLong != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedTagLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedTagLong in User::~User\n");
}
}
#else
free(m_sChangedTagLong);
#endif
#ifdef _WIN32
if(m_sChangedConnectionShort != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedConnectionShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedConnectionShort in User::~User\n");
}
}
#else
free(m_sChangedConnectionShort);
#endif
#ifdef _WIN32
if(m_sChangedConnectionLong != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedConnectionLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedConnectionLong in User::~User\n");
}
}
#else
free(m_sChangedConnectionLong);
#endif
#ifdef _WIN32
if(m_sChangedEmailShort != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedEmailShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedEmailShort in User::~User\n");
}
}
#else
free(m_sChangedEmailShort);
#endif
#ifdef _WIN32
if(m_sChangedEmailLong != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sChangedEmailLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sChangedEmailLong in User::~User\n");
}
}
#else
free(m_sChangedEmailLong);
#endif
if(((m_ui32SupportBits & User::SUPPORTBIT_ZPIPE) == User::SUPPORTBIT_ZPIPE) == true)
DcCommands::m_Ptr->m_ui32StatZPipe--;
ServerManager::m_ui32Parts++;
#ifdef _BUILD_GUI
if(::SendMessage(MainWindowPageUsersChat::m_Ptr->m_hWndPageItems[MainWindowPageUsersChat::BTN_SHOW_COMMANDS], BM_GETCHECK, 0, 0) == BST_CHECKED) {
RichEditAppendText(MainWindowPageUsersChat::m_Ptr->m_hWndPageItems[MainWindowPageUsersChat::REDT_CHAT], ("x User removed: " + string(m_sNick, m_ui8NickLen) + " (Socket " + string(m_Socket) + ")").c_str());
}
#endif
if(m_sNick != sDefaultNick) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sNick) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sNick in User::~User\n");
}
#else
free(m_sNick);
#endif
}
delete m_pLogInOut;
if(m_pCmdActive4Search != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdActive4Search);
}
if(m_pCmdActive6Search != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdActive6Search);
}
if(m_pCmdPassiveSearch != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdPassiveSearch);
}
PrcsdUsrCmd * cur = NULL,
* next = m_pCmdStrt;
while(next != NULL) {
cur = next;
next = cur->m_pNext;
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate cur->m_sCommand in User::~User\n");
}
#else
free(cur->m_sCommand);
#endif
delete cur;
}
PrcsdToUsrCmd * curto = NULL,
* nextto = m_pCmdToUserStrt;
while(nextto != NULL) {
curto = nextto;
nextto = curto->m_pNext;
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curto->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate curto->m_sCommand in User::~User\n");
}
#else
free(curto->m_sCommand);
#endif
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curto->m_sToNick) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate curto->m_sToNick in User::~User\n");
}
#else
free(curto->m_sToNick);
#endif
delete curto;
}
}
//---------------------------------------------------------------------------
bool User::MakeLock() {
// This code computes the valid Lock string including the Pk= string
// For maximum speed we just find two random numbers - start and step
// Step is added each cycle to the start and the ascii 122 boundary is
// checked. If overflow occurs then the overflowed value is added to the
// ascii 48 value ("0") and continues.
// The lock has fixed length 63 bytes
#ifdef _WIN32
#ifdef _BUILD_GUI
#ifndef _M_X64
static const char sLock[] = "$Lock EXTENDEDPROTOCOL win Pk=PtokaX|";
#else
static const char sLock[] = "$Lock EXTENDEDPROTOCOL wg6 Pk=PtokaX|";
#endif
#else
#ifndef _M_X64
static const char sLock[] = "$Lock EXTENDEDPROTOCOL wis Pk=PtokaX|";
#elif _M_ARM
static const char sLock[] = "$Lock EXTENDEDPROTOCOL wsa Pk=PtokaX|";
#else
static const char sLock[] = "$Lock EXTENDEDPROTOCOL ws6 Pk=PtokaX|";
#endif
#endif
#else
static const char sLock[] = "$Lock EXTENDEDPROTOCOL nix Pk=PtokaX|";
#endif
static const size_t szLockLen = sizeof(sLock)-1;
size_t szAllignLen = Allign1024(m_ui32SendBufDataLen+szLockLen);
char * pOldBuf = m_pSendBuf;
#ifdef _WIN32
if(m_pSendBuf == NULL) {
m_pSendBuf = (char *)HeapAlloc(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, szAllignLen);
} else {
m_pSendBuf = (char *)HeapReAlloc(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, szAllignLen);
}
#else
m_pSendBuf = (char *)realloc(pOldBuf, szAllignLen);
#endif
if(m_pSendBuf == NULL) {
m_pSendBuf = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes in User::MakeLock\n", szAllignLen);
return false;
}
m_ui32SendBufLen = (uint32_t)(szAllignLen-1);
m_pSendBufHead = m_pSendBuf;
// append data to the buffer
memcpy(m_pSendBuf, sLock, szLockLen);
m_ui32SendBufDataLen += szLockLen;
m_pSendBuf[m_ui32SendBufDataLen] = '\0';
for(uint8_t ui8i = 22; ui8i < 49; ui8i++) {
#ifdef _WIN32
m_pSendBuf[ui8i] = (char)((rand() % 74) + 48);
#else
m_pSendBuf[ui8i] = (char)((random() % 74) + 48);
#endif
}
// Memo(string(pSendBuf, ui32SendBufDataLen));
#ifdef _WIN32
m_pLogInOut->m_pBuffer = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, 64);
#else
m_pLogInOut->m_pBuffer = (char *)malloc(64);
#endif
if(m_pLogInOut->m_pBuffer == NULL) {
AppendDebugLog("%s - [MEM] Cannot allocate 64 bytes for pBuffer in User::MakeLock\n");
return false;
}
memcpy(m_pLogInOut->m_pBuffer, m_pSendBuf, szLockLen);
m_pLogInOut->m_pBuffer[szLockLen] = '\0';
return true;
}
//---------------------------------------------------------------------------
bool User::DoRecv() {
if((m_ui32BoolBits & BIT_ERROR) == BIT_ERROR || m_ui8State >= STATE_CLOSING)
return false;
#ifdef _WIN32
u_long iAvailBytes = 0;
if(ioctlsocket(m_Socket, FIONREAD, &iAvailBytes) == SOCKET_ERROR) {
int iError = WSAGetLastError();
#else
int iAvailBytes = 0;
if(ioctl(m_Socket, FIONREAD, &iAvailBytes) == -1) {
#endif
UdpDebug::m_Ptr->BroadcastFormat("[ERR] %s (%s): ioctlsocket(FIONREAD) error %s (%d). User is being closed.", m_sNick, m_sIP,
#ifdef _WIN32
WSErrorStr(iError), iError);
#else
ErrnoStr(errno), errno);
#endif
m_ui32BoolBits |= BIT_ERROR;
Close();
return false;
}
// PPK ... check flood ...
if(iAvailBytes != 0 && ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NODEFLOODRECV) == false) {
if(SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_ACTION] != 0) {
if(m_ui32Recvs == 0) {
m_ui64RecvsTick = ServerManager::m_ui64ActualTick;
}
m_ui32Recvs += iAvailBytes;
if(DeFloodCheckForDataFlood(this, DEFLOOD_MAX_DOWN, SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_ACTION],
m_ui32Recvs, m_ui64RecvsTick, SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_KB],
(uint32_t)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_TIME]) == true) {
return false;
}
if(m_ui32Recvs != 0) {
m_ui32Recvs -= iAvailBytes;
}
}
if(SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_ACTION2] != 0) {
if(m_ui32Recvs2 == 0) {
m_ui64RecvsTick2 = ServerManager::m_ui64ActualTick;
}
m_ui32Recvs2 += iAvailBytes;
if(DeFloodCheckForDataFlood(this, DEFLOOD_MAX_DOWN, SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_ACTION2],
m_ui32Recvs2, m_ui64RecvsTick2, SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_KB2],
(uint32_t)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_DOWN_TIME2]) == true) {
return false;
}
if(m_ui32Recvs2 != 0) {
m_ui32Recvs2 -= iAvailBytes;
}
}
}
if(iAvailBytes == 0) {
// we need to try recv to catch connection error or closed connection
iAvailBytes = 16;
} else if(iAvailBytes > 16384) {
// receive max. 16384 bytes to receive buffer
iAvailBytes = 16384;
}
size_t szAllignLen = 0;
if(m_ui32RecvBufLen < m_ui32RecvBufDataLen+iAvailBytes) {
szAllignLen = Allign512(m_ui32RecvBufDataLen+iAvailBytes);
} else if(m_ui32RecvCalled > 60) {
szAllignLen = Allign512(m_ui32RecvBufDataLen+iAvailBytes);
if(m_ui32RecvBufLen <= szAllignLen) {
szAllignLen = 0;
}
m_ui32RecvCalled = 0;
}
if(szAllignLen != 0) {
char * pOldBuf = m_pRecvBuf;
#ifdef _WIN32
if(m_pRecvBuf == NULL) {
m_pRecvBuf = (char *)HeapAlloc(ServerManager::m_hRecvHeap, HEAP_NO_SERIALIZE, szAllignLen);
} else {
m_pRecvBuf = (char *)HeapReAlloc(ServerManager::m_hRecvHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, szAllignLen);
}
#else
m_pRecvBuf = (char *)realloc(pOldBuf, szAllignLen);
#endif
if(m_pRecvBuf == NULL) {
m_pRecvBuf = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot (re)allocate %zu bytes for pRecvBuf in User::DoRecv\n", szAllignLen);
return false;
}
m_ui32RecvBufLen = (uint32_t)(szAllignLen-1);
}
// receive new data to pRecvBuf
int recvlen = recv(m_Socket, m_pRecvBuf+m_ui32RecvBufDataLen, m_ui32RecvBufLen-m_ui32RecvBufDataLen, 0);
m_ui32RecvCalled++;
#ifdef _WIN32
if(recvlen == SOCKET_ERROR) {
int iError = WSAGetLastError();
if(iError != WSAEWOULDBLOCK) {
#else
if(recvlen == -1) {
if(errno != EAGAIN) {
#endif
UdpDebug::m_Ptr->BroadcastFormat("[ERR] %s (%s): recv() error %s (%d). User is being closed.", m_sNick, m_sIP,
#ifdef _WIN32
WSErrorStr(iError), iError);
#else
ErrnoStr(errno), errno);
#endif
m_ui32BoolBits |= BIT_ERROR;
Close();
return false;
} else {
return false;
}
} else if(recvlen == 0) { // regular close
#ifdef _WIN32
#ifdef _BUILD_GUI
if(::SendMessage(MainWindowPageUsersChat::m_Ptr->m_hWndPageItems[MainWindowPageUsersChat::BTN_SHOW_COMMANDS], BM_GETCHECK, 0, 0) == BST_CHECKED) {
int iRet = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "- User has closed the connection: %s (%s)", m_sNick, m_sIP);
if(iRet > 0) {
RichEditAppendText(MainWindowPageUsersChat::m_Ptr->m_hWndPageItems[MainWindowPageUsersChat::REDT_CHAT], ServerManager::m_pGlobalBuffer);
}
}
#endif
#endif
m_ui32BoolBits |= BIT_ERROR;
Close();
return false;
}
m_ui32Recvs += recvlen;
m_ui32Recvs2 += recvlen;
ServerManager::m_ui64BytesRead += recvlen;
m_ui32RecvBufDataLen += recvlen;
m_pRecvBuf[m_ui32RecvBufDataLen] = '\0';
if(UserProcessLines(this, m_ui32RecvBufDataLen-recvlen) == true) {
return true;
}
return false;
}
//---------------------------------------------------------------------------
void User::SendChar(const char * sText, const size_t szTextLen) {
if(m_ui8State >= STATE_CLOSING || szTextLen == 0)
return;
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false || szTextLen < ZMINDATALEN) {
if(PutInSendBuf(sText, szTextLen)) {
Try2Send();
}
} else {
uint32_t iLen = 0;
char *sData = ZlibUtility::m_Ptr->CreateZPipe(sText, szTextLen, iLen);
if(iLen == 0) {
if(PutInSendBuf(sText, szTextLen)) {
Try2Send();
}
} else {
ServerManager::m_ui64BytesSentSaved += szTextLen-iLen;
if(PutInSendBuf(sData, iLen)) {
Try2Send();
}
}
}
}
//---------------------------------------------------------------------------
void User::SendCharDelayed(const char * sText, const size_t szTextLen) {
if(m_ui8State >= STATE_CLOSING || szTextLen == 0) {
return;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false || szTextLen < ZMINDATALEN) {
PutInSendBuf(sText, szTextLen);
} else {
uint32_t iLen = 0;
char *sPipeData = ZlibUtility::m_Ptr->CreateZPipe(sText, szTextLen, iLen);
if(iLen == 0) {
PutInSendBuf(sText, szTextLen);
} else {
PutInSendBuf(sPipeData, iLen);
ServerManager::m_ui64BytesSentSaved += szTextLen-iLen;
}
}
}
//---------------------------------------------------------------------------
void User::SendFormat(const char * sFrom, const bool bDelayed, const char * sFormatMsg, ...) {
if(m_ui8State >= STATE_CLOSING) {
return;
}
va_list vlArgs;
va_start(vlArgs, sFormatMsg);
int iRet = vsnprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, sFormatMsg, vlArgs);
va_end(vlArgs);
if(iRet <= 0) {
AppendDebugLogFormat("[ERR] vsnprintf wrong value %d in User::SendFormatDelayed from: %s\n", iRet, sFrom);
return;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false || (size_t)iRet < ZMINDATALEN) {
if(PutInSendBuf(ServerManager::m_pGlobalBuffer, iRet) == true && bDelayed == false) {
Try2Send();
}
} else {
uint32_t iLen = 0;
char *sData = ZlibUtility::m_Ptr->CreateZPipe(ServerManager::m_pGlobalBuffer, iRet, iLen);
if(iLen == 0) {
if(PutInSendBuf(ServerManager::m_pGlobalBuffer, iRet) == true && bDelayed == false) {
Try2Send();
}
} else {
if(PutInSendBuf(sData, iLen) == true && bDelayed == false) {
Try2Send();
}
ServerManager::m_ui64BytesSentSaved += iRet-iLen;
}
}
}
//---------------------------------------------------------------------------
void User::SendFormatCheckPM(const char * sFrom, const char * sOtherNick, const bool bDelayed, const char * sFormatMsg, ...) {
if(m_ui8State >= STATE_CLOSING) {
return;
}
int iMsgLen = 0;
if(sOtherNick != NULL) {
iMsgLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "$To: %s From: %s $", m_sNick, sOtherNick);
if(iMsgLen <= 0) {
AppendDebugLogFormat("[ERR] snprintf wrong value %d in User::SendFormatCheckPM from: %s\n", iMsgLen, sFrom);
return;
}
}
va_list vlArgs;
va_start(vlArgs, sFormatMsg);
int iRet = vsnprintf(ServerManager::m_pGlobalBuffer+iMsgLen, ServerManager::m_szGlobalBufferSize-iMsgLen, sFormatMsg, vlArgs);
va_end(vlArgs);
if(iRet <= 0) {
AppendDebugLogFormat("[ERR] vsnprintf wrong value %d in User::SendFormatCheckPM from: %s\n", iRet, sFrom);
return;
}
iMsgLen += iRet;
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false || (size_t)iMsgLen < ZMINDATALEN) {
if(PutInSendBuf(ServerManager::m_pGlobalBuffer, iMsgLen) == true && bDelayed == false) {
Try2Send();
}
} else {
uint32_t iLen = 0;
char *sData = ZlibUtility::m_Ptr->CreateZPipe(ServerManager::m_pGlobalBuffer, iMsgLen, iLen);
if(iLen == 0) {
if(PutInSendBuf(ServerManager::m_pGlobalBuffer, iMsgLen) == true && bDelayed == false) {
Try2Send();
}
} else {
if(PutInSendBuf(sData, iLen) == true && bDelayed == false) {
Try2Send();
}
ServerManager::m_ui64BytesSentSaved += iMsgLen-iLen;
}
}
}
//---------------------------------------------------------------------------
bool User::PutInSendBuf(const char * sText, const size_t szTxtLen) {
m_ui32SendCalled++;
size_t szAllignLen = 0;
if(m_ui32SendBufLen < m_ui32SendBufDataLen+szTxtLen) {
if(m_pSendBuf == NULL) {
szAllignLen = Allign1024(m_ui32SendBufDataLen+szTxtLen);
} else {
if((size_t)(m_pSendBufHead-m_pSendBuf) > szTxtLen) {
uint32_t offset = (uint32_t)(m_pSendBufHead-m_pSendBuf);
memmove(m_pSendBuf, m_pSendBufHead, (m_ui32SendBufDataLen-offset));
m_pSendBufHead = m_pSendBuf;
m_ui32SendBufDataLen = m_ui32SendBufDataLen-offset;
} else {
szAllignLen = Allign1024(m_ui32SendBufDataLen+szTxtLen);
size_t szMaxBufLen = (size_t)(((m_ui32BoolBits & BIT_BIG_SEND_BUFFER) == BIT_BIG_SEND_BUFFER) == true ?
((Users::m_Ptr->m_ui32MyInfosTagLen > Users::m_Ptr->m_ui32MyInfosLen ? Users::m_Ptr->m_ui32MyInfosTagLen : Users::m_Ptr->m_ui32MyInfosLen)*2) :
(Users::m_Ptr->m_ui32MyInfosTagLen > Users::m_Ptr->m_ui32MyInfosLen ? Users::m_Ptr->m_ui32MyInfosTagLen : Users::m_Ptr->m_ui32MyInfosLen));
szMaxBufLen = szMaxBufLen < 262144 ? 262144 :szMaxBufLen;
if(szAllignLen > szMaxBufLen) {
// does the buffer size reached the maximum
if(SettingManager::m_Ptr->m_bBools[SETBOOL_KEEP_SLOW_USERS] == false || (m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) {
// we want to drop the slow user
m_ui32BoolBits |= BIT_ERROR;
Close();
UdpDebug::m_Ptr->BroadcastFormat("[SYS] %s (%s) SendBuffer overflow (AL:%zu[SL:%u|NL:%zu|FL:%zu]/ML:%zu). User disconnected.",
m_sNick, m_sIP, szAllignLen, m_ui32SendBufDataLen, szTxtLen, m_pSendBufHead-m_pSendBuf, szMaxBufLen);
return false;
} else {
UdpDebug::m_Ptr->BroadcastFormat("[SYS] %s (%s) SendBuffer overflow (AL:%zu[SL:%u|NL:%zu|FL:%zu]/ML:%zu). Buffer cleared - user stays online.",
m_sNick, m_sIP, szAllignLen, m_ui32SendBufDataLen, szTxtLen, m_pSendBufHead-m_pSendBuf, szMaxBufLen);
}
// we want to keep the slow user online
// PPK ... i don't want to corrupt last command, get rest of it and add to new buffer ;)
char *sTemp = (char *)memchr(m_pSendBufHead, '|', m_ui32SendBufDataLen-(m_pSendBufHead-m_pSendBuf));
if(sTemp != NULL) {
uint32_t iOldSBDataLen = m_ui32SendBufDataLen;
uint32_t iRestCommandLen = (uint32_t)((sTemp-m_pSendBufHead)+1);
if(m_pSendBuf != m_pSendBufHead) {
memmove(m_pSendBuf, m_pSendBufHead, iRestCommandLen);
}
m_ui32SendBufDataLen = iRestCommandLen;
// If is not needed then don't lost all data, try to find some space with removing only few oldest commands
if(szTxtLen < szMaxBufLen && iOldSBDataLen > (uint32_t)((sTemp+1)-m_pSendBuf) && (iOldSBDataLen-((sTemp+1)-m_pSendBuf)) > (uint32_t)szTxtLen) {
char *sTemp1;
// try to remove min half of send bufer
if(iOldSBDataLen > (m_ui32SendBufLen/2) && (uint32_t)((sTemp+1+szTxtLen)-m_pSendBuf) < (m_ui32SendBufLen/2)) {
sTemp1 = (char *)memchr(m_pSendBuf+(m_ui32SendBufLen/2), '|', iOldSBDataLen-(m_ui32SendBufLen/2));
} else {
sTemp1 = (char *)memchr(sTemp+1+szTxtLen, '|', iOldSBDataLen-((sTemp+1+szTxtLen)-m_pSendBuf));
}
if(sTemp1 != NULL) {
iRestCommandLen = (uint32_t)(iOldSBDataLen-((sTemp1+1)-m_pSendBuf));
memmove(m_pSendBuf+m_ui32SendBufDataLen, sTemp1+1, iRestCommandLen);
m_ui32SendBufDataLen += iRestCommandLen;
}
}
} else {
m_pSendBuf[0] = '|';
m_pSendBuf[1] = '\0';
m_ui32SendBufDataLen = 1;
}
size_t szAllignTxtLen = Allign1024(szTxtLen+m_ui32SendBufDataLen);
char * pOldBuf = m_pSendBuf;
#ifdef _WIN32
m_pSendBuf = (char *)HeapReAlloc(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, szAllignTxtLen);
#else
m_pSendBuf = (char *)realloc(pOldBuf, szAllignTxtLen);
#endif
if(m_pSendBuf == NULL) {
m_pSendBuf = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in User::PutInSendBuf-keepslow\n", szAllignLen);
return false;
}
m_ui32SendBufLen = (uint32_t)(szAllignTxtLen-1);
m_pSendBufHead = m_pSendBuf;
szAllignLen = 0;
} else {
szAllignLen = Allign1024(m_ui32SendBufDataLen+szTxtLen);
}
}
}
} else if(m_ui32SendCalled > 100) {
szAllignLen = Allign1024(m_ui32SendBufDataLen+szTxtLen);
if(m_ui32SendBufLen <= szAllignLen) {
szAllignLen = 0;
}
m_ui32SendCalled = 0;
}
if(szAllignLen != 0) {
uint32_t offset = (m_pSendBuf == NULL ? 0 : (uint32_t)(m_pSendBufHead-m_pSendBuf));
char * pOldBuf = m_pSendBuf;
#ifdef _WIN32
if(m_pSendBuf == NULL) {
m_pSendBuf = (char *)HeapAlloc(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, szAllignLen);
} else {
m_pSendBuf = (char *)HeapReAlloc(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, szAllignLen);
}
#else
m_pSendBuf = (char *)realloc(pOldBuf, szAllignLen);
#endif
if(m_pSendBuf == NULL) {
m_pSendBuf = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot (re)allocate %zu bytes for new pSendBuf in User::PutInSendBuf\n", szAllignLen);
return false;
}
m_ui32SendBufLen = (uint32_t)(szAllignLen-1);
m_pSendBufHead = m_pSendBuf+offset;
}
// append data to the buffer
memcpy(m_pSendBuf+m_ui32SendBufDataLen, sText, szTxtLen);
m_ui32SendBufDataLen += (uint32_t)szTxtLen;
m_pSendBuf[m_ui32SendBufDataLen] = '\0';
return true;
}
//---------------------------------------------------------------------------
bool User::Try2Send() {
if((m_ui32BoolBits & BIT_ERROR) == BIT_ERROR || m_ui32SendBufDataLen == 0) {
return false;
}
// compute length of unsent data
int32_t offset = (int32_t)(m_pSendBufHead - m_pSendBuf);
int32_t len = m_ui32SendBufDataLen - offset;
if(offset < 0 || len < 0) {
AppendDebugLogFormat("[ERR] Negative send values!\nSendBuf: %p\nPlayHead: %p\nDataLen: %u\n", m_pSendBuf, m_pSendBufHead, m_ui32SendBufDataLen);
m_ui32BoolBits |= BIT_ERROR;
Close();
return false;
}
int n = send(m_Socket, m_pSendBufHead, len < 32768 ? len : 32768, 0);
#ifdef _WIN32
if(n == SOCKET_ERROR) {
int iError = WSAGetLastError();
if(iError != WSAEWOULDBLOCK) {
#else
if(n == -1) {
if(errno != EAGAIN) {
#endif
UdpDebug::m_Ptr->BroadcastFormat("[ERR] %s (%s): send() error %s (%d). User is being closed.", m_sNick, m_sIP,
#ifdef _WIN32
WSErrorStr(iError), iError);
#else
ErrnoStr(errno), errno);
#endif
m_ui32BoolBits |= BIT_ERROR;
Close();
return false;
} else {
return true;
}
}
ServerManager::m_ui64BytesSent += n;
// if buffer is sent then mark it as empty (first byte = 0)
// else move remaining data on new place and free old buffer
if(n < len) {
m_pSendBufHead += n;
return true;
} else {
// PPK ... we need to free memory allocated for big buffer on login (userlist, motd...)
if(((m_ui32BoolBits & BIT_BIG_SEND_BUFFER) == BIT_BIG_SEND_BUFFER) == true) {
if(m_pSendBuf != NULL) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hSendHeap, HEAP_NO_SERIALIZE, (void *)m_pSendBuf) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pSendBuf in User::Try2Send\n");
}
#else
free(m_pSendBuf);
#endif
m_pSendBuf = NULL;
m_pSendBufHead = m_pSendBuf;
m_ui32SendBufLen = 0;
m_ui32SendBufDataLen = 0;
}
m_ui32BoolBits &= ~BIT_BIG_SEND_BUFFER;
} else {
m_pSendBuf[0] = '\0';
m_pSendBufHead = m_pSendBuf;
m_ui32SendBufDataLen = 0;
}
return false;
}
}
//---------------------------------------------------------------------------
void User::SetIP(char * sIP) {
strcpy(m_sIP, sIP);
m_ui8IpLen = (uint8_t)strlen(sIP);
}
//------------------------------------------------------------------------------
void User::SetNick(char * sNick, const uint8_t ui8NickLen) {
if(m_sNick != sDefaultNick && m_sNick != NULL) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sNick) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sNick in User::SetNick\n");
}
#else
free(m_sNick);
#endif
}
#ifdef _WIN32
m_sNick = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, ui8NickLen+1);
#else
m_sNick = (char *)malloc(ui8NickLen+1);
#endif
if(m_sNick == NULL) {
m_sNick = (char *)sDefaultNick;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %" PRIu8 " bytes for m_sNick in User::SetNick\n", m_ui8NickLen+1);
return;
}
memcpy(m_sNick, sNick, ui8NickLen);
m_sNick[ui8NickLen] = '\0';
m_ui8NickLen = ui8NickLen;
m_ui32NickHash = HashNick(m_sNick, m_ui8NickLen);
}
//------------------------------------------------------------------------------
void User::SetMyInfoOriginal(char * sMyInfo, const uint16_t ui16MyInfoLen) {
char * sOldMyInfo = m_sMyInfoOriginal;
char * sOldDescription = m_sDescription;
uint8_t ui8OldDescriptionLen = m_ui8DescriptionLen;
char * sOldTag = m_sTag;
uint8_t ui8OldTagLen = m_ui8TagLen;
char * sOldConnection = m_sConnection;
uint8_t ui8OldConnectionLen = m_ui8ConnectionLen;
char * sOldEmail = m_sEmail;
uint8_t ui8OldEmailLen = m_ui8EmailLen;
uint64_t ui64OldShareSize = m_ui64SharedSize;
if(m_sMyInfoOriginal != NULL) {
m_sConnection = NULL;
m_ui8ConnectionLen = 0;
m_sDescription = NULL;
m_ui8DescriptionLen = 0;
m_sEmail = NULL;
m_ui8EmailLen = 0;
m_sTag = NULL;
m_ui8TagLen = 0;
m_sClient = NULL;
m_ui8ClientLen = 0;
m_sTagVersion = NULL;
m_ui8TagVersionLen = 0;
m_sMyInfoOriginal = NULL;
}
#ifdef _WIN32
m_sMyInfoOriginal = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, ui16MyInfoLen+1);
#else
m_sMyInfoOriginal = (char *)malloc(ui16MyInfoLen+1);
#endif
if(m_sMyInfoOriginal == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %hu bytes for m_sMyInfoOriginal in UserSetMyInfoOriginal\n", ui16MyInfoLen+1);
return;
}
memcpy(m_sMyInfoOriginal, sMyInfo, ui16MyInfoLen);
m_sMyInfoOriginal[ui16MyInfoLen] = '\0';
m_ui16MyInfoOriginalLen = ui16MyInfoLen;
UserParseMyInfo(this);
if(ui8OldDescriptionLen != m_ui8DescriptionLen || (m_ui8DescriptionLen > 0 && memcmp(sOldDescription, m_sDescription, m_ui8DescriptionLen) != 0)) {
m_ui32InfoBits |= INFOBIT_DESCRIPTION_CHANGED;
} else {
m_ui32InfoBits &= ~INFOBIT_DESCRIPTION_CHANGED;
}
if(ui8OldTagLen != m_ui8TagLen || (m_ui8TagLen > 0 && memcmp(sOldTag, m_sTag, m_ui8TagLen) != 0)) {
m_ui32InfoBits |= INFOBIT_TAG_CHANGED;
} else {
m_ui32InfoBits &= ~INFOBIT_TAG_CHANGED;
}
if(ui8OldConnectionLen != m_ui8ConnectionLen || (m_ui8ConnectionLen > 0 && memcmp(sOldConnection, m_sConnection, m_ui8ConnectionLen) != 0)) {
m_ui32InfoBits |= INFOBIT_CONNECTION_CHANGED;
} else {
m_ui32InfoBits &= ~INFOBIT_CONNECTION_CHANGED;
}
if(ui8OldEmailLen != m_ui8EmailLen || (m_ui8EmailLen > 0 && memcmp(sOldEmail, m_sEmail, m_ui8EmailLen) != 0)) {
m_ui32InfoBits |= INFOBIT_EMAIL_CHANGED;
} else {
m_ui32InfoBits &= ~INFOBIT_EMAIL_CHANGED;
}
if(ui64OldShareSize != m_ui64SharedSize) {
m_ui32InfoBits |= INFOBIT_SHARE_CHANGED;
} else {
m_ui32InfoBits &= ~INFOBIT_SHARE_CHANGED;
}
if(sOldMyInfo != NULL) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)sOldMyInfo) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sOldMyInfo in UserSetMyInfoOriginal\n");
}
#else
free(sOldMyInfo);
#endif
}
if(((m_ui32InfoBits & INFOBIT_SHARE_SHORT_PERM) == INFOBIT_SHARE_SHORT_PERM) == false) {
m_ui64ChangedSharedSizeShort = m_ui64SharedSize;
}
if(((m_ui32InfoBits & INFOBIT_SHARE_LONG_PERM) == INFOBIT_SHARE_LONG_PERM) == false) {
m_ui64ChangedSharedSizeLong = m_ui64SharedSize;
}
}
//------------------------------------------------------------------------------
static void UserSetMyInfoLong(User * pUser, char * sMyInfoLong, const uint16_t &ui16MyInfoLongLen) {
if(pUser->m_sMyInfoLong != NULL) {
if(SettingManager::m_Ptr->m_ui8FullMyINFOOption != 2) {
Users::m_Ptr->DelFromMyInfosTag(pUser);
}
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pUser->m_sMyInfoLong) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pUser->m_sMyInfoLong in UserSetMyInfoLong\n");
}
#else
free(pUser->m_sMyInfoLong);
#endif
}
#ifdef _WIN32
pUser->m_sMyInfoLong = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, ui16MyInfoLongLen+1);
#else
pUser->m_sMyInfoLong = (char *)malloc(ui16MyInfoLongLen+1);
#endif
if(pUser->m_sMyInfoLong == NULL) {
pUser->m_ui32BoolBits |= User::BIT_ERROR;
pUser->Close();
AppendDebugLogFormat("[MEM] Cannot allocate %hu bytes for m_sMyInfoLong in UserSetMyInfoLong\n", ui16MyInfoLongLen+1);
return;
}
memcpy(pUser->m_sMyInfoLong, sMyInfoLong, ui16MyInfoLongLen);
pUser->m_sMyInfoLong[ui16MyInfoLongLen] = '\0';
pUser->m_ui16MyInfoLongLen = ui16MyInfoLongLen;
}
//------------------------------------------------------------------------------
static void UserSetMyInfoShort(User * pUser, char * sMyInfoShort, const uint16_t &ui16MyInfoShortLen) {
if(pUser->m_sMyInfoShort != NULL) {
if(SettingManager::m_Ptr->m_ui8FullMyINFOOption != 0) {
Users::m_Ptr->DelFromMyInfos(pUser);
}
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pUser->m_sMyInfoShort) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pUser->m_sMyInfoShort in UserSetMyInfoShort\n");
}
#else
free(pUser->m_sMyInfoShort);
#endif
}
#ifdef _WIN32
pUser->m_sMyInfoShort = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, ui16MyInfoShortLen+1);
#else
pUser->m_sMyInfoShort = (char *)malloc(ui16MyInfoShortLen+1);
#endif
if(pUser->m_sMyInfoShort == NULL) {
pUser->m_ui32BoolBits |= User::BIT_ERROR;
pUser->Close();
AppendDebugLogFormat("[MEM] Cannot allocate %hu bytes for m_sMyInfoShort in UserSetMyInfoShort\n", ui16MyInfoShortLen+1);
return;
}
memcpy(pUser->m_sMyInfoShort, sMyInfoShort, ui16MyInfoShortLen);
pUser->m_sMyInfoShort[ui16MyInfoShortLen] = '\0';
pUser->m_ui16MyInfoShortLen = ui16MyInfoShortLen;
}
//------------------------------------------------------------------------------
void User::SetVersion(char * sVersion) {
#ifdef _WIN32
if(m_sVersion) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sVersion) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sVersion in User::SetVersion\n");
}
}
#else
free(m_sVersion);
#endif
size_t szLen = strlen(sVersion);
#ifdef _WIN32
m_sVersion = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szLen+1);
#else
m_sVersion = (char *)malloc(szLen+1);
#endif
if(m_sVersion == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for m_sVersion in User::SetVersion\n", szLen+1);
return;
}
memcpy(m_sVersion, sVersion, szLen);
m_sVersion[szLen] = '\0';
}
//------------------------------------------------------------------------------
void User::SetLastChat(char * sData, const size_t szLen) {
#ifdef _WIN32
if(m_sLastChat != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastChat) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastChat in User::SetLastChat\n");
}
}
#else
free(m_sLastChat);
#endif
#ifdef _WIN32
m_sLastChat = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szLen+1);
#else
m_sLastChat = (char *)malloc(szLen+1);
#endif
if(m_sLastChat == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for m_sLastChat in User::SetLastChat\n", szLen+1);
return;
}
memcpy(m_sLastChat, sData, szLen);
m_sLastChat[szLen] = '\0';
m_ui16SameChatMsgs = 1;
m_ui64SameChatsTick = ServerManager::m_ui64ActualTick;
m_ui16LastChatLen = (uint16_t)szLen;
m_ui16SameMultiChats = 0;
m_ui16LastChatLines = 0;
}
//------------------------------------------------------------------------------
void User::SetLastPM(char * sData, const size_t szLen) {
#ifdef _WIN32
if(m_sLastPM != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastPM) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastPM in User::SetLastPM\n");
}
}
#else
free(m_sLastPM);
#endif
#ifdef _WIN32
m_sLastPM = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szLen+1);
#else
m_sLastPM = (char *)malloc(szLen+1);
#endif
if(m_sLastPM == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for m_sLastPM in User::SetLastPM\n", szLen+1);
return;
}
memcpy(m_sLastPM, sData, szLen);
m_sLastPM[szLen] = '\0';
m_ui16SamePMs = 1;
m_ui64SamePMsTick = ServerManager::m_ui64ActualTick;
m_ui16LastPMLen = (uint16_t)szLen;
m_ui16SameMultiPms = 0;
m_ui16LastPmLines = 0;
}
//------------------------------------------------------------------------------
void User::SetLastSearch(char * sData, const size_t szLen) {
#ifdef _WIN32
if(m_sLastSearch != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_sLastSearch) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate m_sLastSearch in User::SetLastSearch\n");
}
}
#else
free(m_sLastSearch);
#endif
#ifdef _WIN32
m_sLastSearch = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szLen+1);
#else
m_sLastSearch = (char *)malloc(szLen+1);
#endif
if(m_sLastSearch == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for m_sLastSearch in User::SetLastSearch\n", szLen+1);
return;
}
memcpy(m_sLastSearch, sData, szLen);
m_sLastSearch[szLen] = '\0';
m_ui16SameSearchs = 1;
m_ui64SameSearchsTick = ServerManager::m_ui64ActualTick;
m_ui16LastSearchLen = (uint16_t)szLen;
}
//------------------------------------------------------------------------------
void User::SetBuffer(char * sKickMsg, size_t szLen/* = 0*/) {
if(szLen == 0) {
szLen = strlen(sKickMsg);
}
if(m_pLogInOut == NULL) {
m_pLogInOut = new (std::nothrow) LoginLogout();
if(m_pLogInOut == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLog("%s - [MEM] Cannot allocate new pLogInOut in User::SetBuffer\n");
return;
}
}
void * pOldBuf = m_pLogInOut->m_pBuffer;
if(szLen < 512) {
#ifdef _WIN32
if(m_pLogInOut->m_pBuffer == NULL) {
m_pLogInOut->m_pBuffer = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szLen+1);
} else {
m_pLogInOut->m_pBuffer = (char *)HeapReAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, pOldBuf, szLen+1);
}
#else
m_pLogInOut->m_pBuffer = (char *)realloc(pOldBuf, szLen+1);
#endif
if(m_pLogInOut->m_pBuffer == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for pBuffer in User::SetBuffer\n", szLen+1);
return;
}
memcpy(m_pLogInOut->m_pBuffer, sKickMsg, szLen);
m_pLogInOut->m_pBuffer[szLen] = '\0';
} else {
#ifdef _WIN32
if(m_pLogInOut->m_pBuffer == NULL) {
m_pLogInOut->m_pBuffer = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, 512);
} else {
m_pLogInOut->m_pBuffer = (char *)HeapReAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, pOldBuf, 512);
}
#else
m_pLogInOut->m_pBuffer = (char *)realloc(pOldBuf, 512);
#endif
if(m_pLogInOut->m_pBuffer == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLog("%s - [MEM] Cannot allocate 512 bytes for pBuffer in User::SetBuffer\n");
return;
}
memcpy(m_pLogInOut->m_pBuffer, sKickMsg, 508);
m_pLogInOut->m_pBuffer[511] = '\0';
m_pLogInOut->m_pBuffer[510] = '.';
m_pLogInOut->m_pBuffer[509] = '.';
m_pLogInOut->m_pBuffer[508] = '.';
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void User::FreeBuffer() {
if(m_pLogInOut->m_pBuffer != NULL) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)m_pLogInOut->m_pBuffer) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pLogInOut->pBuffer in User::FreeBuffer\n");
}
#else
free(m_pLogInOut->m_pBuffer);
#endif
m_pLogInOut->m_pBuffer = NULL;
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void User::Close(const bool bNoQuit/* = false*/) {
if(m_ui8State >= STATE_CLOSING) {
return;
}
// nick in hash table ?
if((m_ui32BoolBits & BIT_HASHED) == BIT_HASHED) {
HashManager::m_Ptr->Remove(this);
}
// nick in nick/op list ?
if(m_ui8State >= STATE_ADDME_2LOOP) {
Users::m_Ptr->DelFromNickList(m_sNick, (m_ui32BoolBits & BIT_OPERATOR) == BIT_OPERATOR);
Users::m_Ptr->DelFromUserIP(this);
// PPK ... fix for QuickList nad ghost...
// and fixing redirect all too ;)
// and fix disconnect on send error too =)
if(bNoQuit == false) {
int iMsgLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "$Quit %s|", m_sNick);
if(iMsgLen > 0) {
GlobalDataQueue::m_Ptr->AddQueueItem(ServerManager::m_pGlobalBuffer, iMsgLen, NULL, 0, GlobalDataQueue::CMD_QUIT);
}
Users::m_Ptr->Add2RecTimes(this);
}
#ifdef _BUILD_GUI
if(::SendMessage(MainWindowPageUsersChat::m_Ptr->m_hWndPageItems[MainWindowPageUsersChat::BTN_AUTO_UPDATE_USERLIST], BM_GETCHECK, 0, 0) == BST_CHECKED) {
MainWindowPageUsersChat::m_Ptr->RemoveUser(this);
}
#endif
//sqldb->FinalizeVisit(u);
#ifdef _WITH_SQLITE
DBSQLite::m_Ptr->UpdateRecord(this);
#elif _WITH_POSTGRES
DBPostgreSQL::m_Ptr->UpdateRecord(this);
#elif _WITH_MYSQL
DBMySQL::m_Ptr->UpdateRecord(this);
#endif
if(((m_ui32BoolBits & BIT_HAVE_SHARECOUNTED) == BIT_HAVE_SHARECOUNTED) == true) {
ServerManager::m_ui64TotalShare -= m_ui64SharedSize;
m_ui32BoolBits &= ~BIT_HAVE_SHARECOUNTED;
}
ScriptManager::m_Ptr->UserDisconnected(this);
}
if(m_ui8State > STATE_ADDME_2LOOP) {
ServerManager::m_ui32Logged--;
}
m_ui8State = STATE_CLOSING;
if(m_pCmdActive4Search != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdActive4Search);
m_pCmdActive4Search = NULL;
}
if(m_pCmdActive6Search != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdActive6Search);
m_pCmdActive6Search = NULL;
}
if(m_pCmdPassiveSearch != NULL) {
User::DeletePrcsdUsrCmd(m_pCmdPassiveSearch);
m_pCmdPassiveSearch = NULL;
}
PrcsdUsrCmd * cur = NULL,
* next = m_pCmdStrt;
while(next != NULL) {
cur = next;
next = cur->m_pNext;
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate cur->m_sCommand in User::Close\n");
}
#else
free(cur->m_sCommand);
#endif
cur->m_sCommand = NULL;
delete cur;
}
m_pCmdStrt = NULL;
m_pCmdEnd = NULL;
PrcsdToUsrCmd * curto = NULL,
* nextto = m_pCmdToUserStrt;
while(nextto != NULL) {
curto = nextto;
nextto = curto->m_pNext;
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curto->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate curto->m_sCommand in User::Close\n");
}
#else
free(curto->m_sCommand);
#endif
curto->m_sCommand = NULL;
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curto->m_sToNick) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate curto->m_sToNick in User::Close\n");
}
#else
free(curto->m_sToNick);
#endif
curto->m_sToNick = NULL;
delete curto;
}
m_pCmdToUserStrt = NULL;
m_pCmdToUserEnd = NULL;
if(m_sMyInfoLong) {
if(SettingManager::m_Ptr->m_ui8FullMyINFOOption != 2) {
Users::m_Ptr->DelFromMyInfosTag(this);
}
}
if(m_sMyInfoShort) {
if(SettingManager::m_Ptr->m_ui8FullMyINFOOption != 0) {
Users::m_Ptr->DelFromMyInfos(this);
}
}
if(m_ui32SendBufDataLen == 0 || (m_ui32BoolBits & BIT_ERROR) == BIT_ERROR) {
m_ui8State = STATE_REMME;
} else {
if(m_pLogInOut == NULL) {
m_pLogInOut = new (std::nothrow) LoginLogout();
if(m_pLogInOut == NULL) {
m_ui8State = STATE_REMME;
AppendDebugLog("%s - [MEM] Cannot allocate new pLogInOut in User::Close\n");
return;
}
}
m_pLogInOut->m_ui32ToCloseLoops = 100;
}
}
//---------------------------------------------------------------------------
void User::Add2Userlist() {
Users::m_Ptr->Add2NickList(this);
Users::m_Ptr->Add2UserIP(this);
switch(SettingManager::m_Ptr->m_ui8FullMyINFOOption) {
case 0: {
GenerateMyInfoLong();
Users::m_Ptr->Add2MyInfosTag(this);
return;
}
case 1: {
GenerateMyInfoLong();
Users::m_Ptr->Add2MyInfosTag(this);
GenerateMyInfoShort();
Users::m_Ptr->Add2MyInfos(this);
return;
}
case 2: {
GenerateMyInfoShort();
Users::m_Ptr->Add2MyInfos(this);
return;
}
default:
break;
}
}
//------------------------------------------------------------------------------
void User::AddUserList() {
m_ui32BoolBits |= BIT_BIG_SEND_BUFFER;
m_ui64LastNicklist = ServerManager::m_ui64ActualTick;
if(((m_ui32SupportBits & SUPPORTBIT_NOHELLO) == SUPPORTBIT_NOHELLO) == false) {
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::ALLOWEDOPCHAT) == false || (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] == false ||
(SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] == true && SettingManager::m_Ptr->m_bBotsSameNick == true))) {
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pNickList, Users::m_Ptr->m_ui32NickListLen);
} else {
if(Users::m_Ptr->m_ui32ZNickListLen == 0) {
Users::m_Ptr->m_pZNickList = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pNickList, Users::m_Ptr->m_ui32NickListLen, Users::m_Ptr->m_pZNickList,
Users::m_Ptr->m_ui32ZNickListLen, Users::m_Ptr->m_ui32ZNickListSize, Allign16K);
if(Users::m_Ptr->m_ui32ZNickListLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pNickList, Users::m_Ptr->m_ui32NickListLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZNickList, Users::m_Ptr->m_ui32ZNickListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32NickListLen-Users::m_Ptr->m_ui32ZNickListLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZNickList, Users::m_Ptr->m_ui32ZNickListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32NickListLen-Users::m_Ptr->m_ui32ZNickListLen;
}
}
} else {
// PPK ... OpChat bot is now visible only for OPs ;)
int iLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "%s$$|", SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_NICK]);
if(iLen > 0) {
if(Users::m_Ptr->m_ui32NickListSize < Users::m_Ptr->m_ui32NickListLen+iLen) {
char * pOldBuf = Users::m_Ptr->m_pNickList;
#ifdef _WIN32
Users::m_Ptr->m_pNickList = (char *)HeapReAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, Users::m_Ptr->m_ui32NickListSize+NICKLISTSIZE+1);
#else
Users::m_Ptr->m_pNickList = (char *)realloc(pOldBuf, Users::m_Ptr->m_ui32NickListSize+NICKLISTSIZE+1);
#endif
if(Users::m_Ptr->m_pNickList == NULL) {
Users::m_Ptr->m_pNickList = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot reallocate %u bytes for m_pNickList in User::AddUserList\n", Users::m_Ptr->m_ui32NickListSize+NICKLISTSIZE+1);
return;
}
Users::m_Ptr->m_ui32NickListSize += NICKLISTSIZE;
}
memcpy(Users::m_Ptr->m_pNickList+Users::m_Ptr->m_ui32NickListLen-1, ServerManager::m_pGlobalBuffer, iLen);
Users::m_Ptr->m_pNickList[Users::m_Ptr->m_ui32NickListLen+(iLen-1)] = '\0';
SendCharDelayed(Users::m_Ptr->m_pNickList, Users::m_Ptr->m_ui32NickListLen+(iLen-1));
Users::m_Ptr->m_pNickList[Users::m_Ptr->m_ui32NickListLen-1] = '|';
Users::m_Ptr->m_pNickList[Users::m_Ptr->m_ui32NickListLen] = '\0';
}
}
}
switch(SettingManager::m_Ptr->m_ui8FullMyINFOOption) {
case 0: {
if(Users::m_Ptr->m_ui32MyInfosTagLen == 0) {
break;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen);
} else {
if(Users::m_Ptr->m_ui32ZMyInfosTagLen == 0) {
Users::m_Ptr->m_pZMyInfosTag = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen, Users::m_Ptr->m_pZMyInfosTag,
Users::m_Ptr->m_ui32ZMyInfosTagLen, Users::m_Ptr->m_ui32ZMyInfosTagSize, Allign128K);
if(Users::m_Ptr->m_ui32ZMyInfosTagLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfosTag, Users::m_Ptr->m_ui32ZMyInfosTagLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosTagLen-Users::m_Ptr->m_ui32ZMyInfosTagLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfosTag, Users::m_Ptr->m_ui32ZMyInfosTagLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosTagLen-Users::m_Ptr->m_ui32ZMyInfosTagLen;
}
}
break;
}
case 1: {
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::SENDFULLMYINFOS) == false) {
if(Users::m_Ptr->m_ui32MyInfosLen == 0) {
break;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen);
} else {
if(Users::m_Ptr->m_ui32ZMyInfosLen == 0) {
Users::m_Ptr->m_pZMyInfos = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen, Users::m_Ptr->m_pZMyInfos,
Users::m_Ptr->m_ui32ZMyInfosLen, Users::m_Ptr->m_ui32ZMyInfosSize, Allign128K);
if(Users::m_Ptr->m_ui32ZMyInfosLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfos, Users::m_Ptr->m_ui32ZMyInfosLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosLen-Users::m_Ptr->m_ui32ZMyInfosLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfos, Users::m_Ptr->m_ui32ZMyInfosLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosLen-Users::m_Ptr->m_ui32ZMyInfosLen;
}
}
} else {
if(Users::m_Ptr->m_ui32MyInfosTagLen == 0) {
break;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen);
} else {
if(Users::m_Ptr->m_ui32ZMyInfosTagLen == 0) {
Users::m_Ptr->m_pZMyInfosTag = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen, Users::m_Ptr->m_pZMyInfosTag,
Users::m_Ptr->m_ui32ZMyInfosTagLen, Users::m_Ptr->m_ui32ZMyInfosTagSize, Allign128K);
if(Users::m_Ptr->m_ui32ZMyInfosTagLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pMyInfosTag, Users::m_Ptr->m_ui32MyInfosTagLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfosTag, Users::m_Ptr->m_ui32ZMyInfosTagLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosTagLen-Users::m_Ptr->m_ui32ZMyInfosTagLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfosTag, Users::m_Ptr->m_ui32ZMyInfosTagLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosTagLen-Users::m_Ptr->m_ui32ZMyInfosTagLen;
}
}
}
break;
}
case 2: {
if(Users::m_Ptr->m_ui32MyInfosLen == 0) {
break;
}
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen);
} else {
if(Users::m_Ptr->m_ui32ZMyInfosLen == 0) {
Users::m_Ptr->m_pZMyInfos = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen, Users::m_Ptr->m_pZMyInfos,
Users::m_Ptr->m_ui32ZMyInfosLen, Users::m_Ptr->m_ui32ZMyInfosSize, Allign128K);
if(Users::m_Ptr->m_ui32ZMyInfosLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pMyInfos, Users::m_Ptr->m_ui32MyInfosLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfos, Users::m_Ptr->m_ui32ZMyInfosLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosLen-Users::m_Ptr->m_ui32ZMyInfosLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZMyInfos, Users::m_Ptr->m_ui32ZMyInfosLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32MyInfosLen-Users::m_Ptr->m_ui32ZMyInfosLen;
}
}
}
default:
break;
}
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::ALLOWEDOPCHAT) == false || (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] == false ||
(SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] == true && SettingManager::m_Ptr->m_bBotsSameNick == true))) {
if(Users::m_Ptr->m_ui32OpListLen > 9) {
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pOpList, Users::m_Ptr->m_ui32OpListLen);
} else {
if(Users::m_Ptr->m_ui32ZOpListLen == 0) {
Users::m_Ptr->m_pZOpList = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pOpList, Users::m_Ptr->m_ui32OpListLen, Users::m_Ptr->m_pZOpList,
Users::m_Ptr->m_ui32ZOpListLen, Users::m_Ptr->m_ui32ZOpListSize, Allign16K);
if(Users::m_Ptr->m_ui32ZOpListLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pOpList, Users::m_Ptr->m_ui32OpListLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZOpList, Users::m_Ptr->m_ui32ZOpListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32OpListLen-Users::m_Ptr->m_ui32ZOpListLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZOpList, Users::m_Ptr->m_ui32ZOpListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32OpListLen-Users::m_Ptr->m_ui32ZOpListLen;
}
}
}
} else {
// PPK ... OpChat bot is now visible only for OPs ;)
SendCharDelayed(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_OP_CHAT_MYINFO],
SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_OP_CHAT_MYINFO]);
int iLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "%s$$|", SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_NICK]);
if(iLen > 0) {
if(Users::m_Ptr->m_ui32OpListSize < Users::m_Ptr->m_ui32OpListLen+iLen) {
char * pOldBuf = Users::m_Ptr->m_pOpList;
#ifdef _WIN32
Users::m_Ptr->m_pOpList = (char *)HeapReAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, Users::m_Ptr->m_ui32OpListSize+OPLISTSIZE+1);
#else
Users::m_Ptr->m_pOpList = (char *)realloc(pOldBuf, Users::m_Ptr->m_ui32OpListSize+OPLISTSIZE+1);
#endif
if(Users::m_Ptr->m_pOpList == NULL) {
Users::m_Ptr->m_pOpList = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot reallocate %u bytes for m_pOpList in User::AddUserList\n", Users::m_Ptr->m_ui32OpListSize+OPLISTSIZE+1);
return;
}
Users::m_Ptr->m_ui32OpListSize += OPLISTSIZE;
}
memcpy(Users::m_Ptr->m_pOpList+Users::m_Ptr->m_ui32OpListLen-1, ServerManager::m_pGlobalBuffer, iLen);
Users::m_Ptr->m_pOpList[Users::m_Ptr->m_ui32OpListLen+(iLen-1)] = '\0';
SendCharDelayed(Users::m_Ptr->m_pOpList, Users::m_Ptr->m_ui32OpListLen+(iLen-1));
Users::m_Ptr->m_pOpList[Users::m_Ptr->m_ui32OpListLen-1] = '|';
Users::m_Ptr->m_pOpList[Users::m_Ptr->m_ui32OpListLen] = '\0';
}
}
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::SENDALLUSERIP) == true && ((m_ui32SupportBits & SUPPORTBIT_USERIP2) == SUPPORTBIT_USERIP2) == true) {
if(Users::m_Ptr->m_ui32UserIPListLen > 9) {
if(((m_ui32SupportBits & SUPPORTBIT_ZPIPE) == SUPPORTBIT_ZPIPE) == false) {
SendCharDelayed(Users::m_Ptr->m_pUserIPList, Users::m_Ptr->m_ui32UserIPListLen);
} else {
if(Users::m_Ptr->m_ui32ZUserIPListLen == 0) {
Users::m_Ptr->m_pZUserIPList = ZlibUtility::m_Ptr->CreateZPipe(Users::m_Ptr->m_pUserIPList, Users::m_Ptr->m_ui32UserIPListLen, Users::m_Ptr->m_pZUserIPList,
Users::m_Ptr->m_ui32ZUserIPListLen, Users::m_Ptr->m_ui32ZUserIPListSize, Allign16K);
if(Users::m_Ptr->m_ui32ZUserIPListLen == 0) {
SendCharDelayed(Users::m_Ptr->m_pUserIPList, Users::m_Ptr->m_ui32UserIPListLen);
} else {
PutInSendBuf(Users::m_Ptr->m_pZUserIPList, Users::m_Ptr->m_ui32ZUserIPListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32UserIPListLen-Users::m_Ptr->m_ui32ZUserIPListLen;
}
} else {
PutInSendBuf(Users::m_Ptr->m_pZUserIPList, Users::m_Ptr->m_ui32ZUserIPListLen);
ServerManager::m_ui64BytesSentSaved += Users::m_Ptr->m_ui32UserIPListLen-Users::m_Ptr->m_ui32ZUserIPListLen;
}
}
}
}
}
//---------------------------------------------------------------------------
bool User::GenerateMyInfoLong() { // true == changed
// Prepare myinfo with nick
int iLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "$MyINFO $ALL %s ", m_sNick);
if(iLen <= 0) {
return false;
}
// Add description
if(m_ui8ChangedDescriptionLongLen != 0) {
if(m_sChangedDescriptionLong != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedDescriptionLong, m_ui8ChangedDescriptionLongLen);
iLen += m_ui8ChangedDescriptionLongLen;
}
if(((m_ui32InfoBits & INFOBIT_DESCRIPTION_LONG_PERM) == INFOBIT_DESCRIPTION_LONG_PERM) == false) {
if(m_sChangedDescriptionLong != NULL) {
User::FreeInfo(m_sChangedDescriptionLong, "sChangedDescriptionLong");
m_sChangedDescriptionLong = NULL;
}
m_ui8ChangedDescriptionLongLen = 0;
}
} else if(m_sDescription != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sDescription, (size_t)m_ui8DescriptionLen);
iLen += m_ui8DescriptionLen;
}
// Add tag
if(m_ui8ChangedTagLongLen != 0) {
if(m_sChangedTagLong != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedTagLong, m_ui8ChangedTagLongLen);
iLen += m_ui8ChangedTagLongLen;
}
if(((m_ui32InfoBits & INFOBIT_TAG_LONG_PERM) == INFOBIT_TAG_LONG_PERM) == false) {
if(m_sChangedTagLong != NULL) {
User::FreeInfo(m_sChangedTagLong, "sChangedTagLong");
m_sChangedTagLong = NULL;
}
m_ui8ChangedTagLongLen = 0;
}
} else if(m_sTag != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sTag, (size_t)m_ui8TagLen);
iLen += (int)m_ui8TagLen;
}
memcpy(ServerManager::m_pGlobalBuffer+iLen, "$ $", 3);
iLen += 3;
// Add connection
if(m_ui8ChangedConnectionLongLen != 0) {
if(m_sChangedConnectionLong != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedConnectionLong, m_ui8ChangedConnectionLongLen);
iLen += m_ui8ChangedConnectionLongLen;
}
if(((m_ui32InfoBits & INFOBIT_CONNECTION_LONG_PERM) == INFOBIT_CONNECTION_LONG_PERM) == false) {
if(m_sChangedConnectionLong != NULL) {
User::FreeInfo(m_sChangedConnectionLong, "sChangedConnectionLong");
m_sChangedConnectionLong = NULL;
}
m_ui8ChangedConnectionLongLen = 0;
}
} else if(m_sConnection != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sConnection, m_ui8ConnectionLen);
iLen += m_ui8ConnectionLen;
}
// add magicbyte
uint8_t ui8Magic = m_ui8MagicByte;
if(((m_ui32BoolBits & User::SUPPORTBIT_TLS2) == User::SUPPORTBIT_TLS2) == false) {
// should not be set if user not have TLS2 support
ui8Magic &= ~0x10;
ui8Magic &= ~0x20;
}
if((m_ui32BoolBits & BIT_IPV4) == BIT_IPV4) {
ui8Magic |= 0x40; // IPv4 support
} else {
ui8Magic &= ~0x40; // IPv4 support
}
if((m_ui32BoolBits & BIT_IPV6) == BIT_IPV6) {
ui8Magic |= 0x80; // IPv6 support
} else {
ui8Magic &= ~0x80; // IPv6 support
}
ServerManager::m_pGlobalBuffer[iLen] = ui8Magic;
ServerManager::m_pGlobalBuffer[iLen+1] = '$';
iLen += 2;
// Add email
if(m_ui8ChangedEmailLongLen != 0) {
if(m_sChangedEmailLong != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedEmailLong, m_ui8ChangedEmailLongLen);
iLen += m_ui8ChangedEmailLongLen;
}
if(((m_ui32InfoBits & INFOBIT_EMAIL_LONG_PERM) == INFOBIT_EMAIL_LONG_PERM) == false) {
if(m_sChangedEmailLong != NULL) {
User::FreeInfo(m_sChangedEmailLong, "sChangedEmailLong");
m_sChangedEmailLong = NULL;
}
m_ui8ChangedEmailLongLen = 0;
}
} else if(m_sEmail != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sEmail, (size_t)m_ui8EmailLen);
iLen += (int)m_ui8EmailLen;
}
// Add share and end of myinfo
int iRet = snprintf(ServerManager::m_pGlobalBuffer+iLen, ServerManager::m_szGlobalBufferSize-iLen, "$%" PRIu64 "$|", m_ui64ChangedSharedSizeLong);
if(((m_ui32InfoBits & INFOBIT_SHARE_LONG_PERM) == INFOBIT_SHARE_LONG_PERM) == false) {
m_ui64ChangedSharedSizeLong = m_ui64SharedSize;
}
if(iRet <= 0) {
return false;
}
iLen += iRet;
if(m_sMyInfoLong != NULL) {
if(m_ui16MyInfoLongLen == (uint16_t)iLen && memcmp(m_sMyInfoLong+14+m_ui8NickLen, ServerManager::m_pGlobalBuffer+14+m_ui8NickLen, m_ui16MyInfoLongLen-14-m_ui8NickLen) == 0) {
return false;
}
}
UserSetMyInfoLong(this, ServerManager::m_pGlobalBuffer, (uint16_t)iLen);
return true;
}
//---------------------------------------------------------------------------
bool User::GenerateMyInfoShort() { // true == changed
// Prepare myinfo with nick
int iLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "$MyINFO $ALL %s ", m_sNick);
if(iLen <= 0) {
return false;
}
// Add mode to start of description if is enabled
if(SettingManager::m_Ptr->m_bBools[SETBOOL_MODE_TO_DESCRIPTION] == true && m_sModes[0] != 0) {
char * sActualDescription = NULL;
if(m_ui8ChangedDescriptionShortLen != 0) {
sActualDescription = m_sChangedDescriptionShort;
} else if(SettingManager::m_Ptr->m_bBools[SETBOOL_STRIP_DESCRIPTION] == true) {
sActualDescription = m_sDescription;
}
if(sActualDescription == NULL) {
ServerManager::m_pGlobalBuffer[iLen] = m_sModes[0];
iLen++;
} else if(sActualDescription[0] != m_sModes[0] && sActualDescription[1] != ' ') {
ServerManager::m_pGlobalBuffer[iLen] = m_sModes[0];
ServerManager::m_pGlobalBuffer[iLen+1] = ' ';
iLen += 2;
}
}
// Add description
if(m_ui8ChangedDescriptionShortLen != 0) {
if(m_sChangedDescriptionShort != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedDescriptionShort, m_ui8ChangedDescriptionShortLen);
iLen += m_ui8ChangedDescriptionShortLen;
}
if(((m_ui32InfoBits & INFOBIT_DESCRIPTION_SHORT_PERM) == INFOBIT_DESCRIPTION_SHORT_PERM) == false) {
if(m_sChangedDescriptionShort != NULL) {
User::FreeInfo(m_sChangedDescriptionShort, "sChangedDescriptionShort");
m_sChangedDescriptionShort = NULL;
}
m_ui8ChangedDescriptionShortLen = 0;
}
} else if(SettingManager::m_Ptr->m_bBools[SETBOOL_STRIP_DESCRIPTION] == false && m_sDescription != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sDescription, m_ui8DescriptionLen);
iLen += m_ui8DescriptionLen;
}
// Add tag
if(m_ui8ChangedTagShortLen != 0) {
if(m_sChangedTagShort != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedTagShort, m_ui8ChangedTagShortLen);
iLen += m_ui8ChangedTagShortLen;
}
if(((m_ui32InfoBits & INFOBIT_TAG_SHORT_PERM) == INFOBIT_TAG_SHORT_PERM) == false) {
if(m_sChangedTagShort != NULL) {
User::FreeInfo(m_sChangedTagShort, "sChangedTagShort");
m_sChangedTagShort = NULL;
}
m_ui8ChangedTagShortLen = 0;
}
} else if(SettingManager::m_Ptr->m_bBools[SETBOOL_STRIP_TAG] == false && m_sTag != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sTag, (size_t)m_ui8TagLen);
iLen += (int)m_ui8TagLen;
}
// Add mode to myinfo if is enabled
if(SettingManager::m_Ptr->m_bBools[SETBOOL_MODE_TO_MYINFO] == true && m_sModes[0] != 0) {
int iRet = snprintf(ServerManager::m_pGlobalBuffer+iLen, ServerManager::m_szGlobalBufferSize-iLen, "$%c$", m_sModes[0]);
if(iRet <= 0) {
return false;
}
iLen += iRet;
} else {
memcpy(ServerManager::m_pGlobalBuffer+iLen, "$ $", 3);
iLen += 3;
}
// Add connection
if(m_ui8ChangedConnectionShortLen != 0) {
if(m_sChangedConnectionShort != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedConnectionShort, m_ui8ChangedConnectionShortLen);
iLen += m_ui8ChangedConnectionShortLen;
}
if(((m_ui32InfoBits & INFOBIT_CONNECTION_SHORT_PERM) == INFOBIT_CONNECTION_SHORT_PERM) == false) {
if(m_sChangedConnectionShort != NULL) {
User::FreeInfo(m_sChangedConnectionShort, "sChangedConnectionShort");
m_sChangedConnectionShort = NULL;
}
m_ui8ChangedConnectionShortLen = 0;
}
} else if(SettingManager::m_Ptr->m_bBools[SETBOOL_STRIP_CONNECTION] == false && m_sConnection != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sConnection, m_ui8ConnectionLen);
iLen += m_ui8ConnectionLen;
}
// add magicbyte
uint8_t ui8Magic = m_ui8MagicByte;
if(((m_ui32BoolBits & User::SUPPORTBIT_TLS2) == User::SUPPORTBIT_TLS2) == false) {
// should not be set if user not have TLS2 support
ui8Magic &= ~0x10;
ui8Magic &= ~0x20;
}
if((m_ui32BoolBits & BIT_IPV4) == BIT_IPV4) {
ui8Magic |= 0x40; // IPv4 support
} else {
ui8Magic &= ~0x40; // IPv4 support
}
if((m_ui32BoolBits & BIT_IPV6) == BIT_IPV6) {
ui8Magic |= 0x80; // IPv6 support
} else {
ui8Magic &= ~0x80; // IPv6 support
}
ServerManager::m_pGlobalBuffer[iLen] = ui8Magic;
ServerManager::m_pGlobalBuffer[iLen+1] = '$';
iLen += 2;
// Add email
if(m_ui8ChangedEmailShortLen != 0) {
if(m_sChangedEmailShort != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sChangedEmailShort, m_ui8ChangedEmailShortLen);
iLen += m_ui8ChangedEmailShortLen;
}
if(((m_ui32InfoBits & INFOBIT_EMAIL_SHORT_PERM) == INFOBIT_EMAIL_SHORT_PERM) == false) {
if(m_sChangedEmailShort != NULL) {
User::FreeInfo(m_sChangedEmailShort, "sChangedEmailShort");
m_sChangedEmailShort = NULL;
}
m_ui8ChangedEmailShortLen = 0;
}
} else if(SettingManager::m_Ptr->m_bBools[SETBOOL_STRIP_EMAIL] == false && m_sEmail != NULL) {
memcpy(ServerManager::m_pGlobalBuffer+iLen, m_sEmail, (size_t)m_ui8EmailLen);
iLen += (int)m_ui8EmailLen;
}
// Add share and end of myinfo
int iRet = snprintf(ServerManager::m_pGlobalBuffer+iLen, ServerManager::m_szGlobalBufferSize-iLen, "$%" PRIu64 "$|", m_ui64ChangedSharedSizeShort);
if(((m_ui32InfoBits & INFOBIT_SHARE_SHORT_PERM) == INFOBIT_SHARE_SHORT_PERM) == false) {
m_ui64ChangedSharedSizeShort = m_ui64SharedSize;
}
if(iRet <= 0) {
return false;
}
iLen += iRet;
if(m_sMyInfoShort != NULL) {
if(m_ui16MyInfoShortLen == (uint16_t)iLen && memcmp(m_sMyInfoShort+14+m_ui8NickLen, ServerManager::m_pGlobalBuffer+14+m_ui8NickLen, m_ui16MyInfoShortLen-14-m_ui8NickLen) == 0) {
return false;
}
}
UserSetMyInfoShort(this, ServerManager::m_pGlobalBuffer, (uint16_t)iLen);
return true;
}
//---------------------------------------------------------------------------
#ifdef _WIN32
void User::FreeInfo(char * sInfo, const char * sName) {
if(sInfo != NULL) {
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)sInfo) == 0) {
AppendDebugLogFormat("[MEM] Cannot deallocate %s in User::FreeInfo\n", sName);
}
}
#else
void User::FreeInfo(char * sInfo, const char */* sName*/) {
free(sInfo);
#endif
}
//------------------------------------------------------------------------------
void User::HasSuspiciousTag() {
if(SettingManager::m_Ptr->m_bBools[SETBOOL_REPORT_SUSPICIOUS_TAG] == true && SettingManager::m_Ptr->m_bBools[SETBOOL_SEND_STATUS_MESSAGES] == true) {
m_sDescription[m_ui8DescriptionLen] = '\0';
GlobalDataQueue::m_Ptr->StatusMessageFormat("User::HasSuspiciousTag", "<%s> *** %s (%s) %s. %s: %s|", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC], m_sNick, m_sIP, LanguageManager::m_Ptr->m_sTexts[LAN_HAS_SUSPICIOUS_TAG_CHECK_HIM],
LanguageManager::m_Ptr->m_sTexts[LAN_FULL_DESCRIPTION], m_sDescription);
m_sDescription[m_ui8DescriptionLen] = '$';
}
m_ui32BoolBits &= ~BIT_HAVE_BADTAG;
}
//---------------------------------------------------------------------------
bool User::ProcessRules() {
// if share limit enabled, check it
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NOSHARELIMIT) == false) {
if((SettingManager::m_Ptr->m_ui64MinShare != 0 && m_ui64SharedSize < SettingManager::m_Ptr->m_ui64MinShare) ||
(SettingManager::m_Ptr->m_ui64MaxShare != 0 && m_ui64SharedSize > SettingManager::m_Ptr->m_ui64MaxShare)) {
SendChar(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_SHARE_LIMIT_MSG], SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_SHARE_LIMIT_MSG]);
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User with low or high share %s (%s) disconnected.", sNick, sIP);
return false;
}
}
// no Tag? Apply rule
if(m_sTag == NULL) {
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NOTAGCHECK) == false) {
if(SettingManager::m_Ptr->m_i16Shorts[SETSHORT_NO_TAG_OPTION] != 0) {
SendChar(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_NO_TAG_MSG], SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_NO_TAG_MSG]);
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User without Tag %s (%s) redirected.", sNick, sIP);
return false;
}
}
} else {
// min and max slot check
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NOSLOTCHECK) == false) {
// TODO 2 -oPTA -ccheckers: $SR based slots fetching for no_tag users
if((SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MIN_SLOTS_LIMIT] != 0 && m_ui32Slots < (uint32_t)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MIN_SLOTS_LIMIT]) ||
(SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_SLOTS_LIMIT] != 0 && m_ui32Slots > (uint32_t)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_SLOTS_LIMIT])) {
SendChar(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_SLOTS_LIMIT_MSG], SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_SLOTS_LIMIT_MSG]);
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User with bad slots %s (%s) disconnected.", sNick, sIP);
return false;
}
}
// slots/hub ration check
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NOSLOTHUBRATIO) == false &&
SettingManager::m_Ptr->m_i16Shorts[SETSHORT_HUB_SLOT_RATIO_HUBS] != 0 && SettingManager::m_Ptr->m_i16Shorts[SETSHORT_HUB_SLOT_RATIO_SLOTS] != 0) {
uint32_t slots = m_ui32Slots;
uint32_t hubs = m_ui32Hubs > 0 ? m_ui32Hubs : 1;
if(((double)slots / hubs) < ((double)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_HUB_SLOT_RATIO_SLOTS] / SettingManager::m_Ptr->m_i16Shorts[SETSHORT_HUB_SLOT_RATIO_HUBS])) {
SendChar(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SLOT_RATIO_MSG], SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_HUB_SLOT_RATIO_MSG]);
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User with bad hub/slot ratio %s (%s) disconnected.", sNick, sIP);
return false;
}
}
// hub checker
if(ProfileManager::m_Ptr->IsAllowed(this, ProfileManager::NOMAXHUBCHECK) == false && SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_HUBS_LIMIT] != 0) {
if(m_ui32Hubs > (uint32_t)SettingManager::m_Ptr->m_i16Shorts[SETSHORT_MAX_HUBS_LIMIT]) {
SendChar(SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_MAX_HUBS_LIMIT_MSG], SettingManager::m_Ptr->m_ui16PreTextsLens[SettingManager::SETPRETXT_MAX_HUBS_LIMIT_MSG]);
//UdpDebug::m_Ptr->BroadcastFormat("[SYS] User with bad hubs count %s (%s) disconnected.", sNick, sIP);
return false;
}
}
}
return true;
}
//------------------------------------------------------------------------------
void User::AddPrcsdCmd(const uint8_t ui8Type, char * sCommand, const size_t szCommandLen, User * pToUser, const bool bIsPm/* = false*/) {
if(ui8Type == PrcsdUsrCmd::CTM_MCTM_RCTM_SR_TO) {
PrcsdToUsrCmd * cur = NULL,
* next = m_pCmdToUserStrt;
while(next != NULL) {
cur = next;
next = cur->m_pNext;
if(cur->m_pToUser == pToUser) {
char * pOldBuf = cur->m_sCommand;
#ifdef _WIN32
cur->m_sCommand = (char *)HeapReAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pOldBuf, cur->m_ui32Len+szCommandLen+1);
#else
cur->m_sCommand = (char *)realloc(pOldBuf, cur->m_ui32Len+szCommandLen+1);
#endif
if(cur->m_sCommand == NULL) {
cur->m_sCommand = pOldBuf;
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in User::AddPrcsdCmd\n", cur->m_ui32Len+szCommandLen+1);
return;
}
memcpy(cur->m_sCommand+cur->m_ui32Len, sCommand, szCommandLen);
cur->m_sCommand[cur->m_ui32Len+szCommandLen] = '\0';
cur->m_ui32Len += (uint32_t)szCommandLen;
cur->m_ui32PmCount += bIsPm == true ? 1 : 0;
return;
}
}
PrcsdToUsrCmd * pNewToCmd = new (std::nothrow) PrcsdToUsrCmd();
if(pNewToCmd == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLog("%s - [MEM] User::AddPrcsdCmd cannot allocate new pNewToCmd\n");
return;
}
#ifdef _WIN32
pNewToCmd->m_sCommand = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szCommandLen+1);
#else
pNewToCmd->m_sCommand = (char *)malloc(szCommandLen+1);
#endif
if(pNewToCmd->m_sCommand == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for sCommand in User::AddPrcsdCmd\n", szCommandLen+1);
delete pNewToCmd;
return;
}
memcpy(pNewToCmd->m_sCommand, sCommand, szCommandLen);
pNewToCmd->m_sCommand[szCommandLen] = '\0';
pNewToCmd->m_ui32Len = (uint32_t)szCommandLen;
pNewToCmd->m_ui32PmCount = bIsPm == true ? 1 : 0;
pNewToCmd->m_ui32Loops = 0;
pNewToCmd->m_pToUser = pToUser;
#ifdef _WIN32
pNewToCmd->m_sToNick = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, pToUser->m_ui8NickLen+1);
#else
pNewToCmd->m_sToNick = (char *)malloc(pToUser->m_ui8NickLen+1);
#endif
if(pNewToCmd->m_sToNick == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %" PRIu8 " bytes for ToNick in User::AddPrcsdCmd\n", pToUser->m_ui8NickLen+1);
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pNewToCmd->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pNewToCmd->sCommand in User::AddPrcsdCmd\n");
}
#else
free(pNewToCmd->m_sCommand);
#endif
delete pNewToCmd;
return;
}
memcpy(pNewToCmd->m_sToNick, pToUser->m_sNick, pToUser->m_ui8NickLen);
pNewToCmd->m_sToNick[pToUser->m_ui8NickLen] = '\0';
pNewToCmd->m_ui32ToNickLen = pToUser->m_ui8NickLen;
pNewToCmd->m_pNext = NULL;
if(m_pCmdToUserStrt == NULL) {
m_pCmdToUserStrt = pNewToCmd;
m_pCmdToUserEnd = pNewToCmd;
} else {
m_pCmdToUserEnd->m_pNext = pNewToCmd;
m_pCmdToUserEnd = pNewToCmd;
}
return;
}
PrcsdUsrCmd * pNewcmd = new (std::nothrow) PrcsdUsrCmd();
if(pNewcmd == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLog("%s - [MEM] User::AddPrcsdCmd cannot allocate new pNewcmd1\n");
return;
}
#ifdef _WIN32
pNewcmd->m_sCommand = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szCommandLen+1);
#else
pNewcmd->m_sCommand = (char *)malloc(szCommandLen+1);
#endif
if(pNewcmd->m_sCommand == NULL) {
m_ui32BoolBits |= BIT_ERROR;
Close();
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for sCommand in User::AddPrcsdCmd1\n", szCommandLen+1);
delete pNewcmd;
return;
}
memcpy(pNewcmd->m_sCommand, sCommand, szCommandLen);
pNewcmd->m_sCommand[szCommandLen] = '\0';
pNewcmd->m_ui32Len = (uint32_t)szCommandLen;
pNewcmd->m_ui8Type = ui8Type;
pNewcmd->m_pNext = NULL;
pNewcmd->m_pPtr = (void *)pToUser;
if(m_pCmdStrt == NULL) {
m_pCmdStrt = pNewcmd;
m_pCmdEnd = pNewcmd;
} else {
m_pCmdEnd->m_pNext = pNewcmd;
m_pCmdEnd = pNewcmd;
}
}
//---------------------------------------------------------------------------
void User::AddMeOrIPv4Check() {
if(((m_ui32BoolBits & BIT_IPV6) == BIT_IPV6) && ((m_ui32SupportBits & SUPPORTBIT_IPV4) == SUPPORTBIT_IPV4) && ServerManager::m_sHubIP[0] != '\0' && ServerManager::m_bUseIPv4 == true) {
m_ui8State = STATE_IPV4_CHECK;
m_pLogInOut->m_ui64IPv4CheckTick = ServerManager::m_ui64ActualTick;
SendFormat("AddMeOrIPv4Check", true, "$ConnectToMe %s %s:%hu|", m_sNick, ServerManager::m_sHubIP, SettingManager::m_Ptr->m_ui16PortNumbers[0]);
} else {
m_ui8State = STATE_ADDME;
}
}
//---------------------------------------------------------------------------
char * User::SetUserInfo(char * sOldData, uint8_t &ui8OldDataLen, char * sNewData, const size_t szNewDataLen, const char * sDataName) {
if(sOldData != NULL) {
User::FreeInfo(sOldData, sDataName);
sOldData = NULL;
ui8OldDataLen = 0;
}
if(szNewDataLen > 0) {
#ifdef _WIN32
sOldData = (char *)HeapAlloc(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, szNewDataLen+1);
#else
sOldData = (char *)malloc(szNewDataLen+1);
#endif
if(sOldData == NULL) {
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes in User::SetUserInfo\n", szNewDataLen+1);
return sOldData;
}
memcpy(sOldData, sNewData, szNewDataLen);
sOldData[szNewDataLen] = '\0';
ui8OldDataLen = (uint8_t)szNewDataLen;
} else {
ui8OldDataLen = 1;
}
return sOldData;
}
//---------------------------------------------------------------------------
void User::RemFromSendBuf(const char * sData, const uint32_t ui32Len, const uint32_t ui32SendBufLen) {
char *match = strstr(m_pSendBuf+ui32SendBufLen, sData);
if(match != NULL) {
memmove(match, match+ui32Len, m_ui32SendBufDataLen-((match+(ui32Len))-m_pSendBuf));
m_ui32SendBufDataLen -= ui32Len;
m_pSendBuf[m_ui32SendBufDataLen] = '\0';
}
}
//------------------------------------------------------------------------------
void User::DeletePrcsdUsrCmd(PrcsdUsrCmd * pCommand) {
#ifdef _WIN32
if(HeapFree(ServerManager::m_hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)pCommand->m_sCommand) == 0) {
AppendDebugLog("%s - [MEM] Cannot deallocate pCommand->m_sCommand in User::DeletePrcsdUsrCmd\n");
}
#else
free(pCommand->m_sCommand);
#endif
delete pCommand;
}
↑ V220 Suspicious sequence of types castings: memsize -> 32-bit integer -> memsize. The value being cast: 'szTxtLen'.
↑ V127 An overflow of the 32-bit 'reqVals' variable is possible inside a long cycle which utilizes a memsize-type loop counter.
↑ V127 An overflow of the 32-bit 'reqVals' variable is possible inside a long cycle which utilizes a memsize-type loop counter.
↑ V127 An overflow of the 32-bit 'reqVals' variable is possible inside a long cycle which utilizes a memsize-type loop counter.
↑ V127 An overflow of the 32-bit 'reqVals' variable is possible inside a long cycle which utilizes a memsize-type loop counter.
↑ V127 An overflow of the 32-bit 'reqVals' variable is possible inside a long cycle which utilizes a memsize-type loop counter.
↑ V525 The code contains the collection of similar blocks. Check items 'm_ui32OLimit', 'm_ui32LLimit', 'm_ui32LLimit', 'm_ui32DLimit' in lines 430, 437, 444, 451.
↑ V575 The potential null pointer is passed into 'atoi' function. Inspect the first argument.
↑ V575 The potential null pointer is passed into 'HeapReAlloc' function. Inspect the third argument.
↑ V769 The 'm_pSendBuf' pointer in the 'm_pSendBuf + m_ui32SendBufDataLen' expression could be nullptr. In such case, resulting value will be senseless and it should not be used.