From 57f64f1f5a8eccff388211e0d08bf9d630d48ada Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:18:57 +0200 Subject: * Restructuring shared. --HG-- branch : trunk --- src/server/shared/Auth/AuthCrypt.cpp | 81 -- src/server/shared/Auth/AuthCrypt.h | 47 - src/server/shared/Auth/BigNumber.cpp | 201 ---- src/server/shared/Auth/BigNumber.h | 96 -- src/server/shared/Auth/CMakeLists.txt | 27 - src/server/shared/Auth/Hmac.cpp | 62 -- src/server/shared/Auth/Hmac.h | 49 - src/server/shared/Auth/SARC4.cpp | 52 - src/server/shared/Auth/SARC4.h | 36 - src/server/shared/Auth/Sha1.cpp | 69 -- src/server/shared/Auth/Sha1.h | 53 - src/server/shared/Auth/md5.c | 385 -------- src/server/shared/Auth/md5.h | 92 -- src/server/shared/ByteBuffer.h | 601 ------------ src/server/shared/Config/CMakeLists.txt | 22 - src/server/shared/Config/Config.cpp | 105 -- src/server/shared/Config/Config.h | 53 - src/server/shared/Config/ConfigEnv.h | 30 - src/server/shared/Config/ConfigLibrary.vcproj | 137 --- src/server/shared/Config/dotconfpp/dotconfpp.cpp | 599 ------------ src/server/shared/Config/dotconfpp/dotconfpp.h | 97 -- src/server/shared/Config/dotconfpp/mempool.cpp | 100 -- src/server/shared/Config/dotconfpp/mempool.h | 46 - src/server/shared/Configuration/CMakeLists.txt | 22 + src/server/shared/Configuration/Config.cpp | 105 ++ src/server/shared/Configuration/Config.h | 53 + src/server/shared/Configuration/ConfigEnv.h | 30 + .../shared/Configuration/ConfigLibrary.vcproj | 137 +++ .../shared/Configuration/dotconfpp/dotconfpp.cpp | 599 ++++++++++++ .../shared/Configuration/dotconfpp/dotconfpp.h | 97 ++ .../shared/Configuration/dotconfpp/mempool.cpp | 100 ++ .../shared/Configuration/dotconfpp/mempool.h | 46 + .../Cryptography/Authentication/AuthCrypt.cpp | 81 ++ .../shared/Cryptography/Authentication/AuthCrypt.h | 47 + src/server/shared/Cryptography/BigNumber.cpp | 201 ++++ src/server/shared/Cryptography/BigNumber.h | 96 ++ src/server/shared/Cryptography/CMakeLists.txt | 27 + src/server/shared/Cryptography/Hmac.cpp | 62 ++ src/server/shared/Cryptography/Hmac.h | 49 + src/server/shared/Cryptography/SARC4.cpp | 52 + src/server/shared/Cryptography/SARC4.h | 36 + src/server/shared/Cryptography/Sha1.cpp | 69 ++ src/server/shared/Cryptography/Sha1.h | 53 + src/server/shared/Cryptography/md5.c | 385 ++++++++ src/server/shared/Cryptography/md5.h | 92 ++ src/server/shared/DataStores/DBCFileLoader.cpp | 270 ++++++ src/server/shared/DataStores/DBCFileLoader.h | 110 +++ src/server/shared/DataStores/DBCStore.h | 265 +++++ src/server/shared/Database/DBCFileLoader.cpp | 270 ------ src/server/shared/Database/DBCFileLoader.h | 110 --- src/server/shared/Database/DBCStore.h | 265 ----- src/server/shared/Debugging/Errors.h | 48 + src/server/shared/Debugging/MemoryLeaks.cpp | 32 + src/server/shared/Debugging/MemoryLeaks.h | 48 + .../shared/Debugging/WheatyExceptionReport.cpp | 1013 ++++++++++++++++++++ .../shared/Debugging/WheatyExceptionReport.h | 118 +++ src/server/shared/DelayExecutor.cpp | 111 --- src/server/shared/DelayExecutor.h | 37 - src/server/shared/Errors.h | 48 - src/server/shared/LockedQueue.h | 139 --- src/server/shared/Log.cpp | 1005 ------------------- src/server/shared/Log.h | 190 ---- src/server/shared/Logging/Log.cpp | 1005 +++++++++++++++++++ src/server/shared/Logging/Log.h | 190 ++++ src/server/shared/MemoryLeaks.cpp | 32 - src/server/shared/MemoryLeaks.h | 48 - src/server/shared/Packets/ByteBuffer.h | 601 ++++++++++++ src/server/shared/Packets/WorldPacket.h | 54 ++ src/server/shared/ProgressBar.cpp | 85 -- src/server/shared/ProgressBar.h | 42 - src/server/shared/ServiceWin32.cpp | 263 ----- src/server/shared/ServiceWin32.h | 31 - src/server/shared/SignalHandler.h | 43 - src/server/shared/Threading.cpp | 232 ----- src/server/shared/Threading.h | 108 --- src/server/shared/Threading/DelayExecutor.cpp | 111 +++ src/server/shared/Threading/DelayExecutor.h | 37 + src/server/shared/Threading/LockedQueue.h | 139 +++ src/server/shared/Threading/Threading.cpp | 232 +++++ src/server/shared/Threading/Threading.h | 108 +++ src/server/shared/Timer.h | 215 ----- src/server/shared/Util.cpp | 468 --------- src/server/shared/Util.h | 536 ----------- src/server/shared/Utilities/ProgressBar.cpp | 85 ++ src/server/shared/Utilities/ProgressBar.h | 42 + src/server/shared/Utilities/ServiceWin32.cpp | 263 +++++ src/server/shared/Utilities/ServiceWin32.h | 31 + src/server/shared/Utilities/SignalHandler.h | 43 + src/server/shared/Utilities/Timer.h | 215 +++++ src/server/shared/Utilities/Util.cpp | 468 +++++++++ src/server/shared/Utilities/Util.h | 536 +++++++++++ src/server/shared/WheatyExceptionReport.cpp | 1013 -------------------- src/server/shared/WheatyExceptionReport.h | 118 --- src/server/shared/WorldPacket.h | 54 -- 94 files changed, 8503 insertions(+), 8503 deletions(-) delete mode 100644 src/server/shared/Auth/AuthCrypt.cpp delete mode 100644 src/server/shared/Auth/AuthCrypt.h delete mode 100644 src/server/shared/Auth/BigNumber.cpp delete mode 100644 src/server/shared/Auth/BigNumber.h delete mode 100644 src/server/shared/Auth/CMakeLists.txt delete mode 100644 src/server/shared/Auth/Hmac.cpp delete mode 100644 src/server/shared/Auth/Hmac.h delete mode 100644 src/server/shared/Auth/SARC4.cpp delete mode 100644 src/server/shared/Auth/SARC4.h delete mode 100644 src/server/shared/Auth/Sha1.cpp delete mode 100644 src/server/shared/Auth/Sha1.h delete mode 100644 src/server/shared/Auth/md5.c delete mode 100644 src/server/shared/Auth/md5.h delete mode 100644 src/server/shared/ByteBuffer.h delete mode 100644 src/server/shared/Config/CMakeLists.txt delete mode 100644 src/server/shared/Config/Config.cpp delete mode 100644 src/server/shared/Config/Config.h delete mode 100644 src/server/shared/Config/ConfigEnv.h delete mode 100644 src/server/shared/Config/ConfigLibrary.vcproj delete mode 100644 src/server/shared/Config/dotconfpp/dotconfpp.cpp delete mode 100644 src/server/shared/Config/dotconfpp/dotconfpp.h delete mode 100644 src/server/shared/Config/dotconfpp/mempool.cpp delete mode 100644 src/server/shared/Config/dotconfpp/mempool.h create mode 100644 src/server/shared/Configuration/CMakeLists.txt create mode 100644 src/server/shared/Configuration/Config.cpp create mode 100644 src/server/shared/Configuration/Config.h create mode 100644 src/server/shared/Configuration/ConfigEnv.h create mode 100644 src/server/shared/Configuration/ConfigLibrary.vcproj create mode 100644 src/server/shared/Configuration/dotconfpp/dotconfpp.cpp create mode 100644 src/server/shared/Configuration/dotconfpp/dotconfpp.h create mode 100644 src/server/shared/Configuration/dotconfpp/mempool.cpp create mode 100644 src/server/shared/Configuration/dotconfpp/mempool.h create mode 100644 src/server/shared/Cryptography/Authentication/AuthCrypt.cpp create mode 100644 src/server/shared/Cryptography/Authentication/AuthCrypt.h create mode 100644 src/server/shared/Cryptography/BigNumber.cpp create mode 100644 src/server/shared/Cryptography/BigNumber.h create mode 100644 src/server/shared/Cryptography/CMakeLists.txt create mode 100644 src/server/shared/Cryptography/Hmac.cpp create mode 100644 src/server/shared/Cryptography/Hmac.h create mode 100644 src/server/shared/Cryptography/SARC4.cpp create mode 100644 src/server/shared/Cryptography/SARC4.h create mode 100644 src/server/shared/Cryptography/Sha1.cpp create mode 100644 src/server/shared/Cryptography/Sha1.h create mode 100644 src/server/shared/Cryptography/md5.c create mode 100644 src/server/shared/Cryptography/md5.h create mode 100644 src/server/shared/DataStores/DBCFileLoader.cpp create mode 100644 src/server/shared/DataStores/DBCFileLoader.h create mode 100644 src/server/shared/DataStores/DBCStore.h delete mode 100644 src/server/shared/Database/DBCFileLoader.cpp delete mode 100644 src/server/shared/Database/DBCFileLoader.h delete mode 100644 src/server/shared/Database/DBCStore.h create mode 100644 src/server/shared/Debugging/Errors.h create mode 100644 src/server/shared/Debugging/MemoryLeaks.cpp create mode 100644 src/server/shared/Debugging/MemoryLeaks.h create mode 100644 src/server/shared/Debugging/WheatyExceptionReport.cpp create mode 100644 src/server/shared/Debugging/WheatyExceptionReport.h delete mode 100644 src/server/shared/DelayExecutor.cpp delete mode 100644 src/server/shared/DelayExecutor.h delete mode 100644 src/server/shared/Errors.h delete mode 100644 src/server/shared/LockedQueue.h delete mode 100644 src/server/shared/Log.cpp delete mode 100644 src/server/shared/Log.h create mode 100644 src/server/shared/Logging/Log.cpp create mode 100644 src/server/shared/Logging/Log.h delete mode 100644 src/server/shared/MemoryLeaks.cpp delete mode 100644 src/server/shared/MemoryLeaks.h create mode 100644 src/server/shared/Packets/ByteBuffer.h create mode 100644 src/server/shared/Packets/WorldPacket.h delete mode 100644 src/server/shared/ProgressBar.cpp delete mode 100644 src/server/shared/ProgressBar.h delete mode 100644 src/server/shared/ServiceWin32.cpp delete mode 100644 src/server/shared/ServiceWin32.h delete mode 100644 src/server/shared/SignalHandler.h delete mode 100644 src/server/shared/Threading.cpp delete mode 100644 src/server/shared/Threading.h create mode 100644 src/server/shared/Threading/DelayExecutor.cpp create mode 100644 src/server/shared/Threading/DelayExecutor.h create mode 100644 src/server/shared/Threading/LockedQueue.h create mode 100644 src/server/shared/Threading/Threading.cpp create mode 100644 src/server/shared/Threading/Threading.h delete mode 100644 src/server/shared/Timer.h delete mode 100644 src/server/shared/Util.cpp delete mode 100644 src/server/shared/Util.h create mode 100644 src/server/shared/Utilities/ProgressBar.cpp create mode 100644 src/server/shared/Utilities/ProgressBar.h create mode 100644 src/server/shared/Utilities/ServiceWin32.cpp create mode 100644 src/server/shared/Utilities/ServiceWin32.h create mode 100644 src/server/shared/Utilities/SignalHandler.h create mode 100644 src/server/shared/Utilities/Timer.h create mode 100644 src/server/shared/Utilities/Util.cpp create mode 100644 src/server/shared/Utilities/Util.h delete mode 100644 src/server/shared/WheatyExceptionReport.cpp delete mode 100644 src/server/shared/WheatyExceptionReport.h delete mode 100644 src/server/shared/WorldPacket.h (limited to 'src/server/shared') diff --git a/src/server/shared/Auth/AuthCrypt.cpp b/src/server/shared/Auth/AuthCrypt.cpp deleted file mode 100644 index b34b922b16a..00000000000 --- a/src/server/shared/Auth/AuthCrypt.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "AuthCrypt.h" -#include "Hmac.h" -#include "Log.h" -#include "BigNumber.h" - -AuthCrypt::AuthCrypt() : _clientDecrypt(SHA_DIGEST_LENGTH), _serverEncrypt(SHA_DIGEST_LENGTH) -{ - _initialized = false; -} - -AuthCrypt::~AuthCrypt() -{ - -} - -void AuthCrypt::Init(BigNumber *K) -{ - uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; - HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); - uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); - - uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; - HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); - uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); - - //SARC4 _serverDecrypt(encryptHash); - _clientDecrypt.Init(decryptHash); - _serverEncrypt.Init(encryptHash); - //SARC4 _clientEncrypt(decryptHash); - - uint8 syncBuf[1024]; - - memset(syncBuf, 0, 1024); - - _serverEncrypt.UpdateData(1024, syncBuf); - //_clientEncrypt.UpdateData(1024, syncBuf); - - memset(syncBuf, 0, 1024); - - //_serverDecrypt.UpdateData(1024, syncBuf); - _clientDecrypt.UpdateData(1024, syncBuf); - - _initialized = true; -} - -void AuthCrypt::DecryptRecv(uint8 *data, size_t len) -{ - if (!_initialized) - return; - - _clientDecrypt.UpdateData(len, data); -} - -void AuthCrypt::EncryptSend(uint8 *data, size_t len) -{ - if (!_initialized) - return; - - _serverEncrypt.UpdateData(len, data); -} - diff --git a/src/server/shared/Auth/AuthCrypt.h b/src/server/shared/Auth/AuthCrypt.h deleted file mode 100644 index 6695dc580cc..00000000000 --- a/src/server/shared/Auth/AuthCrypt.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTHCRYPT_H -#define _AUTHCRYPT_H - -#include -#include "SARC4.h" - -class BigNumber; - -class AuthCrypt -{ - public: - AuthCrypt(); - ~AuthCrypt(); - - void Init(BigNumber *K); - void DecryptRecv(uint8 *, size_t); - void EncryptSend(uint8 *, size_t); - - bool IsInitialized() { return _initialized; } - - private: - SARC4 _clientDecrypt; - SARC4 _serverEncrypt; - bool _initialized; -}; -#endif - diff --git a/src/server/shared/Auth/BigNumber.cpp b/src/server/shared/Auth/BigNumber.cpp deleted file mode 100644 index 64e9ef21ccc..00000000000 --- a/src/server/shared/Auth/BigNumber.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/BigNumber.h" -#include -#include - -BigNumber::BigNumber() -{ - _bn = BN_new(); - _array = NULL; -} - -BigNumber::BigNumber(const BigNumber &bn) -{ - _bn = BN_dup(bn._bn); - _array = NULL; -} - -BigNumber::BigNumber(uint32 val) -{ - _bn = BN_new(); - BN_set_word(_bn, val); - _array = NULL; -} - -BigNumber::~BigNumber() -{ - BN_free(_bn); - if(_array) delete[] _array; -} - -void BigNumber::SetDword(uint32 val) -{ - BN_set_word(_bn, val); -} - -void BigNumber::SetQword(uint64 val) -{ - BN_add_word(_bn, (uint32)(val >> 32)); - BN_lshift(_bn, _bn, 32); - BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); -} - -void BigNumber::SetBinary(const uint8 *bytes, int len) -{ - uint8 t[1000]; - for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; - BN_bin2bn(t, len, _bn); -} - -void BigNumber::SetHexStr(const char *str) -{ - BN_hex2bn(&_bn, str); -} - -void BigNumber::SetRand(int numbits) -{ - BN_rand(_bn, numbits, 0, 1); -} - -BigNumber BigNumber::operator=(const BigNumber &bn) -{ - BN_copy(_bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator+=(const BigNumber &bn) -{ - BN_add(_bn, _bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator-=(const BigNumber &bn) -{ - BN_sub(_bn, _bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator*=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mul(_bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::operator/=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_div(_bn, NULL, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::operator%=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mod(_bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::Exp(const BigNumber &bn) -{ - BigNumber ret; - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_exp(ret._bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return ret; -} - -BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2) -{ - BigNumber ret; - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); - BN_CTX_free(bnctx); - - return ret; -} - -int BigNumber::GetNumBytes(void) -{ - return BN_num_bytes(_bn); -} - -uint32 BigNumber::AsDword() -{ - return (uint32)BN_get_word(_bn); -} - -bool BigNumber::isZero() const -{ - return BN_is_zero(_bn)!=0; -} - -uint8 *BigNumber::AsByteArray(int minSize, bool reverse) -{ - int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); - - if (_array) - { - delete[] _array; - _array = NULL; - } - _array = new uint8[length]; - - // If we need more bytes than length of BigNumber set the rest to 0 - if (length > GetNumBytes()) - memset((void*)_array, 0, length); - - BN_bn2bin(_bn, (unsigned char *)_array); - - if (reverse) - std::reverse(_array, _array + length); - - return _array; -} - -const char *BigNumber::AsHexStr() -{ - return BN_bn2hex(_bn); -} - -const char *BigNumber::AsDecStr() -{ - return BN_bn2dec(_bn); -} - diff --git a/src/server/shared/Auth/BigNumber.h b/src/server/shared/Auth/BigNumber.h deleted file mode 100644 index 1dd43c83fc7..00000000000 --- a/src/server/shared/Auth/BigNumber.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_BIGNUMBER_H -#define _AUTH_BIGNUMBER_H - -#include "Common.h" - -struct bignum_st; - -class BigNumber -{ - public: - BigNumber(); - BigNumber(const BigNumber &bn); - BigNumber(uint32); - ~BigNumber(); - - void SetDword(uint32); - void SetQword(uint64); - void SetBinary(const uint8 *bytes, int len); - void SetHexStr(const char *str); - - void SetRand(int numbits); - - BigNumber operator=(const BigNumber &bn); - - BigNumber operator+=(const BigNumber &bn); - BigNumber operator+(const BigNumber &bn) - { - BigNumber t(*this); - return t += bn; - } - BigNumber operator-=(const BigNumber &bn); - BigNumber operator-(const BigNumber &bn) - { - BigNumber t(*this); - return t -= bn; - } - BigNumber operator*=(const BigNumber &bn); - BigNumber operator*(const BigNumber &bn) - { - BigNumber t(*this); - return t *= bn; - } - BigNumber operator/=(const BigNumber &bn); - BigNumber operator/(const BigNumber &bn) - { - BigNumber t(*this); - return t /= bn; - } - BigNumber operator%=(const BigNumber &bn); - BigNumber operator%(const BigNumber &bn) - { - BigNumber t(*this); - return t %= bn; - } - - bool isZero() const; - - BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); - BigNumber Exp(const BigNumber &); - - int GetNumBytes(void); - - struct bignum_st *BN() { return _bn; } - - uint32 AsDword(); - uint8* AsByteArray(int minSize = 0, bool reverse = true); - - const char *AsHexStr(); - const char *AsDecStr(); - - private: - struct bignum_st *_bn; - uint8 *_array; -}; -#endif - diff --git a/src/server/shared/Auth/CMakeLists.txt b/src/server/shared/Auth/CMakeLists.txt deleted file mode 100644 index 6e5d10d40e5..00000000000 --- a/src/server/shared/Auth/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ - -########### next target ############### - -SET(trinityauth_STAT_SRCS - AuthCrypt.cpp - AuthCrypt.h - BigNumber.cpp - BigNumber.h - Hmac.cpp - Hmac.h - Sha1.cpp - Sha1.h - md5.c - md5.h - SARC4.cpp - SARC4.h -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/framework - ${MYSQL_INCLUDE_DIR} -) - -add_library(trinityauth STATIC ${trinityauth_STAT_SRCS}) diff --git a/src/server/shared/Auth/Hmac.cpp b/src/server/shared/Auth/Hmac.cpp deleted file mode 100644 index a30f1b2d1e2..00000000000 --- a/src/server/shared/Auth/Hmac.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Hmac.h" -#include "BigNumber.h" - -HmacHash::HmacHash(uint32 len, uint8 *seed) -{ - HMAC_CTX_init(&m_ctx); - HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); -} - -HmacHash::~HmacHash() -{ - HMAC_CTX_cleanup(&m_ctx); -} - -void HmacHash::UpdateBigNumber(BigNumber *bn) -{ - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); -} - -void HmacHash::UpdateData(const uint8 *data, int length) -{ - HMAC_Update(&m_ctx, data, length); -} - -void HmacHash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void HmacHash::Finalize() -{ - uint32 length = 0; - HMAC_Final(&m_ctx, (uint8*)m_digest, &length); - ASSERT(length == SHA_DIGEST_LENGTH) -} - -uint8 *HmacHash::ComputeHash(BigNumber *bn) -{ - HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); - Finalize(); - return (uint8*)m_digest; -} diff --git a/src/server/shared/Auth/Hmac.h b/src/server/shared/Auth/Hmac.h deleted file mode 100644 index 845d6e84802..00000000000 --- a/src/server/shared/Auth/Hmac.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_HMAC_H -#define _AUTH_HMAC_H - -#include "Common.h" -#include -#include - -class BigNumber; - -#define SEED_KEY_SIZE 16 - -class HmacHash -{ - public: - HmacHash(uint32 len, uint8 *seed); - ~HmacHash(); - void UpdateBigNumber(BigNumber *bn); - void UpdateData(const uint8 *data, int length); - void UpdateData(const std::string &str); - void Finalize(); - uint8 *ComputeHash(BigNumber *bn); - uint8 *GetDigest() { return (uint8*)m_digest; } - int GetLength() { return SHA_DIGEST_LENGTH; } - private: - HMAC_CTX m_ctx; - uint8 m_digest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Auth/SARC4.cpp b/src/server/shared/Auth/SARC4.cpp deleted file mode 100644 index 80cad4991e9..00000000000 --- a/src/server/shared/Auth/SARC4.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/SARC4.h" -#include - -SARC4::SARC4(uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); -} - -SARC4::SARC4(uint8 *seed, uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -SARC4::~SARC4() -{ - EVP_CIPHER_CTX_cleanup(&m_ctx); -} - -void SARC4::Init(uint8 *seed) -{ - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -void SARC4::UpdateData(int len, uint8 *data) -{ - int outlen = 0; - EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); - EVP_EncryptFinal_ex(&m_ctx, data, &outlen); -} diff --git a/src/server/shared/Auth/SARC4.h b/src/server/shared/Auth/SARC4.h deleted file mode 100644 index 2e408627fc8..00000000000 --- a/src/server/shared/Auth/SARC4.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SARC4_H -#define _AUTH_SARC4_H - -#include "Common.h" -#include - -class SARC4 -{ - public: - SARC4(uint8 len); - SARC4(uint8 *seed, uint8 len); - ~SARC4(); - void Init(uint8 *seed); - void UpdateData(int len, uint8 *data); - private: - EVP_CIPHER_CTX m_ctx; -}; -#endif diff --git a/src/server/shared/Auth/Sha1.cpp b/src/server/shared/Auth/Sha1.cpp deleted file mode 100644 index b63deb2c5f3..00000000000 --- a/src/server/shared/Auth/Sha1.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Sha1.h" -#include "Auth/BigNumber.h" -#include - -Sha1Hash::Sha1Hash() -{ - SHA1_Init(&mC); -} - -Sha1Hash::~Sha1Hash() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::UpdateData(const uint8 *dta, int len) -{ - SHA1_Update(&mC, dta, len); -} - -void Sha1Hash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) -{ - va_list v; - BigNumber *bn; - - va_start(v, bn0); - bn = bn0; - while (bn) - { - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); - bn = va_arg(v, BigNumber *); - } - va_end(v); -} - -void Sha1Hash::Initialize() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::Finalize(void) -{ - SHA1_Final(mDigest, &mC); -} - diff --git a/src/server/shared/Auth/Sha1.h b/src/server/shared/Auth/Sha1.h deleted file mode 100644 index 2d7f361ae9a..00000000000 --- a/src/server/shared/Auth/Sha1.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SHA1_H -#define _AUTH_SHA1_H - -#include "Common.h" -#include -#include - -class BigNumber; - -class Sha1Hash -{ - public: - Sha1Hash(); - ~Sha1Hash(); - - void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); - void UpdateBigNumbers(BigNumber *bn0, ...); - - void UpdateData(const uint8 *dta, int len); - void UpdateData(const std::string &str); - - void Initialize(); - void Finalize(); - - uint8 *GetDigest(void) { return mDigest; }; - int GetLength(void) { return SHA_DIGEST_LENGTH; }; - - private: - SHA_CTX mC; - uint8 mDigest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Auth/md5.c b/src/server/shared/Auth/md5.c deleted file mode 100644 index 3e9735e2dbb..00000000000 --- a/src/server/shared/Auth/md5.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.c is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order -either statically or dynamically; added missing #include -in library. -2002-03-11 lpd Corrected argument list for main(), and added int return -type, in test program and T value program. -2002-02-21 lpd Added missing #include in test program. -2000-07-03 lpd Patched to eliminate warnings about "constant is -unsigned in ANSI C, signed in traditional"; made test program -self-checking. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). -1999-05-03 lpd Original version. -*/ - -#include "md5.h" -#include - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - #if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; - #else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; - #endif - - { - #if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ - #endif - #if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) - { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } - else - { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } - #endif - #if BYTE_ORDER == 0 - else /* dynamic big-endian */ - #endif - #if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - - # if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ - # else - # define xbuf X /* (static only) */ - # endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } - #endif - } - - #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ - #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); - #undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ - #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); - #undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ - #define H(x, y, z) ((x) ^ (y) ^ (z)) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); - #undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ - #define I(x, y, z) ((y) ^ ((x) | ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); - #undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - ++pms->count[1]; - - /* Process an initial partial block. */ - if (offset) - { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = - { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/src/server/shared/Auth/md5.h b/src/server/shared/Auth/md5.h deleted file mode 100644 index 0463051b6a6..00000000000 --- a/src/server/shared/Auth/md5.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.h is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Removed support for non-ANSI compilers; removed -references to Ghostscript; clarified derivation from RFC 1321; -now handles byte order either statically or dynamically. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); -added conditionalization for C++ compilation from Martin -Purschke . -1999-05-03 lpd Original version. -*/ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s -{ - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ - #endif - - /* Initialize the algorithm. */ - void md5_init(md5_state_t *pms); - - /* Append a string to the message. */ - void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - - /* Finish the message and return the digest. */ - void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - - #ifdef __cplusplus -} /* end extern "C" */ -#endif -#endif /* md5_INCLUDED */ - diff --git a/src/server/shared/ByteBuffer.h b/src/server/shared/ByteBuffer.h deleted file mode 100644 index ba0240fb58b..00000000000 --- a/src/server/shared/ByteBuffer.h +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _BYTEBUFFER_H -#define _BYTEBUFFER_H - -#include "Common.h" -#include "Errors.h" -#include "Log.h" -#include "Utilities/ByteConverter.h" - -class ByteBufferException -{ - public: - ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) - : add(_add), pos(_pos), esize(_esize), size(_size) - { - PrintPosError(); - } - - void PrintPosError() const - { - sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, - (add ? "put" : "get"), pos, size, esize); - } - private: - bool add; - size_t pos; - size_t esize; - size_t size; -}; - -class ByteBuffer -{ - public: - const static size_t DEFAULT_SIZE = 0x1000; - - // constructor - ByteBuffer(): _rpos(0), _wpos(0) - { - _storage.reserve(DEFAULT_SIZE); - } - - // constructor - ByteBuffer(size_t res): _rpos(0), _wpos(0) - { - _storage.reserve(res); - } - - // copy constructor - ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } - - void clear() - { - _storage.clear(); - _rpos = _wpos = 0; - } - - template void append(T value) - { - EndianConvert(value); - append((uint8 *)&value, sizeof(value)); - } - - template void put(size_t pos,T value) - { - EndianConvert(value); - put(pos,(uint8 *)&value,sizeof(value)); - } - - ByteBuffer &operator<<(uint8 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint16 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint32 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint64 value) - { - append(value); - return *this; - } - - // signed as in 2e complement - ByteBuffer &operator<<(int8 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int16 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int32 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int64 value) - { - append(value); - return *this; - } - - // floating points - ByteBuffer &operator<<(float value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(double value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(const std::string &value) - { - append((uint8 const *)value.c_str(), value.length()); - append((uint8)0); - return *this; - } - - ByteBuffer &operator<<(const char *str) - { - append((uint8 const *)str, str ? strlen(str) : 0); - append((uint8)0); - return *this; - } - - ByteBuffer &operator>>(bool &value) - { - value = read() > 0 ? true : false; - return *this; - } - - ByteBuffer &operator>>(uint8 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint16 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint32 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint64 &value) - { - value = read(); - return *this; - } - - //signed as in 2e complement - ByteBuffer &operator>>(int8 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int16 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int32 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int64 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(float &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(double &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(std::string& value) - { - value.clear(); - while (rpos() < size()) // prevent crash at wrong string format in packet - { - char c = read(); - if (c == 0) - break; - value += c; - } - return *this; - } - - uint8 operator[](size_t pos) const - { - return read(pos); - } - - size_t rpos() const { return _rpos; } - - size_t rpos(size_t rpos_) - { - _rpos = rpos_; - return _rpos; - } - - size_t wpos() const { return _wpos; } - - size_t wpos(size_t wpos_) - { - _wpos = wpos_; - return _wpos; - } - - template - void read_skip() { read_skip(sizeof(T)); } - - void read_skip(size_t skip) - { - if(_rpos + skip > size()) - throw ByteBufferException(false, _rpos, skip, size()); - _rpos += skip; - } - - template T read() - { - T r = read(_rpos); - _rpos += sizeof(T); - return r; - } - - template T read(size_t pos) const - { - if(pos + sizeof(T) > size()) - throw ByteBufferException(false, pos, sizeof(T), size()); - T val = *((T const*)&_storage[pos]); - EndianConvert(val); - return val; - } - - void read(uint8 *dest, size_t len) - { - if(_rpos + len > size()) - throw ByteBufferException(false, _rpos, len, size()); - memcpy(dest, &_storage[_rpos], len); - _rpos += len; - } - - bool readPackGUID(uint64& guid) - { - if(rpos() + 1 > size()) - return false; - - guid = 0; - - uint8 guidmark = 0; - (*this) >> guidmark; - - for (int i = 0; i < 8; ++i) - { - if(guidmark & (uint8(1) << i)) - { - if(rpos() + 1 > size()) - return false; - - uint8 bit; - (*this) >> bit; - guid |= (uint64(bit) << (i * 8)); - } - } - - return true; - } - - const uint8 *contents() const { return &_storage[0]; } - - size_t size() const { return _storage.size(); } - bool empty() const { return _storage.empty(); } - - void resize(size_t newsize) - { - _storage.resize(newsize); - _rpos = 0; - _wpos = size(); - } - - void reserve(size_t ressize) - { - if (ressize > size()) - _storage.reserve(ressize); - } - - void append(const std::string& str) - { - append((uint8 const*)str.c_str(), str.size() + 1); - } - - void append(const char *src, size_t cnt) - { - return append((const uint8 *)src, cnt); - } - - template void append(const T *src, size_t cnt) - { - return append((const uint8 *)src, cnt * sizeof(T)); - } - - void append(const uint8 *src, size_t cnt) - { - if (!cnt) - return; - - ASSERT(size() < 10000000); - - if (_storage.size() < _wpos + cnt) - _storage.resize(_wpos + cnt); - memcpy(&_storage[_wpos], src, cnt); - _wpos += cnt; - } - - void append(const ByteBuffer& buffer) - { - if(buffer.wpos()) - append(buffer.contents(), buffer.wpos()); - } - - // can be used in SMSG_MONSTER_MOVE opcode - void appendPackXYZ(float x, float y, float z) - { - uint32 packed = 0; - packed |= ((int)(x / 0.25f) & 0x7FF); - packed |= ((int)(y / 0.25f) & 0x7FF) << 11; - packed |= ((int)(z / 0.25f) & 0x3FF) << 22; - *this << packed; - } - - void appendPackGUID(uint64 guid) - { - uint8 packGUID[8+1]; - packGUID[0] = 0; - size_t size = 1; - for(uint8 i = 0;guid != 0;++i) - { - if(guid & 0xFF) - { - packGUID[0] |= uint8(1 << i); - packGUID[size] = uint8(guid & 0xFF); - ++size; - } - - guid >>= 8; - } - append(packGUID, size); - } - - void put(size_t pos, const uint8 *src, size_t cnt) - { - if(pos + cnt > size()) - throw ByteBufferException(true, pos, cnt, size()); - memcpy(&_storage[pos], src, cnt); - } - - void print_storage() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - for (uint32 i = 0; i < size(); ++i) - sLog.outDebugInLine("%u - ", read(i) ); - sLog.outDebug(" "); - } - - void textlike() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - for (uint32 i = 0; i < size(); ++i) - sLog.outDebugInLine("%c", read(i) ); - sLog.outDebug(" "); - } - - void hexlike() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - uint32 j = 1, k = 1; - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - - for (uint32 i = 0; i < size(); ++i) - { - if ((i == (j * 8)) && ((i != (k * 16)))) - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("| 0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("| %X ", read(i) ); - } - ++j; - } - else if (i == (k * 16)) - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("\n"); - - sLog.outDebugInLine("0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("\n"); - - sLog.outDebugInLine("%X ", read(i) ); - } - - ++k; - ++j; - } - else - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("%X ", read(i) ); - } - } - } - sLog.outDebugInLine("\n"); - } - - protected: - size_t _rpos, _wpos; - std::vector _storage; -}; - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::vector v) -{ - b << (uint32)v.size(); - for (typename std::vector::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while(vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::list v) -{ - b << (uint32)v.size(); - for (typename std::list::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::list &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while(vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::map &m) -{ - b << (uint32)m.size(); - for (typename std::map::iterator i = m.begin(); i != m.end(); ++i) - { - b << i->first << i->second; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::map &m) -{ - uint32 msize; - b >> msize; - m.clear(); - while(msize--) - { - K k; - V v; - b >> k >> v; - m.insert(make_pair(k, v)); - } - return b; -} - -// TODO: Make a ByteBuffer.cpp and move all this inlining to it. -template<> inline std::string ByteBuffer::read() -{ - std::string tmp; - *this >> tmp; - return tmp; -} - -template<> -inline void ByteBuffer::read_skip() -{ - std::string temp; - *this >> temp; -} - -template<> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} - -template<> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} -#endif - diff --git a/src/server/shared/Config/CMakeLists.txt b/src/server/shared/Config/CMakeLists.txt deleted file mode 100644 index da1c2e8aa3b..00000000000 --- a/src/server/shared/Config/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -########### next target ############### - -SET(trinityconfig_STAT_SRCS - dotconfpp/dotconfpp.cpp - dotconfpp/dotconfpp.h - dotconfpp/mempool.cpp - dotconfpp/mempool.h - Config.cpp - Config.h - ConfigEnv.h -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/framework -) - -add_library(trinityconfig STATIC ${trinityconfig_STAT_SRCS}) - diff --git a/src/server/shared/Config/Config.cpp b/src/server/shared/Config/Config.cpp deleted file mode 100644 index 39830104a7c..00000000000 --- a/src/server/shared/Config/Config.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ConfigEnv.h" -#include "Policies/SingletonImp.h" - -INSTANTIATE_SINGLETON_1(Config); - -Config::Config() : mIgnoreCase(true), mConf(NULL) -{ -} - -Config::~Config() -{ - delete mConf; -} - -bool Config::SetSource(const char *file, bool ignorecase) -{ - mIgnoreCase = ignorecase; - mFilename = file; - - return Reload(); -} - -bool Config::Reload() -{ - delete mConf; - - mConf = new DOTCONFDocument(mIgnoreCase ? - DOTCONFDocument::CASEINSENSETIVE : - DOTCONFDocument::CASESENSETIVE); - - if (mConf->setContent(mFilename.c_str()) == -1) - { - delete mConf; - mConf = NULL; - return false; - } - - return true; -} - -std::string Config::GetStringDefault(const char * name, std::string def) -{ - if(!mConf) - return std::string(def); - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return std::string(def); - return std::string(node->getValue()); -}; - -bool Config::GetBoolDefault(const char * name, const bool def) -{ - if(!mConf) - return false; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - const char * str = node->getValue(); - if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 || - strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 || - strcmp(str, "1") == 0) - return true; - else - return false; -}; - -int32 Config::GetIntDefault(const char * name, const int32 def) -{ - if(!mConf) - return def; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - return atoi(node->getValue()); -}; - -float Config::GetFloatDefault(const char * name, const float def) -{ - if(!mConf) - return def; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - return atof(node->getValue()); -}; diff --git a/src/server/shared/Config/Config.h b/src/server/shared/Config/Config.h deleted file mode 100644 index ccc76073e46..00000000000 --- a/src/server/shared/Config/Config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#include -#include "Platform/Define.h" - -class DOTCONFDocument; - -class Config -{ - public: - Config(); - ~Config(); - - bool SetSource(const char *file, bool ignorecase = true); - bool Reload(); - - std::string GetStringDefault(const char * name, std::string def); - bool GetBoolDefault(const char * name, const bool def); - int32 GetIntDefault(const char * name, const int32 def); - float GetFloatDefault(const char * name, const float def); - - std::string GetFilename() const { return mFilename; } - private: - std::string mFilename; - bool mIgnoreCase; - DOTCONFDocument *mConf; -}; - -#define sConfig Trinity::Singleton::Instance() - -#endif - diff --git a/src/server/shared/Config/ConfigEnv.h b/src/server/shared/Config/ConfigEnv.h deleted file mode 100644 index 16e596fd2da..00000000000 --- a/src/server/shared/Config/ConfigEnv.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if !defined(CONFIGENVIRONMENT_H) - -#define CONFIGENVIRONMENT_H - -#include "Common.h" -#include "dotconfpp/dotconfpp.h" -#include "Config.h" - -#endif - diff --git a/src/server/shared/Config/ConfigLibrary.vcproj b/src/server/shared/Config/ConfigLibrary.vcproj deleted file mode 100644 index a8f1fc322e7..00000000000 --- a/src/server/shared/Config/ConfigLibrary.vcproj +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.cpp b/src/server/shared/Config/dotconfpp/dotconfpp.cpp deleted file mode 100644 index 8760b118e38..00000000000 --- a/src/server/shared/Config/dotconfpp/dotconfpp.cpp +++ /dev/null @@ -1,599 +0,0 @@ - -#include "Common.h" - -#include "dotconfpp.h" - -#ifdef WIN32 -#define PATH_MAX _MAX_PATH -#define strcasecmp stricmp -#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH) -#include -#else -#include -#include -#include -#include -#endif - -#if !defined(R_OK) -#define R_OK 04 -#endif - -DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), - values(NULL), valuesCount(0), - name(NULL), lineNum(0), fileName(NULL), closed(true) -{ -} - -DOTCONFDocumentNode::~DOTCONFDocumentNode() -{ - free(name); - if(values != NULL){ - for (int i = 0 ; i < valuesCount; i++){ - free(values[i]); - } - free(values); - } -} - -void DOTCONFDocumentNode::pushValue(char * _value) -{ - ++valuesCount; - values = (char**)realloc(values, valuesCount*sizeof(char*)); - values[valuesCount-1] = strdup(_value); -} - -const char* DOTCONFDocumentNode::getValue(int index) const -{ - if(index >= valuesCount){ - return NULL; - } - return values[index]; -} - -DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): - mempool(NULL), - curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL) -{ - if(caseSensitivity == CASESENSETIVE){ - cmp_func = strcmp; - } else { - cmp_func = strcasecmp; - } - - mempool = new AsyncDNSMemPool(1024); - mempool->initialize(); -} - -DOTCONFDocument::~DOTCONFDocument() -{ - for (std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){ - delete(*i); - } - for (std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){ - free(*i); - } - for (std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){ - free(*i); - } - free(fileName); - delete mempool; -} - -int DOTCONFDocument::cleanupLine(char * line) -{ - char * start = line; - char * bg = line; - bool multiline = false; - bool concat = false; - char * word = NULL; - - if(!words.empty() && quoted) - concat = true; - - while(*line){ - if((*line == '#' || *line == ';') && !quoted){ - *bg = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - break; - } - if(*line == '=' && !quoted){ - *line = ' ';continue; - } - - // Allowing \" in there causes problems with directory paths - // like "C:\TrinIty\" - //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ - if(*line == '\\' && (*(line+1) == '\'')) { - *bg++ = *(line+1); - line+=2; continue; - } - if(*line == '\\' && *(line+1) == 'n'){ - *bg++ = '\n'; - line+=2; continue; - } - if(*line == '\\' && *(line+1) == 'r'){ - *bg++ = '\r'; - line+=2; continue; - } - if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ - *bg = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - multiline = true; - break; - } - if(*line == '"' || *line == '\''){ - quoted = !quoted; - ++line; continue; - } - if(isspace((unsigned char)*line) && !quoted){ - *bg++ = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - start = bg; - while(isspace((unsigned char)*++line)) {} - - continue; - } - *bg++ = *line++; - } - - if(quoted && !multiline){ - error(curLine, fileName, "unterminated quote"); - return -1; - } - - return multiline?1:0; -} - -int DOTCONFDocument::parseLine() -{ - char * word = NULL; - char * nodeName = NULL; - char * nodeValue = NULL; - DOTCONFDocumentNode * tagNode = NULL; - bool newNode = false; - - for (std::list::iterator i = words.begin(); i != words.end(); ++i) { - word = *i; - - if(*word == '<'){ - newNode = true; - } - - if(newNode){ - nodeValue = NULL; - nodeName = NULL; - newNode = false; - } - - size_t wordLen = strlen(word); - if(word[wordLen-1] == '>'){ - word[wordLen-1] = 0; - newNode = true; - } - - if(nodeName == NULL){ - nodeName = word; - bool closed = true; - if(*nodeName == '<'){ - if(*(nodeName+1) != '/'){ - ++nodeName; - closed = false; - } else { - nodeName+=2; - std::list::reverse_iterator itr=nodeTree.rbegin(); - for (; itr!=nodeTree.rend(); ++itr){ - if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){ - (*itr)->closed = true; - curParent = (*itr)->parentNode; - curPrev = *itr; - break; - } - } - if(itr==nodeTree.rend()){ - error(curLine, fileName, "not matched closing tag ", nodeName); - return -1; - } - continue; - } - } - tagNode = new DOTCONFDocumentNode; - tagNode->name = strdup(nodeName); - tagNode->document = this; - tagNode->fileName = processedFiles.back(); - tagNode->lineNum = curLine; - tagNode->closed = closed; - if(!nodeTree.empty()){ - DOTCONFDocumentNode * prev = nodeTree.back(); - if(prev->closed){ - - curPrev->nextNode = tagNode; - tagNode->previousNode = curPrev; - tagNode->parentNode = curParent; - - } else { - prev->childNode = tagNode; - tagNode->parentNode = prev; - curParent = prev; - } - } - nodeTree.push_back(tagNode); - curPrev = tagNode; - } else { - nodeValue = word; - tagNode->pushValue(nodeValue); - } - } - - return 0; -} -int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) -{ - char str[512]; - int ret = 0; - curLine = 0; - curParent = _parent; - - quoted = false; - size_t slen = 0; - - while(fgets(str, 511, file)){ - ++curLine; - slen = strlen(str); - if( slen >= 510 ){ - error(curLine, fileName, "warning: line too long"); - } - if(str[slen-1] != '\n'){ - str[slen] = '\n'; - str[slen+1] = 0; - } - if((ret = cleanupLine(str)) == -1){ - break; - } - if(ret == 0){ - if(!words.empty()){ - ret = parseLine(); - mempool->free(); - words.clear(); - if(ret == -1){ - break; - } - } - } - } - - return ret; -} - -int DOTCONFDocument::checkConfig(const std::list::iterator & from) -{ - int ret = 0; - - DOTCONFDocumentNode * tagNode = NULL; - int vi = 0; - for (std::list::iterator i = from; i != nodeTree.end(); ++i){ - tagNode = *i; - if(!tagNode->closed){ - error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); - ret = -1; - break; - } - vi = 0; - while( vi < tagNode->valuesCount ){ - - if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ - ret = macroSubstitute(tagNode, vi ); - mempool->free(); - if(ret == -1){ - break; - } - } - ++vi; - } - if(ret == -1){ - break; - } - } - - return ret; -} - -int DOTCONFDocument::setContent(const char * _fileName) -{ - int ret = 0; - char realpathBuf[PATH_MAX]; - - if(realpath(_fileName, realpathBuf) == NULL){ - error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno)); - return -1; - } - - fileName = strdup(realpathBuf); - - processedFiles.push_back(strdup(realpathBuf)); - - if(( file = fopen(fileName, "r")) == NULL){ - error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); - return -1; - } - // Try read utf8 header and skip it if exist - uint32 utf8header = 0; - fgets((char*)&utf8header, 4, file); // Try read header - if (utf8header!=0x00BFBBEF) // If not exist - fseek(file, 0, SEEK_SET); // Reset read position - - ret = parseFile(); - - (void) fclose(file); - - if(!ret){ - - if( (ret = checkConfig(nodeTree.begin())) == -1){ - return -1; - } - - std::list::iterator from; - DOTCONFDocumentNode * tagNode = NULL; - int vi = 0; - for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ - tagNode = *i; - if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){ - vi = 0; - while( vi < tagNode->valuesCount ){ - if(access(tagNode->values[vi], R_OK) == -1){ - error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno)); - return -1; - } - if(realpath(tagNode->values[vi], realpathBuf) == NULL){ - error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno)); - return -1; - } - - bool processed = false; - for (std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){ - if(!strcmp(*itInode, realpathBuf)){ - processed = true; - break; - } - } - if(processed){ - break; - } - - processedFiles.push_back(strdup(realpathBuf)); - - file = fopen(tagNode->values[vi], "r"); - if(file == NULL){ - error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno)); - return -1; - } - - fileName = strdup(realpathBuf); - from = nodeTree.end(); --from; - - ret = parseFile(); - (void) fclose(file); - if(ret == -1) - return -1; - if(checkConfig(++from) == -1){ - return -1; - } - ++vi; - } - } - } - - if(!requiredOptions.empty()) - ret = checkRequiredOptions(); - } - - return ret; -} - -int DOTCONFDocument::checkRequiredOptions() -{ - for (std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){ - bool matched = false; - for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ - if(!cmp_func((*i)->name, *ci)){ - matched = true; - break; - } - } - if(!matched){ - error(0, NULL, "required option '%s' not specified", *ci); - return -1; - } - } - return 0; -} - -void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...) -{ - va_list args; - va_start(args, fmt); - - size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50; - char * buf = (char*)mempool->alloc(len); - - if(lineNum) - (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt); - else - (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt); - - (void) vfprintf(stderr, buf, args); - - va_end(args); -} - -char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) -{ - char * buf = NULL; - char * variable = macro+2; - - char * endBr = strchr(macro, '}'); - - if(!endBr){ - error(lineNum, fileName, "unterminated '{'"); - return NULL; - } - *endBr = 0; - - char * defaultValue = strchr(variable, ':'); - - if(defaultValue){ - *defaultValue++ = 0; - if(*defaultValue != '-'){ - error(lineNum, fileName, "incorrect macro substitution syntax"); - return NULL; - } - ++defaultValue; - if(*defaultValue == '"' || *defaultValue == '\''){ - ++defaultValue; - defaultValue[strlen(defaultValue)-1] = 0; - } - } else { - defaultValue = NULL; - } - - char * subs = getenv(variable); - if( subs ){ - buf = mempool->strdup(subs); - } else { - std::list::iterator i = nodeTree.begin(); - DOTCONFDocumentNode * tagNode = NULL; - for (; i!=nodeTree.end(); i++){ - tagNode = *i; - if(!cmp_func(tagNode->name, variable)){ - if(tagNode->valuesCount != 0){ - buf = mempool->strdup(tagNode->values[0]); - break; - } - } - } - if( i == nodeTree.end() ){ - if( defaultValue ){ - buf = mempool->strdup(defaultValue); - } else { - error(lineNum, fileName, "substitution not found and default value not given"); - return NULL; - } - } - } - return buf; -} - -int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) -{ - int ret = 0; - char * macro = tagNode->values[valueIndex]; - size_t valueLen = strlen(tagNode->values[valueIndex])+1; - char * value = (char*)mempool->alloc(valueLen); - char * v = value; - char * subs = NULL; - - while(*macro){ - if(*macro == '$' && *(macro+1) == '{'){ - char * m = strchr(macro, '}'); - subs = getSubstitution(macro, tagNode->lineNum); - if(subs == NULL){ - ret = -1; - break; - } - macro = m + 1; - *v = 0; - v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); - strcpy(v, value); - value = strcat(v, subs); - v = value + strlen(value); - continue; - } - *v++ = *macro++; - } - *v = 0; - - free(tagNode->values[valueIndex]); - tagNode->values[valueIndex] = strdup(value); - return ret; -} - -const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const -{ - if ( !nodeTree.empty() ) { - return *nodeTree.begin(); - } else { - return NULL; - } -} - -const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const -{ - - std::list::const_iterator i = nodeTree.begin(); - - if(startNode == NULL) - startNode = parentNode; - - if(startNode != NULL){ - while( i != nodeTree.end() && (*i) != startNode ){ - ++i; - } - if( i != nodeTree.end() ) ++i; - } - - for (; i!=nodeTree.end(); ++i){ - - if((*i)->parentNode != parentNode){ - continue; - } - if(!cmp_func(nodeName, (*i)->name)){ - return *i; - } - } - return NULL; -} - -void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) -{ - while(*requiredOptionNames){ - requiredOptions.push_back(strdup( *requiredOptionNames )); - ++requiredOptionNames; - } -} - diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.h b/src/server/shared/Config/dotconfpp/dotconfpp.h deleted file mode 100644 index 554b152f693..00000000000 --- a/src/server/shared/Config/dotconfpp/dotconfpp.h +++ /dev/null @@ -1,97 +0,0 @@ - - -#ifndef DOTCONFPP_H -#define DOTCONFPP_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "mempool.h" - -class DOTCONFDocument; - -class DOTCONFDocumentNode -{ -friend class DOTCONFDocument; -private: - DOTCONFDocumentNode * previousNode; - DOTCONFDocumentNode * nextNode; - DOTCONFDocumentNode * parentNode; - DOTCONFDocumentNode * childNode; - char ** values; - int valuesCount; - char * name; - const DOTCONFDocument * document; - int lineNum; - char * fileName; - bool closed; - - void pushValue(char * _value); - -public: - DOTCONFDocumentNode(); - ~DOTCONFDocumentNode(); - - const char * getConfigurationFileName()const { return fileName; } - int getConfigurationLineNumber() const { return lineNum; } - - const DOTCONFDocumentNode * getNextNode() const { return nextNode; } - const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } - const DOTCONFDocumentNode * getParentNode() const { return parentNode; } - const DOTCONFDocumentNode * getChildNode() const { return childNode; } - const char* getValue(int index = 0) const; - const char * getName() const { return name; } - const DOTCONFDocument * getDocument() const { return document; } -}; - -class DOTCONFDocument -{ -public: - enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE }; -protected: - AsyncDNSMemPool * mempool; -private: - DOTCONFDocumentNode * curParent; - DOTCONFDocumentNode * curPrev; - int curLine; - bool quoted; - std::list nodeTree; - std::list requiredOptions; - std::list processedFiles; - FILE * file; - char * fileName; - std::list words; - int (*cmp_func)(const char *, const char *); - - int checkRequiredOptions(); - int parseLine(); - int parseFile(DOTCONFDocumentNode * _parent = NULL); - int checkConfig(const std::list::iterator & from); - int cleanupLine(char * line); - char * getSubstitution(char * macro, int lineNum); - int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); - -protected: - virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5); - -public: - DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE); - virtual ~DOTCONFDocument(); - - int setContent(const char * _fileName); - - void setRequiredOptionNames(const char ** requiredOptionNames); - const DOTCONFDocumentNode * getFirstNode() const; - const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; -}; - -#endif - diff --git a/src/server/shared/Config/dotconfpp/mempool.cpp b/src/server/shared/Config/dotconfpp/mempool.cpp deleted file mode 100644 index a23e33808bd..00000000000 --- a/src/server/shared/Config/dotconfpp/mempool.cpp +++ /dev/null @@ -1,100 +0,0 @@ - - -#include "mempool.h" - -AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): - pool(NULL), pos(0), size(_size) -{ - pool = ::malloc(size); -} - -AsyncDNSMemPool::PoolChunk::~PoolChunk() -{ - ::free(pool); -} - -AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): - chunks(NULL), chunksCount(0), defaultSize(_defaultSize), - poolUsage(0), poolUsageCounter(0) -{ -} - -AsyncDNSMemPool::~AsyncDNSMemPool() -{ - for (size_t i = 0; isize - chunk->pos) >= size){ - chunk->pos += size; - return ((char*)chunk->pool) + chunk->pos - size; - } - } - addNewChunk(size); - chunks[chunksCount-1]->pos = size; - return chunks[chunksCount-1]->pool; -} - -void AsyncDNSMemPool::free() -{ - size_t pu = 0; - size_t psz = 0; - ++poolUsageCounter; - - for (size_t i = 0; ipos; - psz += chunks[i]->size; - chunks[i]->pos = 0; - } - poolUsage=(poolUsage>pu)?poolUsage:pu; - - if(poolUsageCounter >= 10 && chunksCount > 1){ - psz -= chunks[chunksCount-1]->size; - if(poolUsage < psz){ - --chunksCount; - delete chunks[chunksCount]; - } - poolUsage = 0; - poolUsageCounter = 0; - } -} - -void * AsyncDNSMemPool::calloc(size_t size) -{ - return ::memset(this->alloc(size), 0, size); -} - -char * AsyncDNSMemPool::strdup(const char *str) -{ - return ::strcpy((char*)this->alloc(strlen(str)+1), str); -} - diff --git a/src/server/shared/Config/dotconfpp/mempool.h b/src/server/shared/Config/dotconfpp/mempool.h deleted file mode 100644 index 185b50798e1..00000000000 --- a/src/server/shared/Config/dotconfpp/mempool.h +++ /dev/null @@ -1,46 +0,0 @@ - - -#ifndef ASYNC_DNS_MEMPOOL_H -#define ASYNC_DNS_MEMPOOL_H - -#include -#include -#include - -#undef free -#undef calloc -#undef strdup - -class AsyncDNSMemPool -{ -private: - struct PoolChunk { - void * pool; - size_t pos; - size_t size; - - PoolChunk(size_t _size); - ~PoolChunk(); - }; - PoolChunk ** chunks; - size_t chunksCount; - size_t defaultSize; - - size_t poolUsage; - size_t poolUsageCounter; - - void addNewChunk(size_t size); - -public: - AsyncDNSMemPool(size_t _defaultSize = 4096); - virtual ~AsyncDNSMemPool(); - - int initialize(); - void free(); - void * alloc(size_t size); - void * calloc(size_t size); - char * strdup(const char *str); -}; - -#endif - diff --git a/src/server/shared/Configuration/CMakeLists.txt b/src/server/shared/Configuration/CMakeLists.txt new file mode 100644 index 00000000000..da1c2e8aa3b --- /dev/null +++ b/src/server/shared/Configuration/CMakeLists.txt @@ -0,0 +1,22 @@ + +########### next target ############### + +SET(trinityconfig_STAT_SRCS + dotconfpp/dotconfpp.cpp + dotconfpp/dotconfpp.h + dotconfpp/mempool.cpp + dotconfpp/mempool.h + Config.cpp + Config.h + ConfigEnv.h +) + +include_directories( + ${ACE_INCLUDE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/framework +) + +add_library(trinityconfig STATIC ${trinityconfig_STAT_SRCS}) + diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp new file mode 100644 index 00000000000..39830104a7c --- /dev/null +++ b/src/server/shared/Configuration/Config.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ConfigEnv.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(Config); + +Config::Config() : mIgnoreCase(true), mConf(NULL) +{ +} + +Config::~Config() +{ + delete mConf; +} + +bool Config::SetSource(const char *file, bool ignorecase) +{ + mIgnoreCase = ignorecase; + mFilename = file; + + return Reload(); +} + +bool Config::Reload() +{ + delete mConf; + + mConf = new DOTCONFDocument(mIgnoreCase ? + DOTCONFDocument::CASEINSENSETIVE : + DOTCONFDocument::CASESENSETIVE); + + if (mConf->setContent(mFilename.c_str()) == -1) + { + delete mConf; + mConf = NULL; + return false; + } + + return true; +} + +std::string Config::GetStringDefault(const char * name, std::string def) +{ + if(!mConf) + return std::string(def); + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return std::string(def); + return std::string(node->getValue()); +}; + +bool Config::GetBoolDefault(const char * name, const bool def) +{ + if(!mConf) + return false; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + const char * str = node->getValue(); + if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 || + strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 || + strcmp(str, "1") == 0) + return true; + else + return false; +}; + +int32 Config::GetIntDefault(const char * name, const int32 def) +{ + if(!mConf) + return def; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + return atoi(node->getValue()); +}; + +float Config::GetFloatDefault(const char * name, const float def) +{ + if(!mConf) + return def; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + return atof(node->getValue()); +}; diff --git a/src/server/shared/Configuration/Config.h b/src/server/shared/Configuration/Config.h new file mode 100644 index 00000000000..ccc76073e46 --- /dev/null +++ b/src/server/shared/Configuration/Config.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include "Platform/Define.h" + +class DOTCONFDocument; + +class Config +{ + public: + Config(); + ~Config(); + + bool SetSource(const char *file, bool ignorecase = true); + bool Reload(); + + std::string GetStringDefault(const char * name, std::string def); + bool GetBoolDefault(const char * name, const bool def); + int32 GetIntDefault(const char * name, const int32 def); + float GetFloatDefault(const char * name, const float def); + + std::string GetFilename() const { return mFilename; } + private: + std::string mFilename; + bool mIgnoreCase; + DOTCONFDocument *mConf; +}; + +#define sConfig Trinity::Singleton::Instance() + +#endif + diff --git a/src/server/shared/Configuration/ConfigEnv.h b/src/server/shared/Configuration/ConfigEnv.h new file mode 100644 index 00000000000..16e596fd2da --- /dev/null +++ b/src/server/shared/Configuration/ConfigEnv.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(CONFIGENVIRONMENT_H) + +#define CONFIGENVIRONMENT_H + +#include "Common.h" +#include "dotconfpp/dotconfpp.h" +#include "Config.h" + +#endif + diff --git a/src/server/shared/Configuration/ConfigLibrary.vcproj b/src/server/shared/Configuration/ConfigLibrary.vcproj new file mode 100644 index 00000000000..a8f1fc322e7 --- /dev/null +++ b/src/server/shared/Configuration/ConfigLibrary.vcproj @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp b/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp new file mode 100644 index 00000000000..8760b118e38 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp @@ -0,0 +1,599 @@ + +#include "Common.h" + +#include "dotconfpp.h" + +#ifdef WIN32 +#define PATH_MAX _MAX_PATH +#define strcasecmp stricmp +#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH) +#include +#else +#include +#include +#include +#include +#endif + +#if !defined(R_OK) +#define R_OK 04 +#endif + +DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), + values(NULL), valuesCount(0), + name(NULL), lineNum(0), fileName(NULL), closed(true) +{ +} + +DOTCONFDocumentNode::~DOTCONFDocumentNode() +{ + free(name); + if(values != NULL){ + for (int i = 0 ; i < valuesCount; i++){ + free(values[i]); + } + free(values); + } +} + +void DOTCONFDocumentNode::pushValue(char * _value) +{ + ++valuesCount; + values = (char**)realloc(values, valuesCount*sizeof(char*)); + values[valuesCount-1] = strdup(_value); +} + +const char* DOTCONFDocumentNode::getValue(int index) const +{ + if(index >= valuesCount){ + return NULL; + } + return values[index]; +} + +DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): + mempool(NULL), + curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL) +{ + if(caseSensitivity == CASESENSETIVE){ + cmp_func = strcmp; + } else { + cmp_func = strcasecmp; + } + + mempool = new AsyncDNSMemPool(1024); + mempool->initialize(); +} + +DOTCONFDocument::~DOTCONFDocument() +{ + for (std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){ + delete(*i); + } + for (std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){ + free(*i); + } + for (std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){ + free(*i); + } + free(fileName); + delete mempool; +} + +int DOTCONFDocument::cleanupLine(char * line) +{ + char * start = line; + char * bg = line; + bool multiline = false; + bool concat = false; + char * word = NULL; + + if(!words.empty() && quoted) + concat = true; + + while(*line){ + if((*line == '#' || *line == ';') && !quoted){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + break; + } + if(*line == '=' && !quoted){ + *line = ' ';continue; + } + + // Allowing \" in there causes problems with directory paths + // like "C:\TrinIty\" + //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ + if(*line == '\\' && (*(line+1) == '\'')) { + *bg++ = *(line+1); + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'n'){ + *bg++ = '\n'; + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'r'){ + *bg++ = '\r'; + line+=2; continue; + } + if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + multiline = true; + break; + } + if(*line == '"' || *line == '\''){ + quoted = !quoted; + ++line; continue; + } + if(isspace((unsigned char)*line) && !quoted){ + *bg++ = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + start = bg; + while(isspace((unsigned char)*++line)) {} + + continue; + } + *bg++ = *line++; + } + + if(quoted && !multiline){ + error(curLine, fileName, "unterminated quote"); + return -1; + } + + return multiline?1:0; +} + +int DOTCONFDocument::parseLine() +{ + char * word = NULL; + char * nodeName = NULL; + char * nodeValue = NULL; + DOTCONFDocumentNode * tagNode = NULL; + bool newNode = false; + + for (std::list::iterator i = words.begin(); i != words.end(); ++i) { + word = *i; + + if(*word == '<'){ + newNode = true; + } + + if(newNode){ + nodeValue = NULL; + nodeName = NULL; + newNode = false; + } + + size_t wordLen = strlen(word); + if(word[wordLen-1] == '>'){ + word[wordLen-1] = 0; + newNode = true; + } + + if(nodeName == NULL){ + nodeName = word; + bool closed = true; + if(*nodeName == '<'){ + if(*(nodeName+1) != '/'){ + ++nodeName; + closed = false; + } else { + nodeName+=2; + std::list::reverse_iterator itr=nodeTree.rbegin(); + for (; itr!=nodeTree.rend(); ++itr){ + if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){ + (*itr)->closed = true; + curParent = (*itr)->parentNode; + curPrev = *itr; + break; + } + } + if(itr==nodeTree.rend()){ + error(curLine, fileName, "not matched closing tag ", nodeName); + return -1; + } + continue; + } + } + tagNode = new DOTCONFDocumentNode; + tagNode->name = strdup(nodeName); + tagNode->document = this; + tagNode->fileName = processedFiles.back(); + tagNode->lineNum = curLine; + tagNode->closed = closed; + if(!nodeTree.empty()){ + DOTCONFDocumentNode * prev = nodeTree.back(); + if(prev->closed){ + + curPrev->nextNode = tagNode; + tagNode->previousNode = curPrev; + tagNode->parentNode = curParent; + + } else { + prev->childNode = tagNode; + tagNode->parentNode = prev; + curParent = prev; + } + } + nodeTree.push_back(tagNode); + curPrev = tagNode; + } else { + nodeValue = word; + tagNode->pushValue(nodeValue); + } + } + + return 0; +} +int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) +{ + char str[512]; + int ret = 0; + curLine = 0; + curParent = _parent; + + quoted = false; + size_t slen = 0; + + while(fgets(str, 511, file)){ + ++curLine; + slen = strlen(str); + if( slen >= 510 ){ + error(curLine, fileName, "warning: line too long"); + } + if(str[slen-1] != '\n'){ + str[slen] = '\n'; + str[slen+1] = 0; + } + if((ret = cleanupLine(str)) == -1){ + break; + } + if(ret == 0){ + if(!words.empty()){ + ret = parseLine(); + mempool->free(); + words.clear(); + if(ret == -1){ + break; + } + } + } + } + + return ret; +} + +int DOTCONFDocument::checkConfig(const std::list::iterator & from) +{ + int ret = 0; + + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for (std::list::iterator i = from; i != nodeTree.end(); ++i){ + tagNode = *i; + if(!tagNode->closed){ + error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); + ret = -1; + break; + } + vi = 0; + while( vi < tagNode->valuesCount ){ + + if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ + ret = macroSubstitute(tagNode, vi ); + mempool->free(); + if(ret == -1){ + break; + } + } + ++vi; + } + if(ret == -1){ + break; + } + } + + return ret; +} + +int DOTCONFDocument::setContent(const char * _fileName) +{ + int ret = 0; + char realpathBuf[PATH_MAX]; + + if(realpath(_fileName, realpathBuf) == NULL){ + error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + + processedFiles.push_back(strdup(realpathBuf)); + + if(( file = fopen(fileName, "r")) == NULL){ + error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); + return -1; + } + // Try read utf8 header and skip it if exist + uint32 utf8header = 0; + fgets((char*)&utf8header, 4, file); // Try read header + if (utf8header!=0x00BFBBEF) // If not exist + fseek(file, 0, SEEK_SET); // Reset read position + + ret = parseFile(); + + (void) fclose(file); + + if(!ret){ + + if( (ret = checkConfig(nodeTree.begin())) == -1){ + return -1; + } + + std::list::iterator from; + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + tagNode = *i; + if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){ + vi = 0; + while( vi < tagNode->valuesCount ){ + if(access(tagNode->values[vi], R_OK) == -1){ + error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + if(realpath(tagNode->values[vi], realpathBuf) == NULL){ + error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + bool processed = false; + for (std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){ + if(!strcmp(*itInode, realpathBuf)){ + processed = true; + break; + } + } + if(processed){ + break; + } + + processedFiles.push_back(strdup(realpathBuf)); + + file = fopen(tagNode->values[vi], "r"); + if(file == NULL){ + error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + from = nodeTree.end(); --from; + + ret = parseFile(); + (void) fclose(file); + if(ret == -1) + return -1; + if(checkConfig(++from) == -1){ + return -1; + } + ++vi; + } + } + } + + if(!requiredOptions.empty()) + ret = checkRequiredOptions(); + } + + return ret; +} + +int DOTCONFDocument::checkRequiredOptions() +{ + for (std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){ + bool matched = false; + for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + if(!cmp_func((*i)->name, *ci)){ + matched = true; + break; + } + } + if(!matched){ + error(0, NULL, "required option '%s' not specified", *ci); + return -1; + } + } + return 0; +} + +void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + + size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50; + char * buf = (char*)mempool->alloc(len); + + if(lineNum) + (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt); + else + (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt); + + (void) vfprintf(stderr, buf, args); + + va_end(args); +} + +char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) +{ + char * buf = NULL; + char * variable = macro+2; + + char * endBr = strchr(macro, '}'); + + if(!endBr){ + error(lineNum, fileName, "unterminated '{'"); + return NULL; + } + *endBr = 0; + + char * defaultValue = strchr(variable, ':'); + + if(defaultValue){ + *defaultValue++ = 0; + if(*defaultValue != '-'){ + error(lineNum, fileName, "incorrect macro substitution syntax"); + return NULL; + } + ++defaultValue; + if(*defaultValue == '"' || *defaultValue == '\''){ + ++defaultValue; + defaultValue[strlen(defaultValue)-1] = 0; + } + } else { + defaultValue = NULL; + } + + char * subs = getenv(variable); + if( subs ){ + buf = mempool->strdup(subs); + } else { + std::list::iterator i = nodeTree.begin(); + DOTCONFDocumentNode * tagNode = NULL; + for (; i!=nodeTree.end(); i++){ + tagNode = *i; + if(!cmp_func(tagNode->name, variable)){ + if(tagNode->valuesCount != 0){ + buf = mempool->strdup(tagNode->values[0]); + break; + } + } + } + if( i == nodeTree.end() ){ + if( defaultValue ){ + buf = mempool->strdup(defaultValue); + } else { + error(lineNum, fileName, "substitution not found and default value not given"); + return NULL; + } + } + } + return buf; +} + +int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) +{ + int ret = 0; + char * macro = tagNode->values[valueIndex]; + size_t valueLen = strlen(tagNode->values[valueIndex])+1; + char * value = (char*)mempool->alloc(valueLen); + char * v = value; + char * subs = NULL; + + while(*macro){ + if(*macro == '$' && *(macro+1) == '{'){ + char * m = strchr(macro, '}'); + subs = getSubstitution(macro, tagNode->lineNum); + if(subs == NULL){ + ret = -1; + break; + } + macro = m + 1; + *v = 0; + v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); + strcpy(v, value); + value = strcat(v, subs); + v = value + strlen(value); + continue; + } + *v++ = *macro++; + } + *v = 0; + + free(tagNode->values[valueIndex]); + tagNode->values[valueIndex] = strdup(value); + return ret; +} + +const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const +{ + if ( !nodeTree.empty() ) { + return *nodeTree.begin(); + } else { + return NULL; + } +} + +const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const +{ + + std::list::const_iterator i = nodeTree.begin(); + + if(startNode == NULL) + startNode = parentNode; + + if(startNode != NULL){ + while( i != nodeTree.end() && (*i) != startNode ){ + ++i; + } + if( i != nodeTree.end() ) ++i; + } + + for (; i!=nodeTree.end(); ++i){ + + if((*i)->parentNode != parentNode){ + continue; + } + if(!cmp_func(nodeName, (*i)->name)){ + return *i; + } + } + return NULL; +} + +void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) +{ + while(*requiredOptionNames){ + requiredOptions.push_back(strdup( *requiredOptionNames )); + ++requiredOptionNames; + } +} + diff --git a/src/server/shared/Configuration/dotconfpp/dotconfpp.h b/src/server/shared/Configuration/dotconfpp/dotconfpp.h new file mode 100644 index 00000000000..554b152f693 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/dotconfpp.h @@ -0,0 +1,97 @@ + + +#ifndef DOTCONFPP_H +#define DOTCONFPP_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "mempool.h" + +class DOTCONFDocument; + +class DOTCONFDocumentNode +{ +friend class DOTCONFDocument; +private: + DOTCONFDocumentNode * previousNode; + DOTCONFDocumentNode * nextNode; + DOTCONFDocumentNode * parentNode; + DOTCONFDocumentNode * childNode; + char ** values; + int valuesCount; + char * name; + const DOTCONFDocument * document; + int lineNum; + char * fileName; + bool closed; + + void pushValue(char * _value); + +public: + DOTCONFDocumentNode(); + ~DOTCONFDocumentNode(); + + const char * getConfigurationFileName()const { return fileName; } + int getConfigurationLineNumber() const { return lineNum; } + + const DOTCONFDocumentNode * getNextNode() const { return nextNode; } + const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } + const DOTCONFDocumentNode * getParentNode() const { return parentNode; } + const DOTCONFDocumentNode * getChildNode() const { return childNode; } + const char* getValue(int index = 0) const; + const char * getName() const { return name; } + const DOTCONFDocument * getDocument() const { return document; } +}; + +class DOTCONFDocument +{ +public: + enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE }; +protected: + AsyncDNSMemPool * mempool; +private: + DOTCONFDocumentNode * curParent; + DOTCONFDocumentNode * curPrev; + int curLine; + bool quoted; + std::list nodeTree; + std::list requiredOptions; + std::list processedFiles; + FILE * file; + char * fileName; + std::list words; + int (*cmp_func)(const char *, const char *); + + int checkRequiredOptions(); + int parseLine(); + int parseFile(DOTCONFDocumentNode * _parent = NULL); + int checkConfig(const std::list::iterator & from); + int cleanupLine(char * line); + char * getSubstitution(char * macro, int lineNum); + int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); + +protected: + virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5); + +public: + DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE); + virtual ~DOTCONFDocument(); + + int setContent(const char * _fileName); + + void setRequiredOptionNames(const char ** requiredOptionNames); + const DOTCONFDocumentNode * getFirstNode() const; + const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; +}; + +#endif + diff --git a/src/server/shared/Configuration/dotconfpp/mempool.cpp b/src/server/shared/Configuration/dotconfpp/mempool.cpp new file mode 100644 index 00000000000..a23e33808bd --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/mempool.cpp @@ -0,0 +1,100 @@ + + +#include "mempool.h" + +AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): + pool(NULL), pos(0), size(_size) +{ + pool = ::malloc(size); +} + +AsyncDNSMemPool::PoolChunk::~PoolChunk() +{ + ::free(pool); +} + +AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): + chunks(NULL), chunksCount(0), defaultSize(_defaultSize), + poolUsage(0), poolUsageCounter(0) +{ +} + +AsyncDNSMemPool::~AsyncDNSMemPool() +{ + for (size_t i = 0; isize - chunk->pos) >= size){ + chunk->pos += size; + return ((char*)chunk->pool) + chunk->pos - size; + } + } + addNewChunk(size); + chunks[chunksCount-1]->pos = size; + return chunks[chunksCount-1]->pool; +} + +void AsyncDNSMemPool::free() +{ + size_t pu = 0; + size_t psz = 0; + ++poolUsageCounter; + + for (size_t i = 0; ipos; + psz += chunks[i]->size; + chunks[i]->pos = 0; + } + poolUsage=(poolUsage>pu)?poolUsage:pu; + + if(poolUsageCounter >= 10 && chunksCount > 1){ + psz -= chunks[chunksCount-1]->size; + if(poolUsage < psz){ + --chunksCount; + delete chunks[chunksCount]; + } + poolUsage = 0; + poolUsageCounter = 0; + } +} + +void * AsyncDNSMemPool::calloc(size_t size) +{ + return ::memset(this->alloc(size), 0, size); +} + +char * AsyncDNSMemPool::strdup(const char *str) +{ + return ::strcpy((char*)this->alloc(strlen(str)+1), str); +} + diff --git a/src/server/shared/Configuration/dotconfpp/mempool.h b/src/server/shared/Configuration/dotconfpp/mempool.h new file mode 100644 index 00000000000..185b50798e1 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/mempool.h @@ -0,0 +1,46 @@ + + +#ifndef ASYNC_DNS_MEMPOOL_H +#define ASYNC_DNS_MEMPOOL_H + +#include +#include +#include + +#undef free +#undef calloc +#undef strdup + +class AsyncDNSMemPool +{ +private: + struct PoolChunk { + void * pool; + size_t pos; + size_t size; + + PoolChunk(size_t _size); + ~PoolChunk(); + }; + PoolChunk ** chunks; + size_t chunksCount; + size_t defaultSize; + + size_t poolUsage; + size_t poolUsageCounter; + + void addNewChunk(size_t size); + +public: + AsyncDNSMemPool(size_t _defaultSize = 4096); + virtual ~AsyncDNSMemPool(); + + int initialize(); + void free(); + void * alloc(size_t size); + void * calloc(size_t size); + char * strdup(const char *str); +}; + +#endif + diff --git a/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp b/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp new file mode 100644 index 00000000000..b34b922b16a --- /dev/null +++ b/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AuthCrypt.h" +#include "Hmac.h" +#include "Log.h" +#include "BigNumber.h" + +AuthCrypt::AuthCrypt() : _clientDecrypt(SHA_DIGEST_LENGTH), _serverEncrypt(SHA_DIGEST_LENGTH) +{ + _initialized = false; +} + +AuthCrypt::~AuthCrypt() +{ + +} + +void AuthCrypt::Init(BigNumber *K) +{ + uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; + HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); + uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); + + uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; + HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); + uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); + + //SARC4 _serverDecrypt(encryptHash); + _clientDecrypt.Init(decryptHash); + _serverEncrypt.Init(encryptHash); + //SARC4 _clientEncrypt(decryptHash); + + uint8 syncBuf[1024]; + + memset(syncBuf, 0, 1024); + + _serverEncrypt.UpdateData(1024, syncBuf); + //_clientEncrypt.UpdateData(1024, syncBuf); + + memset(syncBuf, 0, 1024); + + //_serverDecrypt.UpdateData(1024, syncBuf); + _clientDecrypt.UpdateData(1024, syncBuf); + + _initialized = true; +} + +void AuthCrypt::DecryptRecv(uint8 *data, size_t len) +{ + if (!_initialized) + return; + + _clientDecrypt.UpdateData(len, data); +} + +void AuthCrypt::EncryptSend(uint8 *data, size_t len) +{ + if (!_initialized) + return; + + _serverEncrypt.UpdateData(len, data); +} + diff --git a/src/server/shared/Cryptography/Authentication/AuthCrypt.h b/src/server/shared/Cryptography/Authentication/AuthCrypt.h new file mode 100644 index 00000000000..6695dc580cc --- /dev/null +++ b/src/server/shared/Cryptography/Authentication/AuthCrypt.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTHCRYPT_H +#define _AUTHCRYPT_H + +#include +#include "SARC4.h" + +class BigNumber; + +class AuthCrypt +{ + public: + AuthCrypt(); + ~AuthCrypt(); + + void Init(BigNumber *K); + void DecryptRecv(uint8 *, size_t); + void EncryptSend(uint8 *, size_t); + + bool IsInitialized() { return _initialized; } + + private: + SARC4 _clientDecrypt; + SARC4 _serverEncrypt; + bool _initialized; +}; +#endif + diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/server/shared/Cryptography/BigNumber.cpp new file mode 100644 index 00000000000..64e9ef21ccc --- /dev/null +++ b/src/server/shared/Cryptography/BigNumber.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/BigNumber.h" +#include +#include + +BigNumber::BigNumber() +{ + _bn = BN_new(); + _array = NULL; +} + +BigNumber::BigNumber(const BigNumber &bn) +{ + _bn = BN_dup(bn._bn); + _array = NULL; +} + +BigNumber::BigNumber(uint32 val) +{ + _bn = BN_new(); + BN_set_word(_bn, val); + _array = NULL; +} + +BigNumber::~BigNumber() +{ + BN_free(_bn); + if(_array) delete[] _array; +} + +void BigNumber::SetDword(uint32 val) +{ + BN_set_word(_bn, val); +} + +void BigNumber::SetQword(uint64 val) +{ + BN_add_word(_bn, (uint32)(val >> 32)); + BN_lshift(_bn, _bn, 32); + BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); +} + +void BigNumber::SetBinary(const uint8 *bytes, int len) +{ + uint8 t[1000]; + for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; + BN_bin2bn(t, len, _bn); +} + +void BigNumber::SetHexStr(const char *str) +{ + BN_hex2bn(&_bn, str); +} + +void BigNumber::SetRand(int numbits) +{ + BN_rand(_bn, numbits, 0, 1); +} + +BigNumber BigNumber::operator=(const BigNumber &bn) +{ + BN_copy(_bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator+=(const BigNumber &bn) +{ + BN_add(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator-=(const BigNumber &bn) +{ + BN_sub(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator*=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mul(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator/=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_div(_bn, NULL, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator%=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::Exp(const BigNumber &bn) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_exp(ret._bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +int BigNumber::GetNumBytes(void) +{ + return BN_num_bytes(_bn); +} + +uint32 BigNumber::AsDword() +{ + return (uint32)BN_get_word(_bn); +} + +bool BigNumber::isZero() const +{ + return BN_is_zero(_bn)!=0; +} + +uint8 *BigNumber::AsByteArray(int minSize, bool reverse) +{ + int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); + + if (_array) + { + delete[] _array; + _array = NULL; + } + _array = new uint8[length]; + + // If we need more bytes than length of BigNumber set the rest to 0 + if (length > GetNumBytes()) + memset((void*)_array, 0, length); + + BN_bn2bin(_bn, (unsigned char *)_array); + + if (reverse) + std::reverse(_array, _array + length); + + return _array; +} + +const char *BigNumber::AsHexStr() +{ + return BN_bn2hex(_bn); +} + +const char *BigNumber::AsDecStr() +{ + return BN_bn2dec(_bn); +} + diff --git a/src/server/shared/Cryptography/BigNumber.h b/src/server/shared/Cryptography/BigNumber.h new file mode 100644 index 00000000000..1dd43c83fc7 --- /dev/null +++ b/src/server/shared/Cryptography/BigNumber.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_BIGNUMBER_H +#define _AUTH_BIGNUMBER_H + +#include "Common.h" + +struct bignum_st; + +class BigNumber +{ + public: + BigNumber(); + BigNumber(const BigNumber &bn); + BigNumber(uint32); + ~BigNumber(); + + void SetDword(uint32); + void SetQword(uint64); + void SetBinary(const uint8 *bytes, int len); + void SetHexStr(const char *str); + + void SetRand(int numbits); + + BigNumber operator=(const BigNumber &bn); + + BigNumber operator+=(const BigNumber &bn); + BigNumber operator+(const BigNumber &bn) + { + BigNumber t(*this); + return t += bn; + } + BigNumber operator-=(const BigNumber &bn); + BigNumber operator-(const BigNumber &bn) + { + BigNumber t(*this); + return t -= bn; + } + BigNumber operator*=(const BigNumber &bn); + BigNumber operator*(const BigNumber &bn) + { + BigNumber t(*this); + return t *= bn; + } + BigNumber operator/=(const BigNumber &bn); + BigNumber operator/(const BigNumber &bn) + { + BigNumber t(*this); + return t /= bn; + } + BigNumber operator%=(const BigNumber &bn); + BigNumber operator%(const BigNumber &bn) + { + BigNumber t(*this); + return t %= bn; + } + + bool isZero() const; + + BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); + BigNumber Exp(const BigNumber &); + + int GetNumBytes(void); + + struct bignum_st *BN() { return _bn; } + + uint32 AsDword(); + uint8* AsByteArray(int minSize = 0, bool reverse = true); + + const char *AsHexStr(); + const char *AsDecStr(); + + private: + struct bignum_st *_bn; + uint8 *_array; +}; +#endif + diff --git a/src/server/shared/Cryptography/CMakeLists.txt b/src/server/shared/Cryptography/CMakeLists.txt new file mode 100644 index 00000000000..6e5d10d40e5 --- /dev/null +++ b/src/server/shared/Cryptography/CMakeLists.txt @@ -0,0 +1,27 @@ + +########### next target ############### + +SET(trinityauth_STAT_SRCS + AuthCrypt.cpp + AuthCrypt.h + BigNumber.cpp + BigNumber.h + Hmac.cpp + Hmac.h + Sha1.cpp + Sha1.h + md5.c + md5.h + SARC4.cpp + SARC4.h +) + +include_directories( + ${ACE_INCLUDE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/framework + ${MYSQL_INCLUDE_DIR} +) + +add_library(trinityauth STATIC ${trinityauth_STAT_SRCS}) diff --git a/src/server/shared/Cryptography/Hmac.cpp b/src/server/shared/Cryptography/Hmac.cpp new file mode 100644 index 00000000000..a30f1b2d1e2 --- /dev/null +++ b/src/server/shared/Cryptography/Hmac.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Hmac.h" +#include "BigNumber.h" + +HmacHash::HmacHash(uint32 len, uint8 *seed) +{ + HMAC_CTX_init(&m_ctx); + HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); +} + +HmacHash::~HmacHash() +{ + HMAC_CTX_cleanup(&m_ctx); +} + +void HmacHash::UpdateBigNumber(BigNumber *bn) +{ + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); +} + +void HmacHash::UpdateData(const uint8 *data, int length) +{ + HMAC_Update(&m_ctx, data, length); +} + +void HmacHash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void HmacHash::Finalize() +{ + uint32 length = 0; + HMAC_Final(&m_ctx, (uint8*)m_digest, &length); + ASSERT(length == SHA_DIGEST_LENGTH) +} + +uint8 *HmacHash::ComputeHash(BigNumber *bn) +{ + HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); + Finalize(); + return (uint8*)m_digest; +} diff --git a/src/server/shared/Cryptography/Hmac.h b/src/server/shared/Cryptography/Hmac.h new file mode 100644 index 00000000000..845d6e84802 --- /dev/null +++ b/src/server/shared/Cryptography/Hmac.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_HMAC_H +#define _AUTH_HMAC_H + +#include "Common.h" +#include +#include + +class BigNumber; + +#define SEED_KEY_SIZE 16 + +class HmacHash +{ + public: + HmacHash(uint32 len, uint8 *seed); + ~HmacHash(); + void UpdateBigNumber(BigNumber *bn); + void UpdateData(const uint8 *data, int length); + void UpdateData(const std::string &str); + void Finalize(); + uint8 *ComputeHash(BigNumber *bn); + uint8 *GetDigest() { return (uint8*)m_digest; } + int GetLength() { return SHA_DIGEST_LENGTH; } + private: + HMAC_CTX m_ctx; + uint8 m_digest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/SARC4.cpp b/src/server/shared/Cryptography/SARC4.cpp new file mode 100644 index 00000000000..80cad4991e9 --- /dev/null +++ b/src/server/shared/Cryptography/SARC4.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/SARC4.h" +#include + +SARC4::SARC4(uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); +} + +SARC4::SARC4(uint8 *seed, uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +SARC4::~SARC4() +{ + EVP_CIPHER_CTX_cleanup(&m_ctx); +} + +void SARC4::Init(uint8 *seed) +{ + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +void SARC4::UpdateData(int len, uint8 *data) +{ + int outlen = 0; + EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); + EVP_EncryptFinal_ex(&m_ctx, data, &outlen); +} diff --git a/src/server/shared/Cryptography/SARC4.h b/src/server/shared/Cryptography/SARC4.h new file mode 100644 index 00000000000..2e408627fc8 --- /dev/null +++ b/src/server/shared/Cryptography/SARC4.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SARC4_H +#define _AUTH_SARC4_H + +#include "Common.h" +#include + +class SARC4 +{ + public: + SARC4(uint8 len); + SARC4(uint8 *seed, uint8 len); + ~SARC4(); + void Init(uint8 *seed); + void UpdateData(int len, uint8 *data); + private: + EVP_CIPHER_CTX m_ctx; +}; +#endif diff --git a/src/server/shared/Cryptography/Sha1.cpp b/src/server/shared/Cryptography/Sha1.cpp new file mode 100644 index 00000000000..b63deb2c5f3 --- /dev/null +++ b/src/server/shared/Cryptography/Sha1.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Sha1.h" +#include "Auth/BigNumber.h" +#include + +Sha1Hash::Sha1Hash() +{ + SHA1_Init(&mC); +} + +Sha1Hash::~Sha1Hash() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::UpdateData(const uint8 *dta, int len) +{ + SHA1_Update(&mC, dta, len); +} + +void Sha1Hash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) +{ + va_list v; + BigNumber *bn; + + va_start(v, bn0); + bn = bn0; + while (bn) + { + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); + bn = va_arg(v, BigNumber *); + } + va_end(v); +} + +void Sha1Hash::Initialize() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::Finalize(void) +{ + SHA1_Final(mDigest, &mC); +} + diff --git a/src/server/shared/Cryptography/Sha1.h b/src/server/shared/Cryptography/Sha1.h new file mode 100644 index 00000000000..2d7f361ae9a --- /dev/null +++ b/src/server/shared/Cryptography/Sha1.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SHA1_H +#define _AUTH_SHA1_H + +#include "Common.h" +#include +#include + +class BigNumber; + +class Sha1Hash +{ + public: + Sha1Hash(); + ~Sha1Hash(); + + void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); + void UpdateBigNumbers(BigNumber *bn0, ...); + + void UpdateData(const uint8 *dta, int len); + void UpdateData(const std::string &str); + + void Initialize(); + void Finalize(); + + uint8 *GetDigest(void) { return mDigest; }; + int GetLength(void) { return SHA_DIGEST_LENGTH; }; + + private: + SHA_CTX mC; + uint8 mDigest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/md5.c b/src/server/shared/Cryptography/md5.c new file mode 100644 index 00000000000..3e9735e2dbb --- /dev/null +++ b/src/server/shared/Cryptography/md5.c @@ -0,0 +1,385 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.c is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order +either statically or dynamically; added missing #include +in library. +2002-03-11 lpd Corrected argument list for main(), and added int return +type, in test program and T value program. +2002-02-21 lpd Added missing #include in test program. +2000-07-03 lpd Patched to eliminate warnings about "constant is +unsigned in ANSI C, signed in traditional"; made test program +self-checking. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). +1999-05-03 lpd Original version. +*/ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + #if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; + #else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; + #endif + + { + #if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + #endif + #if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) + { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } + else + { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } + #endif + #if BYTE_ORDER == 0 + else /* dynamic big-endian */ + #endif + #if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + + # if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ + # else + # define xbuf X /* (static only) */ + # endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } + #endif + } + + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ + #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); + #undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ + #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); + #undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); + #undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ + #define I(x, y, z) ((y) ^ ((x) | ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); + #undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + ++pms->count[1]; + + /* Process an initial partial block. */ + if (offset) + { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/server/shared/Cryptography/md5.h b/src/server/shared/Cryptography/md5.h new file mode 100644 index 00000000000..0463051b6a6 --- /dev/null +++ b/src/server/shared/Cryptography/md5.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.h is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Removed support for non-ANSI compilers; removed +references to Ghostscript; clarified derivation from RFC 1321; +now handles byte order either statically or dynamically. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); +added conditionalization for C++ compilation from Martin +Purschke . +1999-05-03 lpd Original version. +*/ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ + #endif + + /* Initialize the algorithm. */ + void md5_init(md5_state_t *pms); + + /* Append a string to the message. */ + void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + + /* Finish the message and return the digest. */ + void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + + #ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* md5_INCLUDED */ + diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp new file mode 100644 index 00000000000..bad87a36fce --- /dev/null +++ b/src/server/shared/DataStores/DBCFileLoader.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "DBCFileLoader.h" + +DBCFileLoader::DBCFileLoader() +{ + data = NULL; + fieldsOffset = NULL; +} + +bool DBCFileLoader::Load(const char *filename, const char *fmt) +{ + uint32 header; + if (data) + { + delete [] data; + data = NULL; + } + + FILE * f = fopen(filename,"rb"); + if (!f) + return false; + + if (fread(&header,4,1,f)!=1) // Number of records + return false; + + EndianConvert(header); + + if (header!=0x43424457) + return false; //'WDBC' + + if (fread(&recordCount,4,1,f)!=1) // Number of records + return false; + + EndianConvert(recordCount); + + if (fread(&fieldCount,4,1,f)!=1) // Number of fields + return false; + + EndianConvert(fieldCount); + + if (fread(&recordSize,4,1,f)!=1) // Size of a record + return false; + + EndianConvert(recordSize); + + if (fread(&stringSize,4,1,f)!=1) // String size + return false; + + EndianConvert(stringSize); + + fieldsOffset = new uint32[fieldCount]; + fieldsOffset[0] = 0; + for (uint32 i = 1; i < fieldCount; i++) + { + fieldsOffset[i] = fieldsOffset[i - 1]; + if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields + fieldsOffset[i] += 1; + else // 4 byte fields (int32/float/strings) + fieldsOffset[i] += 4; + } + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + + if (fread(data,recordSize*recordCount+stringSize,1,f)!=1) + return false; + + fclose(f); + + return true; +} + +DBCFileLoader::~DBCFileLoader() +{ + if (data) + delete [] data; + + if (fieldsOffset) + delete [] fieldsOffset; +} + +DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x=0; format[x]; ++x) + { + switch(format[x]) + { + case FT_FLOAT: + case FT_INT: + recordsize+=4; + break; + case FT_STRING: + recordsize+=sizeof(char*); + break; + case FT_SORT: + i=x; + break; + case FT_IND: + i=x; + recordsize+=4; + break; + case FT_BYTE: + recordsize += 1; + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable) +{ + /* + format STRING, NA, FLOAT,NA,INT <=> + struct{ + char* field0, + float field1, + int field2 + }entry; + + this func will generate entry[rows] data; + */ + + typedef char * ptr; + if (strlen(format)!=fieldCount) + return NULL; + + //get struct size and index pos + int32 i; + uint32 recordsize=GetFormatRecordSize(format,&i); + + if (i>=0) + { + uint32 maxi=0; + //find max index + for (uint32 y=0; ymaxi)maxi=ind; + } + + // If higher index avalible from sql - use it instead of dbcs + if (sqlHighestIndex > maxi) + maxi = sqlHighestIndex; + + ++maxi; + records=maxi; + indexTable=new ptr[maxi]; + memset(indexTable,0,maxi*sizeof(ptr)); + } + else + { + records = recordCount + sqlRecordCount; + indexTable = new ptr[recordCount+ sqlRecordCount]; + } + + char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize]; + + uint32 offset=0; + + for (uint32 y =0; y=0) + indexTable[getRecord(y).getUInt(i)]=&dataTable[offset]; + else + indexTable[y]=&dataTable[offset]; + + for (uint32 x=0; x + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBC_FILE_LOADER_H +#define DBC_FILE_LOADER_H +#include "Platform/Define.h" +#include "Utilities/ByteConverter.h" +#include + +enum +{ + FT_NA='x', //not used or unknown, 4 byte size + FT_NA_BYTE='X', //not used or unknown, byte + FT_STRING='s', //char* + FT_FLOAT='f', //float + FT_INT='i', //uint32 + FT_BYTE='b', //uint8 + FT_SORT='d', //sorted by this field, field is not included + FT_IND='n', //the same,but parsed to data + FT_LOGIC='l', //Logical (boolean) + FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc + FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc +}; + +class DBCFileLoader +{ + public: + DBCFileLoader(); + ~DBCFileLoader(); + + bool Load(const char *filename, const char *fmt); + + class Record + { + public: + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + float val = *reinterpret_cast(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint32 getUInt(size_t field) const + { + assert(field < file.fieldCount); + uint32 val = *reinterpret_cast(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint8 getUInt8(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+file.GetOffset(field)); + } + + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + return reinterpret_cast(file.stringTable + stringOffset); + } + + private: + Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} + unsigned char *offset; + DBCFileLoader &file; + + friend class DBCFileLoader; + + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + + uint32 GetNumRows() const { return recordCount; } + uint32 GetRowSize() const { return recordSize; } + uint32 GetCols() const { return fieldCount; } + uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } + bool IsLoaded() { return data != NULL; } + char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable); + char* AutoProduceStrings(const char* fmt, char* dataTable); + static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); + private: + + uint32 recordSize; + uint32 recordCount; + uint32 fieldCount; + uint32 stringSize; + uint32 *fieldsOffset; + unsigned char *data; + unsigned char *stringTable; +}; +#endif diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h new file mode 100644 index 00000000000..61e2f7a6d06 --- /dev/null +++ b/src/server/shared/DataStores/DBCStore.h @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBCSTORE_H +#define DBCSTORE_H + +#include "DBCFileLoader.h" +#include "Log.h" + +struct SqlDbc +{ + const std::string * formatString; + const std::string * indexName; + std::string sqlTableName; + int32 indexPos; + int32 sqlIndexPos; + SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt) + :formatString(_format),sqlIndexPos(0), indexName (_idname) + { + // Convert dbc file name to sql table name + sqlTableName = *_filename; + for (uint32 i = 0; i< sqlTableName.size(); ++i) + { + if (isalpha(sqlTableName[i])) + sqlTableName[i] = tolower(sqlTableName[i]); + else if (sqlTableName[i] == '.') + sqlTableName[i] = '_'; + } + + // Get sql index position + DBCFileLoader::GetFormatRecordSize(fmt, &indexPos); + if (indexPos>=0) + { + for (int32 x=0; x < formatString->size(); x++) + { + // Count only fields present in sql + if ((*formatString)[x] == FT_SQL_PRESENT) + { + if (x == indexPos) + break; + ++sqlIndexPos; + } + } + } + } +}; + +template +class DBCStorage +{ + typedef std::list StringPoolList; + public: + explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } + ~DBCStorage() { Clear(); } + + T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } + uint32 GetNumRows() const { return nCount; } + char const* GetFormat() const { return fmt; } + uint32 GetFieldCount() const { return fieldCount; } + + bool Load(char const* fn, SqlDbc * sql) + { + DBCFileLoader dbc; + // Check if load was sucessful, only then continue + if (!dbc.Load(fn, fmt)) + return false; + + uint32 sqlRecordCount = 0; + uint32 sqlHighestIndex = 0; + Field *fields = NULL; + QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); + // Load data from sql + if (sql) + { + std::string query = "SELECT * FROM " + sql->sqlTableName; + if (sql->indexPos >= 0) + query +=" ORDER BY + " + *sql->indexName + " DESC"; + query += ";"; + + result = WorldDatabase.Query(query.c_str()); + if (result) + { + sqlRecordCount = result->GetRowCount(); + if (sql->indexPos >= 0) + { + fields = result->Fetch(); + sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32(); + } + // Check if sql index pos is valid + if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos) + { + sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str()); + return false; + } + } + } + char * sqlDataTable; + fieldCount = dbc.GetCols(); + m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable); + + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + // Insert sql data into arrays + if (result) + { + if (indexTable) + { + uint32 offset = 0; + uint32 rowIndex = dbc.GetNumRows(); + do + { + if (!fields) + fields = result->Fetch(); + + if(sql->indexPos >= 0) + { + uint32 id = fields[sql->sqlIndexPos].GetUInt32(); + if (indexTable[id]) + { + sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str()); + return false; + } + indexTable[id]=(T*)&sqlDataTable[offset]; + } + else + indexTable[rowIndex]=(T*)&sqlDataTable[offset]; + uint32 columnNumber = 0; + uint32 sqlColumnNumber = 0; + + for (; columnNumber < sql->formatString->size(); ++columnNumber) + { + if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT) + { + switch(fmt[columnNumber]) + { + case FT_FLOAT: + *((float*)(&sqlDataTable[offset]))= 0.0f; + offset+=4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&sqlDataTable[offset]))=uint32(0); + offset+=4; + break; + case FT_BYTE: + *((uint8*)(&sqlDataTable[offset]))=uint8(0); + offset+=1; + break; + case FT_STRING: + // Beginning of the pool - empty string + *((char**)(&sqlDataTable[offset]))=m_stringPoolList.back(); + offset+=sizeof(char*); + break; + } + } + else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT) + { + bool validSqlColumn = true; + switch(fmt[columnNumber]) + { + case FT_FLOAT: + *((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat(); + offset+=4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32(); + offset+=4; + break; + case FT_BYTE: + *((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8(); + offset+=1; + break; + case FT_STRING: + sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); + return false; + case FT_SORT: + break; + default: + validSqlColumn = false; + } + if (validSqlColumn && (columnNumber != (sql->formatString->size()-1))) + sqlColumnNumber++; + } + else + { + sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); + return false; + } + } + if (sqlColumnNumber != (result->GetFieldCount()-1)) + { + sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str()); + return false; + } + + fields = NULL; + ++rowIndex; + }while (result->NextRow()); + } + } + + // error in dbc file at loading if NULL + return indexTable!=NULL; + } + + bool LoadStringsFrom(char const* fn) + { + // DBC must be already loaded using Load + if(!indexTable) + return false; + + DBCFileLoader dbc; + // Check if load was successful, only then continue + if(!dbc.Load(fn, fmt)) + return false; + + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + return true; + } + + void Clear() + { + if (!indexTable) + return; + + delete[] ((char*)indexTable); + indexTable = NULL; + delete[] ((char*)m_dataTable); + m_dataTable = NULL; + + while(!m_stringPoolList.empty()) + { + delete[] m_stringPoolList.front(); + m_stringPoolList.pop_front(); + } + nCount = 0; + } + + private: + char const* fmt; + uint32 nCount; + uint32 fieldCount; + T** indexTable; + T* m_dataTable; + StringPoolList m_stringPoolList; +}; + +#endif diff --git a/src/server/shared/Database/DBCFileLoader.cpp b/src/server/shared/Database/DBCFileLoader.cpp deleted file mode 100644 index bad87a36fce..00000000000 --- a/src/server/shared/Database/DBCFileLoader.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include "DBCFileLoader.h" - -DBCFileLoader::DBCFileLoader() -{ - data = NULL; - fieldsOffset = NULL; -} - -bool DBCFileLoader::Load(const char *filename, const char *fmt) -{ - uint32 header; - if (data) - { - delete [] data; - data = NULL; - } - - FILE * f = fopen(filename,"rb"); - if (!f) - return false; - - if (fread(&header,4,1,f)!=1) // Number of records - return false; - - EndianConvert(header); - - if (header!=0x43424457) - return false; //'WDBC' - - if (fread(&recordCount,4,1,f)!=1) // Number of records - return false; - - EndianConvert(recordCount); - - if (fread(&fieldCount,4,1,f)!=1) // Number of fields - return false; - - EndianConvert(fieldCount); - - if (fread(&recordSize,4,1,f)!=1) // Size of a record - return false; - - EndianConvert(recordSize); - - if (fread(&stringSize,4,1,f)!=1) // String size - return false; - - EndianConvert(stringSize); - - fieldsOffset = new uint32[fieldCount]; - fieldsOffset[0] = 0; - for (uint32 i = 1; i < fieldCount; i++) - { - fieldsOffset[i] = fieldsOffset[i - 1]; - if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields - fieldsOffset[i] += 1; - else // 4 byte fields (int32/float/strings) - fieldsOffset[i] += 4; - } - - data = new unsigned char[recordSize*recordCount+stringSize]; - stringTable = data + recordSize*recordCount; - - if (fread(data,recordSize*recordCount+stringSize,1,f)!=1) - return false; - - fclose(f); - - return true; -} - -DBCFileLoader::~DBCFileLoader() -{ - if (data) - delete [] data; - - if (fieldsOffset) - delete [] fieldsOffset; -} - -DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) -{ - assert(data); - return Record(*this, data + id*recordSize); -} - -uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos) -{ - uint32 recordsize = 0; - int32 i = -1; - for (uint32 x=0; format[x]; ++x) - { - switch(format[x]) - { - case FT_FLOAT: - case FT_INT: - recordsize+=4; - break; - case FT_STRING: - recordsize+=sizeof(char*); - break; - case FT_SORT: - i=x; - break; - case FT_IND: - i=x; - recordsize+=4; - break; - case FT_BYTE: - recordsize += 1; - break; - } - } - - if (index_pos) - *index_pos = i; - - return recordsize; -} - -char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable) -{ - /* - format STRING, NA, FLOAT,NA,INT <=> - struct{ - char* field0, - float field1, - int field2 - }entry; - - this func will generate entry[rows] data; - */ - - typedef char * ptr; - if (strlen(format)!=fieldCount) - return NULL; - - //get struct size and index pos - int32 i; - uint32 recordsize=GetFormatRecordSize(format,&i); - - if (i>=0) - { - uint32 maxi=0; - //find max index - for (uint32 y=0; ymaxi)maxi=ind; - } - - // If higher index avalible from sql - use it instead of dbcs - if (sqlHighestIndex > maxi) - maxi = sqlHighestIndex; - - ++maxi; - records=maxi; - indexTable=new ptr[maxi]; - memset(indexTable,0,maxi*sizeof(ptr)); - } - else - { - records = recordCount + sqlRecordCount; - indexTable = new ptr[recordCount+ sqlRecordCount]; - } - - char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize]; - - uint32 offset=0; - - for (uint32 y =0; y=0) - indexTable[getRecord(y).getUInt(i)]=&dataTable[offset]; - else - indexTable[y]=&dataTable[offset]; - - for (uint32 x=0; x - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DBC_FILE_LOADER_H -#define DBC_FILE_LOADER_H -#include "Platform/Define.h" -#include "Utilities/ByteConverter.h" -#include - -enum -{ - FT_NA='x', //not used or unknown, 4 byte size - FT_NA_BYTE='X', //not used or unknown, byte - FT_STRING='s', //char* - FT_FLOAT='f', //float - FT_INT='i', //uint32 - FT_BYTE='b', //uint8 - FT_SORT='d', //sorted by this field, field is not included - FT_IND='n', //the same,but parsed to data - FT_LOGIC='l', //Logical (boolean) - FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc - FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc -}; - -class DBCFileLoader -{ - public: - DBCFileLoader(); - ~DBCFileLoader(); - - bool Load(const char *filename, const char *fmt); - - class Record - { - public: - float getFloat(size_t field) const - { - assert(field < file.fieldCount); - float val = *reinterpret_cast(offset+file.GetOffset(field)); - EndianConvert(val); - return val; - } - uint32 getUInt(size_t field) const - { - assert(field < file.fieldCount); - uint32 val = *reinterpret_cast(offset+file.GetOffset(field)); - EndianConvert(val); - return val; - } - uint8 getUInt8(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast(offset+file.GetOffset(field)); - } - - const char *getString(size_t field) const - { - assert(field < file.fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file.stringSize); - return reinterpret_cast(file.stringTable + stringOffset); - } - - private: - Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} - unsigned char *offset; - DBCFileLoader &file; - - friend class DBCFileLoader; - - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - - uint32 GetNumRows() const { return recordCount; } - uint32 GetRowSize() const { return recordSize; } - uint32 GetCols() const { return fieldCount; } - uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } - bool IsLoaded() { return data != NULL; } - char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable); - char* AutoProduceStrings(const char* fmt, char* dataTable); - static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); - private: - - uint32 recordSize; - uint32 recordCount; - uint32 fieldCount; - uint32 stringSize; - uint32 *fieldsOffset; - unsigned char *data; - unsigned char *stringTable; -}; -#endif diff --git a/src/server/shared/Database/DBCStore.h b/src/server/shared/Database/DBCStore.h deleted file mode 100644 index 61e2f7a6d06..00000000000 --- a/src/server/shared/Database/DBCStore.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DBCSTORE_H -#define DBCSTORE_H - -#include "DBCFileLoader.h" -#include "Log.h" - -struct SqlDbc -{ - const std::string * formatString; - const std::string * indexName; - std::string sqlTableName; - int32 indexPos; - int32 sqlIndexPos; - SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt) - :formatString(_format),sqlIndexPos(0), indexName (_idname) - { - // Convert dbc file name to sql table name - sqlTableName = *_filename; - for (uint32 i = 0; i< sqlTableName.size(); ++i) - { - if (isalpha(sqlTableName[i])) - sqlTableName[i] = tolower(sqlTableName[i]); - else if (sqlTableName[i] == '.') - sqlTableName[i] = '_'; - } - - // Get sql index position - DBCFileLoader::GetFormatRecordSize(fmt, &indexPos); - if (indexPos>=0) - { - for (int32 x=0; x < formatString->size(); x++) - { - // Count only fields present in sql - if ((*formatString)[x] == FT_SQL_PRESENT) - { - if (x == indexPos) - break; - ++sqlIndexPos; - } - } - } - } -}; - -template -class DBCStorage -{ - typedef std::list StringPoolList; - public: - explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } - ~DBCStorage() { Clear(); } - - T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } - uint32 GetNumRows() const { return nCount; } - char const* GetFormat() const { return fmt; } - uint32 GetFieldCount() const { return fieldCount; } - - bool Load(char const* fn, SqlDbc * sql) - { - DBCFileLoader dbc; - // Check if load was sucessful, only then continue - if (!dbc.Load(fn, fmt)) - return false; - - uint32 sqlRecordCount = 0; - uint32 sqlHighestIndex = 0; - Field *fields = NULL; - QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); - // Load data from sql - if (sql) - { - std::string query = "SELECT * FROM " + sql->sqlTableName; - if (sql->indexPos >= 0) - query +=" ORDER BY + " + *sql->indexName + " DESC"; - query += ";"; - - result = WorldDatabase.Query(query.c_str()); - if (result) - { - sqlRecordCount = result->GetRowCount(); - if (sql->indexPos >= 0) - { - fields = result->Fetch(); - sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32(); - } - // Check if sql index pos is valid - if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos) - { - sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str()); - return false; - } - } - } - char * sqlDataTable; - fieldCount = dbc.GetCols(); - m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable); - - m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); - - // Insert sql data into arrays - if (result) - { - if (indexTable) - { - uint32 offset = 0; - uint32 rowIndex = dbc.GetNumRows(); - do - { - if (!fields) - fields = result->Fetch(); - - if(sql->indexPos >= 0) - { - uint32 id = fields[sql->sqlIndexPos].GetUInt32(); - if (indexTable[id]) - { - sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str()); - return false; - } - indexTable[id]=(T*)&sqlDataTable[offset]; - } - else - indexTable[rowIndex]=(T*)&sqlDataTable[offset]; - uint32 columnNumber = 0; - uint32 sqlColumnNumber = 0; - - for (; columnNumber < sql->formatString->size(); ++columnNumber) - { - if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT) - { - switch(fmt[columnNumber]) - { - case FT_FLOAT: - *((float*)(&sqlDataTable[offset]))= 0.0f; - offset+=4; - break; - case FT_IND: - case FT_INT: - *((uint32*)(&sqlDataTable[offset]))=uint32(0); - offset+=4; - break; - case FT_BYTE: - *((uint8*)(&sqlDataTable[offset]))=uint8(0); - offset+=1; - break; - case FT_STRING: - // Beginning of the pool - empty string - *((char**)(&sqlDataTable[offset]))=m_stringPoolList.back(); - offset+=sizeof(char*); - break; - } - } - else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT) - { - bool validSqlColumn = true; - switch(fmt[columnNumber]) - { - case FT_FLOAT: - *((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat(); - offset+=4; - break; - case FT_IND: - case FT_INT: - *((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32(); - offset+=4; - break; - case FT_BYTE: - *((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8(); - offset+=1; - break; - case FT_STRING: - sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - case FT_SORT: - break; - default: - validSqlColumn = false; - } - if (validSqlColumn && (columnNumber != (sql->formatString->size()-1))) - sqlColumnNumber++; - } - else - { - sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - } - } - if (sqlColumnNumber != (result->GetFieldCount()-1)) - { - sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str()); - return false; - } - - fields = NULL; - ++rowIndex; - }while (result->NextRow()); - } - } - - // error in dbc file at loading if NULL - return indexTable!=NULL; - } - - bool LoadStringsFrom(char const* fn) - { - // DBC must be already loaded using Load - if(!indexTable) - return false; - - DBCFileLoader dbc; - // Check if load was successful, only then continue - if(!dbc.Load(fn, fmt)) - return false; - - m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); - - return true; - } - - void Clear() - { - if (!indexTable) - return; - - delete[] ((char*)indexTable); - indexTable = NULL; - delete[] ((char*)m_dataTable); - m_dataTable = NULL; - - while(!m_stringPoolList.empty()) - { - delete[] m_stringPoolList.front(); - m_stringPoolList.pop_front(); - } - nCount = 0; - } - - private: - char const* fmt; - uint32 nCount; - uint32 fieldCount; - T** indexTable; - T* m_dataTable; - StringPoolList m_stringPoolList; -}; - -#endif diff --git a/src/server/shared/Debugging/Errors.h b/src/server/shared/Debugging/Errors.h new file mode 100644 index 00000000000..15c6b1414ed --- /dev/null +++ b/src/server/shared/Debugging/Errors.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_ERRORS_H +#define TRINITYCORE_ERRORS_H + +#include "Common.h" + +#if PLATFORM != PLATFORM_WINDOWS +#ifndef HAVE_CONFIG_H +#include +#endif +#endif + +#ifdef HAVE_ACE_STACK_TRACE_H +#include "ace/Stack_Trace.h" +#endif + +#ifdef HAVE_ACE_STACK_TRACE_H // old versions ACE not have Stack_Trace.h but used at some oS for better compatibility +#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__,__FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); } } +#else +#define WPAssert( assertion ) { if (!(assertion)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED2:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #assertion); assert( #assertion &&0 ); } } +#endif +#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); } +#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); } + +#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); } + +#define ASSERT WPAssert +#endif + diff --git a/src/server/shared/Debugging/MemoryLeaks.cpp b/src/server/shared/Debugging/MemoryLeaks.cpp new file mode 100644 index 00000000000..ef7e36c3b57 --- /dev/null +++ b/src/server/shared/Debugging/MemoryLeaks.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MemoryLeaks.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1( MemoryManager ) ; + +MemoryManager::MemoryManager( ) +{ + #if COMPILER == MICROSOFT + // standard leak check initialization + //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + // uncomment to disable Visual Leak Detector from code + //VLDDisable(); + #endif +} diff --git a/src/server/shared/Debugging/MemoryLeaks.h b/src/server/shared/Debugging/MemoryLeaks.h new file mode 100644 index 00000000000..c8b8fb8e1b1 --- /dev/null +++ b/src/server/shared/Debugging/MemoryLeaks.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYSERVER_MEMORY_H +#define TRINITYSERVER_MEMORY_H + +#include "Platform/CompilerDefs.h" + +#if COMPILER == COMPILER_MICROSOFT + +#ifndef _WIN64 +// Visual Leak Detector support enabled +//#include +// standard Visual Studio leak check disabled, +//# define _CRTDBG_MAP_ALLOC +//# include +//# include +#else +//# define _CRTDBG_MAP_ALLOC +//# include +//# include +#endif + +#endif + + +#include "Policies/Singleton.h" + +struct MemoryManager : public Trinity::Singleton < MemoryManager > +{ + MemoryManager(); +}; +#endif diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp new file mode 100644 index 00000000000..8fb5d5e2d2a --- /dev/null +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -0,0 +1,1013 @@ +//========================================== +// Matt Pietrek +// MSDN Magazine, 2002 +// FILE: WheatyExceptionReport.CPP +//========================================== +#define WIN32_LEAN_AND_MEAN +#pragma warning(disable:4996) +#pragma warning(disable:4312) +#pragma warning(disable:4311) +#include +#include +#include +#include +#define _NO_CVCONST_H +#include +#include "WheatyExceptionReport.h" +#include "SystemConfig.h" +#include "revision.h" +#define CrashFolder _T("Crashes") +//#pragma comment(linker, "/defaultlib:dbghelp.lib") + +inline LPTSTR ErrorMessage(DWORD dw) +{ + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL); + return (LPTSTR)lpMsgBuf; +} + +//============================== Global Variables ============================= + +// +// Declare the static variables of the WheatyExceptionReport class +// +TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; +LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; +HANDLE WheatyExceptionReport::m_hReportFile; +HANDLE WheatyExceptionReport::m_hProcess; + +// Declare global instance of class +WheatyExceptionReport g_WheatyExceptionReport; + +//============================== Class Methods ============================= + +WheatyExceptionReport::WheatyExceptionReport() // Constructor +{ + // Install the unhandled exception filter function + m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); + m_hProcess = GetCurrentProcess(); +} + +//============ +// Destructor +//============ +WheatyExceptionReport::~WheatyExceptionReport() +{ + if (m_previousFilter) + SetUnhandledExceptionFilter(m_previousFilter); +} + +//=========================================================== +// Entry point where control comes on an unhandled exception +//=========================================================== +LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( +PEXCEPTION_POINTERS pExceptionInfo) +{ + TCHAR module_folder_name[MAX_PATH]; + GetModuleFileName(0, module_folder_name, MAX_PATH); + TCHAR* pos = _tcsrchr(module_folder_name, '\\'); + if (!pos) + return 0; + pos[0] = '\0'; + ++pos; + + TCHAR crash_folder_path[MAX_PATH]; + sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder); + if (!CreateDirectory(crash_folder_path, NULL)) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + return 0; + } + + SYSTEMTIME systime; + GetLocalTime(&systime); + sprintf(m_szLogFileName, "%s\\%s_[%u-%u_%u-%u-%u].txt", + crash_folder_path, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); + + m_hReportFile = CreateFile(m_szLogFileName, + GENERIC_WRITE, + 0, + 0, + OPEN_ALWAYS, + FILE_FLAG_WRITE_THROUGH, + 0); + + if (m_hReportFile) + { + SetFilePointer(m_hReportFile, 0, 0, FILE_END); + + GenerateExceptionReport(pExceptionInfo); + + CloseHandle(m_hReportFile); + m_hReportFile = 0; + } + + if (m_previousFilter) + return m_previousFilter(pExceptionInfo); + else + return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; +} + +BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) +{ + if (!sProcessorName) + return FALSE; + + HKEY hKey; + LONG lRet; + lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), + 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) + return FALSE; + TCHAR szTmp[2048]; + DWORD cntBytes = sizeof(szTmp); + lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL, + (LPBYTE)szTmp, &cntBytes); + if (lRet != ERROR_SUCCESS) + return FALSE; + ::RegCloseKey(hKey); + sProcessorName[0] = '\0'; + // Skip spaces + TCHAR* psz = szTmp; + while (iswspace(*psz)) + ++psz; + _tcsncpy(sProcessorName, psz, maxcount); + return TRUE; +} + +BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax) +{ + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + // If that fails, try using the OSVERSIONINFO structure. + OSVERSIONINFOEX osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + BOOL bOsVersionInfoEx; + bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!::GetVersionEx((OSVERSIONINFO*)&osvi)) + return FALSE; + } + *szVersion = _T('\0'); + TCHAR wszTmp[128]; + switch (osvi.dwPlatformId) + { + // Windows NT product family. + case VER_PLATFORM_WIN32_NT: + // Test for the specific product family. + if (osvi.dwMajorVersion == 6) + _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); + if (osvi.dwMajorVersion <= 4) + _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); + + // Test for specific product on Windows NT 4.0 SP6 and later. + if (bOsVersionInfoEx) + { + // Test for the workstation type. + #if WINVER < 0x0500 + if (osvi.wReserved[1] == VER_NT_WORKSTATION) + #else + if (osvi.wProductType == VER_NT_WORKSTATION) + #endif // WINVER < 0x0500 + { + if (osvi.dwMajorVersion == 4) + _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_PERSONAL) + #else + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Home Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_EMBEDDEDNT) + #else + else if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Embedded "), cntMax); + else + _tcsncat(szVersion, _T("Professional "), cntMax); + } + // Test for the server type. + #if WINVER < 0x0500 + else if (osvi.wReserved[1] == VER_NT_SERVER) + #else + else if (osvi.wProductType == VER_NT_SERVER) + #endif // WINVER < 0x0500 + { + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_DATACENTER) + #else + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Datacenter Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Enterprise Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] == VER_SUITE_BLADE) + #else + else if (osvi.wSuiteMask == VER_SUITE_BLADE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Web Edition "), cntMax); + else + _tcsncat(szVersion, _T("Standard Edition "), cntMax); + } + else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_DATACENTER) + #else + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Datacenter Server "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Advanced Server "), cntMax); + else + _tcsncat(szVersion, _T("Server "), cntMax); + } + else // Windows NT 4.0 + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); + else + _tcsncat(szVersion, _T("Server 4.0 "), cntMax); + } + } + } + // Display service pack (if any) and build number. + if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0) + { + HKEY hKey; + LONG lRet; + + // Test for SP6 versus SP6a. + lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey); + if (lRet == ERROR_SUCCESS) + { + _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"), + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + else // Windows NT 4.0 prior to SP6a + { + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + ::RegCloseKey(hKey); + } + else // Windows NT 3.51 and earlier or Windows 2000 and later + { + if (!_tcslen(osvi.szCSDVersion)) + _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"), + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + else + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + break; + default: + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + break; + } + + return TRUE; +} + +void WheatyExceptionReport::PrintSystemInfo() +{ + SYSTEM_INFO SystemInfo; + ::GetSystemInfo(&SystemInfo); + + MEMORYSTATUS MemoryStatus; + MemoryStatus.dwLength = sizeof (MEMORYSTATUS); + ::GlobalMemoryStatus(&MemoryStatus); + TCHAR sString[1024]; + _tprintf(_T("//=====================================================\r\n")); + if (_GetProcessorName(sString, countof(sString))) + _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), + sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); + else + _tprintf(_T("*** Hardware ***\r\nProcessor: \r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), + SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); + + if (_GetWindowsVersion(sString, countof(sString))) + _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); + else + _tprintf(_T("\r\n*** Operation System:\r\n\r\n")); +} + +//=========================================================================== +void WheatyExceptionReport::printTracesForAllThreads() +{ + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + DWORD dwOwnerPID = GetCurrentProcessId(); + m_hProcess = GetCurrentProcess(); + // Take a snapshot of all running threads + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) + return; + + // Fill in the size of the structure before using it. + te32.dwSize = sizeof(THREADENTRY32); + + // Retrieve information about the first thread, + // and exit if unsuccessful + if (!Thread32First(hThreadSnap, &te32)) + { + CloseHandle(hThreadSnap); // Must clean up the + // snapshot object! + return; + } + + // Now walk the thread list of the system, + // and display information about each thread + // associated with the specified process + do + { + if (te32.th32OwnerProcessID == dwOwnerPID) + { + CONTEXT context; + context.ContextFlags = 0xffffffff; + HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,false, te32.th32ThreadID); + if (threadHandle && GetThreadContext(threadHandle, &context)) + { + WriteStackDetails(&context, false, threadHandle); + } + CloseHandle(threadHandle); + } + } while(Thread32Next(hThreadSnap, &te32)); + +// Don't forget to clean up the snapshot object. + CloseHandle(hThreadSnap); +} + +//=========================================================================== +// Open the report file, and write the desired information to it. Called by +// WheatyUnhandledExceptionFilter +//=========================================================================== +void WheatyExceptionReport::GenerateExceptionReport( +PEXCEPTION_POINTERS pExceptionInfo) +{ + SYSTEMTIME systime; + GetLocalTime(&systime); + + // Start out with a banner + _tprintf(_T("Revision: %s\r\n"), _FULLVERSION); + _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); + PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; + + PrintSystemInfo(); + // First print information about the type of fault + _tprintf(_T("\r\n//=====================================================\r\n")); + _tprintf(_T("Exception code: %08X %s\r\n"), + pExceptionRecord->ExceptionCode, + GetExceptionString(pExceptionRecord->ExceptionCode)); + + // Now print information about where the fault occured + TCHAR szFaultingModule[MAX_PATH]; + DWORD section; + DWORD_PTR offset; + GetLogicalAddress(pExceptionRecord->ExceptionAddress, + szFaultingModule, + sizeof(szFaultingModule), + section, offset); + +#ifdef _M_IX86 + _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"), + pExceptionRecord->ExceptionAddress, + section, offset, szFaultingModule); +#endif +#ifdef _M_X64 + _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), + pExceptionRecord->ExceptionAddress, + section, offset, szFaultingModule); +#endif + + PCONTEXT pCtx = pExceptionInfo->ContextRecord; + + // Show the registers + #ifdef _M_IX86 // X86 Only! + _tprintf(_T("\r\nRegisters:\r\n")); + + _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n") + ,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, + pCtx->Esi, pCtx->Edi); + + _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip); + _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), + pCtx->SegSs, pCtx->Esp, pCtx->Ebp); + _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), + pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); + _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); + #endif + + #ifdef _M_X64 + _tprintf(_T("\r\nRegisters:\r\n")); + _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") + _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n") + ,pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, + pCtx->Rsi, pCtx->Rdi ,pCtx->R9,pCtx->R10,pCtx->R11,pCtx->R12,pCtx->R13,pCtx->R14,pCtx->R15); + _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); + _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), + pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); + _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), + pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); + _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); + #endif + + SymSetOptions(SYMOPT_DEFERRED_LOADS); + + // Initialize DbgHelp + if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) + { + _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"), + ErrorMessage(GetLastError())); + } + + CONTEXT trashableContext = *pCtx; + + WriteStackDetails(&trashableContext, false, NULL); + printTracesForAllThreads(); + +// #ifdef _M_IX86 // X86 Only! + + _tprintf(_T("========================\r\n")); + _tprintf(_T("Local Variables And Parameters\r\n")); + + trashableContext = *pCtx; + WriteStackDetails(&trashableContext, true, NULL); + + _tprintf(_T("========================\r\n")); + _tprintf(_T("Global Variables\r\n")); + + SymEnumSymbols(GetCurrentProcess(), + (DWORD64)GetModuleHandle(szFaultingModule), + 0, EnumerateSymbolsCallback, 0); + // #endif // X86 Only! + + SymCleanup(GetCurrentProcess()); + + _tprintf(_T("\r\n")); +} + +//====================================================================== +// Given an exception code, returns a pointer to a static string with a +// description of the exception +//====================================================================== +LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) +{ + #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); + + switch (dwCode) + { + EXCEPTION(ACCESS_VIOLATION) + EXCEPTION(DATATYPE_MISALIGNMENT) + EXCEPTION(BREAKPOINT) + EXCEPTION(SINGLE_STEP) + EXCEPTION(ARRAY_BOUNDS_EXCEEDED) + EXCEPTION(FLT_DENORMAL_OPERAND) + EXCEPTION(FLT_DIVIDE_BY_ZERO) + EXCEPTION(FLT_INEXACT_RESULT) + EXCEPTION(FLT_INVALID_OPERATION) + EXCEPTION(FLT_OVERFLOW) + EXCEPTION(FLT_STACK_CHECK) + EXCEPTION(FLT_UNDERFLOW) + EXCEPTION(INT_DIVIDE_BY_ZERO) + EXCEPTION(INT_OVERFLOW) + EXCEPTION(PRIV_INSTRUCTION) + EXCEPTION(IN_PAGE_ERROR) + EXCEPTION(ILLEGAL_INSTRUCTION) + EXCEPTION(NONCONTINUABLE_EXCEPTION) + EXCEPTION(STACK_OVERFLOW) + EXCEPTION(INVALID_DISPOSITION) + EXCEPTION(GUARD_PAGE) + EXCEPTION(INVALID_HANDLE) + } + + // If not one of the "known" exceptions, try to get the string + // from NTDLL.DLL's message table. + + static TCHAR szBuffer[512] = { 0 }; + + FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, + GetModuleHandle(_T("NTDLL.DLL")), + dwCode, 0, szBuffer, sizeof(szBuffer), 0); + + return szBuffer; +} + +//============================================================================= +// Given a linear address, locates the module, section, and offset containing +// that address. +// +// Note: the szModule paramater buffer is an output buffer of length specified +// by the len parameter (in characters!) +//============================================================================= +BOOL WheatyExceptionReport::GetLogicalAddress( +PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) +{ + MEMORY_BASIC_INFORMATION mbi; + + if (!VirtualQuery(addr, &mbi, sizeof(mbi))) + return FALSE; + + DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; + + if (!GetModuleFileName((HMODULE)hMod, szModule, len)) + return FALSE; + + // Point to the DOS header in memory + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; + + // From the DOS header, find the NT (PE) header + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew)); + + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); + + DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address + + // Iterate through the section table, looking for the one that encompasses + // the linear address. + for (unsigned i = 0; + i < pNtHdr->FileHeader.NumberOfSections; + i++, pSection++) + { + DWORD_PTR sectionStart = pSection->VirtualAddress; + DWORD_PTR sectionEnd = sectionStart + + DWORD_PTR(max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); + + // Is the address in this section??? + if ((rva >= sectionStart) && (rva <= sectionEnd)) + { + // Yes, address is in the section. Calculate section and offset, + // and store in the "section" & "offset" params, which were + // passed by reference. + section = i+1; + offset = rva - sectionStart; + return TRUE; + } + } + + return FALSE; // Should never get here! +} + +// It contains SYMBOL_INFO structure plus additional +// space for the name of the symbol +struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE +{ + CSymbolInfoPackage() + { + si.SizeOfStruct = sizeof(SYMBOL_INFO); + si.MaxNameLen = sizeof(name); + } +}; + +//============================================================ +// Walks the stack, and writes the results to the report file +//============================================================ +void WheatyExceptionReport::WriteStackDetails( +PCONTEXT pContext, +bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output +{ + _tprintf(_T("\r\nCall stack:\r\n")); + + _tprintf(_T("Address Frame Function SourceFile\r\n")); + + DWORD dwMachineType = 0; + // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag + + STACKFRAME64 sf; + memset(&sf, 0, sizeof(sf)); + + #ifdef _M_IX86 + // Initialize the STACKFRAME structure for the first call. This is only + // necessary for Intel CPUs, and isn't mentioned in the documentation. + sf.AddrPC.Offset = pContext->Eip; + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Offset = pContext->Esp; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Offset = pContext->Ebp; + sf.AddrFrame.Mode = AddrModeFlat; + + dwMachineType = IMAGE_FILE_MACHINE_I386; + #endif + +#ifdef _M_X64 + sf.AddrPC.Offset = pContext->Rip; + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Offset = pContext->Rsp; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Offset = pContext->Rbp; + sf.AddrFrame.Mode = AddrModeFlat; + dwMachineType = IMAGE_FILE_MACHINE_AMD64; +#endif + + while (1) + { + // Get the next stack frame + if (! StackWalk64(dwMachineType, + m_hProcess, + pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), + &sf, + pContext, + 0, + SymFunctionTableAccess64, + SymGetModuleBase64, + 0)) + break; + if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure + break; // the frame is OK. Bail if not. +#ifdef _M_IX86 + _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); +#endif +#ifdef _M_X64 + _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); +#endif + + DWORD64 symDisplacement = 0; // Displacement of the input address, + // relative to the start of the symbol + + // Get the name of the function for this stack frame entry + CSymbolInfoPackage sip; + if (SymFromAddr( + m_hProcess, // Process handle of the current process + sf.AddrPC.Offset, // Symbol address + &symDisplacement, // Address of the variable that will receive the displacement + &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) + { + _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement); + + } + else // No symbol found. Print out the logical address instead. + { + TCHAR szModule[MAX_PATH] = _T(""); + DWORD section = 0; + DWORD_PTR offset = 0; + + GetLogicalAddress((PVOID)sf.AddrPC.Offset, + szModule, sizeof(szModule), section, offset); +#ifdef _M_IX86 + _tprintf(_T("%04X:%08X %s"), section, offset, szModule); +#endif +#ifdef _M_X64 + _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule); +#endif + } + + // Get the source line for this stack frame entry + IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; + DWORD dwLineDisplacement; + if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, + &dwLineDisplacement, &lineInfo)) + { + _tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber); + } + + _tprintf(_T("\r\n")); + + // Write out the variables, if desired + if (bWriteVariables) + { + // Use SymSetContext to get just the locals/params for this frame + IMAGEHLP_STACK_FRAME imagehlpStackFrame; + imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; + SymSetContext(m_hProcess, &imagehlpStackFrame, 0); + + // Enumerate the locals/parameters + SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf); + + _tprintf(_T("\r\n")); + } + } + +} + +////////////////////////////////////////////////////////////////////////////// +// The function invoked by SymEnumSymbols +////////////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK +WheatyExceptionReport::EnumerateSymbolsCallback( +PSYMBOL_INFO pSymInfo, +ULONG SymbolSize, +PVOID UserContext) +{ + + char szBuffer[2048]; + + __try + { + if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, + szBuffer, sizeof(szBuffer))) + _tprintf(_T("\t%s\r\n"), szBuffer); + } + __except(1) + { + _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name); + } + + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// Given a SYMBOL_INFO representing a particular variable, displays its +// contents. If it's a user defined type, display the members and their +// values. +////////////////////////////////////////////////////////////////////////////// +bool WheatyExceptionReport::FormatSymbolValue( +PSYMBOL_INFO pSym, +STACKFRAME * sf, +char * pszBuffer, +unsigned cbBuffer) +{ + char * pszCurrBuffer = pszBuffer; + + // Indicate if the variable is a local or parameter + if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) + pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter "); + else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) + pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); + + // If it's a function, don't do anything. + if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK + return false; + + DWORD_PTR pVariable = 0; // Will point to the variable's data in memory + + if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) + { + // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) + { // This may change!!! + pVariable = sf->AddrFrame.Offset; + pVariable += (DWORD_PTR)pSym->Address; + } + // else + // return false; + } + else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) + { + return false; // Don't try to report register variable + } + else + { + pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable + } + + // Determine if the variable is a user defined type (UDT). IF so, bHandled + // will return true. + bool bHandled; + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer,pSym->ModBase, pSym->TypeIndex, + 0, pVariable, bHandled, pSym->Name); + + if (!bHandled) + { + // The symbol wasn't a UDT, so do basic, stupid formatting of the + // variable. Based on the size, we're assuming it's a char, WORD, or + // DWORD. + BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); + pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + + // Emit the variable name + pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name); + + pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size, + (PVOID)pVariable); + } + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// If it's a user defined type (UDT), recurse through its members until we're +// at fundamental types. When he hit fundamental types, return +// bHandled = false, so that FormatSymbolValue() will format them. +////////////////////////////////////////////////////////////////////////////// +char * WheatyExceptionReport::DumpTypeIndex( +char * pszCurrBuffer, +DWORD64 modBase, +DWORD dwTypeIndex, +unsigned nestingLevel, +DWORD_PTR offset, +bool & bHandled, +char* Name) +{ + bHandled = false; + + // Get the name of the symbol. This will either be a Type name (if a UDT), + // or the structure member name. + WCHAR * pwszTypeName; + if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, + &pwszTypeName)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName); + LocalFree(pwszTypeName); + } + + // Determine how many children this type has. + DWORD dwChildrenCount = 0; + SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, + &dwChildrenCount); + + if (!dwChildrenCount) // If no children, we're done + return pszCurrBuffer; + + // Prepare to get an array of "TypeIds", representing each of the children. + // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a + // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. + struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS + { + ULONG MoreChildIds[1024]; + FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} + } children; + + children.Count = dwChildrenCount; + children.Start= 0; + + // Get the array of TypeIds, one for each child type + if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, + &children)) + { + return pszCurrBuffer; + } + + // Append a line feed + pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); + + // Iterate through each of the children + for (unsigned i = 0; i < dwChildrenCount; i++) + { + // Add appropriate indentation level (since this routine is recursive) + for (unsigned j = 0; j <= nestingLevel+1; j++) + pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); + + // Recurse for each of the child types + bool bHandled2; + BasicType basicType = GetBasicType(children.ChildId[i], modBase); + pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, + children.ChildId[i], nestingLevel+1, + offset, bHandled2, ""/*Name */); + + // If the child wasn't a UDT, format it appropriately + if (!bHandled2) + { + // Get the offset of the child member, relative to its parent + DWORD dwMemberOffset; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], + TI_GET_OFFSET, &dwMemberOffset); + + // Get the real "TypeId" of the child. We need this for the + // SymGetTypeInfo(TI_GET_TYPEID) call below. + DWORD typeId; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], + TI_GET_TYPEID, &typeId); + + // Get the size of the child member + ULONG64 length; + SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH,&length); + + // Calculate the address of the member + DWORD_PTR dwFinalOffset = offset + dwMemberOffset; + + // BasicType basicType = GetBasicType(children.ChildId[i], modBase); + // + // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + // + // Emit the variable name + // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name); + + pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, + length, (PVOID)dwFinalOffset); + + pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); + } + } + + bHandled = true; + return pszCurrBuffer; +} + +char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, +BasicType basicType, +DWORD64 length, +PVOID pAddress) +{ + // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) + if (length == 1) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); + else if (length == 2) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); + else if (length == 4) + { + if (basicType == btFloat) + { + pszCurrBuffer += sprintf(pszCurrBuffer," = %f", *(PFLOAT)pAddress); + } + else if (basicType == btChar) + { + if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", + *(PDWORD)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", + *(PDWORD)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer," = %X", *(PDWORD)pAddress); + } + else if (length == 8) + { + if (basicType == btFloat) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", + *(double *)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", + *(DWORD64*)pAddress); + } + + return pszCurrBuffer; +} + +BasicType +WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) +{ + BasicType basicType; + if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, + TI_GET_BASETYPE, &basicType)) + { + return basicType; + } + + // Get the real "TypeId" of the child. We need this for the + // SymGetTypeInfo(TI_GET_TYPEID) call below. + DWORD typeId; + if (SymGetTypeInfo(m_hProcess,modBase, typeIndex, TI_GET_TYPEID, &typeId)) + { + if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, + &basicType)) + { + return basicType; + } + } + + return btNoType; +} + +//============================================================================ +// Helper function that writes to the report file, and allows the user to use +// printf style formating +//============================================================================ +int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) +{ + TCHAR szBuff[1024]; + int retValue; + DWORD cbWritten; + va_list argptr; + + va_start(argptr, format); + retValue = vsprintf(szBuff, format, argptr); + va_end(argptr); + + WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); + + return retValue; +} + diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h new file mode 100644 index 00000000000..33fb4bc5b0e --- /dev/null +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -0,0 +1,118 @@ +#ifndef _WHEATYEXCEPTIONREPORT_ +#define _WHEATYEXCEPTIONREPORT_ + +#include + +#if _MSC_VER < 1400 +# define countof(array) (sizeof(array) / sizeof(array[0])) +#else +# include +# define countof _countof +#endif // _MSC_VER < 1400 + +enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31 +}; + +const char* const rgBaseType[] = +{ + " ", // btNoType = 0, + " void ", // btVoid = 1, + " char* ", // btChar = 2, + " wchar_t* ", // btWChar = 3, + " signed char ", + " unsigned char ", + " int ", // btInt = 6, + " unsigned int ", // btUInt = 7, + " float ", // btFloat = 8, + " ", // btBCD = 9, + " bool ", // btBool = 10, + " short ", + " unsigned short ", + " long ", // btLong = 13, + " unsigned long ", // btULong = 14, + " __int8 ", + " __int16 ", + " __int32 ", + " __int64 ", + " __int128 ", + " unsigned __int8 ", + " unsigned __int16 ", + " unsigned __int32 ", + " unsigned __int64 ", + " unsigned __int128 ", + " ", // btCurrency = 25, + " ", // btDate = 26, + " VARIANT ", // btVariant = 27, + " ", // btComplex = 28, + " ", // btBit = 29, + " BSTR ", // btBSTR = 30, + " HRESULT " // btHresult = 31 +}; + +class WheatyExceptionReport +{ + public: + + WheatyExceptionReport(); + ~WheatyExceptionReport(); + + // entry point where control comes on an unhandled exception + static LONG WINAPI WheatyUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo); + + static void printTracesForAllThreads(); + private: + // where report info is extracted and generated + static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); + static void PrintSystemInfo(); + static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); + static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); + + // Helper functions + static LPTSTR GetExceptionString(DWORD dwCode); + static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, + DWORD& section, DWORD_PTR& offset); + + static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); + + static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); + + static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); + + static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*); + + static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress); + + static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); + + static int __cdecl _tprintf(const TCHAR * format, ...); + + // Variables used by the class + static TCHAR m_szLogFileName[MAX_PATH]; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static HANDLE m_hReportFile; + static HANDLE m_hProcess; +}; + +extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class +#endif //WheatyExceptionReport + diff --git a/src/server/shared/DelayExecutor.cpp b/src/server/shared/DelayExecutor.cpp deleted file mode 100644 index 9a718823232..00000000000 --- a/src/server/shared/DelayExecutor.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include - -#include "DelayExecutor.h" - -DelayExecutor* DelayExecutor::instance() -{ - return ACE_Singleton::instance(); -} - -DelayExecutor::DelayExecutor() - : activated_(false), pre_svc_hook_(0), post_svc_hook_(0) -{ -} - -DelayExecutor::~DelayExecutor() -{ - if (pre_svc_hook_) - delete pre_svc_hook_; - - if (post_svc_hook_) - delete post_svc_hook_; - - deactivate(); -} - -int DelayExecutor::deactivate() -{ - if (!activated()) - return -1; - - activated(false); - queue_.queue()->deactivate(); - wait(); - - return 0; -} - -int DelayExecutor::svc() -{ - if (pre_svc_hook_) - pre_svc_hook_->call(); - - for (;;) - { - ACE_Method_Request* rq = queue_.dequeue(); - - if (!rq) - break; - - rq->call(); - delete rq; - } - - if (post_svc_hook_) - post_svc_hook_->call(); - - return 0; -} - -int DelayExecutor::activate(int num_threads, ACE_Method_Request* pre_svc_hook, ACE_Method_Request* post_svc_hook) -{ - if (activated()) - return -1; - - if (num_threads < 1) - return -1; - - if (pre_svc_hook_) - delete pre_svc_hook_; - - if (post_svc_hook_) - delete post_svc_hook_; - - pre_svc_hook_ = pre_svc_hook; - post_svc_hook_ = post_svc_hook; - - queue_.queue()->activate(); - - if (ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, num_threads) == -1) - return -1; - - activated(true); - - return true; -} - -int DelayExecutor::execute(ACE_Method_Request* new_req) -{ - if (new_req == NULL) - return -1; - - if (queue_.enqueue(new_req, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) - { - delete new_req; - ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("DelayExecutor::execute enqueue")), -1); - } - - return 0; -} - -bool DelayExecutor::activated() -{ - return activated_; -} - -void DelayExecutor::activated(bool s) -{ - activated_ = s; -} diff --git a/src/server/shared/DelayExecutor.h b/src/server/shared/DelayExecutor.h deleted file mode 100644 index 664d8ca78a2..00000000000 --- a/src/server/shared/DelayExecutor.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _M_DELAY_EXECUTOR_H -#define _M_DELAY_EXECUTOR_H - -#include -#include -#include - -class DelayExecutor : protected ACE_Task_Base -{ - public: - - DelayExecutor(); - virtual ~DelayExecutor(); - - static DelayExecutor* instance(); - - int execute(ACE_Method_Request* new_req); - - int activate(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL); - - int deactivate(); - - bool activated(); - - virtual int svc(); - - private: - - ACE_Activation_Queue queue_; - ACE_Method_Request* pre_svc_hook_; - ACE_Method_Request* post_svc_hook_; - bool activated_; - - void activated(bool s); -}; - -#endif // _M_DELAY_EXECUTOR_H diff --git a/src/server/shared/Errors.h b/src/server/shared/Errors.h deleted file mode 100644 index 15c6b1414ed..00000000000 --- a/src/server/shared/Errors.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_ERRORS_H -#define TRINITYCORE_ERRORS_H - -#include "Common.h" - -#if PLATFORM != PLATFORM_WINDOWS -#ifndef HAVE_CONFIG_H -#include -#endif -#endif - -#ifdef HAVE_ACE_STACK_TRACE_H -#include "ace/Stack_Trace.h" -#endif - -#ifdef HAVE_ACE_STACK_TRACE_H // old versions ACE not have Stack_Trace.h but used at some oS for better compatibility -#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__,__FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); } } -#else -#define WPAssert( assertion ) { if (!(assertion)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED2:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #assertion); assert( #assertion &&0 ); } } -#endif -#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); } -#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); } - -#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); } - -#define ASSERT WPAssert -#endif - diff --git a/src/server/shared/LockedQueue.h b/src/server/shared/LockedQueue.h deleted file mode 100644 index 9f8afae6c14..00000000000 --- a/src/server/shared/LockedQueue.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LOCKEDQUEUE_H -#define LOCKEDQUEUE_H - -#include -#include -#include -#include -#include "Errors.h" - -namespace ACE_Based -{ - template > - class LockedQueue - { - //! Lock access to the queue. - LockType _lock; - - //! Storage backing the queue. - StorageType _queue; - - //! Cancellation flag. - volatile bool _canceled; - - public: - - //! Create a LockedQueue. - LockedQueue() - : _canceled(false) - { - } - - //! Destroy a LockedQueue. - virtual ~LockedQueue() - { - } - - //! Adds an item to the queue. - void add(const T& item) - { - lock(); - - //ASSERT(!this->_canceled); - // throw Cancellation_Exception(); - - _queue.push_back(item); - - unlock(); - } - - //! Gets the next result in the queue, if any. - bool next(T& result) - { - // ACE_Guard g(this->_lock); - ACE_GUARD_RETURN (LockType, g, this->_lock, false); - - if (_queue.empty()) - return false; - - //ASSERT (!_queue.empty() || !this->_canceled); - // throw Cancellation_Exception(); - result = _queue.front(); - _queue.pop_front(); - - return true; - } - - //! Peeks at the top of the queue. Remember to unlock after use. - T& peek() - { - lock(); - - T& result = _queue.front(); - - return result; - } - - //! Cancels the queue. - void cancel() - { - lock(); - - _canceled = true; - - unlock(); - } - - //! Checks if the queue is cancelled. - bool cancelled() - { - ACE_Guard g(this->_lock); - return _canceled; - } - - //! Locks the queue for access. - void lock() - { - this->_lock.acquire(); - } - - //! Unlocks the queue. - void unlock() - { - this->_lock.release(); - } - - ///! Calls pop_front of the queue - void pop_front() - { - ACE_GUARD (LockType, g, this->_lock); - _queue.pop_front(); - } - - ///! Checks if we're empty or not with locks held - bool empty() - { - ACE_GUARD_RETURN (LockType, g, this->_lock, false); - return _queue.empty(); - } - }; -} -#endif diff --git a/src/server/shared/Log.cpp b/src/server/shared/Log.cpp deleted file mode 100644 index 187b9eaa79b..00000000000 --- a/src/server/shared/Log.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Log.h" -#include "Policies/SingletonImp.h" -#include "Config/ConfigEnv.h" -#include "Util.h" - -#include -#include - -INSTANTIATE_SINGLETON_1( Log ); - -Log::Log() : - raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), - dberLogfile(NULL), chatLogfile(NULL), m_gmlog_per_account(false), - m_enableLogDBLater(false), m_enableLogDB(false), m_colored(false), - arenaLogFile(NULL) -{ - Initialize(); -} - -Log::~Log() -{ - if( logfile != NULL ) - fclose(logfile); - logfile = NULL; - - if( gmLogfile != NULL ) - fclose(gmLogfile); - gmLogfile = NULL; - - if (charLogfile != NULL) - fclose(charLogfile); - charLogfile = NULL; - - if( dberLogfile != NULL ) - fclose(dberLogfile); - dberLogfile = NULL; - - if (raLogfile != NULL) - fclose(raLogfile); - raLogfile = NULL; - - if (chatLogfile != NULL) - fclose(chatLogfile); - chatLogfile = NULL; - - if (arenaLogFile != NULL) - fclose(arenaLogFile); - arenaLogFile = NULL; -} - -void Log::SetLogLevel(char *Level) -{ - int32 NewLevel =atoi((char*)Level); - if ( NewLevel <0 ) - NewLevel = 0; - m_logLevel = NewLevel; - - outString( "LogLevel is %u",m_logLevel ); -} - -void Log::SetLogFileLevel(char *Level) -{ - int32 NewLevel =atoi((char*)Level); - if ( NewLevel <0 ) - NewLevel = 0; - m_logFileLevel = NewLevel; - - outString( "LogFileLevel is %u",m_logFileLevel ); -} - -void Log::SetDBLogLevel(char *Level) -{ - int32 NewLevel = atoi((char*)Level); - if ( NewLevel < 0 ) - NewLevel = 0; - m_dbLogLevel = NewLevel; - - outString( "DBLogLevel is %u",m_dbLogLevel ); -} - -void Log::Initialize() -{ - /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs - m_dbChar = sConfig.GetBoolDefault("LogDB.Char", false); - m_dbRA = sConfig.GetBoolDefault("LogDB.RA", false); - m_dbGM = sConfig.GetBoolDefault("LogDB.GM", false); - m_dbChat = sConfig.GetBoolDefault("LogDB.Chat", false); - - /// Realm must be 0 by default - SetRealmID(0); - - /// Common log files data - m_logsDir = sConfig.GetStringDefault("LogsDir",""); - if (!m_logsDir.empty()) - if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) - m_logsDir.append("/"); - - m_logsTimestamp = "_" + GetTimestampStr(); - - /// Open specific log files - logfile = openLogFile("LogFile","LogTimestamp","w"); - InitColors(sConfig.GetStringDefault("LogColors", "")); - - m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount",false); - if(!m_gmlog_per_account) - gmLogfile = openLogFile("GMLogFile","GmLogTimestamp","a"); - else - { - // GM log settings for per account case - m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", ""); - if(!m_gmlog_filename_format.empty()) - { - bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp",false); - - size_t dot_pos = m_gmlog_filename_format.find_last_of("."); - if(dot_pos!=m_gmlog_filename_format.npos) - { - if(m_gmlog_timestamp) - m_gmlog_filename_format.insert(dot_pos,m_logsTimestamp); - - m_gmlog_filename_format.insert(dot_pos,"_#%u"); - } - else - { - m_gmlog_filename_format += "_#%u"; - - if(m_gmlog_timestamp) - m_gmlog_filename_format += m_logsTimestamp; - } - - m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format; - } - } - - charLogfile = openLogFile("CharLogFile","CharLogTimestamp","a"); - - dberLogfile = openLogFile("DBErrorLogFile",NULL,"a"); - raLogfile = openLogFile("RaLogFile",NULL,"a"); - chatLogfile = openLogFile("ChatLogFile","ChatLogTimestamp","a"); - arenaLogFile = openLogFile("ArenaLogFile",NULL,"a"); - - // Main log file settings - m_logLevel = sConfig.GetIntDefault("LogLevel", LOGL_NORMAL); - m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", LOGL_NORMAL); - m_dbLogLevel = sConfig.GetIntDefault("DBLogLevel", LOGL_NORMAL); - - m_logFilter = 0; - - if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true)) - m_logFilter |= LOG_FILTER_TRANSPORT_MOVES; - if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true)) - m_logFilter |= LOG_FILTER_CREATURE_MOVES; - if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) - m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; - if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) - m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; - - // Char log settings - m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); - m_charLog_Dump_Separate = sConfig.GetBoolDefault("CharLogDump.Separate", false); - if (m_charLog_Dump_Separate) - { - m_dumpsDir = sConfig.GetStringDefault("CharLogDump.SeparateDir", ""); - if (!m_dumpsDir.empty()) - if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\')) - m_dumpsDir.append("/"); - } -} - -FILE* Log::openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode) -{ - std::string logfn=sConfig.GetStringDefault(configFileName, ""); - if(logfn.empty()) - return NULL; - - if(configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag,false)) - { - size_t dot_pos = logfn.find_last_of("."); - if(dot_pos!=logfn.npos) - logfn.insert(dot_pos,m_logsTimestamp); - else - logfn += m_logsTimestamp; - } - - return fopen((m_logsDir+logfn).c_str(), mode); -} - -FILE* Log::openGmlogPerAccount(uint32 account) -{ - if(m_gmlog_filename_format.empty()) - return NULL; - - char namebuf[TRINITY_PATH_MAX]; - snprintf(namebuf,TRINITY_PATH_MAX,m_gmlog_filename_format.c_str(),account); - return fopen(namebuf, "a"); -} - -void Log::outTimestamp(FILE* file) -{ - time_t t = time(NULL); - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); -} - -void Log::InitColors(const std::string& str) -{ - if(str.empty()) - { - m_colored = false; - return; - } - - int color[4]; - - std::istringstream ss(str); - - for (uint8 i = 0; i < LogLevels; ++i) - { - ss >> color[i]; - - if(!ss) - return; - - if(color[i] < 0 || color[i] >= Colors) - return; - } - - for (uint8 i = 0; i < LogLevels; ++i) - m_colors[i] = ColorTypes(color[i]); - - m_colored = true; -} - -void Log::SetColor(bool stdout_stream, ColorTypes color) -{ - #if PLATFORM == PLATFORM_WINDOWS - static WORD WinColorFG[Colors] = - { - 0, // BLACK - FOREGROUND_RED, // RED - FOREGROUND_GREEN, // GREEN - FOREGROUND_RED | FOREGROUND_GREEN, // BROWN - FOREGROUND_BLUE, // BLUE - FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA - FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE - // YELLOW - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, - // RED_BOLD - FOREGROUND_RED | FOREGROUND_INTENSITY, - // GREEN_BOLD - FOREGROUND_GREEN | FOREGROUND_INTENSITY, - FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD - // MAGENTA_BOLD - FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // CYAN_BOLD - FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // WHITE_BOLD - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY - }; - - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); - SetConsoleTextAttribute(hConsole, WinColorFG[color]); - #else - enum ANSITextAttr - { - TA_NORMAL=0, - TA_BOLD=1, - TA_BLINK=5, - TA_REVERSE=7 - }; - - enum ANSIFgTextAttr - { - FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, - FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW - }; - - enum ANSIBgTextAttr - { - BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, - BG_MAGENTA, BG_CYAN, BG_WHITE - }; - - static uint8 UnixColorFG[Colors] = - { - FG_BLACK, // BLACK - FG_RED, // RED - FG_GREEN, // GREEN - FG_BROWN, // BROWN - FG_BLUE, // BLUE - FG_MAGENTA, // MAGENTA - FG_CYAN, // CYAN - FG_WHITE, // WHITE - FG_YELLOW, // YELLOW - FG_RED, // LRED - FG_GREEN, // LGREEN - FG_BLUE, // LBLUE - FG_MAGENTA, // LMAGENTA - FG_CYAN, // LCYAN - FG_WHITE // LWHITE - }; - - fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : "")); - #endif -} - -void Log::ResetColor(bool stdout_stream) -{ - #if PLATFORM == PLATFORM_WINDOWS - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); - SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ); - #else - fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m"); - #endif -} - -std::string Log::GetTimestampStr() -{ - time_t t = time(NULL); - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - char buf[20]; - snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); - return std::string(buf); -} - -void Log::outDB(LogTypes type, const char * str) -{ - if (!str || type >= MAX_LOG_TYPES) - return; - - std::string new_str(str); - if (new_str.empty()) - return; - LoginDatabase.escape_string(new_str); - - LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " - "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str()); -} - -void Log::outString(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB) - { - // we don't want empty strings in the DB - std::string s(str); - if (s.empty() || s == " ") - return; - - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_STRING, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(true,m_colors[LOGL_NORMAL]); - - va_list ap; - - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - if(logfile) - { - outTimestamp(logfile); - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n"); - va_end(ap); - - fflush(logfile); - } - fflush(stdout); -} - -void Log::outString() -{ - printf("\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stdout); -} - -void Log::outCrash(const char * err, ...) -{ - if (!err) - return; - - if (m_enableLogDB) - { - va_list ap2; - va_start(ap2, err); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); - outDB(LOG_TYPE_CRASH, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stdout, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf(stderr, "\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "CRASH ALERT: "); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stderr); -} - -void Log::outError(const char * err, ...) -{ - if (!err) - return; - - if (m_enableLogDB) - { - va_list ap2; - va_start(ap2, err); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); - outDB(LOG_TYPE_ERROR, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stderr, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf( stderr, "\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "ERROR: "); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stderr); -} - -void Log::outArena(const char * str, ...) -{ - if (!str) - return; - - if (arenaLogFile) - { - va_list ap; - outTimestamp(arenaLogFile); - va_start(ap, str); - vfprintf(arenaLogFile, str, ap); - fprintf(arenaLogFile, "\n"); - va_end(ap); - fflush(arenaLogFile); - } - fflush(stdout); -} - -void Log::outErrorDb(const char * err, ...) -{ - if (!err) - return; - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stderr, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf( stderr, "\n" ); - - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "ERROR: " ); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n" ); - fflush(logfile); - } - - if (dberLogfile) - { - outTimestamp(dberLogfile); - va_start(ap, err); - vfprintf(dberLogfile, err, ap); - va_end(ap); - - fprintf(dberLogfile, "\n" ); - fflush(dberLogfile); - } - fflush(stderr); -} - -void Log::outBasic(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_BASIC, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_NORMAL) - { - if (m_colored) - SetColor(true,m_colors[LOGL_BASIC]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n" ); - va_end(ap); - fflush(logfile); - } - } - fflush(stdout); -} - -void Log::outDetail(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_DETAIL, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_BASIC) - { - if (m_colored) - SetColor(true,m_colors[LOGL_DETAIL]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - } - - fflush(stdout); -} - -void Log::outDebugInLine(const char * str, ...) -{ - if (!str) - return; - - if (m_logLevel > LOGL_DETAIL) - { - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - //if(m_colored) - // ResetColor(true); - - if (logfile) - { - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - } - } -} - -void Log::outDebug(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_DEBUG, nnew_str); - va_end(ap2); - } - - if( m_logLevel > LOGL_DETAIL ) - { - if (m_colored) - SetColor(true,m_colors[LOGL_DEBUG]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if(m_colored) - ResetColor(true); - - printf( "\n" ); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - - fprintf(logfile, "\n" ); - fflush(logfile); - } - } - fflush(stdout); -} - -void Log::outStringInLine(const char * str, ...) -{ - if (!str) - return; - - va_list ap; - - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (logfile) - { - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - } -} - -void Log::outCommand(uint32 account, const char * str, ...) -{ - if (!str) - return; - - // TODO: support accountid - if (m_enableLogDB && m_dbGM) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_GM, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_NORMAL) - { - if (m_colored) - SetColor(true,m_colors[LOGL_BASIC]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n" ); - va_end(ap); - fflush(logfile); - } - } - - if (m_gmlog_per_account) - { - if (FILE* per_file = openGmlogPerAccount (account)) - { - outTimestamp(per_file); - va_list ap; - va_start(ap, str); - vfprintf(per_file, str, ap); - fprintf(per_file, "\n" ); - va_end(ap); - fclose(per_file); - } - } - else if (gmLogfile) - { - outTimestamp(gmLogfile); - va_list ap; - va_start(ap, str); - vfprintf(gmLogfile, str, ap); - fprintf(gmLogfile, "\n" ); - va_end(ap); - fflush(gmLogfile); - } - - fflush(stdout); -} - -void Log::outChar(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbChar) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_CHAR, nnew_str); - va_end(ap2); - } - - if (charLogfile) - { - outTimestamp(charLogfile); - va_list ap; - va_start(ap, str); - vfprintf(charLogfile, str, ap); - fprintf(charLogfile, "\n" ); - va_end(ap); - fflush(charLogfile); - } -} - -void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name) -{ - FILE *file = NULL; - if (m_charLog_Dump_Separate) - { - char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0 - snprintf(fileName, 29, "%d_%s.log", guid, name); - std::string sFileName(m_dumpsDir); - sFileName.append(fileName); - file = fopen((m_logsDir + sFileName).c_str(), "w"); - } - else - file = charLogfile; - if (file) - { - fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", - account_id, guid, name, str); - fflush(file); - if (m_charLog_Dump_Separate) - fclose(file); - } -} - -void Log::outRemote(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbRA) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_RA, nnew_str); - va_end(ap2); - } - - if (raLogfile) - { - outTimestamp(raLogfile); - va_list ap; - va_start(ap, str); - vfprintf(raLogfile, str, ap); - fprintf(raLogfile, "\n" ); - va_end(ap); - fflush(raLogfile); - } - fflush(stdout); -} - -void Log::outChat(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbChat) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_CHAT, nnew_str); - va_end(ap2); - } - - if (chatLogfile) - { - outTimestamp(chatLogfile); - va_list ap; - va_start(ap, str); - vfprintf(chatLogfile, str, ap); - fprintf(chatLogfile, "\n" ); - fflush(chatLogfile); - va_end(ap); - } - fflush(stdout); -} - -void outstring_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outString(buf); -} - -void detail_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outDetail(buf); -} - -void debug_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outDebug(buf); -} - -void error_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outError(buf); -} - -void error_db_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outErrorDb(buf); -} - diff --git a/src/server/shared/Log.h b/src/server/shared/Log.h deleted file mode 100644 index deb6c55e4e0..00000000000 --- a/src/server/shared/Log.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_LOG_H -#define TRINITYCORE_LOG_H - -#include "Common.h" -#include "Policies/Singleton.h" -#include "Database/DatabaseEnv.h" - -class Config; - -enum LogFilters -{ - LOG_FILTER_TRANSPORT_MOVES = 1, - LOG_FILTER_CREATURE_MOVES = 2, - LOG_FILTER_VISIBILITY_CHANGES = 4, - LOG_FILTER_ACHIEVEMENT_UPDATES = 8 -}; - -enum LogTypes -{ - LOG_TYPE_STRING = 0, - LOG_TYPE_ERROR = 1, - LOG_TYPE_BASIC = 2, - LOG_TYPE_DETAIL = 3, - LOG_TYPE_DEBUG = 4, - LOG_TYPE_CHAR = 5, - LOG_TYPE_WORLD = 6, - LOG_TYPE_RA = 7, - LOG_TYPE_GM = 8, - LOG_TYPE_CRASH = 9, - LOG_TYPE_CHAT = 10, - MAX_LOG_TYPES -}; - -enum LogLevel -{ - LOGL_NORMAL = 0, - LOGL_BASIC, - LOGL_DETAIL, - LOGL_DEBUG -}; - -const int LogLevels = int(LOGL_DEBUG)+1; - -enum ColorTypes -{ - BLACK, - RED, - GREEN, - BROWN, - BLUE, - MAGENTA, - CYAN, - GREY, - YELLOW, - LRED, - LGREEN, - LBLUE, - LMAGENTA, - LCYAN, - WHITE -}; - -const int Colors = int(WHITE)+1; - -class Log : public Trinity::Singleton > -{ - friend class Trinity::OperatorNew; - Log(); - ~Log(); - - public: - void Initialize(); - - void InitColors(const std::string& init_str); - void SetColor(bool stdout_stream, ColorTypes color); - void ResetColor(bool stdout_stream); - - void outDB( LogTypes type, const char * str ); - void outString( const char * str, ... ) ATTR_PRINTF(2,3); - void outString( ); - void outStringInLine( const char * str, ... ) ATTR_PRINTF(2,3); - void outError( const char * err, ... ) ATTR_PRINTF(2,3); - void outCrash( const char * err, ... ) ATTR_PRINTF(2,3); - void outBasic( const char * str, ... ) ATTR_PRINTF(2,3); - void outDetail( const char * str, ... ) ATTR_PRINTF(2,3); - void outDebug( const char * str, ... ) ATTR_PRINTF(2,3); - void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3); - void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3); - void outChar( const char * str, ... ) ATTR_PRINTF(2,3); - void outCommand( uint32 account, const char * str, ...) ATTR_PRINTF(3,4); - void outRemote( const char * str, ... ) ATTR_PRINTF(2,3); - void outChat( const char * str, ... ) ATTR_PRINTF(2,3); - void outArena( const char * str, ... ) ATTR_PRINTF(2,3); - void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name ); - - static void outTimestamp(FILE* file); - static std::string GetTimestampStr(); - - void SetLogLevel(char * Level); - void SetLogFileLevel(char * Level); - void SetDBLogLevel(char * Level); - void SetRealmID(uint32 id) { realm = id; } - - uint32 getLogFilter() const { return m_logFilter; } - bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } - bool IsOutCharDump() const { return m_charLog_Dump; } - - bool GetLogDB() { return m_enableLogDB; } - bool GetLogDBLater() { return m_enableLogDBLater; } - void SetLogDB(bool enable) { m_enableLogDB = enable; } - void SetLogDBLater(bool value) { m_enableLogDBLater = value; } - private: - FILE* openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode); - FILE* openGmlogPerAccount(uint32 account); - - FILE* raLogfile; - FILE* logfile; - FILE* gmLogfile; - FILE* charLogfile; - FILE* dberLogfile; - FILE* chatLogfile; - FILE* arenaLogFile; - - // cache values for after initilization use (like gm log per account case) - std::string m_logsDir; - std::string m_logsTimestamp; - - // gm log control - bool m_gmlog_per_account; - std::string m_gmlog_filename_format; - - bool m_enableLogDBLater; - bool m_enableLogDB; - uint32 realm; - - // log coloring - bool m_colored; - ColorTypes m_colors[4]; - - // log levels: - // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug - uint8 m_dbLogLevel; - uint8 m_logLevel; - uint8 m_logFileLevel; - uint8 m_logFilter; - bool m_dbChar; - bool m_dbRA; - bool m_dbGM; - bool m_dbChat; - bool m_charLog_Dump; - bool m_charLog_Dump_Separate; - std::string m_dumpsDir; -}; - -#define sLog Trinity::Singleton::Instance() - -#ifdef TRINITY_DEBUG -#define DEBUG_LOG Trinity::Singleton::Instance().outDebug -#else -#define DEBUG_LOG -#endif - -// primary for script library -void outstring_log(const char * str, ...) ATTR_PRINTF(1,2); -void detail_log(const char * str, ...) ATTR_PRINTF(1,2); -void debug_log(const char * str, ...) ATTR_PRINTF(1,2); -void error_log(const char * str, ...) ATTR_PRINTF(1,2); -void error_db_log(const char * str, ...) ATTR_PRINTF(1,2); -#endif - diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp new file mode 100644 index 00000000000..187b9eaa79b --- /dev/null +++ b/src/server/shared/Logging/Log.cpp @@ -0,0 +1,1005 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "Policies/SingletonImp.h" +#include "Config/ConfigEnv.h" +#include "Util.h" + +#include +#include + +INSTANTIATE_SINGLETON_1( Log ); + +Log::Log() : + raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), + dberLogfile(NULL), chatLogfile(NULL), m_gmlog_per_account(false), + m_enableLogDBLater(false), m_enableLogDB(false), m_colored(false), + arenaLogFile(NULL) +{ + Initialize(); +} + +Log::~Log() +{ + if( logfile != NULL ) + fclose(logfile); + logfile = NULL; + + if( gmLogfile != NULL ) + fclose(gmLogfile); + gmLogfile = NULL; + + if (charLogfile != NULL) + fclose(charLogfile); + charLogfile = NULL; + + if( dberLogfile != NULL ) + fclose(dberLogfile); + dberLogfile = NULL; + + if (raLogfile != NULL) + fclose(raLogfile); + raLogfile = NULL; + + if (chatLogfile != NULL) + fclose(chatLogfile); + chatLogfile = NULL; + + if (arenaLogFile != NULL) + fclose(arenaLogFile); + arenaLogFile = NULL; +} + +void Log::SetLogLevel(char *Level) +{ + int32 NewLevel =atoi((char*)Level); + if ( NewLevel <0 ) + NewLevel = 0; + m_logLevel = NewLevel; + + outString( "LogLevel is %u",m_logLevel ); +} + +void Log::SetLogFileLevel(char *Level) +{ + int32 NewLevel =atoi((char*)Level); + if ( NewLevel <0 ) + NewLevel = 0; + m_logFileLevel = NewLevel; + + outString( "LogFileLevel is %u",m_logFileLevel ); +} + +void Log::SetDBLogLevel(char *Level) +{ + int32 NewLevel = atoi((char*)Level); + if ( NewLevel < 0 ) + NewLevel = 0; + m_dbLogLevel = NewLevel; + + outString( "DBLogLevel is %u",m_dbLogLevel ); +} + +void Log::Initialize() +{ + /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs + m_dbChar = sConfig.GetBoolDefault("LogDB.Char", false); + m_dbRA = sConfig.GetBoolDefault("LogDB.RA", false); + m_dbGM = sConfig.GetBoolDefault("LogDB.GM", false); + m_dbChat = sConfig.GetBoolDefault("LogDB.Chat", false); + + /// Realm must be 0 by default + SetRealmID(0); + + /// Common log files data + m_logsDir = sConfig.GetStringDefault("LogsDir",""); + if (!m_logsDir.empty()) + if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) + m_logsDir.append("/"); + + m_logsTimestamp = "_" + GetTimestampStr(); + + /// Open specific log files + logfile = openLogFile("LogFile","LogTimestamp","w"); + InitColors(sConfig.GetStringDefault("LogColors", "")); + + m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount",false); + if(!m_gmlog_per_account) + gmLogfile = openLogFile("GMLogFile","GmLogTimestamp","a"); + else + { + // GM log settings for per account case + m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", ""); + if(!m_gmlog_filename_format.empty()) + { + bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp",false); + + size_t dot_pos = m_gmlog_filename_format.find_last_of("."); + if(dot_pos!=m_gmlog_filename_format.npos) + { + if(m_gmlog_timestamp) + m_gmlog_filename_format.insert(dot_pos,m_logsTimestamp); + + m_gmlog_filename_format.insert(dot_pos,"_#%u"); + } + else + { + m_gmlog_filename_format += "_#%u"; + + if(m_gmlog_timestamp) + m_gmlog_filename_format += m_logsTimestamp; + } + + m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format; + } + } + + charLogfile = openLogFile("CharLogFile","CharLogTimestamp","a"); + + dberLogfile = openLogFile("DBErrorLogFile",NULL,"a"); + raLogfile = openLogFile("RaLogFile",NULL,"a"); + chatLogfile = openLogFile("ChatLogFile","ChatLogTimestamp","a"); + arenaLogFile = openLogFile("ArenaLogFile",NULL,"a"); + + // Main log file settings + m_logLevel = sConfig.GetIntDefault("LogLevel", LOGL_NORMAL); + m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", LOGL_NORMAL); + m_dbLogLevel = sConfig.GetIntDefault("DBLogLevel", LOGL_NORMAL); + + m_logFilter = 0; + + if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true)) + m_logFilter |= LOG_FILTER_TRANSPORT_MOVES; + if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true)) + m_logFilter |= LOG_FILTER_CREATURE_MOVES; + if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) + m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; + if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) + m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; + + // Char log settings + m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); + m_charLog_Dump_Separate = sConfig.GetBoolDefault("CharLogDump.Separate", false); + if (m_charLog_Dump_Separate) + { + m_dumpsDir = sConfig.GetStringDefault("CharLogDump.SeparateDir", ""); + if (!m_dumpsDir.empty()) + if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\')) + m_dumpsDir.append("/"); + } +} + +FILE* Log::openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode) +{ + std::string logfn=sConfig.GetStringDefault(configFileName, ""); + if(logfn.empty()) + return NULL; + + if(configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag,false)) + { + size_t dot_pos = logfn.find_last_of("."); + if(dot_pos!=logfn.npos) + logfn.insert(dot_pos,m_logsTimestamp); + else + logfn += m_logsTimestamp; + } + + return fopen((m_logsDir+logfn).c_str(), mode); +} + +FILE* Log::openGmlogPerAccount(uint32 account) +{ + if(m_gmlog_filename_format.empty()) + return NULL; + + char namebuf[TRINITY_PATH_MAX]; + snprintf(namebuf,TRINITY_PATH_MAX,m_gmlog_filename_format.c_str(),account); + return fopen(namebuf, "a"); +} + +void Log::outTimestamp(FILE* file) +{ + time_t t = time(NULL); + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); +} + +void Log::InitColors(const std::string& str) +{ + if(str.empty()) + { + m_colored = false; + return; + } + + int color[4]; + + std::istringstream ss(str); + + for (uint8 i = 0; i < LogLevels; ++i) + { + ss >> color[i]; + + if(!ss) + return; + + if(color[i] < 0 || color[i] >= Colors) + return; + } + + for (uint8 i = 0; i < LogLevels; ++i) + m_colors[i] = ColorTypes(color[i]); + + m_colored = true; +} + +void Log::SetColor(bool stdout_stream, ColorTypes color) +{ + #if PLATFORM == PLATFORM_WINDOWS + static WORD WinColorFG[Colors] = + { + 0, // BLACK + FOREGROUND_RED, // RED + FOREGROUND_GREEN, // GREEN + FOREGROUND_RED | FOREGROUND_GREEN, // BROWN + FOREGROUND_BLUE, // BLUE + FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA + FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE + // YELLOW + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + // RED_BOLD + FOREGROUND_RED | FOREGROUND_INTENSITY, + // GREEN_BOLD + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD + // MAGENTA_BOLD + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + // CYAN_BOLD + FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + // WHITE_BOLD + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY + }; + + HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); + SetConsoleTextAttribute(hConsole, WinColorFG[color]); + #else + enum ANSITextAttr + { + TA_NORMAL=0, + TA_BOLD=1, + TA_BLINK=5, + TA_REVERSE=7 + }; + + enum ANSIFgTextAttr + { + FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, + FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW + }; + + enum ANSIBgTextAttr + { + BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, + BG_MAGENTA, BG_CYAN, BG_WHITE + }; + + static uint8 UnixColorFG[Colors] = + { + FG_BLACK, // BLACK + FG_RED, // RED + FG_GREEN, // GREEN + FG_BROWN, // BROWN + FG_BLUE, // BLUE + FG_MAGENTA, // MAGENTA + FG_CYAN, // CYAN + FG_WHITE, // WHITE + FG_YELLOW, // YELLOW + FG_RED, // LRED + FG_GREEN, // LGREEN + FG_BLUE, // LBLUE + FG_MAGENTA, // LMAGENTA + FG_CYAN, // LCYAN + FG_WHITE // LWHITE + }; + + fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : "")); + #endif +} + +void Log::ResetColor(bool stdout_stream) +{ + #if PLATFORM == PLATFORM_WINDOWS + HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); + SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ); + #else + fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m"); + #endif +} + +std::string Log::GetTimestampStr() +{ + time_t t = time(NULL); + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + char buf[20]; + snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); + return std::string(buf); +} + +void Log::outDB(LogTypes type, const char * str) +{ + if (!str || type >= MAX_LOG_TYPES) + return; + + std::string new_str(str); + if (new_str.empty()) + return; + LoginDatabase.escape_string(new_str); + + LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " + "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str()); +} + +void Log::outString(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB) + { + // we don't want empty strings in the DB + std::string s(str); + if (s.empty() || s == " ") + return; + + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_STRING, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(true,m_colors[LOGL_NORMAL]); + + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + if(logfile) + { + outTimestamp(logfile); + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n"); + va_end(ap); + + fflush(logfile); + } + fflush(stdout); +} + +void Log::outString() +{ + printf("\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stdout); +} + +void Log::outCrash(const char * err, ...) +{ + if (!err) + return; + + if (m_enableLogDB) + { + va_list ap2; + va_start(ap2, err); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); + outDB(LOG_TYPE_CRASH, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stdout, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf(stderr, "\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "CRASH ALERT: "); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stderr); +} + +void Log::outError(const char * err, ...) +{ + if (!err) + return; + + if (m_enableLogDB) + { + va_list ap2; + va_start(ap2, err); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); + outDB(LOG_TYPE_ERROR, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf( stderr, "\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "ERROR: "); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stderr); +} + +void Log::outArena(const char * str, ...) +{ + if (!str) + return; + + if (arenaLogFile) + { + va_list ap; + outTimestamp(arenaLogFile); + va_start(ap, str); + vfprintf(arenaLogFile, str, ap); + fprintf(arenaLogFile, "\n"); + va_end(ap); + fflush(arenaLogFile); + } + fflush(stdout); +} + +void Log::outErrorDb(const char * err, ...) +{ + if (!err) + return; + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf( stderr, "\n" ); + + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "ERROR: " ); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n" ); + fflush(logfile); + } + + if (dberLogfile) + { + outTimestamp(dberLogfile); + va_start(ap, err); + vfprintf(dberLogfile, err, ap); + va_end(ap); + + fprintf(dberLogfile, "\n" ); + fflush(dberLogfile); + } + fflush(stderr); +} + +void Log::outBasic(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_BASIC, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_NORMAL) + { + if (m_colored) + SetColor(true,m_colors[LOGL_BASIC]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n" ); + va_end(ap); + fflush(logfile); + } + } + fflush(stdout); +} + +void Log::outDetail(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_DETAIL, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_BASIC) + { + if (m_colored) + SetColor(true,m_colors[LOGL_DETAIL]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + } + + fflush(stdout); +} + +void Log::outDebugInLine(const char * str, ...) +{ + if (!str) + return; + + if (m_logLevel > LOGL_DETAIL) + { + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + //if(m_colored) + // ResetColor(true); + + if (logfile) + { + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + } + } +} + +void Log::outDebug(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_DEBUG, nnew_str); + va_end(ap2); + } + + if( m_logLevel > LOGL_DETAIL ) + { + if (m_colored) + SetColor(true,m_colors[LOGL_DEBUG]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if(m_colored) + ResetColor(true); + + printf( "\n" ); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + + fprintf(logfile, "\n" ); + fflush(logfile); + } + } + fflush(stdout); +} + +void Log::outStringInLine(const char * str, ...) +{ + if (!str) + return; + + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (logfile) + { + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + } +} + +void Log::outCommand(uint32 account, const char * str, ...) +{ + if (!str) + return; + + // TODO: support accountid + if (m_enableLogDB && m_dbGM) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_GM, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_NORMAL) + { + if (m_colored) + SetColor(true,m_colors[LOGL_BASIC]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n" ); + va_end(ap); + fflush(logfile); + } + } + + if (m_gmlog_per_account) + { + if (FILE* per_file = openGmlogPerAccount (account)) + { + outTimestamp(per_file); + va_list ap; + va_start(ap, str); + vfprintf(per_file, str, ap); + fprintf(per_file, "\n" ); + va_end(ap); + fclose(per_file); + } + } + else if (gmLogfile) + { + outTimestamp(gmLogfile); + va_list ap; + va_start(ap, str); + vfprintf(gmLogfile, str, ap); + fprintf(gmLogfile, "\n" ); + va_end(ap); + fflush(gmLogfile); + } + + fflush(stdout); +} + +void Log::outChar(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbChar) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_CHAR, nnew_str); + va_end(ap2); + } + + if (charLogfile) + { + outTimestamp(charLogfile); + va_list ap; + va_start(ap, str); + vfprintf(charLogfile, str, ap); + fprintf(charLogfile, "\n" ); + va_end(ap); + fflush(charLogfile); + } +} + +void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name) +{ + FILE *file = NULL; + if (m_charLog_Dump_Separate) + { + char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0 + snprintf(fileName, 29, "%d_%s.log", guid, name); + std::string sFileName(m_dumpsDir); + sFileName.append(fileName); + file = fopen((m_logsDir + sFileName).c_str(), "w"); + } + else + file = charLogfile; + if (file) + { + fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", + account_id, guid, name, str); + fflush(file); + if (m_charLog_Dump_Separate) + fclose(file); + } +} + +void Log::outRemote(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbRA) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_RA, nnew_str); + va_end(ap2); + } + + if (raLogfile) + { + outTimestamp(raLogfile); + va_list ap; + va_start(ap, str); + vfprintf(raLogfile, str, ap); + fprintf(raLogfile, "\n" ); + va_end(ap); + fflush(raLogfile); + } + fflush(stdout); +} + +void Log::outChat(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbChat) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_CHAT, nnew_str); + va_end(ap2); + } + + if (chatLogfile) + { + outTimestamp(chatLogfile); + va_list ap; + va_start(ap, str); + vfprintf(chatLogfile, str, ap); + fprintf(chatLogfile, "\n" ); + fflush(chatLogfile); + va_end(ap); + } + fflush(stdout); +} + +void outstring_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outString(buf); +} + +void detail_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outDetail(buf); +} + +void debug_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outDebug(buf); +} + +void error_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outError(buf); +} + +void error_db_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outErrorDb(buf); +} + diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h new file mode 100644 index 00000000000..deb6c55e4e0 --- /dev/null +++ b/src/server/shared/Logging/Log.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_LOG_H +#define TRINITYCORE_LOG_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Database/DatabaseEnv.h" + +class Config; + +enum LogFilters +{ + LOG_FILTER_TRANSPORT_MOVES = 1, + LOG_FILTER_CREATURE_MOVES = 2, + LOG_FILTER_VISIBILITY_CHANGES = 4, + LOG_FILTER_ACHIEVEMENT_UPDATES = 8 +}; + +enum LogTypes +{ + LOG_TYPE_STRING = 0, + LOG_TYPE_ERROR = 1, + LOG_TYPE_BASIC = 2, + LOG_TYPE_DETAIL = 3, + LOG_TYPE_DEBUG = 4, + LOG_TYPE_CHAR = 5, + LOG_TYPE_WORLD = 6, + LOG_TYPE_RA = 7, + LOG_TYPE_GM = 8, + LOG_TYPE_CRASH = 9, + LOG_TYPE_CHAT = 10, + MAX_LOG_TYPES +}; + +enum LogLevel +{ + LOGL_NORMAL = 0, + LOGL_BASIC, + LOGL_DETAIL, + LOGL_DEBUG +}; + +const int LogLevels = int(LOGL_DEBUG)+1; + +enum ColorTypes +{ + BLACK, + RED, + GREEN, + BROWN, + BLUE, + MAGENTA, + CYAN, + GREY, + YELLOW, + LRED, + LGREEN, + LBLUE, + LMAGENTA, + LCYAN, + WHITE +}; + +const int Colors = int(WHITE)+1; + +class Log : public Trinity::Singleton > +{ + friend class Trinity::OperatorNew; + Log(); + ~Log(); + + public: + void Initialize(); + + void InitColors(const std::string& init_str); + void SetColor(bool stdout_stream, ColorTypes color); + void ResetColor(bool stdout_stream); + + void outDB( LogTypes type, const char * str ); + void outString( const char * str, ... ) ATTR_PRINTF(2,3); + void outString( ); + void outStringInLine( const char * str, ... ) ATTR_PRINTF(2,3); + void outError( const char * err, ... ) ATTR_PRINTF(2,3); + void outCrash( const char * err, ... ) ATTR_PRINTF(2,3); + void outBasic( const char * str, ... ) ATTR_PRINTF(2,3); + void outDetail( const char * str, ... ) ATTR_PRINTF(2,3); + void outDebug( const char * str, ... ) ATTR_PRINTF(2,3); + void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3); + void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3); + void outChar( const char * str, ... ) ATTR_PRINTF(2,3); + void outCommand( uint32 account, const char * str, ...) ATTR_PRINTF(3,4); + void outRemote( const char * str, ... ) ATTR_PRINTF(2,3); + void outChat( const char * str, ... ) ATTR_PRINTF(2,3); + void outArena( const char * str, ... ) ATTR_PRINTF(2,3); + void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name ); + + static void outTimestamp(FILE* file); + static std::string GetTimestampStr(); + + void SetLogLevel(char * Level); + void SetLogFileLevel(char * Level); + void SetDBLogLevel(char * Level); + void SetRealmID(uint32 id) { realm = id; } + + uint32 getLogFilter() const { return m_logFilter; } + bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } + bool IsOutCharDump() const { return m_charLog_Dump; } + + bool GetLogDB() { return m_enableLogDB; } + bool GetLogDBLater() { return m_enableLogDBLater; } + void SetLogDB(bool enable) { m_enableLogDB = enable; } + void SetLogDBLater(bool value) { m_enableLogDBLater = value; } + private: + FILE* openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode); + FILE* openGmlogPerAccount(uint32 account); + + FILE* raLogfile; + FILE* logfile; + FILE* gmLogfile; + FILE* charLogfile; + FILE* dberLogfile; + FILE* chatLogfile; + FILE* arenaLogFile; + + // cache values for after initilization use (like gm log per account case) + std::string m_logsDir; + std::string m_logsTimestamp; + + // gm log control + bool m_gmlog_per_account; + std::string m_gmlog_filename_format; + + bool m_enableLogDBLater; + bool m_enableLogDB; + uint32 realm; + + // log coloring + bool m_colored; + ColorTypes m_colors[4]; + + // log levels: + // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug + uint8 m_dbLogLevel; + uint8 m_logLevel; + uint8 m_logFileLevel; + uint8 m_logFilter; + bool m_dbChar; + bool m_dbRA; + bool m_dbGM; + bool m_dbChat; + bool m_charLog_Dump; + bool m_charLog_Dump_Separate; + std::string m_dumpsDir; +}; + +#define sLog Trinity::Singleton::Instance() + +#ifdef TRINITY_DEBUG +#define DEBUG_LOG Trinity::Singleton::Instance().outDebug +#else +#define DEBUG_LOG +#endif + +// primary for script library +void outstring_log(const char * str, ...) ATTR_PRINTF(1,2); +void detail_log(const char * str, ...) ATTR_PRINTF(1,2); +void debug_log(const char * str, ...) ATTR_PRINTF(1,2); +void error_log(const char * str, ...) ATTR_PRINTF(1,2); +void error_db_log(const char * str, ...) ATTR_PRINTF(1,2); +#endif + diff --git a/src/server/shared/MemoryLeaks.cpp b/src/server/shared/MemoryLeaks.cpp deleted file mode 100644 index ef7e36c3b57..00000000000 --- a/src/server/shared/MemoryLeaks.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MemoryLeaks.h" -#include "Policies/SingletonImp.h" - -INSTANTIATE_SINGLETON_1( MemoryManager ) ; - -MemoryManager::MemoryManager( ) -{ - #if COMPILER == MICROSOFT - // standard leak check initialization - //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - // uncomment to disable Visual Leak Detector from code - //VLDDisable(); - #endif -} diff --git a/src/server/shared/MemoryLeaks.h b/src/server/shared/MemoryLeaks.h deleted file mode 100644 index c8b8fb8e1b1..00000000000 --- a/src/server/shared/MemoryLeaks.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYSERVER_MEMORY_H -#define TRINITYSERVER_MEMORY_H - -#include "Platform/CompilerDefs.h" - -#if COMPILER == COMPILER_MICROSOFT - -#ifndef _WIN64 -// Visual Leak Detector support enabled -//#include -// standard Visual Studio leak check disabled, -//# define _CRTDBG_MAP_ALLOC -//# include -//# include -#else -//# define _CRTDBG_MAP_ALLOC -//# include -//# include -#endif - -#endif - - -#include "Policies/Singleton.h" - -struct MemoryManager : public Trinity::Singleton < MemoryManager > -{ - MemoryManager(); -}; -#endif diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h new file mode 100644 index 00000000000..ba0240fb58b --- /dev/null +++ b/src/server/shared/Packets/ByteBuffer.h @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BYTEBUFFER_H +#define _BYTEBUFFER_H + +#include "Common.h" +#include "Errors.h" +#include "Log.h" +#include "Utilities/ByteConverter.h" + +class ByteBufferException +{ + public: + ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) + : add(_add), pos(_pos), esize(_esize), size(_size) + { + PrintPosError(); + } + + void PrintPosError() const + { + sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, + (add ? "put" : "get"), pos, size, esize); + } + private: + bool add; + size_t pos; + size_t esize; + size_t size; +}; + +class ByteBuffer +{ + public: + const static size_t DEFAULT_SIZE = 0x1000; + + // constructor + ByteBuffer(): _rpos(0), _wpos(0) + { + _storage.reserve(DEFAULT_SIZE); + } + + // constructor + ByteBuffer(size_t res): _rpos(0), _wpos(0) + { + _storage.reserve(res); + } + + // copy constructor + ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } + + void clear() + { + _storage.clear(); + _rpos = _wpos = 0; + } + + template void append(T value) + { + EndianConvert(value); + append((uint8 *)&value, sizeof(value)); + } + + template void put(size_t pos,T value) + { + EndianConvert(value); + put(pos,(uint8 *)&value,sizeof(value)); + } + + ByteBuffer &operator<<(uint8 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint16 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint32 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint64 value) + { + append(value); + return *this; + } + + // signed as in 2e complement + ByteBuffer &operator<<(int8 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int16 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int32 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int64 value) + { + append(value); + return *this; + } + + // floating points + ByteBuffer &operator<<(float value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(double value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(const std::string &value) + { + append((uint8 const *)value.c_str(), value.length()); + append((uint8)0); + return *this; + } + + ByteBuffer &operator<<(const char *str) + { + append((uint8 const *)str, str ? strlen(str) : 0); + append((uint8)0); + return *this; + } + + ByteBuffer &operator>>(bool &value) + { + value = read() > 0 ? true : false; + return *this; + } + + ByteBuffer &operator>>(uint8 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint16 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint32 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint64 &value) + { + value = read(); + return *this; + } + + //signed as in 2e complement + ByteBuffer &operator>>(int8 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int16 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int32 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int64 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(float &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(double &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(std::string& value) + { + value.clear(); + while (rpos() < size()) // prevent crash at wrong string format in packet + { + char c = read(); + if (c == 0) + break; + value += c; + } + return *this; + } + + uint8 operator[](size_t pos) const + { + return read(pos); + } + + size_t rpos() const { return _rpos; } + + size_t rpos(size_t rpos_) + { + _rpos = rpos_; + return _rpos; + } + + size_t wpos() const { return _wpos; } + + size_t wpos(size_t wpos_) + { + _wpos = wpos_; + return _wpos; + } + + template + void read_skip() { read_skip(sizeof(T)); } + + void read_skip(size_t skip) + { + if(_rpos + skip > size()) + throw ByteBufferException(false, _rpos, skip, size()); + _rpos += skip; + } + + template T read() + { + T r = read(_rpos); + _rpos += sizeof(T); + return r; + } + + template T read(size_t pos) const + { + if(pos + sizeof(T) > size()) + throw ByteBufferException(false, pos, sizeof(T), size()); + T val = *((T const*)&_storage[pos]); + EndianConvert(val); + return val; + } + + void read(uint8 *dest, size_t len) + { + if(_rpos + len > size()) + throw ByteBufferException(false, _rpos, len, size()); + memcpy(dest, &_storage[_rpos], len); + _rpos += len; + } + + bool readPackGUID(uint64& guid) + { + if(rpos() + 1 > size()) + return false; + + guid = 0; + + uint8 guidmark = 0; + (*this) >> guidmark; + + for (int i = 0; i < 8; ++i) + { + if(guidmark & (uint8(1) << i)) + { + if(rpos() + 1 > size()) + return false; + + uint8 bit; + (*this) >> bit; + guid |= (uint64(bit) << (i * 8)); + } + } + + return true; + } + + const uint8 *contents() const { return &_storage[0]; } + + size_t size() const { return _storage.size(); } + bool empty() const { return _storage.empty(); } + + void resize(size_t newsize) + { + _storage.resize(newsize); + _rpos = 0; + _wpos = size(); + } + + void reserve(size_t ressize) + { + if (ressize > size()) + _storage.reserve(ressize); + } + + void append(const std::string& str) + { + append((uint8 const*)str.c_str(), str.size() + 1); + } + + void append(const char *src, size_t cnt) + { + return append((const uint8 *)src, cnt); + } + + template void append(const T *src, size_t cnt) + { + return append((const uint8 *)src, cnt * sizeof(T)); + } + + void append(const uint8 *src, size_t cnt) + { + if (!cnt) + return; + + ASSERT(size() < 10000000); + + if (_storage.size() < _wpos + cnt) + _storage.resize(_wpos + cnt); + memcpy(&_storage[_wpos], src, cnt); + _wpos += cnt; + } + + void append(const ByteBuffer& buffer) + { + if(buffer.wpos()) + append(buffer.contents(), buffer.wpos()); + } + + // can be used in SMSG_MONSTER_MOVE opcode + void appendPackXYZ(float x, float y, float z) + { + uint32 packed = 0; + packed |= ((int)(x / 0.25f) & 0x7FF); + packed |= ((int)(y / 0.25f) & 0x7FF) << 11; + packed |= ((int)(z / 0.25f) & 0x3FF) << 22; + *this << packed; + } + + void appendPackGUID(uint64 guid) + { + uint8 packGUID[8+1]; + packGUID[0] = 0; + size_t size = 1; + for(uint8 i = 0;guid != 0;++i) + { + if(guid & 0xFF) + { + packGUID[0] |= uint8(1 << i); + packGUID[size] = uint8(guid & 0xFF); + ++size; + } + + guid >>= 8; + } + append(packGUID, size); + } + + void put(size_t pos, const uint8 *src, size_t cnt) + { + if(pos + cnt > size()) + throw ByteBufferException(true, pos, cnt, size()); + memcpy(&_storage[pos], src, cnt); + } + + void print_storage() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + for (uint32 i = 0; i < size(); ++i) + sLog.outDebugInLine("%u - ", read(i) ); + sLog.outDebug(" "); + } + + void textlike() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + for (uint32 i = 0; i < size(); ++i) + sLog.outDebugInLine("%c", read(i) ); + sLog.outDebug(" "); + } + + void hexlike() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + uint32 j = 1, k = 1; + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + + for (uint32 i = 0; i < size(); ++i) + { + if ((i == (j * 8)) && ((i != (k * 16)))) + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("| 0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("| %X ", read(i) ); + } + ++j; + } + else if (i == (k * 16)) + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("\n"); + + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("\n"); + + sLog.outDebugInLine("%X ", read(i) ); + } + + ++k; + ++j; + } + else + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("%X ", read(i) ); + } + } + } + sLog.outDebugInLine("\n"); + } + + protected: + size_t _rpos, _wpos; + std::vector _storage; +}; + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::vector v) +{ + b << (uint32)v.size(); + for (typename std::vector::iterator i = v.begin(); i != v.end(); ++i) + { + b << *i; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::list v) +{ + b << (uint32)v.size(); + for (typename std::list::iterator i = v.begin(); i != v.end(); ++i) + { + b << *i; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::list &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::map &m) +{ + b << (uint32)m.size(); + for (typename std::map::iterator i = m.begin(); i != m.end(); ++i) + { + b << i->first << i->second; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::map &m) +{ + uint32 msize; + b >> msize; + m.clear(); + while(msize--) + { + K k; + V v; + b >> k >> v; + m.insert(make_pair(k, v)); + } + return b; +} + +// TODO: Make a ByteBuffer.cpp and move all this inlining to it. +template<> inline std::string ByteBuffer::read() +{ + std::string tmp; + *this >> tmp; + return tmp; +} + +template<> +inline void ByteBuffer::read_skip() +{ + std::string temp; + *this >> temp; +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} +#endif + diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h new file mode 100644 index 00000000000..d708959f91d --- /dev/null +++ b/src/server/shared/Packets/WorldPacket.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_WORLDPACKET_H +#define TRINITYCORE_WORLDPACKET_H + +#include "Common.h" +#include "ByteBuffer.h" + +class WorldPacket : public ByteBuffer +{ + public: + // just container for later use + WorldPacket() : ByteBuffer(0), m_opcode(0) + { + } + explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } + // copy constructor + WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) + { + } + + void Initialize(uint16 opcode, size_t newres=200) + { + clear(); + _storage.reserve(newres); + m_opcode = opcode; + } + + uint16 GetOpcode() const { return m_opcode; } + void SetOpcode(uint16 opcode) { m_opcode = opcode; } + + protected: + uint16 m_opcode; +}; +#endif + diff --git a/src/server/shared/ProgressBar.cpp b/src/server/shared/ProgressBar.cpp deleted file mode 100644 index c24d9f86f6b..00000000000 --- a/src/server/shared/ProgressBar.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "ProgressBar.h" - -char const* const barGoLink::empty = " "; -#ifdef _WIN32 -char const* const barGoLink::full = "\x3D"; -#else -char const* const barGoLink::full = "*"; -#endif - -barGoLink::~barGoLink() -{ - printf( "\n" ); - fflush(stdout); -} - -barGoLink::barGoLink( int row_count ) -{ - rec_no = 0; - rec_pos = 0; - indic_len = 50; - num_rec = row_count; - #ifdef _WIN32 - printf( "\x3D" ); - #else - printf( "[" ); - #endif - for (int i = 0; i < indic_len; i++ ) printf( empty ); - #ifdef _WIN32 - printf( "\x3D 0%%\r\x3D" ); - #else - printf( "] 0%%\r[" ); - #endif - fflush(stdout); -} - -void barGoLink::step( void ) -{ - int i, n; - - if ( num_rec == 0 ) return; - ++rec_no; - n = rec_no * indic_len / num_rec; - if ( n != rec_pos ) - { - #ifdef _WIN32 - printf( "\r\x3D" ); - #else - printf( "\r[" ); - #endif - for (i = 0; i < n; i++ ) printf( full ); - for (; i < indic_len; i++ ) printf( empty ); - float percent = (((float)n/(float)indic_len)*100); - #ifdef _WIN32 - printf( "\x3D %i%% \r\x3D", (int)percent); - #else - printf( "] %i%% \r[", (int)percent); - #endif - fflush(stdout); - - rec_pos = n; - } -} - diff --git a/src/server/shared/ProgressBar.h b/src/server/shared/ProgressBar.h deleted file mode 100644 index e7565590278..00000000000 --- a/src/server/shared/ProgressBar.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef TRINITYCORE_PROGRESSBAR_H -#define TRINITYCORE_PROGRESSBAR_H - -#include "Platform/Define.h" - -class barGoLink -{ - static char const * const empty; - static char const * const full; - - int rec_no; - int rec_pos; - int num_rec; - int indic_len; - - public: - - void step( void ); - barGoLink( int ); - ~barGoLink(); -}; -#endif - diff --git a/src/server/shared/ServiceWin32.cpp b/src/server/shared/ServiceWin32.cpp deleted file mode 100644 index 2c1df2ff483..00000000000 --- a/src/server/shared/ServiceWin32.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef WIN32 - -#include "Common.h" -#include "Log.h" -#include -#include -#include - -#if !defined(WINADVAPI) -#if !defined(_ADVAPI32_) -#define WINADVAPI DECLSPEC_IMPORT -#else -#define WINADVAPI -#endif -#endif - -extern int main(int argc, char ** argv); -extern char serviceLongName[]; -extern char serviceName[]; -extern char serviceDescription[]; - -extern int m_ServiceStatus; - -SERVICE_STATUS serviceStatus; - -SERVICE_STATUS_HANDLE serviceStatusHandle = 0; - -typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); - -bool WinServiceInstall() -{ - CSD_T ChangeService_Config2; - HMODULE advapi32; - SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); - - if (serviceControlManager) - { - char path[_MAX_PATH + 10]; - if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) - { - SC_HANDLE service; - std::strcat(path, " --service"); - service = CreateService(serviceControlManager, - serviceName, // name of service - serviceLongName, // service name to display - SERVICE_ALL_ACCESS, // desired access - // service type - SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, - SERVICE_AUTO_START, // start type - SERVICE_ERROR_IGNORE, // error control type - path, // service's binary - 0, // no load ordering group - 0, // no tag identifier - 0, // no dependencies - 0, // LocalSystem account - 0); // no password - if (service) - { - advapi32 = GetModuleHandle("ADVAPI32.DLL"); - if(!advapi32) - { - CloseServiceHandle(service); - CloseServiceHandle(serviceControlManager); - return false; - } - - ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); - if (!ChangeService_Config2) - { - CloseServiceHandle(service); - CloseServiceHandle(serviceControlManager); - return false; - } - - SERVICE_DESCRIPTION sdBuf; - sdBuf.lpDescription = serviceDescription; - ChangeService_Config2( - service, // handle to service - SERVICE_CONFIG_DESCRIPTION, // change: description - &sdBuf); // new data - - SC_ACTION _action[1]; - _action[0].Type = SC_ACTION_RESTART; - _action[0].Delay = 10000; - SERVICE_FAILURE_ACTIONS sfa; - ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); - sfa.lpsaActions = _action; - sfa.cActions = 1; - sfa.dwResetPeriod =INFINITE; - ChangeService_Config2( - service, // handle to service - SERVICE_CONFIG_FAILURE_ACTIONS, // information level - &sfa); // new data - - CloseServiceHandle(service); - - } - } - CloseServiceHandle(serviceControlManager); - } - return true; -} - -bool WinServiceUninstall() -{ - SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); - - if (serviceControlManager) - { - SC_HANDLE service = OpenService(serviceControlManager, - serviceName, SERVICE_QUERY_STATUS | DELETE); - if (service) - { - SERVICE_STATUS serviceStatus2; - if (QueryServiceStatus(service, &serviceStatus2)) - { - if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) - DeleteService(service); - } - CloseServiceHandle(service); - } - - CloseServiceHandle(serviceControlManager); - } - return true; -} - -void WINAPI ServiceControlHandler(DWORD controlCode) -{ - switch (controlCode) - { - case SERVICE_CONTROL_INTERROGATE: - break; - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - m_ServiceStatus = 0; - return; - - case SERVICE_CONTROL_PAUSE: - m_ServiceStatus = 2; - serviceStatus.dwCurrentState = SERVICE_PAUSED; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - break; - - case SERVICE_CONTROL_CONTINUE: - serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - m_ServiceStatus = 1; - break; - - default: - if ( controlCode >= 128 && controlCode <= 255 ) - // user defined control code - break; - else - // unrecognized control code - break; - } - - SetServiceStatus(serviceStatusHandle, &serviceStatus); -} - -void WINAPI ServiceMain(DWORD argc, char *argv[]) -{ - // initialise service status - serviceStatus.dwServiceType = SERVICE_WIN32; - serviceStatus.dwCurrentState = SERVICE_START_PENDING; - serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; - serviceStatus.dwWin32ExitCode = NO_ERROR; - serviceStatus.dwServiceSpecificExitCode = NO_ERROR; - serviceStatus.dwCheckPoint = 0; - serviceStatus.dwWaitHint = 0; - - serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); - - if ( serviceStatusHandle ) - { - char path[_MAX_PATH + 1]; - unsigned int i, last_slash = 0; - - GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); - - for (i = 0; i < std::strlen(path); i++) - { - if (path[i] == '\\') last_slash = i; - } - - path[last_slash] = 0; - - // service is starting - serviceStatus.dwCurrentState = SERVICE_START_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - // do initialisation here - SetCurrentDirectory(path); - - // running - serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - - //////////////////////// - // service main cycle // - //////////////////////// - - m_ServiceStatus = 1; - argc = 1; - main(argc , argv); - - // service was stopped - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - // do cleanup here - - // service is now stopped - serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - serviceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - } -} - -bool WinServiceRun() -{ - SERVICE_TABLE_ENTRY serviceTable[] = - { - { serviceName, ServiceMain }, - { 0, 0 } - }; - - if (!StartServiceCtrlDispatcher(serviceTable)) - { - sLog.outError("StartService Failed. Error [%u]", ::GetLastError()); - return false; - } - return true; -} -#endif - diff --git a/src/server/shared/ServiceWin32.h b/src/server/shared/ServiceWin32.h deleted file mode 100644 index ddac785a0fb..00000000000 --- a/src/server/shared/ServiceWin32.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef WIN32 -#ifndef _WIN32_SERVICE_ -#define _WIN32_SERVICE_ - -bool WinServiceInstall(); -bool WinServiceUninstall(); -bool WinServiceRun(); - -#endif // _WIN32_SERVICE_ -#endif // WIN32 - diff --git a/src/server/shared/SignalHandler.h b/src/server/shared/SignalHandler.h deleted file mode 100644 index 0c4d8143c41..00000000000 --- a/src/server/shared/SignalHandler.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SIGNAL_HANDLER_H__ -#define __SIGNAL_HANDLER_H__ - -#include - -namespace Trinity -{ - -/// Handle termination signals -class SignalHandler : public ACE_Event_Handler -{ - public: - int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL) - { - HandleSignal(SigNum); - return 0; - } - virtual void HandleSignal(int SigNum) {}; -}; - -} - -#endif /* __SIGNAL_HANDLER_H__ */ diff --git a/src/server/shared/Threading.cpp b/src/server/shared/Threading.cpp deleted file mode 100644 index 3938286dbdb..00000000000 --- a/src/server/shared/Threading.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Threading.h" -#include "Errors.h" -#include -#include -#include - -using namespace ACE_Based; - -ThreadPriority::ThreadPriority() -{ - for (int i = Idle; i < MAXPRIORITYNUM; ++i) - m_priority[i] = ACE_THR_PRI_OTHER_DEF; - - m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER); - m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER); - - std::vector _tmp; - - ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER; - ACE_Sched_Priority_Iterator pr_iter(_policy); - - while (pr_iter.more()) - { - _tmp.push_back(pr_iter.priority()); - pr_iter.next(); - } - - ASSERT (!_tmp.empty()); - - if(_tmp.size() >= MAXPRIORITYNUM) - { - const size_t max_pos = _tmp.size(); - size_t min_pos = 1; - size_t norm_pos = 0; - for (size_t i = 0; i < max_pos; ++i) - { - if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) - { - norm_pos = i + 1; - break; - } - } - - //since we have only 7(seven) values in enum Priority - //and 3 we know already (Idle, Normal, Realtime) so - //we need to split each list [Idle...Normal] and [Normal...Realtime] - //into ¹ piesces - const size_t _divider = 4; - size_t _div = (norm_pos - min_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = (norm_pos - 1); - - m_priority[Low] = _tmp[min_pos -= _div]; - m_priority[Lowest] = _tmp[min_pos -= _div ]; - - _div = (max_pos - norm_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = norm_pos - 1; - - m_priority[High] = _tmp[min_pos += _div]; - m_priority[Highest] = _tmp[min_pos += _div]; - } -} - -int ThreadPriority::getPriority(Priority p) const -{ - if(p < Idle) - p = Idle; - - if(p > Realtime) - p = Realtime; - - return m_priority[p]; -} - -#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE) - -Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0) -{ - -} - -Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0) -{ - // register reference to m_task to prevent it deeltion until destructor - if (m_task) - m_task->incReference(); - - bool _start = start(); - ASSERT (_start); -} - -Thread::~Thread() -{ - //Wait(); - - // deleted runnable object (if no other references) - if (m_task) - m_task->decReference(); -} - -//initialize Thread's class static member -Thread::ThreadStorage Thread::m_ThreadStorage; -ThreadPriority Thread::m_TpEnum; - -bool Thread::start() -{ - if (m_task == 0 || m_iThreadId != 0) - return false; - - bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); - - if (res) - m_task->incReference(); - - return res; -} - -bool Thread::wait() -{ - if (!m_hThreadHandle || !m_task) - return false; - - ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1); - int _res = ACE_Thread::join(m_hThreadHandle, &_value); - - m_iThreadId = 0; - m_hThreadHandle = 0; - - return (_res == 0); -} - -void Thread::destroy() -{ - if (!m_iThreadId || !m_task) - return; - - if (ACE_Thread::kill(m_iThreadId, -1) != 0) - return; - - m_iThreadId = 0; - m_hThreadHandle = 0; - - // reference set at ACE_Thread::spawn - m_task->decReference(); -} - -void Thread::suspend() -{ - ACE_Thread::suspend(m_hThreadHandle); -} - -void Thread::resume() -{ - ACE_Thread::resume(m_hThreadHandle); -} - -ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param) -{ - Runnable * _task = (Runnable*)param; - _task->run(); - - // task execution complete, free referecne added at - _task->decReference(); - - return (ACE_THR_FUNC_RETURN)0; -} - -ACE_thread_t Thread::currentId() -{ - return ACE_Thread::self(); -} - -ACE_hthread_t Thread::currentHandle() -{ - ACE_hthread_t _handle; - ACE_Thread::self(_handle); - - return _handle; -} - -Thread * Thread::current() -{ - Thread * _thread = m_ThreadStorage.ts_object(); - if(!_thread) - { - _thread = new Thread(); - _thread->m_iThreadId = Thread::currentId(); - _thread->m_hThreadHandle = Thread::currentHandle(); - - Thread * _oldValue = m_ThreadStorage.ts_object(_thread); - if(_oldValue) - delete _oldValue; - } - - return _thread; -} - -void Thread::setPriority(Priority type) -{ - int _priority = m_TpEnum.getPriority(type); - int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority); - //remove this ASSERT in case you don't want to know is thread priority change was successful or not - ASSERT (_ok == 0); -} - -void Thread::Sleep(unsigned long msecs) -{ - ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs)); -} diff --git a/src/server/shared/Threading.h b/src/server/shared/Threading.h deleted file mode 100644 index fa046117c6e..00000000000 --- a/src/server/shared/Threading.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef THREADING_H -#define THREADING_H - -#include -#include -#include "ace/Atomic_Op.h" -#include - -namespace ACE_Based -{ - - class Runnable - { - public: - virtual ~Runnable() {} - virtual void run() = 0; - - void incReference() { ++m_refs; } - void decReference() - { - if(!--m_refs) - delete this; - } - private: - ACE_Atomic_Op m_refs; - }; - - enum Priority - { - Idle, - Lowest, - Low, - Normal, - High, - Highest, - Realtime, - }; - -#define MAXPRIORITYNUM (Realtime + 1) - - class ThreadPriority - { - public: - ThreadPriority(); - int getPriority(Priority p) const; - - private: - int m_priority[MAXPRIORITYNUM]; - }; - - class Thread - { - public: - Thread(); - explicit Thread(Runnable* instance); - ~Thread(); - - bool start(); - bool wait(); - void destroy(); - - void suspend(); - void resume(); - - void setPriority(Priority type); - - static void Sleep(unsigned long msecs); - static ACE_thread_t currentId(); - static ACE_hthread_t currentHandle(); - static Thread * current(); - - private: - Thread(const Thread&); - Thread& operator=(const Thread&); - - static ACE_THR_FUNC_RETURN ThreadTask(void * param); - - ACE_thread_t m_iThreadId; - ACE_hthread_t m_hThreadHandle; - Runnable * m_task; - - typedef ACE_TSS ThreadStorage; - //global object - container for Thread class representation of every thread - static ThreadStorage m_ThreadStorage; - //use this object to determine current OS thread priority values mapped to enum Priority{} - static ThreadPriority m_TpEnum; - }; - -} -#endif diff --git a/src/server/shared/Threading/DelayExecutor.cpp b/src/server/shared/Threading/DelayExecutor.cpp new file mode 100644 index 00000000000..9a718823232 --- /dev/null +++ b/src/server/shared/Threading/DelayExecutor.cpp @@ -0,0 +1,111 @@ +#include +#include +#include + +#include "DelayExecutor.h" + +DelayExecutor* DelayExecutor::instance() +{ + return ACE_Singleton::instance(); +} + +DelayExecutor::DelayExecutor() + : activated_(false), pre_svc_hook_(0), post_svc_hook_(0) +{ +} + +DelayExecutor::~DelayExecutor() +{ + if (pre_svc_hook_) + delete pre_svc_hook_; + + if (post_svc_hook_) + delete post_svc_hook_; + + deactivate(); +} + +int DelayExecutor::deactivate() +{ + if (!activated()) + return -1; + + activated(false); + queue_.queue()->deactivate(); + wait(); + + return 0; +} + +int DelayExecutor::svc() +{ + if (pre_svc_hook_) + pre_svc_hook_->call(); + + for (;;) + { + ACE_Method_Request* rq = queue_.dequeue(); + + if (!rq) + break; + + rq->call(); + delete rq; + } + + if (post_svc_hook_) + post_svc_hook_->call(); + + return 0; +} + +int DelayExecutor::activate(int num_threads, ACE_Method_Request* pre_svc_hook, ACE_Method_Request* post_svc_hook) +{ + if (activated()) + return -1; + + if (num_threads < 1) + return -1; + + if (pre_svc_hook_) + delete pre_svc_hook_; + + if (post_svc_hook_) + delete post_svc_hook_; + + pre_svc_hook_ = pre_svc_hook; + post_svc_hook_ = post_svc_hook; + + queue_.queue()->activate(); + + if (ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, num_threads) == -1) + return -1; + + activated(true); + + return true; +} + +int DelayExecutor::execute(ACE_Method_Request* new_req) +{ + if (new_req == NULL) + return -1; + + if (queue_.enqueue(new_req, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) + { + delete new_req; + ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("DelayExecutor::execute enqueue")), -1); + } + + return 0; +} + +bool DelayExecutor::activated() +{ + return activated_; +} + +void DelayExecutor::activated(bool s) +{ + activated_ = s; +} diff --git a/src/server/shared/Threading/DelayExecutor.h b/src/server/shared/Threading/DelayExecutor.h new file mode 100644 index 00000000000..664d8ca78a2 --- /dev/null +++ b/src/server/shared/Threading/DelayExecutor.h @@ -0,0 +1,37 @@ +#ifndef _M_DELAY_EXECUTOR_H +#define _M_DELAY_EXECUTOR_H + +#include +#include +#include + +class DelayExecutor : protected ACE_Task_Base +{ + public: + + DelayExecutor(); + virtual ~DelayExecutor(); + + static DelayExecutor* instance(); + + int execute(ACE_Method_Request* new_req); + + int activate(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL); + + int deactivate(); + + bool activated(); + + virtual int svc(); + + private: + + ACE_Activation_Queue queue_; + ACE_Method_Request* pre_svc_hook_; + ACE_Method_Request* post_svc_hook_; + bool activated_; + + void activated(bool s); +}; + +#endif // _M_DELAY_EXECUTOR_H diff --git a/src/server/shared/Threading/LockedQueue.h b/src/server/shared/Threading/LockedQueue.h new file mode 100644 index 00000000000..9f8afae6c14 --- /dev/null +++ b/src/server/shared/Threading/LockedQueue.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LOCKEDQUEUE_H +#define LOCKEDQUEUE_H + +#include +#include +#include +#include +#include "Errors.h" + +namespace ACE_Based +{ + template > + class LockedQueue + { + //! Lock access to the queue. + LockType _lock; + + //! Storage backing the queue. + StorageType _queue; + + //! Cancellation flag. + volatile bool _canceled; + + public: + + //! Create a LockedQueue. + LockedQueue() + : _canceled(false) + { + } + + //! Destroy a LockedQueue. + virtual ~LockedQueue() + { + } + + //! Adds an item to the queue. + void add(const T& item) + { + lock(); + + //ASSERT(!this->_canceled); + // throw Cancellation_Exception(); + + _queue.push_back(item); + + unlock(); + } + + //! Gets the next result in the queue, if any. + bool next(T& result) + { + // ACE_Guard g(this->_lock); + ACE_GUARD_RETURN (LockType, g, this->_lock, false); + + if (_queue.empty()) + return false; + + //ASSERT (!_queue.empty() || !this->_canceled); + // throw Cancellation_Exception(); + result = _queue.front(); + _queue.pop_front(); + + return true; + } + + //! Peeks at the top of the queue. Remember to unlock after use. + T& peek() + { + lock(); + + T& result = _queue.front(); + + return result; + } + + //! Cancels the queue. + void cancel() + { + lock(); + + _canceled = true; + + unlock(); + } + + //! Checks if the queue is cancelled. + bool cancelled() + { + ACE_Guard g(this->_lock); + return _canceled; + } + + //! Locks the queue for access. + void lock() + { + this->_lock.acquire(); + } + + //! Unlocks the queue. + void unlock() + { + this->_lock.release(); + } + + ///! Calls pop_front of the queue + void pop_front() + { + ACE_GUARD (LockType, g, this->_lock); + _queue.pop_front(); + } + + ///! Checks if we're empty or not with locks held + bool empty() + { + ACE_GUARD_RETURN (LockType, g, this->_lock, false); + return _queue.empty(); + } + }; +} +#endif diff --git a/src/server/shared/Threading/Threading.cpp b/src/server/shared/Threading/Threading.cpp new file mode 100644 index 00000000000..3938286dbdb --- /dev/null +++ b/src/server/shared/Threading/Threading.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Threading.h" +#include "Errors.h" +#include +#include +#include + +using namespace ACE_Based; + +ThreadPriority::ThreadPriority() +{ + for (int i = Idle; i < MAXPRIORITYNUM; ++i) + m_priority[i] = ACE_THR_PRI_OTHER_DEF; + + m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER); + m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER); + + std::vector _tmp; + + ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER; + ACE_Sched_Priority_Iterator pr_iter(_policy); + + while (pr_iter.more()) + { + _tmp.push_back(pr_iter.priority()); + pr_iter.next(); + } + + ASSERT (!_tmp.empty()); + + if(_tmp.size() >= MAXPRIORITYNUM) + { + const size_t max_pos = _tmp.size(); + size_t min_pos = 1; + size_t norm_pos = 0; + for (size_t i = 0; i < max_pos; ++i) + { + if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) + { + norm_pos = i + 1; + break; + } + } + + //since we have only 7(seven) values in enum Priority + //and 3 we know already (Idle, Normal, Realtime) so + //we need to split each list [Idle...Normal] and [Normal...Realtime] + //into ¹ piesces + const size_t _divider = 4; + size_t _div = (norm_pos - min_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = (norm_pos - 1); + + m_priority[Low] = _tmp[min_pos -= _div]; + m_priority[Lowest] = _tmp[min_pos -= _div ]; + + _div = (max_pos - norm_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = norm_pos - 1; + + m_priority[High] = _tmp[min_pos += _div]; + m_priority[Highest] = _tmp[min_pos += _div]; + } +} + +int ThreadPriority::getPriority(Priority p) const +{ + if(p < Idle) + p = Idle; + + if(p > Realtime) + p = Realtime; + + return m_priority[p]; +} + +#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE) + +Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0) +{ + +} + +Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0) +{ + // register reference to m_task to prevent it deeltion until destructor + if (m_task) + m_task->incReference(); + + bool _start = start(); + ASSERT (_start); +} + +Thread::~Thread() +{ + //Wait(); + + // deleted runnable object (if no other references) + if (m_task) + m_task->decReference(); +} + +//initialize Thread's class static member +Thread::ThreadStorage Thread::m_ThreadStorage; +ThreadPriority Thread::m_TpEnum; + +bool Thread::start() +{ + if (m_task == 0 || m_iThreadId != 0) + return false; + + bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); + + if (res) + m_task->incReference(); + + return res; +} + +bool Thread::wait() +{ + if (!m_hThreadHandle || !m_task) + return false; + + ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1); + int _res = ACE_Thread::join(m_hThreadHandle, &_value); + + m_iThreadId = 0; + m_hThreadHandle = 0; + + return (_res == 0); +} + +void Thread::destroy() +{ + if (!m_iThreadId || !m_task) + return; + + if (ACE_Thread::kill(m_iThreadId, -1) != 0) + return; + + m_iThreadId = 0; + m_hThreadHandle = 0; + + // reference set at ACE_Thread::spawn + m_task->decReference(); +} + +void Thread::suspend() +{ + ACE_Thread::suspend(m_hThreadHandle); +} + +void Thread::resume() +{ + ACE_Thread::resume(m_hThreadHandle); +} + +ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param) +{ + Runnable * _task = (Runnable*)param; + _task->run(); + + // task execution complete, free referecne added at + _task->decReference(); + + return (ACE_THR_FUNC_RETURN)0; +} + +ACE_thread_t Thread::currentId() +{ + return ACE_Thread::self(); +} + +ACE_hthread_t Thread::currentHandle() +{ + ACE_hthread_t _handle; + ACE_Thread::self(_handle); + + return _handle; +} + +Thread * Thread::current() +{ + Thread * _thread = m_ThreadStorage.ts_object(); + if(!_thread) + { + _thread = new Thread(); + _thread->m_iThreadId = Thread::currentId(); + _thread->m_hThreadHandle = Thread::currentHandle(); + + Thread * _oldValue = m_ThreadStorage.ts_object(_thread); + if(_oldValue) + delete _oldValue; + } + + return _thread; +} + +void Thread::setPriority(Priority type) +{ + int _priority = m_TpEnum.getPriority(type); + int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority); + //remove this ASSERT in case you don't want to know is thread priority change was successful or not + ASSERT (_ok == 0); +} + +void Thread::Sleep(unsigned long msecs) +{ + ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs)); +} diff --git a/src/server/shared/Threading/Threading.h b/src/server/shared/Threading/Threading.h new file mode 100644 index 00000000000..fa046117c6e --- /dev/null +++ b/src/server/shared/Threading/Threading.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef THREADING_H +#define THREADING_H + +#include +#include +#include "ace/Atomic_Op.h" +#include + +namespace ACE_Based +{ + + class Runnable + { + public: + virtual ~Runnable() {} + virtual void run() = 0; + + void incReference() { ++m_refs; } + void decReference() + { + if(!--m_refs) + delete this; + } + private: + ACE_Atomic_Op m_refs; + }; + + enum Priority + { + Idle, + Lowest, + Low, + Normal, + High, + Highest, + Realtime, + }; + +#define MAXPRIORITYNUM (Realtime + 1) + + class ThreadPriority + { + public: + ThreadPriority(); + int getPriority(Priority p) const; + + private: + int m_priority[MAXPRIORITYNUM]; + }; + + class Thread + { + public: + Thread(); + explicit Thread(Runnable* instance); + ~Thread(); + + bool start(); + bool wait(); + void destroy(); + + void suspend(); + void resume(); + + void setPriority(Priority type); + + static void Sleep(unsigned long msecs); + static ACE_thread_t currentId(); + static ACE_hthread_t currentHandle(); + static Thread * current(); + + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + static ACE_THR_FUNC_RETURN ThreadTask(void * param); + + ACE_thread_t m_iThreadId; + ACE_hthread_t m_hThreadHandle; + Runnable * m_task; + + typedef ACE_TSS ThreadStorage; + //global object - container for Thread class representation of every thread + static ThreadStorage m_ThreadStorage; + //use this object to determine current OS thread priority values mapped to enum Priority{} + static ThreadPriority m_TpEnum; + }; + +} +#endif diff --git a/src/server/shared/Timer.h b/src/server/shared/Timer.h deleted file mode 100644 index 3e0a369b655..00000000000 --- a/src/server/shared/Timer.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TIMER_H -#define TRINITY_TIMER_H - -#include "Platform/CompilerDefs.h" - -#if PLATFORM == PLATFORM_WINDOWS -# include -# include -# include -#else -# if defined(__APPLE_CC__) -# include -# endif -# include -# include -#endif - -#if PLATFORM == PLATFORM_WINDOWS -inline uint32 getMSTime() { return GetTickCount(); } -#else -inline uint32 getMSTime() -{ - struct timeval tv; - struct timezone tz; - gettimeofday( &tv, &tz ); - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); -} -#endif - -inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) -{ - // getMSTime() have limited data range and this is case when it overflow in this tick - if (oldMSTime > newMSTime) - return (0xFFFFFFFF - oldMSTime) + newMSTime; - else - return newMSTime - oldMSTime; -} - -struct IntervalTimer -{ - public: - - IntervalTimer() - : _interval(0), _current(0) - { - } - - void Update(time_t diff) - { - _current += diff; - if (_current < 0) - _current = 0; - } - - bool Passed() - { - return _current >= _interval; - } - - void Reset() - { - if (_current >= _interval) - _current -= _interval; - } - - void SetCurrent(time_t current) - { - _current = current; - } - - void SetInterval(time_t interval) - { - _interval = interval; - } - - time_t GetInterval() const - { - return _interval; - } - - time_t GetCurrent() const - { - return _current; - } - - private: - - time_t _interval; - time_t _current; -}; - -struct TimeTracker -{ - public: - - TimeTracker(time_t expiry) - : i_expiryTime(expiry) - { - } - - void Update(time_t diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(time_t interval) - { - i_expiryTime = interval; - } - - time_t GetExpiry() const - { - return i_expiryTime; - } - - private: - - time_t i_expiryTime; -}; - -struct TimeTrackerSmall -{ - public: - - TimeTrackerSmall(uint32 expiry) - : i_expiryTime(expiry) - { - } - - void Update(int32 diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(uint32 interval) - { - i_expiryTime = interval; - } - - int32 GetExpiry() const - { - return i_expiryTime; - } - - private: - - int32 i_expiryTime; -}; - -struct PeriodicTimer -{ - public: - - PeriodicTimer(int32 period, int32 start_time) - : i_expireTime(start_time), i_period(period) - { - } - - bool Update(const uint32 &diff) - { - if ((i_expireTime -= diff) > 0) - return false; - - i_expireTime += i_period > diff ? i_period : diff; - return true; - } - - void SetPeriodic(int32 period, int32 start_time) - { - i_expireTime = start_time; - i_period = period; - } - - // Tracker interface - void TUpdate(int32 diff) { i_expireTime -= diff; } - bool TPassed() const { return i_expireTime <= 0; } - void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } - - private: - - int32 i_period; - int32 i_expireTime; -}; - -#endif diff --git a/src/server/shared/Util.cpp b/src/server/shared/Util.cpp deleted file mode 100644 index a3c017fdbfd..00000000000 --- a/src/server/shared/Util.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Util.h" - -#include "sockets/socket_include.h" -#include "utf8cpp/utf8.h" -#include "mersennetwister/MersenneTwister.h" -#include - -typedef ACE_TSS MTRandTSS; -static MTRandTSS mtRand; - -int32 irand (int32 min, int32 max) -{ - return int32 (mtRand->randInt (max - min)) + min; -} - -uint32 urand (uint32 min, uint32 max) -{ - return mtRand->randInt (max - min) + min; -} - -int32 rand32 () -{ - return mtRand->randInt (); -} - -double rand_norm(void) -{ - return mtRand->randExc (); -} - -double rand_chance (void) -{ - return mtRand->randExc (100.0); -} - -Tokens StrSplit(const std::string &src, const std::string &sep) -{ - Tokens r; - std::string s; - for (std::string::const_iterator i = src.begin(); i != src.end(); i++) - { - if (sep.find(*i) != std::string::npos) - { - if (s.length()) r.push_back(s); - s = ""; - } - else - { - s += *i; - } - } - if (s.length()) r.push_back(s); - return r; -} - -void stripLineInvisibleChars(std::string &str) -{ - static std::string invChars = " \t\7\n"; - - size_t wpos = 0; - - bool space = false; - for (size_t pos = 0; pos < str.size(); ++pos) - { - if(invChars.find(str[pos])!=std::string::npos) - { - if(!space) - { - str[wpos++] = ' '; - space = true; - } - } - else - { - if(wpos!=pos) - str[wpos++] = str[pos]; - else - ++wpos; - space = false; - } - } - - if(wpos < str.size()) - str.erase(wpos,str.size()); - if(str.find("|TInterface")!=std::string::npos) - str.clear(); - -} - -std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly) -{ - uint32 secs = timeInSecs % MINUTE; - uint32 minutes = timeInSecs % HOUR / MINUTE; - uint32 hours = timeInSecs % DAY / HOUR; - uint32 days = timeInSecs / DAY; - - std::ostringstream ss; - if(days) - ss << days << (shortText ? "d" : " Day(s) "); - if(hours || hoursOnly) - ss << hours << (shortText ? "h" : " Hour(s) "); - if(!hoursOnly) - { - if(minutes) - ss << minutes << (shortText ? "m" : " Minute(s) "); - if(secs || (!days && !hours && !minutes) ) - ss << secs << (shortText ? "s" : " Second(s)."); - } - - return ss.str(); -} - -uint32 TimeStringToSecs(const std::string& timestring) -{ - uint32 secs = 0; - uint32 buffer = 0; - uint32 multiplier = 0; - - for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ ) - { - if(isdigit(*itr)) - { - buffer*=10; - buffer+= (*itr)-'0'; - } - else - { - switch(*itr) - { - case 'd': multiplier = DAY; break; - case 'h': multiplier = HOUR; break; - case 'm': multiplier = MINUTE; break; - case 's': multiplier = 1; break; - default : return 0; //bad format - } - buffer*=multiplier; - secs+=buffer; - buffer=0; - } - } - - return secs; -} - -std::string TimeToTimestampStr(time_t t) -{ - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - char buf[20]; - snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); - return std::string(buf); -} - -/// Check if the string is a valid ip address representation -bool IsIPAddress(char const* ipaddress) -{ - if(!ipaddress) - return false; - - // Let the big boys do it. - // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD) - return inet_addr(ipaddress) != INADDR_NONE; -} - -/// create PID file -uint32 CreatePIDFile(const std::string& filename) -{ - FILE * pid_file = fopen (filename.c_str(), "w" ); - if (pid_file == NULL) - return 0; - -#ifdef WIN32 - DWORD pid = GetCurrentProcessId(); -#else - pid_t pid = getpid(); -#endif - - fprintf(pid_file, "%d", pid ); - fclose(pid_file); - - return (uint32)pid; -} - -size_t utf8length(std::string& utf8str) -{ - try - { - return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - } - catch(std::exception) - { - utf8str = ""; - return 0; - } -} - -void utf8truncate(std::string& utf8str,size_t len) -{ - try - { - size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - if(wlen <= len) - return; - - std::wstring wstr; - wstr.resize(wlen); - utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); - wstr.resize(len); - char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]); - utf8str.resize(oend-(&utf8str[0])); // remove unused tail - } - catch(std::exception) - { - utf8str = ""; - } -} - -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) -{ - try - { - size_t len = utf8::distance(utf8str,utf8str+csize); - if(len > wsize) - { - if(wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - wsize = len; - utf8::utf8to16(utf8str,utf8str+csize,wstr); - wstr[len] = L'\0'; - } - catch(std::exception) - { - if(wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - return true; -} - -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) -{ - try - { - size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - wstr.resize(len); - - utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); - } - catch(std::exception) - { - wstr = L""; - return false; - } - - return true; -} - -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(size*4); // allocate for most long case - - char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str = ""; - return false; - } - - return true; -} - -bool WStrToUtf8(std::wstring wstr, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(wstr.size()*4); // allocate for most long case - - char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str = ""; - return false; - } - - return true; -} - -typedef wchar_t const* const* wstrlist; - -std::wstring GetMainPartOfName(std::wstring wname, uint32 declension) -{ - // supported only Cyrillic cases - if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) - return wname; - - // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) - - static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)}; - static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)}; - static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)}; - static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)}; - static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)}; - static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)}; - static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)}; - static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)}; - static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)}; - static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)}; - - static wchar_t const* const dropEnds[6][8] = { - { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, - { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, - { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL }, - { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } - }; - - for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr) - { - size_t len = size_t((*itr)[-1]); // get length from string size field - - if(wname.substr(wname.size()-len,len)==*itr) - return wname.substr(0,wname.size()-len); - } - - return wname; -} - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - if(!Utf8toWStr(utf8str,wstr)) - return false; - - conStr.resize(wstr.size()); - CharToOemBuffW(&wstr[0],&conStr[0],wstr.size()); -#else - // not implemented yet - conStr = utf8str; -#endif - - return true; -} - -bool consoleToUtf8(const std::string& conStr,std::string& utf8str) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - wstr.resize(conStr.size()); - OemToCharBuffW(&conStr[0],&wstr[0],conStr.size()); - - return WStrToUtf8(wstr,utf8str); -#else - // not implemented yet - utf8str = conStr; - return true; -#endif -} - -bool Utf8FitTo(const std::string& str, std::wstring search) -{ - std::wstring temp; - - if(!Utf8toWStr(str,temp)) - return false; - - // converting to lower case - wstrToLower( temp ); - - if(temp.find(search) == std::wstring::npos) - return false; - - return true; -} - -void utf8printf(FILE *out, const char *str, ...) -{ - va_list ap; - va_start(ap, str); - vutf8printf(out, str, &ap); - va_end(ap); -} - -void vutf8printf(FILE *out, const char *str, va_list* ap) -{ -#if PLATFORM == PLATFORM_WINDOWS - char temp_buf[32*1024]; - wchar_t wtemp_buf[32*1024]; - - size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); - - size_t wtemp_len = 32*1024-1; - Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); - - CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); - fprintf(out, temp_buf); -#else - vfprintf(out, str, *ap); -#endif -} - -void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result) -{ - std::ostringstream ss; - for (uint32 i=0; i>((1-j)*4)); - char encodedNibble; - if(nibble < 0x0A) - encodedNibble = '0'+nibble; - else - encodedNibble = 'A'+nibble-0x0A; - ss << encodedNibble; - } - } - result = ss.str(); -} - diff --git a/src/server/shared/Util.h b/src/server/shared/Util.h deleted file mode 100644 index 4f997725d25..00000000000 --- a/src/server/shared/Util.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UTIL_H -#define _UTIL_H - -#include "Common.h" - -#include -#include - -typedef std::vector Tokens; - -Tokens StrSplit(const std::string &src, const std::string &sep); - -void stripLineInvisibleChars(std::string &src); - -std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false); -uint32 TimeStringToSecs(const std::string& timestring); -std::string TimeToTimestampStr(time_t t); - -inline uint32 secsToTimeBitFields(time_t secs) -{ - tm* lt = localtime(&secs); - return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; -} - -/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */ - int32 irand(int32 min, int32 max); - -/* Return a random number in the range min..max (inclusive). For reliable results, the difference -* between max and min should be less than RAND32_MAX. */ - uint32 urand(uint32 min, uint32 max); - -/* Return a random number in the range 0 .. RAND32_MAX. */ - int32 rand32(); - -/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits. - * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits). - * With an FPU, there is usually no difference in performance between float and double. */ - double rand_norm(void); - -/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits. - * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits). - * With an FPU, there is usually no difference in performance between float and double. */ - double rand_chance(void); - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_f(float chance) -{ - return chance > rand_chance(); -} - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_i(int chance) -{ - return chance > irand(0, 99); -} - -inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply) -{ - int32 cur = var; - cur += (apply ? val : -val); - if(cur < 0) - cur = 0; - var = cur; -} - -inline void ApplyModFloatVar(float& var, float val, bool apply) -{ - var += (apply ? val : -val); - if(var < 0) - var = 0; -} - -inline void ApplyPercentModFloatVar(float& var, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - val = -99.99f; - var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); -} - -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); -// in wsize==max size of buffer, out wsize==real string size -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); -inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) -{ - return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); -} - -bool WStrToUtf8(std::wstring wstr, std::string& utf8str); -// size==real string size -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); - -size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence -void utf8truncate(std::string& utf8str,size_t len); - -inline bool isBasicLatinCharacter(wchar_t wchar) -{ - if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return true; - if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return true; - return false; -} - -inline bool isExtendedLatinCharacter(wchar_t wchar) -{ - if(isBasicLatinCharacter(wchar)) - return true; - if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return true; - if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return true; - if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return true; - if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return true; - if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return true; - if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK - return true; - if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return true; - return false; -} - -inline bool isCyrillicCharacter(wchar_t wchar) -{ - if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA - return true; - if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO - return true; - return false; -} - -inline bool isEastAsianCharacter(wchar_t wchar) -{ - if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo - return true; - if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana - return true; - if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo - return true; - if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. - return true; - if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A - return true; - if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs - return true; - if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables - return true; - if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms - return true; - return false; -} - -inline bool isNumeric(wchar_t wchar) -{ - return (wchar >= L'0' && wchar <=L'9'); -} - -inline bool isNumeric(char c) -{ - return (c >= '0' && c <='9'); -} - -inline bool isNumericOrSpace(wchar_t wchar) -{ - return isNumeric(wchar) || wchar == L' '; -} - -inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline wchar_t wcharToUpper(wchar_t wchar) -{ - if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return wchar_t(uint16(wchar)-0x0020); - if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return wchar_t(0x1E9E); - if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)-0x0020); - if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return wchar_t(uint16(wchar)-0x0020); - if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) - { - if(wchar % 2 == 1) - return wchar_t(uint16(wchar)-0x0001); - } - if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA - return wchar_t(uint16(wchar)-0x0020); - if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO - return wchar_t(0x0401); - - return wchar; -} - -inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar) -{ - return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar; -} - -inline wchar_t wcharToLower(wchar_t wchar) -{ - if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) - { - if(wchar % 2 == 0) - return wchar_t(uint16(wchar)+0x0001); - } - if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return wchar_t(0x00DF); - if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO - return wchar_t(0x0451); - if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA - return wchar_t(uint16(wchar)+0x0020); - - return wchar; -} - -inline void wstrToUpper(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); -} - -inline void wstrToLower(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); -} - -std::wstring GetMainPartOfName(std::wstring wname, uint32 declension); - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr); -bool consoleToUtf8(const std::string& conStr,std::string& utf8str); -bool Utf8FitTo(const std::string& str, std::wstring search); -void utf8printf(FILE *out, const char *str, ...); -void vutf8printf(FILE *out, const char *str, va_list* ap); - -bool IsIPAddress(char const* ipaddress); -uint32 CreatePIDFile(const std::string& filename); - -void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result); -#endif - -//handler for operations on large flags -#ifndef _FLAG96 -#define _FLAG96 - -#ifndef PAIR64_HIPART -#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000FFFFFFFF)) -#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) -#endif - -class flag96 -{ -private: - uint32 part[3]; -public: - flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0) - { - part[0]=p1; - part[1]=p2; - part[2]=p3; - } - - flag96(uint64 p1, uint32 p2) - { - part[0]=PAIR64_LOPART(p1); - part[1]=PAIR64_HIPART(p1); - part[2]=p2; - } - - inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const - { - return ( - part[0]==p1 && - part[1]==p2 && - part[2]==p3); - }; - - inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const - { - return ( - part[0]&p1 || - part[1]&p2 || - part[2]&p3); - }; - - inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0) - { - part[0]=p1; - part[1]=p2; - part[2]=p3; - }; - - template - inline bool operator < (type & right) - { - for (uint8 i=3; i > 0; --i) - { - if (part[i-1]right.part[i-1]) - return 0; - } - return 0; - }; - - template - inline bool operator < (type & right) const - { - for (uint8 i = 3; i > 0; --i) - { - if (part[i-1]right.part[i-1]) - return 0; - } - return 0; - }; - - template - inline bool operator != (type & right) - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return true; - return false; - } - - template - inline bool operator != (type & right) const - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return true; - return false; - }; - - template - inline bool operator == (type & right) - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return false; - return true; - }; - - template - inline bool operator == (type & right) const - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return false; - return true; - }; - - template - inline void operator = (type & right) - { - part[0]=right.part[0]; - part[1]=right.part[1]; - part[2]=right.part[2]; - }; - - template - inline flag96 operator & (type & right) - { - flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); - return - ret; - }; - template - inline flag96 operator & (type & right) const - { - flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); - return - ret; - }; - - template - inline void operator &= (type & right) - { - *this=*this & right; - }; - - template - inline flag96 operator | (type & right) - { - flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); - return - ret; - }; - - template - inline flag96 operator | (type & right) const - { - flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); - return - ret; - }; - - template - inline void operator |= (type & right) - { - *this=*this | right; - }; - - inline void operator ~ () - { - part[2]=~part[2]; - part[1]=~part[1]; - part[0]=~part[0]; - }; - - template - inline flag96 operator ^ (type & right) - { - flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); - return - ret; - }; - - template - inline flag96 operator ^ (type & right) const - { - flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); - return - ret; - }; - - template - inline void operator ^= (type & right) - { - *this=*this^right; - }; - - inline operator bool() const - { - return( - part[0] != 0 || - part[1] != 0 || - part[2] != 0); - }; - - inline operator bool() - { - return( - part[0] != 0 || - part[1] != 0 || - part[2] != 0); - }; - - inline bool operator ! () const - { - return( - part[0] == 0 && - part[1] == 0 && - part[2] == 0); - }; - - inline bool operator ! () - { - return( - part[0] == 0 && - part[1] == 0 && - part[2] == 0); - }; - - inline uint32 & operator[](uint8 el) - { - return (part[el]); - }; - - inline const uint32 & operator[](uint8 el) const - { - return (part[el]); - }; -}; -#endif diff --git a/src/server/shared/Utilities/ProgressBar.cpp b/src/server/shared/Utilities/ProgressBar.cpp new file mode 100644 index 00000000000..c24d9f86f6b --- /dev/null +++ b/src/server/shared/Utilities/ProgressBar.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "ProgressBar.h" + +char const* const barGoLink::empty = " "; +#ifdef _WIN32 +char const* const barGoLink::full = "\x3D"; +#else +char const* const barGoLink::full = "*"; +#endif + +barGoLink::~barGoLink() +{ + printf( "\n" ); + fflush(stdout); +} + +barGoLink::barGoLink( int row_count ) +{ + rec_no = 0; + rec_pos = 0; + indic_len = 50; + num_rec = row_count; + #ifdef _WIN32 + printf( "\x3D" ); + #else + printf( "[" ); + #endif + for (int i = 0; i < indic_len; i++ ) printf( empty ); + #ifdef _WIN32 + printf( "\x3D 0%%\r\x3D" ); + #else + printf( "] 0%%\r[" ); + #endif + fflush(stdout); +} + +void barGoLink::step( void ) +{ + int i, n; + + if ( num_rec == 0 ) return; + ++rec_no; + n = rec_no * indic_len / num_rec; + if ( n != rec_pos ) + { + #ifdef _WIN32 + printf( "\r\x3D" ); + #else + printf( "\r[" ); + #endif + for (i = 0; i < n; i++ ) printf( full ); + for (; i < indic_len; i++ ) printf( empty ); + float percent = (((float)n/(float)indic_len)*100); + #ifdef _WIN32 + printf( "\x3D %i%% \r\x3D", (int)percent); + #else + printf( "] %i%% \r[", (int)percent); + #endif + fflush(stdout); + + rec_pos = n; + } +} + diff --git a/src/server/shared/Utilities/ProgressBar.h b/src/server/shared/Utilities/ProgressBar.h new file mode 100644 index 00000000000..e7565590278 --- /dev/null +++ b/src/server/shared/Utilities/ProgressBar.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef TRINITYCORE_PROGRESSBAR_H +#define TRINITYCORE_PROGRESSBAR_H + +#include "Platform/Define.h" + +class barGoLink +{ + static char const * const empty; + static char const * const full; + + int rec_no; + int rec_pos; + int num_rec; + int indic_len; + + public: + + void step( void ); + barGoLink( int ); + ~barGoLink(); +}; +#endif + diff --git a/src/server/shared/Utilities/ServiceWin32.cpp b/src/server/shared/Utilities/ServiceWin32.cpp new file mode 100644 index 00000000000..2c1df2ff483 --- /dev/null +++ b/src/server/shared/Utilities/ServiceWin32.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef WIN32 + +#include "Common.h" +#include "Log.h" +#include +#include +#include + +#if !defined(WINADVAPI) +#if !defined(_ADVAPI32_) +#define WINADVAPI DECLSPEC_IMPORT +#else +#define WINADVAPI +#endif +#endif + +extern int main(int argc, char ** argv); +extern char serviceLongName[]; +extern char serviceName[]; +extern char serviceDescription[]; + +extern int m_ServiceStatus; + +SERVICE_STATUS serviceStatus; + +SERVICE_STATUS_HANDLE serviceStatusHandle = 0; + +typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); + +bool WinServiceInstall() +{ + CSD_T ChangeService_Config2; + HMODULE advapi32; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); + + if (serviceControlManager) + { + char path[_MAX_PATH + 10]; + if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) + { + SC_HANDLE service; + std::strcat(path, " --service"); + service = CreateService(serviceControlManager, + serviceName, // name of service + serviceLongName, // service name to display + SERVICE_ALL_ACCESS, // desired access + // service type + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_AUTO_START, // start type + SERVICE_ERROR_IGNORE, // error control type + path, // service's binary + 0, // no load ordering group + 0, // no tag identifier + 0, // no dependencies + 0, // LocalSystem account + 0); // no password + if (service) + { + advapi32 = GetModuleHandle("ADVAPI32.DLL"); + if(!advapi32) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); + if (!ChangeService_Config2) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + SERVICE_DESCRIPTION sdBuf; + sdBuf.lpDescription = serviceDescription; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_DESCRIPTION, // change: description + &sdBuf); // new data + + SC_ACTION _action[1]; + _action[0].Type = SC_ACTION_RESTART; + _action[0].Delay = 10000; + SERVICE_FAILURE_ACTIONS sfa; + ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); + sfa.lpsaActions = _action; + sfa.cActions = 1; + sfa.dwResetPeriod =INFINITE; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_FAILURE_ACTIONS, // information level + &sfa); // new data + + CloseServiceHandle(service); + + } + } + CloseServiceHandle(serviceControlManager); + } + return true; +} + +bool WinServiceUninstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if (serviceControlManager) + { + SC_HANDLE service = OpenService(serviceControlManager, + serviceName, SERVICE_QUERY_STATUS | DELETE); + if (service) + { + SERVICE_STATUS serviceStatus2; + if (QueryServiceStatus(service, &serviceStatus2)) + { + if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) + DeleteService(service); + } + CloseServiceHandle(service); + } + + CloseServiceHandle(serviceControlManager); + } + return true; +} + +void WINAPI ServiceControlHandler(DWORD controlCode) +{ + switch (controlCode) + { + case SERVICE_CONTROL_INTERROGATE: + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + m_ServiceStatus = 0; + return; + + case SERVICE_CONTROL_PAUSE: + m_ServiceStatus = 2; + serviceStatus.dwCurrentState = SERVICE_PAUSED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + break; + + case SERVICE_CONTROL_CONTINUE: + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + m_ServiceStatus = 1; + break; + + default: + if ( controlCode >= 128 && controlCode <= 255 ) + // user defined control code + break; + else + // unrecognized control code + break; + } + + SetServiceStatus(serviceStatusHandle, &serviceStatus); +} + +void WINAPI ServiceMain(DWORD argc, char *argv[]) +{ + // initialise service status + serviceStatus.dwServiceType = SERVICE_WIN32; + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; + serviceStatus.dwWin32ExitCode = NO_ERROR; + serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + serviceStatus.dwCheckPoint = 0; + serviceStatus.dwWaitHint = 0; + + serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); + + if ( serviceStatusHandle ) + { + char path[_MAX_PATH + 1]; + unsigned int i, last_slash = 0; + + GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); + + for (i = 0; i < std::strlen(path); i++) + { + if (path[i] == '\\') last_slash = i; + } + + path[last_slash] = 0; + + // service is starting + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do initialisation here + SetCurrentDirectory(path); + + // running + serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + + //////////////////////// + // service main cycle // + //////////////////////// + + m_ServiceStatus = 1; + argc = 1; + main(argc , argv); + + // service was stopped + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do cleanup here + + // service is now stopped + serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + } +} + +bool WinServiceRun() +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { serviceName, ServiceMain }, + { 0, 0 } + }; + + if (!StartServiceCtrlDispatcher(serviceTable)) + { + sLog.outError("StartService Failed. Error [%u]", ::GetLastError()); + return false; + } + return true; +} +#endif + diff --git a/src/server/shared/Utilities/ServiceWin32.h b/src/server/shared/Utilities/ServiceWin32.h new file mode 100644 index 00000000000..ddac785a0fb --- /dev/null +++ b/src/server/shared/Utilities/ServiceWin32.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef WIN32 +#ifndef _WIN32_SERVICE_ +#define _WIN32_SERVICE_ + +bool WinServiceInstall(); +bool WinServiceUninstall(); +bool WinServiceRun(); + +#endif // _WIN32_SERVICE_ +#endif // WIN32 + diff --git a/src/server/shared/Utilities/SignalHandler.h b/src/server/shared/Utilities/SignalHandler.h new file mode 100644 index 00000000000..0c4d8143c41 --- /dev/null +++ b/src/server/shared/Utilities/SignalHandler.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SIGNAL_HANDLER_H__ +#define __SIGNAL_HANDLER_H__ + +#include + +namespace Trinity +{ + +/// Handle termination signals +class SignalHandler : public ACE_Event_Handler +{ + public: + int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL) + { + HandleSignal(SigNum); + return 0; + } + virtual void HandleSignal(int SigNum) {}; +}; + +} + +#endif /* __SIGNAL_HANDLER_H__ */ diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h new file mode 100644 index 00000000000..3e0a369b655 --- /dev/null +++ b/src/server/shared/Utilities/Timer.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TIMER_H +#define TRINITY_TIMER_H + +#include "Platform/CompilerDefs.h" + +#if PLATFORM == PLATFORM_WINDOWS +# include +# include +# include +#else +# if defined(__APPLE_CC__) +# include +# endif +# include +# include +#endif + +#if PLATFORM == PLATFORM_WINDOWS +inline uint32 getMSTime() { return GetTickCount(); } +#else +inline uint32 getMSTime() +{ + struct timeval tv; + struct timezone tz; + gettimeofday( &tv, &tz ); + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} +#endif + +inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) +{ + // getMSTime() have limited data range and this is case when it overflow in this tick + if (oldMSTime > newMSTime) + return (0xFFFFFFFF - oldMSTime) + newMSTime; + else + return newMSTime - oldMSTime; +} + +struct IntervalTimer +{ + public: + + IntervalTimer() + : _interval(0), _current(0) + { + } + + void Update(time_t diff) + { + _current += diff; + if (_current < 0) + _current = 0; + } + + bool Passed() + { + return _current >= _interval; + } + + void Reset() + { + if (_current >= _interval) + _current -= _interval; + } + + void SetCurrent(time_t current) + { + _current = current; + } + + void SetInterval(time_t interval) + { + _interval = interval; + } + + time_t GetInterval() const + { + return _interval; + } + + time_t GetCurrent() const + { + return _current; + } + + private: + + time_t _interval; + time_t _current; +}; + +struct TimeTracker +{ + public: + + TimeTracker(time_t expiry) + : i_expiryTime(expiry) + { + } + + void Update(time_t diff) + { + i_expiryTime -= diff; + } + + bool Passed() const + { + return i_expiryTime <= 0; + } + + void Reset(time_t interval) + { + i_expiryTime = interval; + } + + time_t GetExpiry() const + { + return i_expiryTime; + } + + private: + + time_t i_expiryTime; +}; + +struct TimeTrackerSmall +{ + public: + + TimeTrackerSmall(uint32 expiry) + : i_expiryTime(expiry) + { + } + + void Update(int32 diff) + { + i_expiryTime -= diff; + } + + bool Passed() const + { + return i_expiryTime <= 0; + } + + void Reset(uint32 interval) + { + i_expiryTime = interval; + } + + int32 GetExpiry() const + { + return i_expiryTime; + } + + private: + + int32 i_expiryTime; +}; + +struct PeriodicTimer +{ + public: + + PeriodicTimer(int32 period, int32 start_time) + : i_expireTime(start_time), i_period(period) + { + } + + bool Update(const uint32 &diff) + { + if ((i_expireTime -= diff) > 0) + return false; + + i_expireTime += i_period > diff ? i_period : diff; + return true; + } + + void SetPeriodic(int32 period, int32 start_time) + { + i_expireTime = start_time; + i_period = period; + } + + // Tracker interface + void TUpdate(int32 diff) { i_expireTime -= diff; } + bool TPassed() const { return i_expireTime <= 0; } + void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } + + private: + + int32 i_period; + int32 i_expireTime; +}; + +#endif diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp new file mode 100644 index 00000000000..a3c017fdbfd --- /dev/null +++ b/src/server/shared/Utilities/Util.cpp @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Util.h" + +#include "sockets/socket_include.h" +#include "utf8cpp/utf8.h" +#include "mersennetwister/MersenneTwister.h" +#include + +typedef ACE_TSS MTRandTSS; +static MTRandTSS mtRand; + +int32 irand (int32 min, int32 max) +{ + return int32 (mtRand->randInt (max - min)) + min; +} + +uint32 urand (uint32 min, uint32 max) +{ + return mtRand->randInt (max - min) + min; +} + +int32 rand32 () +{ + return mtRand->randInt (); +} + +double rand_norm(void) +{ + return mtRand->randExc (); +} + +double rand_chance (void) +{ + return mtRand->randExc (100.0); +} + +Tokens StrSplit(const std::string &src, const std::string &sep) +{ + Tokens r; + std::string s; + for (std::string::const_iterator i = src.begin(); i != src.end(); i++) + { + if (sep.find(*i) != std::string::npos) + { + if (s.length()) r.push_back(s); + s = ""; + } + else + { + s += *i; + } + } + if (s.length()) r.push_back(s); + return r; +} + +void stripLineInvisibleChars(std::string &str) +{ + static std::string invChars = " \t\7\n"; + + size_t wpos = 0; + + bool space = false; + for (size_t pos = 0; pos < str.size(); ++pos) + { + if(invChars.find(str[pos])!=std::string::npos) + { + if(!space) + { + str[wpos++] = ' '; + space = true; + } + } + else + { + if(wpos!=pos) + str[wpos++] = str[pos]; + else + ++wpos; + space = false; + } + } + + if(wpos < str.size()) + str.erase(wpos,str.size()); + if(str.find("|TInterface")!=std::string::npos) + str.clear(); + +} + +std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly) +{ + uint32 secs = timeInSecs % MINUTE; + uint32 minutes = timeInSecs % HOUR / MINUTE; + uint32 hours = timeInSecs % DAY / HOUR; + uint32 days = timeInSecs / DAY; + + std::ostringstream ss; + if(days) + ss << days << (shortText ? "d" : " Day(s) "); + if(hours || hoursOnly) + ss << hours << (shortText ? "h" : " Hour(s) "); + if(!hoursOnly) + { + if(minutes) + ss << minutes << (shortText ? "m" : " Minute(s) "); + if(secs || (!days && !hours && !minutes) ) + ss << secs << (shortText ? "s" : " Second(s)."); + } + + return ss.str(); +} + +uint32 TimeStringToSecs(const std::string& timestring) +{ + uint32 secs = 0; + uint32 buffer = 0; + uint32 multiplier = 0; + + for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ ) + { + if(isdigit(*itr)) + { + buffer*=10; + buffer+= (*itr)-'0'; + } + else + { + switch(*itr) + { + case 'd': multiplier = DAY; break; + case 'h': multiplier = HOUR; break; + case 'm': multiplier = MINUTE; break; + case 's': multiplier = 1; break; + default : return 0; //bad format + } + buffer*=multiplier; + secs+=buffer; + buffer=0; + } + } + + return secs; +} + +std::string TimeToTimestampStr(time_t t) +{ + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + char buf[20]; + snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); + return std::string(buf); +} + +/// Check if the string is a valid ip address representation +bool IsIPAddress(char const* ipaddress) +{ + if(!ipaddress) + return false; + + // Let the big boys do it. + // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD) + return inet_addr(ipaddress) != INADDR_NONE; +} + +/// create PID file +uint32 CreatePIDFile(const std::string& filename) +{ + FILE * pid_file = fopen (filename.c_str(), "w" ); + if (pid_file == NULL) + return 0; + +#ifdef WIN32 + DWORD pid = GetCurrentProcessId(); +#else + pid_t pid = getpid(); +#endif + + fprintf(pid_file, "%d", pid ); + fclose(pid_file); + + return (uint32)pid; +} + +size_t utf8length(std::string& utf8str) +{ + try + { + return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + } + catch(std::exception) + { + utf8str = ""; + return 0; + } +} + +void utf8truncate(std::string& utf8str,size_t len) +{ + try + { + size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + if(wlen <= len) + return; + + std::wstring wstr; + wstr.resize(wlen); + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + wstr.resize(len); + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]); + utf8str.resize(oend-(&utf8str[0])); // remove unused tail + } + catch(std::exception) + { + utf8str = ""; + } +} + +bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) +{ + try + { + size_t len = utf8::distance(utf8str,utf8str+csize); + if(len > wsize) + { + if(wsize > 0) + wstr[0] = L'\0'; + wsize = 0; + return false; + } + + wsize = len; + utf8::utf8to16(utf8str,utf8str+csize,wstr); + wstr[len] = L'\0'; + } + catch(std::exception) + { + if(wsize > 0) + wstr[0] = L'\0'; + wsize = 0; + return false; + } + + return true; +} + +bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) +{ + try + { + size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + wstr.resize(len); + + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + } + catch(std::exception) + { + wstr = L""; + return false; + } + + return true; +} + +bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(size*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +bool WStrToUtf8(std::wstring wstr, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(wstr.size()*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +typedef wchar_t const* const* wstrlist; + +std::wstring GetMainPartOfName(std::wstring wname, uint32 declension) +{ + // supported only Cyrillic cases + if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) + return wname; + + // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) + + static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)}; + static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)}; + static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)}; + static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)}; + static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)}; + static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)}; + static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)}; + static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)}; + static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)}; + static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)}; + + static wchar_t const* const dropEnds[6][8] = { + { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, + { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, + { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL }, + { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } + }; + + for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr) + { + size_t len = size_t((*itr)[-1]); // get length from string size field + + if(wname.substr(wname.size()-len,len)==*itr) + return wname.substr(0,wname.size()-len); + } + + return wname; +} + +bool utf8ToConsole(const std::string& utf8str, std::string& conStr) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + if(!Utf8toWStr(utf8str,wstr)) + return false; + + conStr.resize(wstr.size()); + CharToOemBuffW(&wstr[0],&conStr[0],wstr.size()); +#else + // not implemented yet + conStr = utf8str; +#endif + + return true; +} + +bool consoleToUtf8(const std::string& conStr,std::string& utf8str) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + wstr.resize(conStr.size()); + OemToCharBuffW(&conStr[0],&wstr[0],conStr.size()); + + return WStrToUtf8(wstr,utf8str); +#else + // not implemented yet + utf8str = conStr; + return true; +#endif +} + +bool Utf8FitTo(const std::string& str, std::wstring search) +{ + std::wstring temp; + + if(!Utf8toWStr(str,temp)) + return false; + + // converting to lower case + wstrToLower( temp ); + + if(temp.find(search) == std::wstring::npos) + return false; + + return true; +} + +void utf8printf(FILE *out, const char *str, ...) +{ + va_list ap; + va_start(ap, str); + vutf8printf(out, str, &ap); + va_end(ap); +} + +void vutf8printf(FILE *out, const char *str, va_list* ap) +{ +#if PLATFORM == PLATFORM_WINDOWS + char temp_buf[32*1024]; + wchar_t wtemp_buf[32*1024]; + + size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); + + size_t wtemp_len = 32*1024-1; + Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); + + CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); + fprintf(out, temp_buf); +#else + vfprintf(out, str, *ap); +#endif +} + +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result) +{ + std::ostringstream ss; + for (uint32 i=0; i>((1-j)*4)); + char encodedNibble; + if(nibble < 0x0A) + encodedNibble = '0'+nibble; + else + encodedNibble = 'A'+nibble-0x0A; + ss << encodedNibble; + } + } + result = ss.str(); +} + diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h new file mode 100644 index 00000000000..4f997725d25 --- /dev/null +++ b/src/server/shared/Utilities/Util.h @@ -0,0 +1,536 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UTIL_H +#define _UTIL_H + +#include "Common.h" + +#include +#include + +typedef std::vector Tokens; + +Tokens StrSplit(const std::string &src, const std::string &sep); + +void stripLineInvisibleChars(std::string &src); + +std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false); +uint32 TimeStringToSecs(const std::string& timestring); +std::string TimeToTimestampStr(time_t t); + +inline uint32 secsToTimeBitFields(time_t secs) +{ + tm* lt = localtime(&secs); + return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; +} + +/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */ + int32 irand(int32 min, int32 max); + +/* Return a random number in the range min..max (inclusive). For reliable results, the difference +* between max and min should be less than RAND32_MAX. */ + uint32 urand(uint32 min, uint32 max); + +/* Return a random number in the range 0 .. RAND32_MAX. */ + int32 rand32(); + +/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits. + * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits). + * With an FPU, there is usually no difference in performance between float and double. */ + double rand_norm(void); + +/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits. + * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits). + * With an FPU, there is usually no difference in performance between float and double. */ + double rand_chance(void); + +/* Return true if a random roll fits in the specified chance (range 0-100). */ +inline bool roll_chance_f(float chance) +{ + return chance > rand_chance(); +} + +/* Return true if a random roll fits in the specified chance (range 0-100). */ +inline bool roll_chance_i(int chance) +{ + return chance > irand(0, 99); +} + +inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply) +{ + int32 cur = var; + cur += (apply ? val : -val); + if(cur < 0) + cur = 0; + var = cur; +} + +inline void ApplyModFloatVar(float& var, float val, bool apply) +{ + var += (apply ? val : -val); + if(var < 0) + var = 0; +} + +inline void ApplyPercentModFloatVar(float& var, float val, bool apply) +{ + if (val == -100.0f) // prevent set var to zero + val = -99.99f; + var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); +} + +bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); +// in wsize==max size of buffer, out wsize==real string size +bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); +inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) +{ + return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); +} + +bool WStrToUtf8(std::wstring wstr, std::string& utf8str); +// size==real string size +bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); + +size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence +void utf8truncate(std::string& utf8str,size_t len); + +inline bool isBasicLatinCharacter(wchar_t wchar) +{ + if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z + return true; + if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z + return true; + return false; +} + +inline bool isExtendedLatinCharacter(wchar_t wchar) +{ + if(isBasicLatinCharacter(wchar)) + return true; + if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS + return true; + if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN + return true; + if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S + return true; + if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS + return true; + if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN + return true; + if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK + return true; + if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S + return true; + return false; +} + +inline bool isCyrillicCharacter(wchar_t wchar) +{ + if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA + return true; + if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO + return true; + return false; +} + +inline bool isEastAsianCharacter(wchar_t wchar) +{ + if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo + return true; + if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana + return true; + if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo + return true; + if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. + return true; + if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A + return true; + if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs + return true; + if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables + return true; + if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms + return true; + return false; +} + +inline bool isNumeric(wchar_t wchar) +{ + return (wchar >= L'0' && wchar <=L'9'); +} + +inline bool isNumeric(char c) +{ + return (c >= '0' && c <='9'); +} + +inline bool isNumericOrSpace(wchar_t wchar) +{ + return isNumeric(wchar) || wchar == L' '; +} + +inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline wchar_t wcharToUpper(wchar_t wchar) +{ + if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z + return wchar_t(uint16(wchar)-0x0020); + if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S + return wchar_t(0x1E9E); + if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS + return wchar_t(uint16(wchar)-0x0020); + if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN + return wchar_t(uint16(wchar)-0x0020); + if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) + { + if(wchar % 2 == 1) + return wchar_t(uint16(wchar)-0x0001); + } + if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA + return wchar_t(uint16(wchar)-0x0020); + if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO + return wchar_t(0x0401); + + return wchar; +} + +inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar) +{ + return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar; +} + +inline wchar_t wcharToLower(wchar_t wchar) +{ + if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) + { + if(wchar % 2 == 0) + return wchar_t(uint16(wchar)+0x0001); + } + if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S + return wchar_t(0x00DF); + if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO + return wchar_t(0x0451); + if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA + return wchar_t(uint16(wchar)+0x0020); + + return wchar; +} + +inline void wstrToUpper(std::wstring& str) +{ + std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); +} + +inline void wstrToLower(std::wstring& str) +{ + std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); +} + +std::wstring GetMainPartOfName(std::wstring wname, uint32 declension); + +bool utf8ToConsole(const std::string& utf8str, std::string& conStr); +bool consoleToUtf8(const std::string& conStr,std::string& utf8str); +bool Utf8FitTo(const std::string& str, std::wstring search); +void utf8printf(FILE *out, const char *str, ...); +void vutf8printf(FILE *out, const char *str, va_list* ap); + +bool IsIPAddress(char const* ipaddress); +uint32 CreatePIDFile(const std::string& filename); + +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result); +#endif + +//handler for operations on large flags +#ifndef _FLAG96 +#define _FLAG96 + +#ifndef PAIR64_HIPART +#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000FFFFFFFF)) +#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) +#endif + +class flag96 +{ +private: + uint32 part[3]; +public: + flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + } + + flag96(uint64 p1, uint32 p2) + { + part[0]=PAIR64_LOPART(p1); + part[1]=PAIR64_HIPART(p1); + part[2]=p2; + } + + inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]==p1 && + part[1]==p2 && + part[2]==p3); + }; + + inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]&p1 || + part[1]&p2 || + part[2]&p3); + }; + + inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + }; + + template + inline bool operator < (type & right) + { + for (uint8 i=3; i > 0; --i) + { + if (part[i-1]right.part[i-1]) + return 0; + } + return 0; + }; + + template + inline bool operator < (type & right) const + { + for (uint8 i = 3; i > 0; --i) + { + if (part[i-1]right.part[i-1]) + return 0; + } + return 0; + }; + + template + inline bool operator != (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + } + + template + inline bool operator != (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + }; + + template + inline bool operator == (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template + inline bool operator == (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template + inline void operator = (type & right) + { + part[0]=right.part[0]; + part[1]=right.part[1]; + part[2]=right.part[2]; + }; + + template + inline flag96 operator & (type & right) + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + template + inline flag96 operator & (type & right) const + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + + template + inline void operator &= (type & right) + { + *this=*this & right; + }; + + template + inline flag96 operator | (type & right) + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template + inline flag96 operator | (type & right) const + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template + inline void operator |= (type & right) + { + *this=*this | right; + }; + + inline void operator ~ () + { + part[2]=~part[2]; + part[1]=~part[1]; + part[0]=~part[0]; + }; + + template + inline flag96 operator ^ (type & right) + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template + inline flag96 operator ^ (type & right) const + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template + inline void operator ^= (type & right) + { + *this=*this^right; + }; + + inline operator bool() const + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline operator bool() + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline bool operator ! () const + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline bool operator ! () + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline uint32 & operator[](uint8 el) + { + return (part[el]); + }; + + inline const uint32 & operator[](uint8 el) const + { + return (part[el]); + }; +}; +#endif diff --git a/src/server/shared/WheatyExceptionReport.cpp b/src/server/shared/WheatyExceptionReport.cpp deleted file mode 100644 index 8fb5d5e2d2a..00000000000 --- a/src/server/shared/WheatyExceptionReport.cpp +++ /dev/null @@ -1,1013 +0,0 @@ -//========================================== -// Matt Pietrek -// MSDN Magazine, 2002 -// FILE: WheatyExceptionReport.CPP -//========================================== -#define WIN32_LEAN_AND_MEAN -#pragma warning(disable:4996) -#pragma warning(disable:4312) -#pragma warning(disable:4311) -#include -#include -#include -#include -#define _NO_CVCONST_H -#include -#include "WheatyExceptionReport.h" -#include "SystemConfig.h" -#include "revision.h" -#define CrashFolder _T("Crashes") -//#pragma comment(linker, "/defaultlib:dbghelp.lib") - -inline LPTSTR ErrorMessage(DWORD dw) -{ - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - return (LPTSTR)lpMsgBuf; -} - -//============================== Global Variables ============================= - -// -// Declare the static variables of the WheatyExceptionReport class -// -TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; -LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; -HANDLE WheatyExceptionReport::m_hReportFile; -HANDLE WheatyExceptionReport::m_hProcess; - -// Declare global instance of class -WheatyExceptionReport g_WheatyExceptionReport; - -//============================== Class Methods ============================= - -WheatyExceptionReport::WheatyExceptionReport() // Constructor -{ - // Install the unhandled exception filter function - m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); - m_hProcess = GetCurrentProcess(); -} - -//============ -// Destructor -//============ -WheatyExceptionReport::~WheatyExceptionReport() -{ - if (m_previousFilter) - SetUnhandledExceptionFilter(m_previousFilter); -} - -//=========================================================== -// Entry point where control comes on an unhandled exception -//=========================================================== -LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( -PEXCEPTION_POINTERS pExceptionInfo) -{ - TCHAR module_folder_name[MAX_PATH]; - GetModuleFileName(0, module_folder_name, MAX_PATH); - TCHAR* pos = _tcsrchr(module_folder_name, '\\'); - if (!pos) - return 0; - pos[0] = '\0'; - ++pos; - - TCHAR crash_folder_path[MAX_PATH]; - sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder); - if (!CreateDirectory(crash_folder_path, NULL)) - { - if (GetLastError() != ERROR_ALREADY_EXISTS) - return 0; - } - - SYSTEMTIME systime; - GetLocalTime(&systime); - sprintf(m_szLogFileName, "%s\\%s_[%u-%u_%u-%u-%u].txt", - crash_folder_path, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); - - m_hReportFile = CreateFile(m_szLogFileName, - GENERIC_WRITE, - 0, - 0, - OPEN_ALWAYS, - FILE_FLAG_WRITE_THROUGH, - 0); - - if (m_hReportFile) - { - SetFilePointer(m_hReportFile, 0, 0, FILE_END); - - GenerateExceptionReport(pExceptionInfo); - - CloseHandle(m_hReportFile); - m_hReportFile = 0; - } - - if (m_previousFilter) - return m_previousFilter(pExceptionInfo); - else - return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; -} - -BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) -{ - if (!sProcessorName) - return FALSE; - - HKEY hKey; - LONG lRet; - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), - 0, KEY_QUERY_VALUE, &hKey); - if (lRet != ERROR_SUCCESS) - return FALSE; - TCHAR szTmp[2048]; - DWORD cntBytes = sizeof(szTmp); - lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL, - (LPBYTE)szTmp, &cntBytes); - if (lRet != ERROR_SUCCESS) - return FALSE; - ::RegCloseKey(hKey); - sProcessorName[0] = '\0'; - // Skip spaces - TCHAR* psz = szTmp; - while (iswspace(*psz)) - ++psz; - _tcsncpy(sProcessorName, psz, maxcount); - return TRUE; -} - -BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax) -{ - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - // If that fails, try using the OSVERSIONINFO structure. - OSVERSIONINFOEX osvi = { 0 }; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - BOOL bOsVersionInfoEx; - bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!::GetVersionEx((OSVERSIONINFO*)&osvi)) - return FALSE; - } - *szVersion = _T('\0'); - TCHAR wszTmp[128]; - switch (osvi.dwPlatformId) - { - // Windows NT product family. - case VER_PLATFORM_WIN32_NT: - // Test for the specific product family. - if (osvi.dwMajorVersion == 6) - _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); - if (osvi.dwMajorVersion <= 4) - _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); - - // Test for specific product on Windows NT 4.0 SP6 and later. - if (bOsVersionInfoEx) - { - // Test for the workstation type. - #if WINVER < 0x0500 - if (osvi.wReserved[1] == VER_NT_WORKSTATION) - #else - if (osvi.wProductType == VER_NT_WORKSTATION) - #endif // WINVER < 0x0500 - { - if (osvi.dwMajorVersion == 4) - _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_PERSONAL) - #else - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Home Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_EMBEDDEDNT) - #else - else if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Embedded "), cntMax); - else - _tcsncat(szVersion, _T("Professional "), cntMax); - } - // Test for the server type. - #if WINVER < 0x0500 - else if (osvi.wReserved[1] == VER_NT_SERVER) - #else - else if (osvi.wProductType == VER_NT_SERVER) - #endif // WINVER < 0x0500 - { - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_DATACENTER) - #else - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Datacenter Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Enterprise Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] == VER_SUITE_BLADE) - #else - else if (osvi.wSuiteMask == VER_SUITE_BLADE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Web Edition "), cntMax); - else - _tcsncat(szVersion, _T("Standard Edition "), cntMax); - } - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_DATACENTER) - #else - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Datacenter Server "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Advanced Server "), cntMax); - else - _tcsncat(szVersion, _T("Server "), cntMax); - } - else // Windows NT 4.0 - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); - else - _tcsncat(szVersion, _T("Server 4.0 "), cntMax); - } - } - } - // Display service pack (if any) and build number. - if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0) - { - HKEY hKey; - LONG lRet; - - // Test for SP6 versus SP6a. - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey); - if (lRet == ERROR_SUCCESS) - { - _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - else // Windows NT 4.0 prior to SP6a - { - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - ::RegCloseKey(hKey); - } - else // Windows NT 3.51 and earlier or Windows 2000 and later - { - if (!_tcslen(osvi.szCSDVersion)) - _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - else - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - break; - default: - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - break; - } - - return TRUE; -} - -void WheatyExceptionReport::PrintSystemInfo() -{ - SYSTEM_INFO SystemInfo; - ::GetSystemInfo(&SystemInfo); - - MEMORYSTATUS MemoryStatus; - MemoryStatus.dwLength = sizeof (MEMORYSTATUS); - ::GlobalMemoryStatus(&MemoryStatus); - TCHAR sString[1024]; - _tprintf(_T("//=====================================================\r\n")); - if (_GetProcessorName(sString, countof(sString))) - _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - else - _tprintf(_T("*** Hardware ***\r\nProcessor: \r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - - if (_GetWindowsVersion(sString, countof(sString))) - _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); - else - _tprintf(_T("\r\n*** Operation System:\r\n\r\n")); -} - -//=========================================================================== -void WheatyExceptionReport::printTracesForAllThreads() -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - DWORD dwOwnerPID = GetCurrentProcessId(); - m_hProcess = GetCurrentProcess(); - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return; - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - { - CloseHandle(hThreadSnap); // Must clean up the - // snapshot object! - return; - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - CONTEXT context; - context.ContextFlags = 0xffffffff; - HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,false, te32.th32ThreadID); - if (threadHandle && GetThreadContext(threadHandle, &context)) - { - WriteStackDetails(&context, false, threadHandle); - } - CloseHandle(threadHandle); - } - } while(Thread32Next(hThreadSnap, &te32)); - -// Don't forget to clean up the snapshot object. - CloseHandle(hThreadSnap); -} - -//=========================================================================== -// Open the report file, and write the desired information to it. Called by -// WheatyUnhandledExceptionFilter -//=========================================================================== -void WheatyExceptionReport::GenerateExceptionReport( -PEXCEPTION_POINTERS pExceptionInfo) -{ - SYSTEMTIME systime; - GetLocalTime(&systime); - - // Start out with a banner - _tprintf(_T("Revision: %s\r\n"), _FULLVERSION); - _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); - PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; - - PrintSystemInfo(); - // First print information about the type of fault - _tprintf(_T("\r\n//=====================================================\r\n")); - _tprintf(_T("Exception code: %08X %s\r\n"), - pExceptionRecord->ExceptionCode, - GetExceptionString(pExceptionRecord->ExceptionCode)); - - // Now print information about where the fault occured - TCHAR szFaultingModule[MAX_PATH]; - DWORD section; - DWORD_PTR offset; - GetLogicalAddress(pExceptionRecord->ExceptionAddress, - szFaultingModule, - sizeof(szFaultingModule), - section, offset); - -#ifdef _M_IX86 - _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif -#ifdef _M_X64 - _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif - - PCONTEXT pCtx = pExceptionInfo->ContextRecord; - - // Show the registers - #ifdef _M_IX86 // X86 Only! - _tprintf(_T("\r\nRegisters:\r\n")); - - _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n") - ,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, - pCtx->Esi, pCtx->Edi); - - _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip); - _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), - pCtx->SegSs, pCtx->Esp, pCtx->Ebp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); - #endif - - #ifdef _M_X64 - _tprintf(_T("\r\nRegisters:\r\n")); - _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") - _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n") - ,pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, - pCtx->Rsi, pCtx->Rdi ,pCtx->R9,pCtx->R10,pCtx->R11,pCtx->R12,pCtx->R13,pCtx->R14,pCtx->R15); - _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); - _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), - pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); - #endif - - SymSetOptions(SYMOPT_DEFERRED_LOADS); - - // Initialize DbgHelp - if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) - { - _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"), - ErrorMessage(GetLastError())); - } - - CONTEXT trashableContext = *pCtx; - - WriteStackDetails(&trashableContext, false, NULL); - printTracesForAllThreads(); - -// #ifdef _M_IX86 // X86 Only! - - _tprintf(_T("========================\r\n")); - _tprintf(_T("Local Variables And Parameters\r\n")); - - trashableContext = *pCtx; - WriteStackDetails(&trashableContext, true, NULL); - - _tprintf(_T("========================\r\n")); - _tprintf(_T("Global Variables\r\n")); - - SymEnumSymbols(GetCurrentProcess(), - (DWORD64)GetModuleHandle(szFaultingModule), - 0, EnumerateSymbolsCallback, 0); - // #endif // X86 Only! - - SymCleanup(GetCurrentProcess()); - - _tprintf(_T("\r\n")); -} - -//====================================================================== -// Given an exception code, returns a pointer to a static string with a -// description of the exception -//====================================================================== -LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) -{ - #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); - - switch (dwCode) - { - EXCEPTION(ACCESS_VIOLATION) - EXCEPTION(DATATYPE_MISALIGNMENT) - EXCEPTION(BREAKPOINT) - EXCEPTION(SINGLE_STEP) - EXCEPTION(ARRAY_BOUNDS_EXCEEDED) - EXCEPTION(FLT_DENORMAL_OPERAND) - EXCEPTION(FLT_DIVIDE_BY_ZERO) - EXCEPTION(FLT_INEXACT_RESULT) - EXCEPTION(FLT_INVALID_OPERATION) - EXCEPTION(FLT_OVERFLOW) - EXCEPTION(FLT_STACK_CHECK) - EXCEPTION(FLT_UNDERFLOW) - EXCEPTION(INT_DIVIDE_BY_ZERO) - EXCEPTION(INT_OVERFLOW) - EXCEPTION(PRIV_INSTRUCTION) - EXCEPTION(IN_PAGE_ERROR) - EXCEPTION(ILLEGAL_INSTRUCTION) - EXCEPTION(NONCONTINUABLE_EXCEPTION) - EXCEPTION(STACK_OVERFLOW) - EXCEPTION(INVALID_DISPOSITION) - EXCEPTION(GUARD_PAGE) - EXCEPTION(INVALID_HANDLE) - } - - // If not one of the "known" exceptions, try to get the string - // from NTDLL.DLL's message table. - - static TCHAR szBuffer[512] = { 0 }; - - FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, - GetModuleHandle(_T("NTDLL.DLL")), - dwCode, 0, szBuffer, sizeof(szBuffer), 0); - - return szBuffer; -} - -//============================================================================= -// Given a linear address, locates the module, section, and offset containing -// that address. -// -// Note: the szModule paramater buffer is an output buffer of length specified -// by the len parameter (in characters!) -//============================================================================= -BOOL WheatyExceptionReport::GetLogicalAddress( -PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) -{ - MEMORY_BASIC_INFORMATION mbi; - - if (!VirtualQuery(addr, &mbi, sizeof(mbi))) - return FALSE; - - DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; - - if (!GetModuleFileName((HMODULE)hMod, szModule, len)) - return FALSE; - - // Point to the DOS header in memory - PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; - - // From the DOS header, find the NT (PE) header - PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew)); - - PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); - - DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address - - // Iterate through the section table, looking for the one that encompasses - // the linear address. - for (unsigned i = 0; - i < pNtHdr->FileHeader.NumberOfSections; - i++, pSection++) - { - DWORD_PTR sectionStart = pSection->VirtualAddress; - DWORD_PTR sectionEnd = sectionStart - + DWORD_PTR(max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); - - // Is the address in this section??? - if ((rva >= sectionStart) && (rva <= sectionEnd)) - { - // Yes, address is in the section. Calculate section and offset, - // and store in the "section" & "offset" params, which were - // passed by reference. - section = i+1; - offset = rva - sectionStart; - return TRUE; - } - } - - return FALSE; // Should never get here! -} - -// It contains SYMBOL_INFO structure plus additional -// space for the name of the symbol -struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE -{ - CSymbolInfoPackage() - { - si.SizeOfStruct = sizeof(SYMBOL_INFO); - si.MaxNameLen = sizeof(name); - } -}; - -//============================================================ -// Walks the stack, and writes the results to the report file -//============================================================ -void WheatyExceptionReport::WriteStackDetails( -PCONTEXT pContext, -bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output -{ - _tprintf(_T("\r\nCall stack:\r\n")); - - _tprintf(_T("Address Frame Function SourceFile\r\n")); - - DWORD dwMachineType = 0; - // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag - - STACKFRAME64 sf; - memset(&sf, 0, sizeof(sf)); - - #ifdef _M_IX86 - // Initialize the STACKFRAME structure for the first call. This is only - // necessary for Intel CPUs, and isn't mentioned in the documentation. - sf.AddrPC.Offset = pContext->Eip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Esp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Ebp; - sf.AddrFrame.Mode = AddrModeFlat; - - dwMachineType = IMAGE_FILE_MACHINE_I386; - #endif - -#ifdef _M_X64 - sf.AddrPC.Offset = pContext->Rip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Rsp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Rbp; - sf.AddrFrame.Mode = AddrModeFlat; - dwMachineType = IMAGE_FILE_MACHINE_AMD64; -#endif - - while (1) - { - // Get the next stack frame - if (! StackWalk64(dwMachineType, - m_hProcess, - pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), - &sf, - pContext, - 0, - SymFunctionTableAccess64, - SymGetModuleBase64, - 0)) - break; - if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure - break; // the frame is OK. Bail if not. -#ifdef _M_IX86 - _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif -#ifdef _M_X64 - _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif - - DWORD64 symDisplacement = 0; // Displacement of the input address, - // relative to the start of the symbol - - // Get the name of the function for this stack frame entry - CSymbolInfoPackage sip; - if (SymFromAddr( - m_hProcess, // Process handle of the current process - sf.AddrPC.Offset, // Symbol address - &symDisplacement, // Address of the variable that will receive the displacement - &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) - { - _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement); - - } - else // No symbol found. Print out the logical address instead. - { - TCHAR szModule[MAX_PATH] = _T(""); - DWORD section = 0; - DWORD_PTR offset = 0; - - GetLogicalAddress((PVOID)sf.AddrPC.Offset, - szModule, sizeof(szModule), section, offset); -#ifdef _M_IX86 - _tprintf(_T("%04X:%08X %s"), section, offset, szModule); -#endif -#ifdef _M_X64 - _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule); -#endif - } - - // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; - DWORD dwLineDisplacement; - if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, - &dwLineDisplacement, &lineInfo)) - { - _tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber); - } - - _tprintf(_T("\r\n")); - - // Write out the variables, if desired - if (bWriteVariables) - { - // Use SymSetContext to get just the locals/params for this frame - IMAGEHLP_STACK_FRAME imagehlpStackFrame; - imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; - SymSetContext(m_hProcess, &imagehlpStackFrame, 0); - - // Enumerate the locals/parameters - SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf); - - _tprintf(_T("\r\n")); - } - } - -} - -////////////////////////////////////////////////////////////////////////////// -// The function invoked by SymEnumSymbols -////////////////////////////////////////////////////////////////////////////// - -BOOL CALLBACK -WheatyExceptionReport::EnumerateSymbolsCallback( -PSYMBOL_INFO pSymInfo, -ULONG SymbolSize, -PVOID UserContext) -{ - - char szBuffer[2048]; - - __try - { - if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, - szBuffer, sizeof(szBuffer))) - _tprintf(_T("\t%s\r\n"), szBuffer); - } - __except(1) - { - _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name); - } - - return TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// Given a SYMBOL_INFO representing a particular variable, displays its -// contents. If it's a user defined type, display the members and their -// values. -////////////////////////////////////////////////////////////////////////////// -bool WheatyExceptionReport::FormatSymbolValue( -PSYMBOL_INFO pSym, -STACKFRAME * sf, -char * pszBuffer, -unsigned cbBuffer) -{ - char * pszCurrBuffer = pszBuffer; - - // Indicate if the variable is a local or parameter - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) - pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter "); - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) - pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); - - // If it's a function, don't do anything. - if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK - return false; - - DWORD_PTR pVariable = 0; // Will point to the variable's data in memory - - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) - { - // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) - { // This may change!!! - pVariable = sf->AddrFrame.Offset; - pVariable += (DWORD_PTR)pSym->Address; - } - // else - // return false; - } - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) - { - return false; // Don't try to report register variable - } - else - { - pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable - } - - // Determine if the variable is a user defined type (UDT). IF so, bHandled - // will return true. - bool bHandled; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer,pSym->ModBase, pSym->TypeIndex, - 0, pVariable, bHandled, pSym->Name); - - if (!bHandled) - { - // The symbol wasn't a UDT, so do basic, stupid formatting of the - // variable. Based on the size, we're assuming it's a char, WORD, or - // DWORD. - BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); - pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - - // Emit the variable name - pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name); - - pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size, - (PVOID)pVariable); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// If it's a user defined type (UDT), recurse through its members until we're -// at fundamental types. When he hit fundamental types, return -// bHandled = false, so that FormatSymbolValue() will format them. -////////////////////////////////////////////////////////////////////////////// -char * WheatyExceptionReport::DumpTypeIndex( -char * pszCurrBuffer, -DWORD64 modBase, -DWORD dwTypeIndex, -unsigned nestingLevel, -DWORD_PTR offset, -bool & bHandled, -char* Name) -{ - bHandled = false; - - // Get the name of the symbol. This will either be a Type name (if a UDT), - // or the structure member name. - WCHAR * pwszTypeName; - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, - &pwszTypeName)) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName); - LocalFree(pwszTypeName); - } - - // Determine how many children this type has. - DWORD dwChildrenCount = 0; - SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, - &dwChildrenCount); - - if (!dwChildrenCount) // If no children, we're done - return pszCurrBuffer; - - // Prepare to get an array of "TypeIds", representing each of the children. - // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a - // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. - struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS - { - ULONG MoreChildIds[1024]; - FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} - } children; - - children.Count = dwChildrenCount; - children.Start= 0; - - // Get the array of TypeIds, one for each child type - if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, - &children)) - { - return pszCurrBuffer; - } - - // Append a line feed - pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); - - // Iterate through each of the children - for (unsigned i = 0; i < dwChildrenCount; i++) - { - // Add appropriate indentation level (since this routine is recursive) - for (unsigned j = 0; j <= nestingLevel+1; j++) - pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); - - // Recurse for each of the child types - bool bHandled2; - BasicType basicType = GetBasicType(children.ChildId[i], modBase); - pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, - children.ChildId[i], nestingLevel+1, - offset, bHandled2, ""/*Name */); - - // If the child wasn't a UDT, format it appropriately - if (!bHandled2) - { - // Get the offset of the child member, relative to its parent - DWORD dwMemberOffset; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_OFFSET, &dwMemberOffset); - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_TYPEID, &typeId); - - // Get the size of the child member - ULONG64 length; - SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH,&length); - - // Calculate the address of the member - DWORD_PTR dwFinalOffset = offset + dwMemberOffset; - - // BasicType basicType = GetBasicType(children.ChildId[i], modBase); - // - // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - // - // Emit the variable name - // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name); - - pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, - length, (PVOID)dwFinalOffset); - - pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); - } - } - - bHandled = true; - return pszCurrBuffer; -} - -char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, -BasicType basicType, -DWORD64 length, -PVOID pAddress) -{ - // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) - if (length == 1) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); - else if (length == 2) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); - else if (length == 4) - { - if (basicType == btFloat) - { - pszCurrBuffer += sprintf(pszCurrBuffer," = %f", *(PFLOAT)pAddress); - } - else if (basicType == btChar) - { - if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", - *(PDWORD)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", - *(PDWORD)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer," = %X", *(PDWORD)pAddress); - } - else if (length == 8) - { - if (basicType == btFloat) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", - *(double *)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", - *(DWORD64*)pAddress); - } - - return pszCurrBuffer; -} - -BasicType -WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) -{ - BasicType basicType; - if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, - TI_GET_BASETYPE, &basicType)) - { - return basicType; - } - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - if (SymGetTypeInfo(m_hProcess,modBase, typeIndex, TI_GET_TYPEID, &typeId)) - { - if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, - &basicType)) - { - return basicType; - } - } - - return btNoType; -} - -//============================================================================ -// Helper function that writes to the report file, and allows the user to use -// printf style formating -//============================================================================ -int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) -{ - TCHAR szBuff[1024]; - int retValue; - DWORD cbWritten; - va_list argptr; - - va_start(argptr, format); - retValue = vsprintf(szBuff, format, argptr); - va_end(argptr); - - WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); - - return retValue; -} - diff --git a/src/server/shared/WheatyExceptionReport.h b/src/server/shared/WheatyExceptionReport.h deleted file mode 100644 index 33fb4bc5b0e..00000000000 --- a/src/server/shared/WheatyExceptionReport.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef _WHEATYEXCEPTIONREPORT_ -#define _WHEATYEXCEPTIONREPORT_ - -#include - -#if _MSC_VER < 1400 -# define countof(array) (sizeof(array) / sizeof(array[0])) -#else -# include -# define countof _countof -#endif // _MSC_VER < 1400 - -enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK -{ - btNoType = 0, - btVoid = 1, - btChar = 2, - btWChar = 3, - btInt = 6, - btUInt = 7, - btFloat = 8, - btBCD = 9, - btBool = 10, - btLong = 13, - btULong = 14, - btCurrency = 25, - btDate = 26, - btVariant = 27, - btComplex = 28, - btBit = 29, - btBSTR = 30, - btHresult = 31 -}; - -const char* const rgBaseType[] = -{ - " ", // btNoType = 0, - " void ", // btVoid = 1, - " char* ", // btChar = 2, - " wchar_t* ", // btWChar = 3, - " signed char ", - " unsigned char ", - " int ", // btInt = 6, - " unsigned int ", // btUInt = 7, - " float ", // btFloat = 8, - " ", // btBCD = 9, - " bool ", // btBool = 10, - " short ", - " unsigned short ", - " long ", // btLong = 13, - " unsigned long ", // btULong = 14, - " __int8 ", - " __int16 ", - " __int32 ", - " __int64 ", - " __int128 ", - " unsigned __int8 ", - " unsigned __int16 ", - " unsigned __int32 ", - " unsigned __int64 ", - " unsigned __int128 ", - " ", // btCurrency = 25, - " ", // btDate = 26, - " VARIANT ", // btVariant = 27, - " ", // btComplex = 28, - " ", // btBit = 29, - " BSTR ", // btBSTR = 30, - " HRESULT " // btHresult = 31 -}; - -class WheatyExceptionReport -{ - public: - - WheatyExceptionReport(); - ~WheatyExceptionReport(); - - // entry point where control comes on an unhandled exception - static LONG WINAPI WheatyUnhandledExceptionFilter( - PEXCEPTION_POINTERS pExceptionInfo); - - static void printTracesForAllThreads(); - private: - // where report info is extracted and generated - static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); - static void PrintSystemInfo(); - static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); - static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); - - // Helper functions - static LPTSTR GetExceptionString(DWORD dwCode); - static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, - DWORD& section, DWORD_PTR& offset); - - static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); - - static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); - - static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); - - static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*); - - static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress); - - static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); - - static int __cdecl _tprintf(const TCHAR * format, ...); - - // Variables used by the class - static TCHAR m_szLogFileName[MAX_PATH]; - static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; - static HANDLE m_hReportFile; - static HANDLE m_hProcess; -}; - -extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class -#endif //WheatyExceptionReport - diff --git a/src/server/shared/WorldPacket.h b/src/server/shared/WorldPacket.h deleted file mode 100644 index d708959f91d..00000000000 --- a/src/server/shared/WorldPacket.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_WORLDPACKET_H -#define TRINITYCORE_WORLDPACKET_H - -#include "Common.h" -#include "ByteBuffer.h" - -class WorldPacket : public ByteBuffer -{ - public: - // just container for later use - WorldPacket() : ByteBuffer(0), m_opcode(0) - { - } - explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } - // copy constructor - WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) - { - } - - void Initialize(uint16 opcode, size_t newres=200) - { - clear(); - _storage.reserve(newres); - m_opcode = opcode; - } - - uint16 GetOpcode() const { return m_opcode; } - void SetOpcode(uint16 opcode) { m_opcode = opcode; } - - protected: - uint16 m_opcode; -}; -#endif - -- cgit v1.2.3