Merge branch 'tob_patch' into tob_buffupdate

This commit is contained in:
dannuic 2026-04-29 13:27:52 -06:00
commit 966ca5cf07
23 changed files with 236 additions and 90 deletions

View File

@ -3,9 +3,8 @@ on:
push:
branches:
- master
- tob_patch
- develop
pull_request:
jobs:
linux:
name: Linux
@ -26,6 +25,17 @@ jobs:
sudo apt-get update
sudo apt-get install -y build-essential ninja-build ccache uuid-dev
- name: Restore vcpkg Cache
uses: actions/cache@v5
with:
path: |
build/vcpkg_installed
submodules/vcpkg/downloads
key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}-
${{ runner.os }}-vcpkg-
- name: Configure
run: |
cmake -S . -B build -G Ninja \
@ -48,6 +58,9 @@ jobs:
windows:
name: Windows
runs-on: windows-latest
env:
VCPKG_DOWNLOADS: ${{ github.workspace }}\submodules\vcpkg\downloads
VCPKG_BINARY_SOURCES: 'clear;files,${{ github.workspace }}\vcpkg_archives,readwrite'
steps:
- name: Checkout source
uses: actions/checkout@v5
@ -56,12 +69,22 @@ jobs:
- name: Enable long paths
run: git config --global core.longpaths true
- name: Setup MSVC environment
uses: ilammy/msvc-dev-cmd@v1
uses: TheMrMilchmann/setup-msvc-dev@v4
with:
arch: x64
- name: Restore vcpkg Cache
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_DOWNLOADS }}
${{ github.workspace }}/vcpkg_archives
key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}
restore-keys: |
${{ runner.os }}-vcpkg-
- name: Configure
shell: pwsh
run: |

View File

@ -42,7 +42,7 @@ option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON)
if(MSVC)
add_compile_options(/bigobj)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING _HAS_AUTO_PTR_ETC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." OFF)

View File

@ -6,6 +6,7 @@ set(common_sources
bodytypes.cpp
classes.cpp
cli/eqemu_command_handler.cpp
compiler_macros.h
compression.cpp
content/world_content_service.cpp
crash.cpp

20
common/compiler_macros.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#if defined(_MSC_VER)
#define PUSH_DISABLE_DEPRECATED_WARNINGS() __pragma(warning(push)) \
__pragma(warning(disable:4996))
#define POP_DISABLE_DEPRECATED_WARNINGS() __pragma(warning(pop))
#elif defined(__GNUC__) || defined(__clang__)
#define PUSH_DISABLE_DEPRECATED_WARNINGS() _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define POP_DISABLE_DEPRECATED_WARNINGS() _Pragma("GCC diagnostic pop")
#else
#define PUSH_DISABLE_DEPRECATED_WARNINGS()
#define POP_DISABLE_DEPRECATED_WARNINGS()
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#define UNREACHABLE() __assume(0)
#else
#define UNREACHABLE() __builtin_unreachable()
#endif

View File

@ -271,11 +271,7 @@ static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readVa
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
// Implementation of class Features
// ////////////////////////////////
@ -4153,11 +4149,7 @@ Value& Path::make(Value& root) const {
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
static bool containsControlCharacter(const char* str) {
while (*str) {

View File

@ -103,7 +103,7 @@ namespace luabind { namespace detail
if (luabind::move_back_reference(L, ptr))
return;
make_instance(L, std::auto_ptr<T>(ptr));
make_instance(L, std::unique_ptr<T>(ptr));
}
};

View File

@ -335,7 +335,7 @@ namespace luabind
template <class T>
struct default_pointer<null_type, T>
{
typedef std::auto_ptr<T> type;
typedef std::unique_ptr<T> type;
};
template <class Class, class Pointer, class Signature, class Policies>

View File

@ -46,7 +46,7 @@ struct construct_aux<0, T, Pointer, Signature>
object_rep* self = touserdata<object_rep>(self_);
class_rep* cls = self->crep();
std::auto_ptr<T> instance(new T);
std::unique_ptr<T> instance(new T);
inject_backref(self_.interpreter(), instance.get(), instance.get());
void* naked_ptr = instance.get();
@ -55,7 +55,7 @@ struct construct_aux<0, T, Pointer, Signature>
void* storage = self->allocate(sizeof(holder_type));
self->set_instance(new (storage) holder_type(
ptr, registered_class<T>::id, naked_ptr, cls));
std::move(ptr), registered_class<T>::id, naked_ptr, cls));
}
};
@ -92,7 +92,7 @@ struct construct_aux<N, T, Pointer, Signature>
object_rep* self = touserdata<object_rep>(self_);
class_rep* cls = self->crep();
std::auto_ptr<T> instance(new T(BOOST_PP_ENUM_PARAMS(N,_)));
std::unique_ptr<T> instance(new T(BOOST_PP_ENUM_PARAMS(N,_)));
inject_backref(self_.interpreter(), instance.get(), instance.get());
void* naked_ptr = instance.get();
@ -101,7 +101,7 @@ struct construct_aux<N, T, Pointer, Signature>
void* storage = self->allocate(sizeof(holder_type));
self->set_instance(new (storage) holder_type(
ptr, registered_class<T>::id, naked_ptr, cls));
std::move(ptr), registered_class<T>::id, naked_ptr, cls));
}
};

View File

@ -58,7 +58,7 @@ namespace has_get_pointer_
T* get_pointer(T const volatile*);
template<class T>
T* get_pointer(std::auto_ptr<T> const&);
T* get_pointer(std::unique_ptr<T> const&);
# endif

View File

@ -57,7 +57,7 @@ inline mpl::true_ check_const_pointer(void const*)
}
template <class T>
void release_ownership(std::auto_ptr<T>& p)
void release_ownership(std::unique_ptr<T>& p)
{
p.release();
}
@ -83,7 +83,7 @@ public:
P p, class_id dynamic_id, void* dynamic_ptr, class_rep* cls
)
: instance_holder(cls, check_const_pointer(false ? get_pointer(p) : 0))
, p(p)
, p(std::move(p))
, weak(0)
, dynamic_id(dynamic_id)
, dynamic_ptr(dynamic_ptr)

View File

@ -88,7 +88,7 @@ void make_instance(lua_State* L, P p)
try
{
new (storage) holder_type(p, dynamic.first, dynamic.second, cls);
new (storage) holder_type(std::move(p), dynamic.first, dynamic.second, cls);
}
catch (...)
{

View File

@ -169,7 +169,7 @@ namespace luabind { namespace detail
{
if (get_pointer(x))
{
make_instance(L, x);
make_instance(L, std::move(x));
}
else
{
@ -180,8 +180,8 @@ namespace luabind { namespace detail
template <class T>
void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::true_)
{
std::auto_ptr<T> ptr(new T(x));
make_instance(L, ptr);
std::unique_ptr<T> ptr(new T(x));
make_instance(L, std::move(ptr));
}
template <class T>

View File

@ -46,7 +46,7 @@ namespace detail
template <class F, class Policies>
scope def(char const* name, F f, Policies const& policies)
{
return scope(std::auto_ptr<detail::registration>(
return scope(std::unique_ptr<detail::registration>(
new detail::function_registration<F, Policies>(name, f, policies)));
}

View File

@ -56,7 +56,7 @@ namespace luabind {
struct LUABIND_API scope
{
scope();
explicit scope(std::auto_ptr<detail::registration> reg);
explicit scope(std::unique_ptr<detail::registration> reg);
scope(scope const& other_);
~scope();

View File

@ -235,7 +235,7 @@ namespace luabind { namespace detail {
// -- interface ---------------------------------------------------------
class_base::class_base(char const* name)
: scope(std::auto_ptr<registration>(
: scope(std::unique_ptr<registration>(
m_registration = new class_registration(name))
)
{
@ -258,14 +258,14 @@ namespace luabind { namespace detail {
void class_base::add_member(registration* member)
{
std::auto_ptr<registration> ptr(member);
m_registration->m_members.operator,(scope(ptr));
std::unique_ptr<registration> ptr(member);
m_registration->m_members.operator,(scope(std::move(ptr)));
}
void class_base::add_default_member(registration* member)
{
std::auto_ptr<registration> ptr(member);
m_registration->m_default_members.operator,(scope(ptr));
std::unique_ptr<registration> ptr(member);
m_registration->m_default_members.operator,(scope(std::move(ptr)));
}
const char* class_base::name() const

View File

@ -49,7 +49,8 @@ namespace luabind { namespace detail {
{
}
scope::scope(std::auto_ptr<detail::registration> reg)
scope::scope(std::unique_ptr<detail::registration> reg)
: m_chain(reg.release())
{
}
@ -193,7 +194,7 @@ namespace luabind {
};
namespace_::namespace_(char const* name)
: scope(std::auto_ptr<detail::registration>(
: scope(std::unique_ptr<detail::registration>(
m_registration = new registration_(name)))
{
}

View File

@ -16,11 +16,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "encryption.h"
#include "common/compiler_macros.h"
#ifdef EQEMU_USE_OPENSSL
#include <openssl/des.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/provider.h>
#endif
#ifdef EQEMU_USE_MBEDTLS
#include <mbedtls/des.h>
@ -32,6 +33,8 @@
#include <cstring>
#include <string>
#include <memory>
#ifdef ENABLE_SECURITY
#include <sodium.h>
@ -127,21 +130,92 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff
#endif
#ifdef EQEMU_USE_OPENSSL
DES_key_schedule k;
DES_cblock v;
memset(&k, 0, sizeof(DES_key_schedule));
memset(&v, 0, sizeof(DES_cblock));
// Decrypt requires block-aligned input; encrypt zero-pads a trailing
// partial block to match the legacy DES_ncbc_encrypt semantics the
// game protocol expects.
if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) {
return nullptr;
}
DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc);
unsigned char key[8] = {0};
unsigned char iv[8] = {0};
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
return nullptr;
}
bool result = EVP_CipherInit_ex2(ctx, EVP_des_cbc(), key, iv, enc, nullptr) == 1;
if (result) {
EVP_CIPHER_CTX_set_padding(ctx, 0);
const unsigned char* src = reinterpret_cast<const unsigned char*>(buffer_in);
size_t src_len = buffer_in_sz;
std::unique_ptr<unsigned char[]> padded;
if (enc && buffer_in_sz % 8 != 0) {
src_len = ((buffer_in_sz / 8) + 1) * 8;
padded.reset(new unsigned char[src_len]());
memcpy(padded.get(), buffer_in, buffer_in_sz);
src = padded.get();
}
int outl = 0;
int final_len = 0;
result = EVP_CipherUpdate(ctx, reinterpret_cast<unsigned char*>(buffer_out), &outl, src, static_cast<int>(src_len)) == 1
&& EVP_CipherFinal_ex(ctx, reinterpret_cast<unsigned char*>(buffer_out) + outl, &final_len) == 1;
}
EVP_CIPHER_CTX_free(ctx);
if (!result) {
return nullptr;
}
#endif
return buffer_out;
}
#ifdef EQEMU_USE_OPENSSL
static OSSL_PROVIDER *s_legacy_provider = nullptr;
static OSSL_PROVIDER *s_default_provider = nullptr;
#endif
bool eqcrypt_init()
{
#ifdef EQEMU_USE_OPENSSL
if (!s_default_provider) {
s_default_provider = OSSL_PROVIDER_load(nullptr, "default");
}
if (!s_legacy_provider) {
s_legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
}
if (!s_default_provider || !s_legacy_provider) {
char buf[256];
while (auto err = ERR_get_error()) {
ERR_error_string_n(err, buf, sizeof(buf));
LogError("OpenSSL provider load failure: {}", buf);
}
return false;
}
#endif
return true;
}
void eqcrypt_shutdown()
{
#ifdef EQEMU_USE_OPENSSL
if (s_legacy_provider) {
OSSL_PROVIDER_unload(s_legacy_provider);
s_legacy_provider = nullptr;
}
if (s_default_provider) {
OSSL_PROVIDER_unload(s_default_provider);
s_default_provider = nullptr;
}
#endif
}
std::string eqcrypt_md5(const std::string &msg)
{
std::string ret;
@ -164,12 +238,12 @@ std::string eqcrypt_md5(const std::string &msg)
unsigned char md5_digest[16];
char tmp[4];
MD5((const unsigned char*)msg.c_str(), msg.length(), md5_digest);
for (int i = 0; i < 16; ++i) {
sprintf(&tmp[0], "%02x", md5_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
if (EVP_Digest(msg.data(), msg.length(), md5_digest, nullptr, EVP_md5(), nullptr) == 1) {
for (int i = 0; i < 16; ++i) {
sprintf(&tmp[0], "%02x", md5_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
}
}
#endif
@ -198,12 +272,12 @@ std::string eqcrypt_sha1(const std::string &msg)
unsigned char sha_digest[20];
char tmp[4];
SHA1((const unsigned char*)msg.c_str(), msg.length(), sha_digest);
for (int i = 0; i < 20; ++i) {
sprintf(&tmp[0], "%02x", sha_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha1(), nullptr) == 1) {
for (int i = 0; i < 20; ++i) {
sprintf(&tmp[0], "%02x", sha_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
}
}
#endif
@ -232,12 +306,12 @@ std::string eqcrypt_sha512(const std::string &msg)
unsigned char sha_digest[64];
char tmp[4];
SHA512((const unsigned char*)msg.c_str(), msg.length(), sha_digest);
for (int i = 0; i < 64; ++i) {
sprintf(&tmp[0], "%02x", sha_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha512(), nullptr) == 1) {
for (int i = 0; i < 64; ++i) {
sprintf(&tmp[0], "%02x", sha_digest[i]);
ret.push_back(tmp[0]);
ret.push_back(tmp[1]);
}
}
#endif

View File

@ -48,10 +48,20 @@ namespace CryptoHash {
}
std::string GetEncryptionByModeId(uint32 mode);
// DES-CBC with an all-zero key and IV (EQ login protocol obfuscation, not security).
// On encrypt, a trailing partial block is zero-padded to the next 8-byte boundary, so
// buffer_out must be at least ((buffer_in_sz + 7) / 8) * 8 bytes. On decrypt, buffer_in_sz
// must already be a multiple of 8 or the call returns nullptr.
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc);
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode);
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode);
// OpenSSL 3.0 moved DES behind the "legacy" provider; these load/unload it
// for the lifetime of the process. No-op when built against mbedtls.
bool eqcrypt_init();
void eqcrypt_shutdown();
struct EncryptionResult {
std::string password;
int mode = 0;

View File

@ -26,6 +26,7 @@
#include "common/platform.h"
#include "common/timer.h"
#include "common/types.h"
#include "loginserver/encryption.h"
#include "loginserver/login_server.h"
#include "loginserver/loginserver_command_handler.h"
#include "loginserver/loginserver_webserver.h"
@ -160,6 +161,11 @@ int main(int argc, char **argv)
RegisterExecutablePlatform(ExePlatformLogin);
set_exception_handler();
if (!eqcrypt_init()) {
LogError("Failed to initialize crypto providers");
return 1;
}
LogInfo("Logging System Init");
if (argc == 1) {
@ -280,5 +286,7 @@ int main(int argc, char **argv)
LogInfo("Server Manager Shutdown");
delete server.server_manager;
eqcrypt_shutdown();
return 0;
}

View File

@ -17,11 +17,13 @@
*/
#ifdef EMBPERL
#include "zone/embparser.h"
#include "common/compiler_macros.h"
#include "common/features.h"
#include "common/misc_functions.h"
#include "common/seperator.h"
#include "common/strings.h"
#include "zone/embparser.h"
#include "zone/masterentity.h"
#include "zone/qglobals.h"
#include "zone/questmgr.h"
@ -398,6 +400,8 @@ int PerlembParser::EventCommon(
zone
);
}
return 0;
}
int PerlembParser::EventNPC(
@ -1211,31 +1215,33 @@ QuestType PerlembParser::GetQuestTypes(
event_id == EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE
) {
return is_global ? QuestType::SpellGlobal : QuestType::Spell;
} else {
if (npc_mob) {
if (!inst) {
if (npc_mob->IsBot()) {
return is_global ? QuestType::BotGlobal : QuestType::Bot;
} else if (npc_mob->IsMerc()) {
return is_global ? QuestType::MercGlobal : QuestType::Merc;
} else if (npc_mob->IsNPC()) {
return is_global ? QuestType::NPCGlobal : QuestType::NPC;
}
} else {
return is_global ? QuestType::ItemGlobal : QuestType::Item;
}
} else if (!npc_mob && mob) {
if (!inst) {
if (mob->IsClient()) {
return is_global ? QuestType::PlayerGlobal : QuestType::Player;
}
} else {
return is_global ? QuestType::ItemGlobal : QuestType::Item;
}
} else if (zone) {
return is_global ? QuestType::ZoneGlobal : QuestType::Zone;
}
}
if (npc_mob) {
if (!inst) {
if (npc_mob->IsBot()) {
return is_global ? QuestType::BotGlobal : QuestType::Bot;
} else if (npc_mob->IsMerc()) {
return is_global ? QuestType::MercGlobal : QuestType::Merc;
} else if (npc_mob->IsNPC()) {
return is_global ? QuestType::NPCGlobal : QuestType::NPC;
}
} else {
return is_global ? QuestType::ItemGlobal : QuestType::Item;
}
} else if (mob) {
if (!inst) {
if (mob->IsClient()) {
return is_global ? QuestType::PlayerGlobal : QuestType::Player;
}
} else {
return is_global ? QuestType::ItemGlobal : QuestType::Item;
}
} else if (zone) {
return is_global ? QuestType::ZoneGlobal : QuestType::Zone;
}
UNREACHABLE();
}
std::string PerlembParser::GetQuestPackageName(

View File

@ -82,6 +82,16 @@ Lua_Packet::Lua_Packet(const Lua_Packet& o) {
}
}
Lua_Packet::~Lua_Packet()
{
if (owned_) {
EQApplicationPacket* ptr = GetLuaPtrData();
if (ptr) {
delete ptr;
}
}
}
int Lua_Packet::GetSize() {
Lua_Safe_Call_Int();
return static_cast<int>(self->size);

View File

@ -41,7 +41,7 @@ public:
Lua_Packet(int opcode, int size, bool raw);
Lua_Packet& operator=(const Lua_Packet& o);
Lua_Packet(const Lua_Packet& o);
virtual ~Lua_Packet() { if(owned_) { EQApplicationPacket *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } }
virtual ~Lua_Packet();
int GetSize();
int GetOpcode();

View File

@ -48,7 +48,8 @@ public:
Lua_Ptr(T *d) : d_(d) {
}
~Lua_Ptr() {
virtual ~Lua_Ptr() {
}
T *GetLuaPtrData() {